svn commit: r363521 - head/sys/fs/tmpfs
Mateusz Guzik
mjg at FreeBSD.org
Sat Jul 25 10:38:46 UTC 2020
Author: mjg
Date: Sat Jul 25 10:38:44 2020
New Revision: 363521
URL: https://svnweb.freebsd.org/changeset/base/363521
Log:
tmpfs: add support for lockless lookup
Reviewed by: kib
Tested by: pho (in a patchset)
Differential Revision: https://reviews.freebsd.org/D25580
Modified:
head/sys/fs/tmpfs/tmpfs.h
head/sys/fs/tmpfs/tmpfs_subr.c
head/sys/fs/tmpfs/tmpfs_vfsops.c
head/sys/fs/tmpfs/tmpfs_vnops.c
head/sys/fs/tmpfs/tmpfs_vnops.h
Modified: head/sys/fs/tmpfs/tmpfs.h
==============================================================================
--- head/sys/fs/tmpfs/tmpfs.h Sat Jul 25 10:38:05 2020 (r363520)
+++ head/sys/fs/tmpfs/tmpfs.h Sat Jul 25 10:38:44 2020 (r363521)
@@ -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)
{
Modified: head/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_subr.c Sat Jul 25 10:38:05 2020 (r363520)
+++ head/sys/fs/tmpfs/tmpfs_subr.c Sat Jul 25 10:38:44 2020 (r363521)
@@ -75,6 +75,7 @@ static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESE
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
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
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 ucre
{
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,10 +1660,10 @@ tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucre
return (error);
}
+ newmode = node->tn_mode & ~ALLPERMS;
+ newmode |= mode & ALLPERMS;
+ atomic_store_short(&node->tn_mode, newmode);
- node->tn_mode &= ~ALLPERMS;
- node->tn_mode |= mode & ALLPERMS;
-
node->tn_status |= TMPFS_NODE_CHANGED;
ASSERT_VOP_ELOCKED(vp, "chmod2");
@@ -1682,8 +1686,10 @@ tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, st
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, st
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");
Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vfsops.c Sat Jul 25 10:38:05 2020 (r363520)
+++ head/sys/fs/tmpfs/tmpfs_vfsops.c Sat Jul 25 10:38:44 2020 (r363521)
@@ -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;
Modified: head/sys/fs/tmpfs/tmpfs_vnops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vnops.c Sat Jul 25 10:38:05 2020 (r363520)
+++ head/sys/fs/tmpfs/tmpfs_vnops.c Sat Jul 25 10:38:44 2020 (r363521)
@@ -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,7 +319,33 @@ 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)
{
struct vnode *vp = v->a_vp;
@@ -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 @@ out_locked:
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,
Modified: head/sys/fs/tmpfs/tmpfs_vnops.h
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vnops.h Sat Jul 25 10:38:05 2020 (r363520)
+++ head/sys/fs/tmpfs/tmpfs_vnops.h Sat Jul 25 10:38:44 2020 (r363521)
@@ -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;
More information about the svn-src-all
mailing list