From nobody Tue Oct 13 04:01:38 2026 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 4j3gcz0Lclz6vcYG for ; Tue, 13 Oct 2026 04:01: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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j3gcy6r3mz4llr for ; Tue, 13 Oct 2026 04:01:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791864099; 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=VgKYlxefAWTj6tHr+NAOSTSOEs5MNBx/K2pIV9FXbUs=; b=SEd0jy9OoL4EMexsl0kIdRW0sddja6jkScQgvVuX07U5dnCX8e/aSaTZ0G69L7GtWqspBy 1Y83cC/awUjpTEIhemfply2ho6gpBGx/4QGWQDjLJJGksAJAGeQdXSW0FLjD8jmdZO25K1 T9nCWE/EgWQRuCY+D96wSX9Wt0L6lAXQZ6qjo+m5efiKKH90C+YB371Pe2kYC1l86P53gQ cuXo7N+PfAkUrLa696Z+67o1a5PixSvLMYnIpGxS32HrDe9Pu8MsJx/+VMbZ+smfI3TX8H vKfAMIZzgbOa0uGBlQ3MBvje88WgARc8Y4PCIEOQalDH9PYc70WANEZ93F4v5Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791864099; b=osIDyEsL4yoFcRsrYoUY/KvvEBkijm2ApER7ERQRmAIJ8iVcaiEuiHHxjfV2uiMce40tJX 7jzyLvMc73xwZtJ6NOFl7RNg9xpNiShW10pMHXdIJ4X9cHz9nkYQoOzHmygRIgFgV/NtRF pHxxvy4TnND8r/hvZkscjpDk8yNtHCOZrEV62/SNleG4Q4wvtz37J1R12Nd8Z6ni0XZVY4 OVg4cQvRFriRCPvwQ4WStknwJZ2H0bNaDJrrr0KSuNtngBySHbLLVVv/NWubWJ/Gcp5rG7 YZ4BSR+WPqkYbKDEnWrzuenzRJXjPwgyvYOw/GVxyhNND4N5mpIkWy1zct8Twg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791864099; 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=VgKYlxefAWTj6tHr+NAOSTSOEs5MNBx/K2pIV9FXbUs=; b=xYJ7bAWLz8SXgpJJWnITpQiDURp5PXexwv2zE4I4jq7NTCN9WvZfKcwtu7bjhQatbSZMAk nf3jhKbo8FJrr0oL0USsWS8FlxpFEt/zGtLXyf8Dp+SuHoRlg64euEv2T/ecD//l6vigDy OIm0Lmb1BkJAbxK6ahIf1SRxSTnOHIuS6lyT6qfRd6ADhwgvMtJaSetP/GHIbBgTZVydwE vsu1dU9KAvJycaBFQUJKEA6R5A0qAj37WzEBPAdCd2pM9ADC7g68Y9xK88kfY7H+VgbvvO AjQhzr3ol0K8E2B0eSJrHKPgyDV74tnOyJTJk2WjbQDOiHUEANzrMMVqpMBKvQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j3gcy5XGwzyZ8 for ; Tue, 13 Oct 2026 04:01:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 26406 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 13 Oct 2026 04:01:38 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Maxim Sobolev Subject: git: a6728314ff6d - main - ufs: do not busy or reference the mount in ufs_sync_nlink() List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository 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: sobomax X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a6728314ff6d6c73cab55c5bbd0025ed4ab56d53 Auto-Submitted: auto-generated Date: Tue, 13 Oct 2026 04:01:38 +0000 Message-Id: <6acdad22.26406.13de0b9c@gitrepo.freebsd.org> The branch main has been updated by sobomax: URL: https://cgit.FreeBSD.org/src/commit/?id=a6728314ff6d6c73cab55c5bbd0025ed4ab56d53 commit a6728314ff6d6c73cab55c5bbd0025ed4ab56d53 Author: Maxim Sobolev AuthorDate: 2026-10-13 03:57:26 +0000 Commit: Maxim Sobolev CommitDate: 2026-10-13 04:00:26 +0000 ufs: do not busy or reference the mount in ufs_sync_nlink() With soft updates, mkdir(2), link(2) and rename(2) into a directory whose i_nlink is at UFS_LINK_MAX while i_effnlink is below it call ufs_sync_nlink1() to sync the file system and restart. It busied the mount with vfs_busy(mp, 0), which sleeps for as long as an unmount is in progress. The caller is still between vn_start_write() and vn_finished_write() there, and the unmount, once it has set MNTK_UNMOUNT, goes on to suspend writes in VFS_UNMOUNT() and waits in vfs_write_suspend() for that write to end. Neither could make progress, and every later vfs_busy() of the mount, such as from getfsstat(2) or a lookup crossing the mount point, hung behind them. The window is wide: after setting MNTK_UNMOUNT, the unmount waits for the busy references to drain, which includes another thread already syncing in ufs_sync_nlink1(), and for vfs_periodic(). A forced unmount of a file system with a directory at the link limit under mkdir/rmdir load hits it within seconds. This is the deadlock that 29d03af1e4da fixed for VOP_RENAME(), and the same reasoning applies: the caller's vn_start_write() already keeps the unmount from getting past the write suspension, before which ffs_unmount() tears nothing down, so the mount point does not need to be busied for VFS_SYNC(). The extra vfs_ref() taken by the callers is not needed either: a successful vn_start_write() keeps the reference that VOP_GETWRITEMOUNT() took until vn_finished_write() drops it. With both gone, ufs_sync_nlink1() was only VFS_SYNC() and ERELOOKUP, so remove it and call VFS_SYNC() directly from ufs_sync_nlink() and the two places in ufs_rename(). Fixes: 8db679af66b0 ("UFS: make mkdir() and link() reliable when using SU and reaching nlink limit") Fixes: bc6d0d72f4f4 ("UFS rename: make it reliable when using SU and reaching nlink limit") Sponsored by: Sippy Software, Inc. Reviewed by: kib Tested by: pho Differential Revision: https://reviews.freebsd.org/D60204 MFC after: 1 month --- sys/ufs/ufs/ufs_vnops.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index aecb784ec46a..e32257529403 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -202,27 +202,22 @@ ufs_itimes(struct vnode *vp, struct timespec *tsa) VI_UNLOCK(vp); } -static int -ufs_sync_nlink1(struct mount *mp) -{ - int error; - - error = vfs_busy(mp, 0); - if (error == 0) { - VFS_SYNC(mp, MNT_WAIT); - vfs_unbusy(mp); - error = ERELOOKUP; - } - vfs_rel(mp); - return (error); -} - +/* + * With soft updates, i_nlink can stay at UFS_LINK_MAX after links were + * removed, until the removals are on disk. Sync the file system and have + * the caller restart the operation with ERELOOKUP. + * + * The caller is between vn_start_write() and vn_finished_write(). That + * holds a reference on the mount, and keeps an unmount from getting past + * the write suspension in VFS_UNMOUNT(), so the mount does not need to be + * referenced or busied here while the vnodes are unlocked. vfs_busy() + * would even deadlock, as it waits for an unmount in progress to finish. + */ static int ufs_sync_nlink(struct vnode *vp, struct vnode *vp1) { struct inode *ip; struct mount *mp; - int error; ip = VTOI(vp); if (ip->i_nlink < UFS_LINK_MAX) @@ -231,13 +226,12 @@ ufs_sync_nlink(struct vnode *vp, struct vnode *vp1) return (EMLINK); mp = vp->v_mount; - vfs_ref(mp); VOP_UNLOCK(vp); if (vp1 != NULL) VOP_UNLOCK(vp1); - error = ufs_sync_nlink1(mp); + VFS_SYNC(mp, MNT_WAIT); vn_lock_pair(vp, false, LK_EXCLUSIVE, vp1, false, LK_EXCLUSIVE); - return (error); + return (ERELOOKUP); } /* @@ -1452,7 +1446,6 @@ relock: error = EMLINK; goto unlockout; } - vfs_ref(mp); MPASS(!want_seqc_end); VOP_UNLOCK(fdvp); VOP_UNLOCK(fvp); @@ -1460,7 +1453,9 @@ relock: if (tvp != NULL) vref(tvp); VOP_VPUT_PAIR(tdvp, &tvp, true); - error = ufs_sync_nlink1(mp); + /* See ufs_sync_nlink(). */ + VFS_SYNC(mp, MNT_WAIT); + error = ERELOOKUP; vrele(fdvp); vrele(fvp); vrele(tdvp); @@ -1592,14 +1587,15 @@ relock: vn_seqc_write_end(fvp); vn_seqc_write_end(fdvp); want_seqc_end = false; - vfs_ref(mp); VOP_UNLOCK(fdvp); VOP_UNLOCK(fvp); vref(tdvp); if (tvp != NULL) vref(tvp); VOP_VPUT_PAIR(tdvp, &tvp, true); - error = ufs_sync_nlink1(mp); + /* See ufs_sync_nlink(). */ + VFS_SYNC(mp, MNT_WAIT); + error = ERELOOKUP; vrele(fdvp); vrele(fvp); vrele(tdvp);