From nobody Tue Oct 13 04:01:38 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 4j3gd42lTwz6vcKN for ; Tue, 13 Oct 2026 04:01:44 +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 4j3gd36tTDz4mSk for ; Tue, 13 Oct 2026 04:01:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791864104; 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=uHynZl6/oWMUw08PNxFKh4bN4M/WcyqOAQaUHsQTenU4Wp0yX49UtGvRR0abyHexzxGNb2 JHr1Tgw6MlC6qyRinYa/ypiNr8+JgP4lQf7RTwfPB6ynuPrHG+hovipMIBHXkSLUh1vwez d+RVclGAK/l/kjgA6ngAqXVJZnEie8GVTX+aNBivK5tAlodK+WK6GHFKHqHDPsm3iJvQoD 0RO0/6I0Bxgh4KeM1rd3t1RWlCxxVLoLxUjrSIW507Ma3UxfG5KDWhSddCiFq3E8+CZGU0 2G3iD3Zw+UNJ2RHgWt4Vya7DjAE0CbIQaTjd06JUpy+wDW2Ppq4s+y0AxuYYiA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791864104; b=yjm3XbcL7Xfq84wnJj/eZBtv3lvORbDsloGjFNYlj9wJsGDe0Da5/3GANOXvtctrZg4/Wo MpML19RKyxOtb4VZvFFkJ0RdyKGsqmrGjMxcOI092fmhBaXakREhU6brBUGAWDHq87DvTY 12CyO0tds7xdvt+R8SP0yDtMMAzRyo7hRXRZ0lnXFpC0ieq7ekGSNsajgfN8AIsrOjRtHo cXpYoxy+rdUiizoqV4PDoMqJcsR9zAaOgxZp7Sbm9K4tBAVoIqpY/qjakv6fznoOV/zymE P36P4hd5LxHQNeG4n0xn7mIiF6GP7d5ev+7S2ktEnPomN2a0M1QRBab+Mm0UZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791864104; 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=XeHoF7g8e2eJhH7sBvclqTdGY8mBHq/UrZyo/N6HRK14yGYzmuvHF40eNOXKD55c1XDaKw XK2K7k7reJ4qQDOYjYF50SsPqWlhMAW2sq4aGp2obzPtdmhIjZ8jBo2+5s2l+fU60tNucf tXV+QKjSC2jhF3ikfJjCMITNxJpNVmnCMC6qqqrMKl+VBvJGEnASXqfh+vY0UD4ifPx1Uv MGLZiWNPk5/ObWEX3a67M/D5BWZ5RDLDayGzl4aqPW4kqwETfGa4ivbzrjOPEd+XNHPYjj WtT5CxU2xDyLHbGJeoiC4icvHeAArjl4kzkCadkMGHBNFZb1Zb1haUNMtueDJw== 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 4j3gd35h11zyHq for ; Tue, 13 Oct 2026 04:01:43 +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-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches 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);