From patchwork Wed Mar 27 02:04:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13605464 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A7C528DAE for ; Wed, 27 Mar 2024 02:04:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711505091; cv=none; b=Edjb7t5hgwULUU3P2KuHdOdHO7reKb3Tpkkrt7G4LfL4Vpjb4dTioge8uRNgfyc3TKKfKOFDxpmDyegGWZUXenUrwFi7mTlVYfv84jbZ4SxBaTy8Q8hQdJC03QFEUv24E1lDuIkeiQOaU6bYHImlkv/G9BW+9SnTniROm2QDhDw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711505091; c=relaxed/simple; bh=ARj4QM9rKQHgOyulTT6za4FflUl1GqwgyeZQUgGXiIY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kn4RdgYcyjTsXB8OzzSAeVCgSxTRGbXHlhd3LUrCLhOmj/uXV0P2/xFxiyIoe9KPkmNJbtXS7qnpsDrmOU+gahP7Z1BYF0HaURMsuKEjS8TUqWvbuAd8tELKPajLp4orOIWd/WBDGB9jBzbQccgdKZtNsd2ezLSu2gFqjYynXWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KuE6nnQY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KuE6nnQY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E10C6C43609; Wed, 27 Mar 2024 02:04:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711505090; bh=ARj4QM9rKQHgOyulTT6za4FflUl1GqwgyeZQUgGXiIY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KuE6nnQY7NJ/yz3u1lYaq8WdKSRQvnT9zzEll1H1MHELzVybIltJFBBGy+h1dOvtw 81XLbKCnPrOjkrrHsJKxTGyMVl4YGjLnTdg0PGNUYFvMYFwXruAIYbxI/T4RJec7p6 quZRluLMe6E3ZlCDFDyW6DiGI4DFx4vUfxMMd0AGZgtjn9dK/VE1/y1KPrmIezbOmE PDtjJjTFyFTPt1JBw+YvLEz54PQIhKTsEvUGoGcA59Tf8opZhda2RYDpZlT65KNmbz DnCM6cyKYgjI+I+XBDj1bznj93EAn7kQz3Eoc5bZ4J1xshigZgnlcjtf/4h7wsGGA1 6XWzL5OehPybg== Date: Tue, 26 Mar 2024 19:04:50 -0700 Subject: [PATCH 5/5] xfs: ask the dentry cache if it knows the parent of a directory From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <171150383612.3217994.12957852450843135792.stgit@frogsfrogsfrogs> In-Reply-To: <171150383515.3217994.11426825010369201405.stgit@frogsfrogsfrogs> References: <171150383515.3217994.11426825010369201405.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong It's possible that the dentry cache can tell us the parent of a directory. Therefore, when repairing directory dot dot entries, query the dcache as a last resort before scanning the entire filesystem. Signed-off-by: Darrick J. Wong --- fs/xfs/scrub/dir_repair.c | 29 +++++++++++++++++++++++++++++ fs/xfs/scrub/findparent.c | 38 +++++++++++++++++++++++++++++++++++++- fs/xfs/scrub/findparent.h | 1 + fs/xfs/scrub/parent_repair.c | 13 +++++++++++++ fs/xfs/scrub/trace.h | 1 + 5 files changed, 81 insertions(+), 1 deletion(-) diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index 8b6ebf0697397..bbd953017bf49 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -206,6 +206,29 @@ xrep_dir_lookup_parent( return ino; } +/* + * Look up '..' in the dentry cache and confirm that it's really the parent. + * Returns NULLFSINO if the dcache misses or if the hit is implausible. + */ +static inline xfs_ino_t +xrep_dir_dcache_parent( + struct xrep_dir *rd) +{ + struct xfs_scrub *sc = rd->sc; + xfs_ino_t parent_ino; + int error; + + parent_ino = xrep_findparent_from_dcache(sc); + if (parent_ino == NULLFSINO) + return parent_ino; + + error = xrep_findparent_confirm(sc, &parent_ino); + if (error) + return NULLFSINO; + + return parent_ino; +} + /* Try to find the parent of the directory being repaired. */ STATIC int xrep_dir_find_parent( @@ -219,6 +242,12 @@ xrep_dir_find_parent( return 0; } + ino = xrep_dir_dcache_parent(rd); + if (ino != NULLFSINO) { + xrep_findparent_scan_finish_early(&rd->pscan, ino); + return 0; + } + ino = xrep_dir_lookup_parent(rd); if (ino != NULLFSINO) { xrep_findparent_scan_finish_early(&rd->pscan, ino); diff --git a/fs/xfs/scrub/findparent.c b/fs/xfs/scrub/findparent.c index 7b3ec8d7d6cc9..712dd73e4789f 100644 --- a/fs/xfs/scrub/findparent.c +++ b/fs/xfs/scrub/findparent.c @@ -53,7 +53,8 @@ * must not read the scan results without re-taking @sc->ip's ILOCK. * * There are a few shortcuts that we can take to avoid scanning the entire - * filesystem, such as noticing directory tree roots. + * filesystem, such as noticing directory tree roots and querying the dentry + * cache for parent information. */ struct xrep_findparent_info { @@ -410,3 +411,38 @@ xrep_findparent_self_reference( return NULLFSINO; } + +/* Check the dentry cache to see if knows of a parent for the scrub target. */ +xfs_ino_t +xrep_findparent_from_dcache( + struct xfs_scrub *sc) +{ + struct inode *pip = NULL; + struct dentry *dentry, *parent; + xfs_ino_t ret = NULLFSINO; + + dentry = d_find_alias(VFS_I(sc->ip)); + if (!dentry) + goto out; + + parent = dget_parent(dentry); + if (!parent) + goto out_dput; + + ASSERT(parent->d_sb == sc->ip->i_mount->m_super); + + pip = igrab(d_inode(parent)); + dput(parent); + + if (S_ISDIR(pip->i_mode)) { + trace_xrep_findparent_from_dcache(sc->ip, XFS_I(pip)->i_ino); + ret = XFS_I(pip)->i_ino; + } + + xchk_irele(sc, XFS_I(pip)); + +out_dput: + dput(dentry); +out: + return ret; +} diff --git a/fs/xfs/scrub/findparent.h b/fs/xfs/scrub/findparent.h index d946bc81f34e6..501f99d3164ed 100644 --- a/fs/xfs/scrub/findparent.h +++ b/fs/xfs/scrub/findparent.h @@ -45,5 +45,6 @@ void xrep_findparent_scan_finish_early(struct xrep_parent_scan_info *pscan, int xrep_findparent_confirm(struct xfs_scrub *sc, xfs_ino_t *parent_ino); xfs_ino_t xrep_findparent_self_reference(struct xfs_scrub *sc); +xfs_ino_t xrep_findparent_from_dcache(struct xfs_scrub *sc); #endif /* __XFS_SCRUB_FINDPARENT_H__ */ diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c index 0a9651bb0b057..826926c2bb0dd 100644 --- a/fs/xfs/scrub/parent_repair.c +++ b/fs/xfs/scrub/parent_repair.c @@ -118,7 +118,20 @@ xrep_parent_find_dotdot( * then retake the ILOCK so that we can salvage directory entries. */ xchk_iunlock(sc, XFS_ILOCK_EXCL); + + /* Does the VFS dcache have an answer for us? */ + ino = xrep_findparent_from_dcache(sc); + if (ino != NULLFSINO) { + error = xrep_findparent_confirm(sc, &ino); + if (!error && ino != NULLFSINO) { + xrep_findparent_scan_finish_early(&rp->pscan, ino); + goto out_relock; + } + } + + /* Scan the entire filesystem for a parent. */ error = xrep_findparent_scan(&rp->pscan); +out_relock: xchk_ilock(sc, XFS_ILOCK_EXCL); return error; diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index a7cefe6c252e9..883accdd53f04 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -2607,6 +2607,7 @@ DEFINE_EVENT(xrep_parent_salvage_class, name, \ TP_ARGS(dp, ino)) DEFINE_XREP_PARENT_SALVAGE_EVENT(xrep_dir_salvaged_parent); DEFINE_XREP_PARENT_SALVAGE_EVENT(xrep_findparent_dirent); +DEFINE_XREP_PARENT_SALVAGE_EVENT(xrep_findparent_from_dcache); #endif /* IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR) */