Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Jul 2020 10:38:44 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r363521 - head/sys/fs/tmpfs
Message-ID:  <202007251038.06PAci9w044061@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007251038.06PAci9w044061>