tmpfs: add support for lockless lookup
Reviewed by: kib Tested by: pho (in a patchset) Differential Revision: https://reviews.freebsd.org/D25580
This commit is contained in:
parent
9d5a594f0b
commit
172ffe702c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363521
@ -526,6 +526,9 @@ VP_TO_TMPFS_NODE(struct vnode *vp)
|
||||
return (node);
|
||||
}
|
||||
|
||||
#define VP_TO_TMPFS_NODE_SMR(vp) \
|
||||
((struct tmpfs_node *)vn_load_v_data_smr(vp))
|
||||
|
||||
static inline struct tmpfs_node *
|
||||
VP_TO_TMPFS_DIR(struct vnode *vp)
|
||||
{
|
||||
|
@ -75,6 +75,7 @@ static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED;
|
||||
|
||||
static uma_zone_t tmpfs_dirent_pool;
|
||||
static uma_zone_t tmpfs_node_pool;
|
||||
VFS_SMR_DECLARE;
|
||||
|
||||
static int
|
||||
tmpfs_node_ctor(void *mem, int size, void *arg, int flags)
|
||||
@ -131,6 +132,7 @@ tmpfs_subr_init(void)
|
||||
tmpfs_node_pool = uma_zcreate("TMPFS node",
|
||||
sizeof(struct tmpfs_node), tmpfs_node_ctor, tmpfs_node_dtor,
|
||||
tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, 0);
|
||||
VFS_SMR_ZONE_SET(tmpfs_node_pool);
|
||||
}
|
||||
|
||||
void
|
||||
@ -288,7 +290,7 @@ tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *tmp, enum vtype type,
|
||||
if ((mp->mnt_kern_flag & MNT_RDONLY) != 0)
|
||||
return (EROFS);
|
||||
|
||||
nnode = uma_zalloc_arg(tmpfs_node_pool, tmp, M_WAITOK);
|
||||
nnode = uma_zalloc_smr(tmpfs_node_pool, M_WAITOK);
|
||||
|
||||
/* Generic initialization. */
|
||||
nnode->tn_type = type;
|
||||
@ -435,7 +437,7 @@ tmpfs_free_node_locked(struct tmpfs_mount *tmp, struct tmpfs_node *node,
|
||||
panic("tmpfs_free_node: type %p %d", node, (int)node->tn_type);
|
||||
}
|
||||
|
||||
uma_zfree(tmpfs_node_pool, node);
|
||||
uma_zfree_smr(tmpfs_node_pool, node);
|
||||
TMPFS_LOCK(tmp);
|
||||
tmpfs_free_tmp(tmp);
|
||||
return (true);
|
||||
@ -1621,8 +1623,10 @@ tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct thread *p)
|
||||
{
|
||||
int error;
|
||||
struct tmpfs_node *node;
|
||||
mode_t newmode;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, "chmod");
|
||||
ASSERT_VOP_IN_SEQC(vp);
|
||||
|
||||
node = VP_TO_TMPFS_NODE(vp);
|
||||
|
||||
@ -1656,9 +1660,9 @@ tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct thread *p)
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
node->tn_mode &= ~ALLPERMS;
|
||||
node->tn_mode |= mode & ALLPERMS;
|
||||
newmode = node->tn_mode & ~ALLPERMS;
|
||||
newmode |= mode & ALLPERMS;
|
||||
atomic_store_short(&node->tn_mode, newmode);
|
||||
|
||||
node->tn_status |= TMPFS_NODE_CHANGED;
|
||||
|
||||
@ -1682,8 +1686,10 @@ tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
|
||||
struct tmpfs_node *node;
|
||||
uid_t ouid;
|
||||
gid_t ogid;
|
||||
mode_t newmode;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, "chown");
|
||||
ASSERT_VOP_IN_SEQC(vp);
|
||||
|
||||
node = VP_TO_TMPFS_NODE(vp);
|
||||
|
||||
@ -1729,8 +1735,10 @@ tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
|
||||
node->tn_status |= TMPFS_NODE_CHANGED;
|
||||
|
||||
if ((node->tn_mode & (S_ISUID | S_ISGID)) && (ouid != uid || ogid != gid)) {
|
||||
if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID))
|
||||
node->tn_mode &= ~(S_ISUID | S_ISGID);
|
||||
if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID)) {
|
||||
newmode = node->tn_mode & ~(S_ISUID | S_ISGID);
|
||||
atomic_store_short(&node->tn_mode, newmode);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, "chown2");
|
||||
|
@ -462,6 +462,8 @@ tmpfs_mount(struct mount *mp)
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED |
|
||||
MNTK_TEXT_REFS | MNTK_NOMSYNC;
|
||||
if (!nonc)
|
||||
mp->mnt_kern_flag |= MNTK_FPLOOKUP;
|
||||
MNT_IUNLOCK(mp);
|
||||
|
||||
mp->mnt_data = tmp;
|
||||
|
@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/smr.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
@ -64,6 +65,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <fs/tmpfs/tmpfs.h>
|
||||
|
||||
SYSCTL_DECL(_vfs_tmpfs);
|
||||
VFS_SMR_DECLARE;
|
||||
|
||||
static volatile int tmpfs_rename_restarts;
|
||||
SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD,
|
||||
@ -317,6 +319,32 @@ tmpfs_close(struct vop_close_args *v)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see
|
||||
* the comment above cache_fplookup for details.
|
||||
*/
|
||||
int
|
||||
tmpfs_fplookup_vexec(struct vop_fplookup_vexec_args *v)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct tmpfs_node *node;
|
||||
struct ucred *cred;
|
||||
mode_t all_x, mode;
|
||||
|
||||
vp = v->a_vp;
|
||||
node = VP_TO_TMPFS_NODE_SMR(vp);
|
||||
if (__predict_false(node == NULL))
|
||||
return (EAGAIN);
|
||||
|
||||
all_x = S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
mode = atomic_load_short(&node->tn_mode);
|
||||
if (__predict_true((mode & all_x) == all_x))
|
||||
return (0);
|
||||
|
||||
cred = v->a_cred;
|
||||
return (vaccess_vexec_smr(mode, node->tn_uid, node->tn_gid, cred));
|
||||
}
|
||||
|
||||
int
|
||||
tmpfs_access(struct vop_access_args *v)
|
||||
{
|
||||
@ -427,6 +455,7 @@ tmpfs_setattr(struct vop_setattr_args *v)
|
||||
int error;
|
||||
|
||||
MPASS(VOP_ISLOCKED(vp));
|
||||
ASSERT_VOP_IN_SEQC(vp);
|
||||
|
||||
error = 0;
|
||||
|
||||
@ -497,6 +526,7 @@ tmpfs_write(struct vop_write_args *v)
|
||||
struct tmpfs_node *node;
|
||||
off_t oldsize;
|
||||
int error, ioflag;
|
||||
mode_t newmode;
|
||||
|
||||
vp = v->a_vp;
|
||||
uio = v->a_uio;
|
||||
@ -527,8 +557,12 @@ tmpfs_write(struct vop_write_args *v)
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED |
|
||||
TMPFS_NODE_CHANGED;
|
||||
if (node->tn_mode & (S_ISUID | S_ISGID)) {
|
||||
if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID))
|
||||
node->tn_mode &= ~(S_ISUID | S_ISGID);
|
||||
if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID)) {
|
||||
newmode = node->tn_mode & ~(S_ISUID | S_ISGID);
|
||||
vn_seqc_write_begin(vp);
|
||||
atomic_store_short(&node->tn_mode, newmode);
|
||||
vn_seqc_write_end(vp);
|
||||
}
|
||||
}
|
||||
if (error != 0)
|
||||
(void)tmpfs_reg_resize(vp, oldsize, TRUE);
|
||||
@ -806,12 +840,15 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
struct tmpfs_node *tnode;
|
||||
struct tmpfs_node *tdnode;
|
||||
int error;
|
||||
bool want_seqc_end;
|
||||
|
||||
MPASS(VOP_ISLOCKED(tdvp));
|
||||
MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp)));
|
||||
MPASS(fcnp->cn_flags & HASBUF);
|
||||
MPASS(tcnp->cn_flags & HASBUF);
|
||||
|
||||
want_seqc_end = false;
|
||||
|
||||
/*
|
||||
* Disallow cross-device renames.
|
||||
* XXX Why isn't this done by the caller?
|
||||
@ -852,6 +889,13 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
}
|
||||
}
|
||||
|
||||
if (tvp != NULL)
|
||||
vn_seqc_write_begin(tvp);
|
||||
vn_seqc_write_begin(tdvp);
|
||||
vn_seqc_write_begin(fvp);
|
||||
vn_seqc_write_begin(fdvp);
|
||||
want_seqc_end = true;
|
||||
|
||||
tmp = VFS_TO_TMPFS(tdvp->v_mount);
|
||||
tdnode = VP_TO_TMPFS_DIR(tdvp);
|
||||
tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
|
||||
@ -1065,6 +1109,14 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
VOP_UNLOCK(fdvp);
|
||||
|
||||
out:
|
||||
if (want_seqc_end) {
|
||||
if (tvp != NULL)
|
||||
vn_seqc_write_end(tvp);
|
||||
vn_seqc_write_end(tdvp);
|
||||
vn_seqc_write_end(fvp);
|
||||
vn_seqc_write_end(fdvp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release target nodes.
|
||||
* XXX: I don't understand when tdvp can be the same as tvp, but
|
||||
@ -1621,6 +1673,7 @@ struct vop_vector tmpfs_vnodeop_entries = {
|
||||
.vop_mknod = tmpfs_mknod,
|
||||
.vop_open = tmpfs_open,
|
||||
.vop_close = tmpfs_close,
|
||||
.vop_fplookup_vexec = tmpfs_fplookup_vexec,
|
||||
.vop_access = tmpfs_access,
|
||||
.vop_getattr = tmpfs_getattr,
|
||||
.vop_setattr = tmpfs_setattr,
|
||||
|
@ -49,6 +49,7 @@ extern struct vop_vector tmpfs_vnodeop_entries;
|
||||
extern struct vop_vector tmpfs_vnodeop_nonc_entries;
|
||||
|
||||
vop_access_t tmpfs_access;
|
||||
vop_fplookup_vexec_t tmpfs_fplookup_vexec;
|
||||
vop_getattr_t tmpfs_getattr;
|
||||
vop_setattr_t tmpfs_setattr;
|
||||
vop_pathconf_t tmpfs_pathconf;
|
||||
|
Loading…
Reference in New Issue
Block a user