From nobody Thu May 21 20:13:14 2026 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 4gM0340CJXz6dr3K for ; Thu, 21 May 2026 20:13:20 +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 "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gM0336Qwpz3tZr for ; Thu, 21 May 2026 20:13:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779394399; 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=A1v7Dne3LyXU3GooMjgOvWCgJY6tR2TNYqXfAe0R204=; b=FY25ReKMS6+KtJthxcMG9dmR3VcOCi7aF+kvao3HdsOYkCJOKG0X8xDGg4Ghj9N708KZwC wCzlNQMzUQDrJFrXeFuk6LmKgyBSPN29hudfGm5oZsJLRiiH4BCrmmUtvj3D0U1Rrl8Pt1 apv8ZpfGFDwdMhBW5Sdu7Px8iHMk11Rm83oWuKyqzkXrIKCB7g58ScQXUACeozek6vQ6X+ dK44gh4wrYZ1eAoCWT0fNB3tS4F2yR+hKeHMh9/OfzkZHFWfY0MaLgmACBVTShUEUSNEm0 6u7p1PolK1hPbkEteyrckxXNNSGM800EWAw1xZfnJueoxWMSfuk1gsq0tCAnuw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779394399; a=rsa-sha256; cv=none; b=vdML9vVUHrY9Rsj/gtUkOWClwgyJa56dPx21s/px/5BF5rH689o4I3RhYkcdyhS7dtxWvt 8XPHePuFQYBZpMz8tH9x7U86iVti2vy+jKw/zSVsZPb+0nso1tKEfM1TcL4rsZ0iXu2bCF Kx4hWzq2RZo9DoXRJ0gSJYXsN+BEpugKLmLeks6PGf66v6qS1xuOvwy1MPhnxqezc4ZjAD 9Uu2o97lnHVg37ykA/coUCvJAzkUj1oVnwLorJJtGK6RGOjnXwSPw6N0otlfGUJC6N3446 4kGe2Y2elTHW7FTgh1bUiI2FsoutdArwBDo7eUMbmhCmP8M3WMnSQqSOCLHw8Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779394399; 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=A1v7Dne3LyXU3GooMjgOvWCgJY6tR2TNYqXfAe0R204=; b=B8Le+aFX9DKRRmdyKUSuwbo/0tIYdzNuQoI1jIIonXDpOsoxdu99mvk/WNTVjc98l+H5iR 5U3N32kItJGtqTcn2i5Qb0dIdEv6auaN4K3OhpH6LOCoRY2Xa3h2k2vXg+gmQaIBT/zzB1 t8Mt/UCyHUva0XB3wsyNzy2zGGX3wI/+mN6ev4tKaSseQ8i3NGElq6s6IloBzQW2Kt2fNs lKNisJgKN31rd2hTH6zfHgRyP2vbdrJ4onx8kK9JYoKMO7tFs59k3/2JMZkLYhlp62HRus i2LKmGGb7eQGC703Kg3FOkQbl80Eo6u9RrDcX7VVsM9Tj574PjOJvB3NjcFr7A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gM0335nmKznfQ for ; Thu, 21 May 2026 20:13:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3d507 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 21 May 2026 20:13:14 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: ace4a3e177c0 - main - vn_lock_pair(): handle the case of vp1->v_vnlock == vp2->v_vnlock 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: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list 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: ace4a3e177c0da5efd9ceee0d9f46068562e3f5e Auto-Submitted: auto-generated Date: Thu, 21 May 2026 20:13:14 +0000 Message-Id: <6a0f675a.3d507.1d2e5099@gitrepo.freebsd.org> The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=ace4a3e177c0da5efd9ceee0d9f46068562e3f5e commit ace4a3e177c0da5efd9ceee0d9f46068562e3f5e Author: Konstantin Belousov AuthorDate: 2026-05-16 23:19:50 +0000 Commit: Konstantin Belousov CommitDate: 2026-05-21 20:11:47 +0000 vn_lock_pair(): handle the case of vp1->v_vnlock == vp2->v_vnlock It is not enough to check vp1 == vp2 to detect lock recursion, since vnodes might share the locks. This might happen for e.g. stacked filesystems (nullfs and other), and for FFS snapshots. Switch from checking vnode equiality to check v_vnlock equiality, and recheck the condition after vnode relock since reclamation or otner parallel operation might change the vnode locks under us. Return a value (not really an error) indicating the case that vnodes share the lock, to simplify the unlock in caller. Reviewed by: jah, markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57035 --- sys/kern/vfs_vnops.c | 32 +++++++++++++++++++++++++------- sys/sys/vnode.h | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 15704634ff62..1aa20954e4bd 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -4354,9 +4354,16 @@ vn_lock_pair_pause(const char *wmesg) * Only one of LK_SHARED and LK_EXCLUSIVE must be specified. * LK_NODDLKTREAT can be optionally passed. * - * If vp1 == vp2, only one, most exclusive, lock is obtained on it. + * If vp1->v_vnlock == vp2->v_vnlock, only one, most exclusive, lock + * is obtained on the vnode(s). The function accounts for the + * possibility of vp1 or vp2' v_vnlock changing while the + * corresponding vnode is unlocked. + * + * Return values: + * 0 - locked, two unlocks are required + * EDEADLK - locked, vnodes share the same lock, only one unlock is due. */ -void +int vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, struct vnode *vp2, bool vp2_locked, int lkflags2) { @@ -4370,9 +4377,10 @@ vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, MPASS((lkflags2 & ~(LK_SHARED | LK_EXCLUSIVE | LK_NODDLKTREAT)) == 0); if (vp1 == NULL && vp2 == NULL) - return; + return (0); - if (vp1 == vp2) { +recheck_same: + if (vp1 != NULL && vp2 != NULL && vp1->v_vnlock == vp2->v_vnlock) { MPASS(vp1_locked == vp2_locked); /* Select the most exclusive mode for lock. */ @@ -4385,20 +4393,26 @@ vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, /* No need to relock if any lock is exclusive. */ if ((vp1->v_vnlock->lock_object.lo_flags & LK_NOSHARE) != 0) - return; + return (EDEADLK); locked1 = VOP_ISLOCKED(vp1); if (((lkflags1 & LK_SHARED) != 0 && locked1 != LK_EXCLUSIVE) || ((lkflags1 & LK_EXCLUSIVE) != 0 && locked1 == LK_EXCLUSIVE)) - return; + return (EDEADLK); VOP_UNLOCK(vp1); } ASSERT_VOP_UNLOCKED(vp1, "vp1"); vn_lock(vp1, lkflags1 | LK_RETRY); - return; + if (vp1->v_vnlock == vp2->v_vnlock) + return (EDEADLK); + VOP_UNLOCK(vp1); + if (vp2_locked) { + VOP_UNLOCK(vp2); + vp2_locked = false; + } } if (vp1 != NULL) { @@ -4469,6 +4483,9 @@ vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, vn_lock(vp1, lkflags1 | LK_RETRY); vp1_locked = true; } + if (vp1 != NULL && vp2 != NULL && + vp1->v_vnlock == vp2->v_vnlock) + goto recheck_same; } if (vp1 != NULL) { if (lkflags1 == LK_EXCLUSIVE) @@ -4482,6 +4499,7 @@ vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, else ASSERT_VOP_LOCKED(vp2, "vp2 ret"); } + return (0); } int diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 4fee025a93ea..41b5e21fb879 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -781,7 +781,7 @@ bool vn_isdisk_error(struct vnode *vp, int *errp); bool vn_isdisk(struct vnode *vp); int _vn_lock(struct vnode *vp, int flags, const char *file, int line); #define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__) -void vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, +int vn_lock_pair(struct vnode *vp1, bool vp1_locked, int lkflags1, struct vnode *vp2, bool vp2_locked, int lkflags2); int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp); int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,