From owner-svn-src-head@freebsd.org Sat Jul 25 10:38:46 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 056283A6CB9; Sat, 25 Jul 2020 10:38:46 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BDMxK6Nzxz4459; Sat, 25 Jul 2020 10:38:45 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id C004619E7D; Sat, 25 Jul 2020 10:38:45 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 06PAcjep044066; Sat, 25 Jul 2020 10:38:45 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06PAci9w044061; Sat, 25 Jul 2020 10:38:44 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <202007251038.06PAci9w044061@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Sat, 25 Jul 2020 10:38:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363521 - head/sys/fs/tmpfs X-SVN-Group: head X-SVN-Commit-Author: mjg X-SVN-Commit-Paths: head/sys/fs/tmpfs X-SVN-Commit-Revision: 363521 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Jul 2020 10:38:46 -0000 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 #include #include +#include #include #include @@ -64,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include 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;