From nobody Sat Mar 19 10:50:34 2022 X-Original-To: dev-commits-src-main@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 9B68F1A2D207; Sat, 19 Mar 2022 10:50:34 +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 4KLHj63Rn5z4k8Y; Sat, 19 Mar 2022 10:50:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647687034; 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=HtMszg3pBcAO3O0fyPXgtZc1MHIPgfRSreHiCOTPMPs=; b=aOMNeovmJrfEQuBu4AsaOOyztpPA3UX47l1Pxyuj5lP/496gVG7E6OgcahpOv+W3YaAdRO WfE2MBv0zU5gaToSlvmrxqbf/JJsdECmoNCShLY9SIy4SOQ9O5Vxx/5SRv1z8BNzSIte42 mlI4qpBYII58xlGSJ6MNiYAmg1d7zw8zwD0uE3Mid/YXdk8Y5nVbpIJP3WAc4XCyqSYERb hlxb8IbrWuXPh6YQL6H7pVZMGkkKXwQsitHWeMtYOWuesTXf4z+8OWwWLrzHJHLkEpUpe1 tSUPr8jczjsnYufhUuwWJM83qyLqN4jtsWhVkOomNn1gkcOnP5IcuKkRUPKFpQ== 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 4E12212015; Sat, 19 Mar 2022 10:50:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 22JAoYAO034032; Sat, 19 Mar 2022 10:50:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 22JAoY4b034031; Sat, 19 Mar 2022 10:50:34 GMT (envelope-from git) Date: Sat, 19 Mar 2022 10:50:34 GMT Message-Id: <202203191050.22JAoY4b034031@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: aeabf8d4b972 - main - nullfs: hash insertion without vnode lock upgrade List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: aeabf8d4b9727201648887f8aa7dd1930cf0e154 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647687034; 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=HtMszg3pBcAO3O0fyPXgtZc1MHIPgfRSreHiCOTPMPs=; b=l3fFU17wY6EbmnjecoEt/DOo0IqQic1MhZWsZWaWwgisGYw/+Vr3XtXOIDQhmH9sUUba3z dTapd/Z/FKmOUU5CcquiAmWM2yrJuyUBje8rSICK2vPhVPnT0/3fteKpghw3tzYO0HKsf/ R70oDto1tZ0+/Xg4koeD+zzdpGtvSDpusSkICxA/K11hP+txosaTlOL/DQKOvy2m+ueBPU 8uoCu2JX5/AgQ8EYBEaaSQEFC2MDZg/NOM32vzO/huCQe/bg4yr2aBrTH06o55kudjlAb7 ar94t6O91sX5zSzN37KO/1lgHX9koeMifMjfA9XdZDBM/lqaqhnYY/2250q/dg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1647687034; a=rsa-sha256; cv=none; b=PYgVogaBxJ4WdBihgwro29BGacU4R55UQ+lZUXpoku/FWxfYI7yRz5sdQJ3a0HkbDTQX1w CwGMYVVHVychK56wssR/Fh6SmlgeBcwf0hIlIF8FrfCcA/5ybj/+bGSPrBWkDdceZ0rwFH XJ0gCF8U9fX8iKSVQVu0dsSEXga0hK9JzeCgmruqYQlajHNimMVaXJ7MQ3ZTHJldwuO8Pv +gtUQv1MwuSXDQX8EN8rzvZ7g2grtL95dKJb1MDYXDSXcxuWE4AtFPSXSQDhrv8hvajc9v DCZNcMcUJPkTdhOHet5gFOITn0EW51+QnY/Ti7o9j4HlGpEFNxdKtx2a28WxGg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=aeabf8d4b9727201648887f8aa7dd1930cf0e154 commit aeabf8d4b9727201648887f8aa7dd1930cf0e154 Author: Mateusz Guzik AuthorDate: 2022-03-07 11:43:43 +0000 Commit: Mateusz Guzik CommitDate: 2022-03-19 10:47:10 +0000 nullfs: hash insertion without vnode lock upgrade Use the hash lock to serialize instead. This enables shared-locked ".." lookups. Reviewed by: markj Tested by: pho (previous version) Differential Revision: https://reviews.freebsd.org/D34466 --- sys/fs/nullfs/null_subr.c | 114 ++++++++++++++++++++------------------------ sys/fs/nullfs/null_vfsops.c | 2 +- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 6b422410b9ec..b2b6e6837b2d 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -65,7 +65,7 @@ static u_long null_hash_mask; static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table"); MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part"); -static struct vnode * null_hashins(struct mount *, struct null_node *); +static void null_hashins(struct mount *, struct null_node *); /* * Initialise cache headers @@ -93,14 +93,15 @@ nullfs_uninit(struct vfsconf *vfsp) * Return a VREF'ed alias for lower vnode if already exists, else 0. * Lower vnode should be locked on entry and will be left locked on exit. */ -struct vnode * -null_hashget(struct mount *mp, struct vnode *lowervp) +static struct vnode * +null_hashget_locked(struct mount *mp, struct vnode *lowervp) { struct null_node_hashhead *hd; struct null_node *a; struct vnode *vp; ASSERT_VOP_LOCKED(lowervp, "null_hashget"); + rw_assert(&null_hash_lock, RA_LOCKED); /* * Find hash base, and then search the (two-way) linked @@ -109,9 +110,6 @@ null_hashget(struct mount *mp, struct vnode *lowervp) * reference count (but NOT the lower vnode's VREF counter). */ hd = NULL_NHASH(lowervp); - if (LIST_EMPTY(hd)) - return (NULLVP); - rw_rlock(&null_hash_lock); LIST_FOREACH(a, hd, null_hash) { if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) { /* @@ -122,43 +120,50 @@ null_hashget(struct mount *mp, struct vnode *lowervp) */ vp = NULLTOV(a); vref(vp); - rw_runlock(&null_hash_lock); return (vp); } } - rw_runlock(&null_hash_lock); return (NULLVP); } -/* - * Act like null_hashget, but add passed null_node to hash if no existing - * node found. - */ -static struct vnode * +struct vnode * +null_hashget(struct mount *mp, struct vnode *lowervp) +{ + struct null_node_hashhead *hd; + struct vnode *vp; + + hd = NULL_NHASH(lowervp); + if (LIST_EMPTY(hd)) + return (NULLVP); + + rw_rlock(&null_hash_lock); + vp = null_hashget_locked(mp, lowervp); + rw_runlock(&null_hash_lock); + + return (vp); +} + +static void null_hashins(struct mount *mp, struct null_node *xp) { struct null_node_hashhead *hd; +#ifdef INVARIANTS struct null_node *oxp; - struct vnode *ovp; +#endif + + rw_assert(&null_hash_lock, RA_WLOCKED); hd = NULL_NHASH(xp->null_lowervp); - rw_wlock(&null_hash_lock); +#ifdef INVARIANTS LIST_FOREACH(oxp, hd, null_hash) { if (oxp->null_lowervp == xp->null_lowervp && NULLTOV(oxp)->v_mount == mp) { - /* - * See null_hashget for a description of this - * operation. - */ - ovp = NULLTOV(oxp); - vref(ovp); - rw_wunlock(&null_hash_lock); - return (ovp); + VNASSERT(0, NULLTOV(oxp), + ("vnode already in hash")); } } +#endif LIST_INSERT_HEAD(hd, xp, null_hash); - rw_wunlock(&null_hash_lock); - return (NULLVP); } static void @@ -201,19 +206,6 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) return (0); } - /* - * The insmntque1() call below requires the exclusive lock on - * the nullfs vnode. Upgrade the lock now if hash failed to - * provide ready to use vnode. - */ - if (VOP_ISLOCKED(lowervp) != LK_EXCLUSIVE) { - vn_lock(lowervp, LK_UPGRADE | LK_RETRY); - if (VN_IS_DOOMED(lowervp)) { - vput(lowervp); - return (ENOENT); - } - } - /* * We do not serialize vnode creation, instead we will check for * duplicates later, when adding new vnode to hash. @@ -229,20 +221,23 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) return (error); } + VNPASS(vp->v_object == NULL, vp); + VNPASS((vn_irflag_read(vp) & VIRF_PGREAD) == 0, vp); + + rw_wlock(&null_hash_lock); xp->null_vnode = vp; xp->null_lowervp = lowervp; xp->null_flags = 0; vp->v_type = lowervp->v_type; vp->v_data = xp; vp->v_vnlock = lowervp->v_vnlock; - error = insmntque1(vp, mp); - if (error != 0) { - vput(lowervp); + *vpp = null_hashget_locked(mp, lowervp); + if (*vpp != NULL) { + rw_wunlock(&null_hash_lock); + vrele(lowervp); null_destroy_proto(vp, xp); - return (error); + return (0); } - if (lowervp == MOUNTTONULLMOUNT(mp)->nullm_lowerrootvp) - vp->v_vflag |= VV_ROOT; /* * We might miss the case where lower vnode sets VIRF_PGREAD @@ -251,28 +246,23 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) */ if ((vn_irflag_read(lowervp) & VIRF_PGREAD) != 0) { MPASS(lowervp->v_object != NULL); - if ((vn_irflag_read(vp) & VIRF_PGREAD) == 0) { - if (vp->v_object == NULL) - vp->v_object = lowervp->v_object; - else - MPASS(vp->v_object == lowervp->v_object); - vn_irflag_set_cond(vp, VIRF_PGREAD); - } else { - MPASS(vp->v_object != NULL); - } + vp->v_object = lowervp->v_object; + vn_irflag_set(vp, VIRF_PGREAD); } + if (lowervp == MOUNTTONULLMOUNT(mp)->nullm_lowerrootvp) + vp->v_vflag |= VV_ROOT; - /* - * Atomically insert our new node into the hash or vget existing - * if someone else has beaten us to it. - */ - *vpp = null_hashins(mp, xp); - if (*vpp != NULL) { - vrele(lowervp); - vp->v_object = NULL; /* in case VIRF_PGREAD set it */ + error = insmntque1(vp, mp); + if (error != 0) { + rw_wunlock(&null_hash_lock); + vput(lowervp); + vp->v_object = NULL; null_destroy_proto(vp, xp); - return (0); + return (error); } + + null_hashins(mp, xp); + rw_wunlock(&null_hash_lock); *vpp = vp; return (0); diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 1dba5f51d619..21a28dd45570 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -207,7 +207,7 @@ nullfs_mount(struct mount *mp) (MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED); } - mp->mnt_kern_flag |= MNTK_LOOKUP_EXCL_DOTDOT | MNTK_NOMSYNC; + mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNLOCKED_INSMNTQUE; mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & (MNTK_USES_BCACHE | MNTK_NO_IOPF | MNTK_UNMAPPED_BUFS); MNT_IUNLOCK(mp);