From owner-dev-commits-src-all@freebsd.org Fri Mar 12 11:41:24 2021 Return-Path: Delivered-To: dev-commits-src-all@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 22B295762F8; Fri, 12 Mar 2021 11:41:24 +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 4DxkRS0Sbtz3jSF; Fri, 12 Mar 2021 11:41:24 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 3850B16CBD; Fri, 12 Mar 2021 11:32:30 +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 12CBWUPP077554; Fri, 12 Mar 2021 11:32:30 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12CBWUXL077553; Fri, 12 Mar 2021 11:32:30 GMT (envelope-from git) Date: Fri, 12 Mar 2021 11:32:30 GMT Message-Id: <202103121132.12CBWUXL077553@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 16dea8341024 - main - null_vput_pair(): release use reference on dvp earlier MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 16dea8341024b8ee8be619c27d4e63bd81bd9b6c Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Mar 2021 11:41:24 -0000 The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=16dea8341024b8ee8be619c27d4e63bd81bd9b6c commit 16dea8341024b8ee8be619c27d4e63bd81bd9b6c Author: Konstantin Belousov AuthorDate: 2021-03-07 21:08:38 +0000 Commit: Konstantin Belousov CommitDate: 2021-03-12 11:31:08 +0000 null_vput_pair(): release use reference on dvp earlier We might own the last use reference, and then vrele() at the end would need to take the dvp vnode lock to inactivate, which causes deadlock with vp. We cannot vrele() dvp from start since this might unlock ldvp. Handle it by holding the vnode and dropping use ref after lowerfs VOP_VPUT_PAIR() ended. This effectivaly requires unlock of the vp vnode after VOP_VPUT_PAIR(), so the call is changed to set unlock_vp to true unconditionally. This opens more opportunities for vp to be reclaimed, if lvp is still alive we reinstantiate vp with null_nodeget(). Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D29178 --- sys/fs/nullfs/null_vnops.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 45065e0be7b5..bc0f5cdb7801 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -985,33 +985,50 @@ null_vput_pair(struct vop_vput_pair_args *ap) vpp = ap->a_vpp; vp = NULL; lvp = NULL; - if (vpp != NULL) { + mp = NULL; + if (vpp != NULL) vp = *vpp; - if (vp != NULL) { + if (vp != NULL) { + lvp = NULLVPTOLOWERVP(vp); + vref(lvp); + if (!ap->a_unlock_vp) { vhold(vp); + vhold(lvp); mp = vp->v_mount; - lvp = NULLVPTOLOWERVP(vp); - if (ap->a_unlock_vp) - vref(lvp); + vfs_ref(mp); } } - res = VOP_VPUT_PAIR(ldvp, &lvp, ap->a_unlock_vp); + res = VOP_VPUT_PAIR(ldvp, lvp != NULL ? &lvp : NULL, true); + if (vp != NULL && ap->a_unlock_vp) + vrele(vp); + vrele(dvp); + + if (vp == NULL || ap->a_unlock_vp) + return (res); - /* lvp might have been unlocked and vp reclaimed */ - if (vp != NULL) { - if (!ap->a_unlock_vp && vp->v_vnlock != lvp->v_vnlock) { + /* lvp has been unlocked and vp might be reclaimed */ + VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); + if (vp->v_data == NULL && vfs_busy(mp, MBF_NOWAIT) == 0) { + vput(vp); + vget(lvp, LK_EXCLUSIVE | LK_RETRY); + if (VN_IS_DOOMED(lvp)) { + vput(lvp); + vget(vp, LK_EXCLUSIVE | LK_RETRY); + } else { error = null_nodeget(mp, lvp, &vp1); if (error == 0) { - vput(vp); *vpp = vp1; + } else { + vget(vp, LK_EXCLUSIVE | LK_RETRY); } } - if (ap->a_unlock_vp) - vrele(vp); - vdrop(vp); + vfs_unbusy(mp); } - vrele(dvp); + vdrop(lvp); + vdrop(vp); + vfs_rel(mp); + return (res); }