From nobody Fri Jul 07 01:15:47 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4QxwSg4Zhjz4lCmK; Fri, 7 Jul 2023 01:15:47 +0000 (UTC) (envelope-from git@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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4QxwSg44dDz3QDQ; Fri, 7 Jul 2023 01:15:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1688692547; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=TFkQAgyawLbGXTAM90iCH7rNMh+FIMNs4v+im08zwTk=; b=uv30IsCliIEz4PJUzbw/G4DT4jsEj5U+u6gHQOUt5f5EbYvLiOZr8WDA6wvpeGaMBAs0l1 JZOb0rl4wC2/AzFMD9oltW4KpCQGrJnfLBON2uprlxLRtfSl8sWvb3DLtvyO+ZXG0d1AXE Ow+ISWakwUD/JawXMOvno4u8dktPzmqO18tWOr0n2TJCS9781n5VDYVQvLyzmR2jeIPS5T fxfJCcpg3vv58DkM/I5FPLAj5ZtYaY5cZyssZv5582aaKQKs1PZ89iZn8U/OzR6ozxI4zU UgF5gE102uz56SksdsFRjW1k/mG4muwnvqGw+5NMbAUQxpd3OtUZtt820znGOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1688692547; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=TFkQAgyawLbGXTAM90iCH7rNMh+FIMNs4v+im08zwTk=; b=DkfeqhhmKdJgbw7CrQex3pTjJ0Jv0aqb1OB2L3LeyKx+4A0Mix1XtnV8LTr99gk3aRIo7b HTZgqqSY7Miqw1GgmW0c43JUBTSQRMiCSiLDPDZwA2H06tRBjbFD2Kclv7t6zZg+o0HjMA KNWBjOX6mvC1IYVglhHvuutEV5yQyaktcLuZUdAATR5GeTNoSEO3GlICKSft2XfQQPoU35 6nRNnKawiGQUa+ah8/wInVRJEORgrAl6/aa6WDPL/MlgEATSbzhAWXr6nzjAlyYaPV3tig MNJldqoJ7eifezxS+8QZEG/SvxpTZsB3DIxUK3bCf2bKuo49Uxey02qcUajFXg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1688692547; a=rsa-sha256; cv=none; b=l2gXBqcspI+5K/nFjXl2O4KJFKnoyfwVqpGvv5cUZdcvbD3IM5NC2rVvmGb3SbNJ0MjM6c nJZXb3KmVUaUR+BEkXmKGcl0Kkgk24bE8nN95jfWzvI80o2GHqhL+bs/3tL6s9h3mBLY6p eqj+btOLXYsEWL3yLVd6yqi0gqjZMijShcUf2FYsxwZ4yCkZyQrFCccMCmQ7DpLu++n6Y9 kKgGgsHAbAtz0FcbaSBGq3ekY2/5ueA9bUM6EpvnDUiu60CEDg92CxB6oUFEjBCrZak7Tc WQzgw/scSp6DJW5H7Gs3lHiSYoDnz3Ml9NmmlPZBUt8UZ99bZJCw9t4iCcLZTA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4QxwSg37KXzKF4; Fri, 7 Jul 2023 01:15:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3671FlYS059717; Fri, 7 Jul 2023 01:15:47 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3671FlQe059716; Fri, 7 Jul 2023 01:15:47 GMT (envelope-from git) Date: Fri, 7 Jul 2023 01:15:47 GMT Message-Id: <202307070115.3671FlQe059716@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mateusz Guzik Subject: git: 80bd5ef07025 - main - vfs: factor out mount point traversal to a dedicated routine List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mjg X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 80bd5ef0702562c546fa1717e8fe221058974eac Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=80bd5ef0702562c546fa1717e8fe221058974eac commit 80bd5ef0702562c546fa1717e8fe221058974eac Author: Mateusz Guzik AuthorDate: 2023-07-05 23:01:17 +0000 Commit: Mateusz Guzik CommitDate: 2023-07-07 01:15:04 +0000 vfs: factor out mount point traversal to a dedicated routine While here tidy up asserts in the area. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D40883 --- sys/kern/vfs_lookup.c | 142 +++++++++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 60 deletions(-) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 5a5560a4c26f..1f62cf3e6652 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -871,6 +871,79 @@ vfs_lookup_failifexists(struct nameidata *ndp) return (EEXIST); } +static int __noinline +vfs_lookup_cross_mount(struct nameidata *ndp) +{ + struct componentname *cnp; + struct mount *mp; + struct vnode *dp, *tdp; + int error, crosslkflags; + bool crosslock; + + cnp = &ndp->ni_cnd; + dp = ndp->ni_vp; + + /* + * The vnode has been mounted on, find the root of the mounted + * filesystem. + */ + for (;;) { + mp = dp->v_mountedhere; + ASSERT_VOP_LOCKED(dp, __func__); + VNPASS((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0 && mp != NULL, dp); + + crosslock = (dp->v_vflag & VV_CROSSLOCK) != 0; + crosslkflags = enforce_lkflags(mp, cnp->cn_lkflags); + if (__predict_false(crosslock)) { + /* + * We are going to be holding the vnode lock, which + * in this case is shared by the root vnode of the + * filesystem mounted at mp, across the call to + * VFS_ROOT(). Make the situation clear to the + * filesystem by passing LK_CANRECURSE if the + * lock is held exclusive, or by clearinng + * LK_NODDLKTREAT to allow recursion on the shared + * lock in the presence of an exclusive waiter. + */ + if (VOP_ISLOCKED(dp) == LK_EXCLUSIVE) { + crosslkflags &= ~LK_SHARED; + crosslkflags |= LK_EXCLUSIVE | LK_CANRECURSE; + } else if ((crosslkflags & LK_EXCLUSIVE) != 0) { + error = vn_lock(dp, LK_UPGRADE); + if (error != 0) + break; + if (dp->v_mountedhere != mp) { + continue; + } + } else + crosslkflags &= ~LK_NODDLKTREAT; + } + if (vfs_busy(mp, 0) != 0) + continue; + if (__predict_true(!crosslock)) + vput(dp); + if (dp != ndp->ni_dvp) + vput(ndp->ni_dvp); + else + vrele(ndp->ni_dvp); + vrefact(vp_crossmp); + ndp->ni_dvp = vp_crossmp; + error = VFS_ROOT(mp, crosslkflags, &tdp); + vfs_unbusy(mp); + if (__predict_false(crosslock)) + vput(dp); + if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT)) + panic("vp_crossmp exclusively locked or reclaimed"); + if (error != 0) + break; + ndp->ni_vp = dp = tdp; + if ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) == 0) + break; + } + + return (error); +} + /* * Search a pathname. * This is a very central and rather complicated routine. @@ -919,7 +992,6 @@ vfs_lookup(struct nameidata *ndp) char *lastchar; /* location of the last character */ struct vnode *dp = NULL; /* the directory we are searching */ struct vnode *tdp; /* saved dp */ - struct mount *mp; /* mount table entry */ struct prison *pr; size_t prev_ni_pathlen; /* saved ndp->ni_pathlen */ int docache; /* == 0 do not cache last component */ @@ -930,8 +1002,6 @@ vfs_lookup(struct nameidata *ndp) struct componentname *cnp = &ndp->ni_cnd; int lkflags_save; int ni_dvp_unlocked; - int crosslkflags; - bool crosslock; /* * Setup: break out flag bits into variables. @@ -1283,66 +1353,18 @@ good: ni_dvp_unlocked = 1; } goto success; - } else if ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0) { - if ((cnp->cn_flags & NOCROSSMOUNT) != 0) - goto nextname; - } else - goto nextname; + } - /* - * Check to see if the vnode has been mounted on; - * if so find the root of the mounted filesystem. - */ - do { - mp = dp->v_mountedhere; - KASSERT(mp != NULL, - ("%s: NULL mountpoint for VIRF_MOUNTPOINT vnode", __func__)); - crosslock = (dp->v_vflag & VV_CROSSLOCK) != 0; - crosslkflags = enforce_lkflags(mp, cnp->cn_lkflags); - if (__predict_false(crosslock)) { - /* - * We are going to be holding the vnode lock, which - * in this case is shared by the root vnode of the - * filesystem mounted at mp, across the call to - * VFS_ROOT(). Make the situation clear to the - * filesystem by passing LK_CANRECURSE if the - * lock is held exclusive, or by clearinng - * LK_NODDLKTREAT to allow recursion on the shared - * lock in the presence of an exclusive waiter. - */ - if (VOP_ISLOCKED(dp) == LK_EXCLUSIVE) { - crosslkflags &= ~LK_SHARED; - crosslkflags |= LK_EXCLUSIVE | LK_CANRECURSE; - } else if ((crosslkflags & LK_EXCLUSIVE) != 0) { - error = vn_lock(dp, LK_UPGRADE); - if (error != 0) - goto bad_unlocked; - if (dp->v_mountedhere != mp) { - continue; - } - } else - crosslkflags &= ~LK_NODDLKTREAT; - } - if (vfs_busy(mp, 0) != 0) - continue; - if (__predict_true(!crosslock)) - vput(dp); - if (dp != ndp->ni_dvp) - vput(ndp->ni_dvp); - else - vrele(ndp->ni_dvp); - vrefact(vp_crossmp); - ndp->ni_dvp = vp_crossmp; - error = VFS_ROOT(mp, crosslkflags, &tdp); - vfs_unbusy(mp); - if (__predict_false(crosslock)) - vput(dp); - if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT)) - panic("vp_crossmp exclusively locked or reclaimed"); + if ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0 && + (cnp->cn_flags & NOCROSSMOUNT) == 0) { + error = vfs_lookup_cross_mount(ndp); if (error != 0) goto bad_unlocked; - ndp->ni_vp = dp = tdp; - } while ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0); + /* + * FALLTHROUGH to nextname + */ + dp = ndp->ni_vp; + } nextname: /*