From nobody Thu Feb 24 04:00:38 2022 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 3E2DB180B1EA; Thu, 24 Feb 2022 04:00:39 +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 4K3zhk6ldNz4bpS; Thu, 24 Feb 2022 04:00:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1645675239; 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=VPleaMtAc1yt+XJopu+dMJ7AygrLlZ74DshKc3gZVoI=; b=Z9PMuIdHH9qTxFvMAUKF4oyMkbpguNMCPgeg3F+arpM0qyUFEC7fCVK0/2iRBl5Fpa9IGb j72pGpbHn71KVreturERKdVTtSegyreDztDkvu6xZ4vHy0DdlEeefo/ZwcfBH4rqqitfeG qRLWG1XWbgRjybg00zBHEuyxMKZTfn8vS/Eur7Hm6iGQZXIR4HgAN7ZF+2GoJxoxkkyRK8 3/G65Uf5jxHimW4LPe1daXrtxdx9iMcLxpIqYR60olHEsfYlHwkKDkrOvt6NLMRXu177jD bj8Dg9/RvIwHLdkdFjvtfdFiO8oh9caIYM/omDF0SwNXJG3PA7emdpf47jG2uQ== 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 C965925003; Thu, 24 Feb 2022 04:00:38 +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 21O40c0a016249; Thu, 24 Feb 2022 04:00:38 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 21O40cZ3016248; Thu, 24 Feb 2022 04:00:38 GMT (envelope-from git) Date: Thu, 24 Feb 2022 04:00:38 GMT Message-Id: <202202240400.21O40cZ3016248@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Jason A. Harmening" Subject: git: fcb164742b6f - main - unionfs: rework unionfs_getwritemount() 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: jah X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: fcb164742b6fb3c0f0d5995f90955acb6706d73e Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1645675239; 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=VPleaMtAc1yt+XJopu+dMJ7AygrLlZ74DshKc3gZVoI=; b=gwi5XNoZj60lPTlaybaCTKTnskH4ah7df+gDDN6hYIIFMQ9OLT4bWRKm3EojDY1hxwu3CC 0ED0jsUdH/FQu70bQAPWFCetIASdwnv1jYs+bcfUcJBDq8AVR2a8qyDGfBNAlIUYKM3mlf RM906X+94ZMlnQJx2HTYBVxEW5NKR3Jub2L7GXSiwHHCpEnC4hQRCg5ziwkIFGlPTGQJkN 3z6R+FYRBElQFxfLTmxPSoaH545qkX2RJHEj6XcTNOu99rcN6W6WNH7isR0zYn70gJSgan YICeFnfLzjupOLxWnWmMEVF5/wM5X3HXzARbfXrb8muQWP2iknxVfZxdXXSBng== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1645675239; a=rsa-sha256; cv=none; b=KMTPX8ZXP/InC7ldMeUx9MDHQo/JJUOSMTyWBi0hPv6X6X2OuuHMZdpQhplihZ1oajIqVI hU1w4kRha+4j/hjzRJfdrTSm60M3kt50dCKAcAoAfGygScBmhTAqmymrIstS1PqXByV2gO nnWfzkv2c7vmYhF8S8fTL1FqamDL7gISitSek0Dn8GZe2XSw1WJR36tMwe+dMFy8p84hBv i+2sYxu810hkifSJnV6XTAuCVsV10qR2P1JkwMTIOB2v3sF39QOXFkRp3QaR/VTDKSqUhv WAAUXNRmiuLtMnmxamZ4uD1ErB5WLxUd8nQ9Kz+Etk8CfqMkaA9iEY03bpR4Fg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=fcb164742b6fb3c0f0d5995f90955acb6706d73e commit fcb164742b6fb3c0f0d5995f90955acb6706d73e Author: Jason A. Harmening AuthorDate: 2022-02-15 03:52:21 +0000 Commit: Jason A. Harmening CommitDate: 2022-02-24 04:10:02 +0000 unionfs: rework unionfs_getwritemount() VOP_GETWRITEMOUNT() is called on the vn_start_write() path without any vnode locks guaranteed to be held. It's therefore unsafe to blindly access per-mount and per-vnode data. Instead, follow the approach taken by nullfs and use the vnode interlock coupled with the hold count to ensure the mount and the vnode won't be recycled while they are being accessed. Reviewed by: kib (earlier version), markj, pho Tested by: pho Differential Revision: https://reviews.freebsd.org/D34282 --- sys/fs/unionfs/union_vnops.c | 49 ++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 8e881ffd19bb..dcea0c27abd5 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -1764,33 +1764,52 @@ unionfs_readlink(struct vop_readlink_args *ap) static int unionfs_getwritemount(struct vop_getwritemount_args *ap) { + struct unionfs_node *unp; struct vnode *uvp; - struct vnode *vp; + struct vnode *vp, *ovp; int error; UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n"); error = 0; vp = ap->a_vp; + uvp = NULLVP; - if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY)) - return (EACCES); - - KASSERT_UNIONFS_VNODE(vp); - - uvp = UNIONFSVPTOUPPERVP(vp); - if (uvp == NULLVP && VREG == vp->v_type) - uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp); + VI_LOCK(vp); + unp = VTOUNIONFS(vp); + if (unp != NULL) + uvp = unp->un_uppervp; - if (uvp != NULLVP) - error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); - else { + /* + * If our node has no upper vnode, check the parent directory. + * We may be initiating a write operation that will produce a + * new upper vnode through CoW. + */ + if (uvp == NULLVP && unp != NULL) { + ovp = vp; + vp = unp->un_dvp; + /* + * Only the root vnode should have an empty parent, but it + * should not have an empty uppervp, so we shouldn't get here. + */ + VNASSERT(vp != NULL, ovp, ("%s: NULL parent vnode", __func__)); + VI_UNLOCK(ovp); VI_LOCK(vp); - if (vp->v_holdcnt == 0) - error = EOPNOTSUPP; - else + unp = VTOUNIONFS(vp); + if (unp != NULL) + uvp = unp->un_uppervp; + if (uvp == NULLVP) error = EACCES; + } + + if (uvp != NULLVP) { + vholdnz(uvp); + VI_UNLOCK(vp); + error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); + vdrop(uvp); + } else { VI_UNLOCK(vp); + *(ap->a_mpp) = NULL; } UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error);