Add mount option for tmpfs(5) to not use namecache.

The option "nonc" disables using of namecache for the created mount,
by default namecache is used.  The rationale for the option is that
namecache duplicates the information which is already kept in memory
by tmpfs.  Since it believed that namecache scales better than tmpfs,
or will scale better, do not enable the option by default.  On the
other hand, smaller machines may benefit from lesser namecache
pressure.

Discussed with:	mjg
Tested by:	pho (as part of larger patch)
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2017-01-19 19:46:49 +00:00
parent 08c053e71c
commit 00ac6a98d8
5 changed files with 54 additions and 17 deletions

View File

@ -385,7 +385,9 @@ struct tmpfs_mount {
uma_zone_t tm_node_pool;
/* Read-only status. */
int tm_ronly;
bool tm_ronly;
/* Do not use namecache. */
bool tm_nonc;
};
#define TMPFS_LOCK(tm) mtx_lock(&(tm)->tm_allnode_lock)
#define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->tm_allnode_lock)
@ -530,4 +532,11 @@ VP_TO_TMPFS_DIR(struct vnode *vp)
return (node);
}
static inline bool
tmpfs_use_nc(struct vnode *vp)
{
return (!(VFS_TO_TMPFS(vp->v_mount)->tm_nonc));
}
#endif /* _FS_TMPFS_TMPFS_H_ */

View File

@ -591,7 +591,8 @@ loop:
TMPFS_NODE_UNLOCK(node);
/* Get a new vnode and associate it with our node. */
error = getnewvnode("tmpfs", mp, &tmpfs_vnodeop_entries, &vp);
error = getnewvnode("tmpfs", mp, VFS_TO_TMPFS(mp)->tm_nonc ?
&tmpfs_vnodeop_nonc_entries : &tmpfs_vnodeop_entries, &vp);
if (error != 0)
goto unlock;
MPASS(vp != NULL);

View File

@ -79,7 +79,7 @@ static void tmpfs_susp_clean(struct mount *);
static const char *tmpfs_opts[] = {
"from", "size", "maxfilesize", "inodes", "uid", "gid", "mode", "export",
"union", NULL
"union", "nonc", NULL
};
static const char *tmpfs_updateopts[] = {
@ -138,6 +138,7 @@ tmpfs_mount(struct mount *mp)
struct tmpfs_node *root;
struct thread *td = curthread;
int error;
bool nonc;
/* Size counters. */
u_quad_t pages;
off_t nodes_max, size_max, maxfilesize;
@ -186,6 +187,7 @@ tmpfs_mount(struct mount *mp)
size_max = 0;
if (vfs_getopt_size(mp->mnt_optnew, "maxfilesize", &maxfilesize) != 0)
maxfilesize = 0;
nonc = vfs_getopt(mp->mnt_optnew, "nonc", NULL, NULL) == 0;
/* Do not allow mounts if we do not have enough memory to preserve
* the minimum reserved pages. */
@ -236,6 +238,7 @@ tmpfs_mount(struct mount *mp)
sizeof(struct tmpfs_node), tmpfs_node_ctor, tmpfs_node_dtor,
tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, 0);
tmp->tm_ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
tmp->tm_nonc = nonc;
/* Allocate the root node. */
error = tmpfs_alloc_node(mp, tmp, VDIR, root_uid, root_gid,

View File

@ -76,11 +76,8 @@ tmpfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
}
static int
tmpfs_lookup(struct vop_cachedlookup_args *v)
tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct tmpfs_dirent *de;
struct tmpfs_node *dnode, *pnode;
struct tmpfs_mount *tm;
@ -213,7 +210,7 @@ tmpfs_lookup(struct vop_cachedlookup_args *v)
* request was for creation, as it does not improve timings on
* emprical tests.
*/
if ((cnp->cn_flags & MAKEENTRY) != 0)
if ((cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
cache_enter(dvp, *vpp, cnp);
out:
@ -226,6 +223,20 @@ out:
return (error);
}
static int
tmpfs_cached_lookup(struct vop_cachedlookup_args *v)
{
return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp));
}
static int
tmpfs_lookup(struct vop_lookup_args *v)
{
return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp));
}
static int
tmpfs_create(struct vop_create_args *v)
{
@ -238,7 +249,7 @@ tmpfs_create(struct vop_create_args *v)
MPASS(vap->va_type == VREG || vap->va_type == VSOCK);
error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0)
if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
cache_enter(dvp, *vpp, cnp);
return (error);
}
@ -1013,10 +1024,12 @@ tmpfs_rename(struct vop_rename_args *v)
tmpfs_dir_attach(tdvp, de);
cache_purge(fvp);
if (tvp != NULL)
cache_purge(tvp);
cache_purge_negative(tdvp);
if (tmpfs_use_nc(fvp)) {
cache_purge(fvp);
if (tvp != NULL)
cache_purge(tvp);
cache_purge_negative(tdvp);
}
error = 0;
@ -1129,8 +1142,10 @@ tmpfs_rmdir(struct vop_rmdir_args *v)
TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(dnode);
cache_purge(dvp);
cache_purge(vp);
if (tmpfs_use_nc(dvp)) {
cache_purge(dvp);
cache_purge(vp);
}
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
@ -1274,7 +1289,8 @@ tmpfs_reclaim(struct vop_reclaim_args *v)
else
vnode_destroy_vobject(vp);
vp->v_object = NULL;
cache_purge(vp);
if (tmpfs_use_nc(vp))
cache_purge(vp);
TMPFS_NODE_LOCK(node);
tmpfs_free_vp(vp);
@ -1538,7 +1554,7 @@ restart:
struct vop_vector tmpfs_vnodeop_entries = {
.vop_default = &default_vnodeops,
.vop_lookup = vfs_cache_lookup,
.vop_cachedlookup = tmpfs_lookup,
.vop_cachedlookup = tmpfs_cached_lookup,
.vop_create = tmpfs_create,
.vop_mknod = tmpfs_mknod,
.vop_open = tmpfs_open,
@ -1567,3 +1583,10 @@ struct vop_vector tmpfs_vnodeop_entries = {
.vop_vptocnp = tmpfs_vptocnp,
};
/*
* Same vector for mounts which do not use namecache.
*/
struct vop_vector tmpfs_vnodeop_nonc_entries = {
.vop_default = &tmpfs_vnodeop_entries,
.vop_lookup = tmpfs_lookup,
};

View File

@ -44,6 +44,7 @@
*/
extern struct vop_vector tmpfs_vnodeop_entries;
extern struct vop_vector tmpfs_vnodeop_nonc_entries;
vop_access_t tmpfs_access;
vop_getattr_t tmpfs_getattr;