From owner-dev-commits-src-all@freebsd.org Fri Feb 12 01:07:25 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 6A21353D27F; Fri, 12 Feb 2021 01:07:25 +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 4DcFhn0S56z3NNf; Fri, 12 Feb 2021 01:07:20 +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 3C0AE1B1BE; Fri, 12 Feb 2021 01:07:18 +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 11C17I5G070700; Fri, 12 Feb 2021 01:07:18 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 11C17IYh070699; Fri, 12 Feb 2021 01:07:18 GMT (envelope-from git) Date: Fri, 12 Feb 2021 01:07:18 GMT Message-Id: <202102120107.11C17IYh070699@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: 74a3652f832f - main - ufs_direnter: move directory truncation to ffs_vput_pair(). 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: 74a3652f832f4ed0f1ad9f7eb60d70013b478e1a 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 Feb 2021 01:07:25 -0000 The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=74a3652f832f4ed0f1ad9f7eb60d70013b478e1a commit 74a3652f832f4ed0f1ad9f7eb60d70013b478e1a Author: Konstantin Belousov AuthorDate: 2021-01-27 20:34:14 +0000 Commit: Konstantin Belousov CommitDate: 2021-02-12 01:02:21 +0000 ufs_direnter: move directory truncation to ffs_vput_pair(). VOP_VPUT_PAIR() provides the hook to do the truncation right before unlock, which is required since truncation might need to fsync(), which itself might unlock the directory vnode. Set new flag IN_ENDOFF which indicates that i_endoff is valid and should be checked against inode size. Excessive size is chomped, but this operation is advisory and failure to truncate should not result in the failure of the main VOP. Reviewed by: chs, mckusick Tested by: pho MFC after: 2 weeks Sponsored by: The FreeBSD Foundation --- sys/ufs/ffs/ffs_vnops.c | 44 ++++++++++++++++++++++++++++++++++++++------ sys/ufs/ufs/inode.h | 2 ++ sys/ufs/ufs/ufs_lookup.c | 25 ++++++------------------- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 2ac67adad5f2..dd0f1ba6b81d 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include "opt_directio.h" #include "opt_ffs.h" +#include "opt_ufs.h" #include #include @@ -99,6 +100,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#ifdef UFS_DIRHASH +#include +#endif #include #include @@ -1929,6 +1934,7 @@ ffs_vput_pair(struct vop_vput_pair_args *ap) struct inode *dp, *ip; ino_t ip_ino; u_int64_t ip_gen; + off_t old_size; int error, vp_locked; dvp = ap->a_dvp; @@ -1936,14 +1942,14 @@ ffs_vput_pair(struct vop_vput_pair_args *ap) vpp = ap->a_vpp; vp = vpp != NULL ? *vpp : NULL; - if ((dp->i_flag & IN_NEEDSYNC) == 0) { + if ((dp->i_flag & (IN_NEEDSYNC | IN_ENDOFF)) == 0) { vput(dvp); if (vp != NULL && ap->a_unlock_vp) vput(vp); return (0); } - mp = NULL; + mp = dvp->v_mount; if (vp != NULL) { if (ap->a_unlock_vp) { vput(vp); @@ -1953,14 +1959,40 @@ ffs_vput_pair(struct vop_vput_pair_args *ap) ip = VTOI(vp); ip_ino = ip->i_number; ip_gen = ip->i_gen; - mp = vp->v_mount; VOP_UNLOCK(vp); } } - do { - error = ffs_syncvnode(dvp, MNT_WAIT, 0); - } while (error == ERELOOKUP); + /* + * If compaction or fsync was requested do it in ffs_vput_pair() + * now that other locks are no longer held. + */ + if ((dp->i_flag & IN_ENDOFF) != 0) { + dp->i_flag &= ~IN_ENDOFF; + if (I_ENDOFF(dp) != 0 && I_ENDOFF(dp) < dp->i_size) { + old_size = dp->i_size; + error = UFS_TRUNCATE(dvp, (off_t)I_ENDOFF(dp), + IO_NORMAL | (DOINGASYNC(dvp) ? 0 : IO_SYNC), + curthread->td_ucred); + if (error != 0 && error != ERELOOKUP) { + if (!ffs_fsfail_cleanup(VFSTOUFS(mp), error)) { + vn_printf(dvp, + "IN_ENDOFF: failed to truncate, " + "error %d\n", error); + } +#ifdef UFS_DIRHASH + ufsdirhash_free(dp); +#endif + } + } + SET_I_ENDOFF(dp, 0); + } + if ((dp->i_flag & IN_NEEDSYNC) != 0) { + do { + error = ffs_syncvnode(dvp, MNT_WAIT, 0); + } while (error == ERELOOKUP); + } + vput(dvp); if (vp == NULL || ap->a_unlock_vp) diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 16db8d6d5cea..4515dcbed401 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -152,6 +152,8 @@ struct inode { #define IN_IBLKDATA 0x0800 /* datasync requires inode block update */ #define IN_SIZEMOD 0x1000 /* Inode size has been modified */ +#define IN_ENDOFF 0x2000 /* Free space at the end of directory, + try to truncate when possible */ #define PRINT_INODE_FLAGS "\20\20b16\17b15\16b14\15sizemod" \ "\14iblkdata\13is_ufs2\12truncated\11ea_lockwait\10ea_locked" \ diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index e614f189a623..3036bce81caf 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -1112,27 +1112,14 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename) } } UFS_INODE_SET_FLAG(dp, IN_CHANGE | IN_UPDATE); + /* - * If all went well, and the directory can be shortened, proceed - * with the truncation. Note that we have to unlock the inode for - * the entry that we just entered, as the truncation may need to - * lock other inodes which can lead to deadlock if we also hold a - * lock on the newly entered node. + * If all went well, and the directory can be shortened, mark directory inode + * with the truncation request right before unlock. */ - if (isrename == 0 && error == 0 && - I_ENDOFF(dp) != 0 && I_ENDOFF(dp) < dp->i_size) { - if (tvp != NULL) - VOP_UNLOCK(tvp); - error = UFS_TRUNCATE(dvp, (off_t)I_ENDOFF(dp), - IO_NORMAL | (DOINGASYNC(dvp) ? 0 : IO_SYNC), cr); - if (error != 0) - vn_printf(dvp, - "ufs_direnter: failed to truncate, error %d\n", - error); - error = 0; - if (tvp != NULL) - vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); - } + if (isrename == 0 && error == 0) + UFS_INODE_SET_FLAG(dp, IN_ENDOFF); + return (error); }