From 5e1c7d0b29f7e05b01e448d2579a469cf3a0d350 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 22 Apr 2024 09:48:30 -0700 Subject: xfs: invalidate dentries for a file before moving it to the orphanage Invalidate the cached dentries that point to the file that we're moving to lost+found before we actually move it. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/scrub/orphanage.c | 47 ++++++++++++++++++++--------------------------- fs/xfs/scrub/trace.h | 2 -- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/fs/xfs/scrub/orphanage.c b/fs/xfs/scrub/orphanage.c index 2b142e6de8f3..7148d8362db8 100644 --- a/fs/xfs/scrub/orphanage.c +++ b/fs/xfs/scrub/orphanage.c @@ -434,16 +434,17 @@ xrep_adoption_check_dcache( { struct qstr qname = QSTR_INIT(adopt->xname->name, adopt->xname->len); + struct xfs_scrub *sc = adopt->sc; struct dentry *d_orphanage, *d_child; int error = 0; - d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage)); + d_orphanage = d_find_alias(VFS_I(sc->orphanage)); if (!d_orphanage) return 0; d_child = d_hash_and_lookup(d_orphanage, &qname); if (d_child) { - trace_xrep_adoption_check_child(adopt->sc->mp, d_child); + trace_xrep_adoption_check_child(sc->mp, d_child); if (d_is_positive(d_child)) { ASSERT(d_is_negative(d_child)); @@ -454,33 +455,15 @@ xrep_adoption_check_dcache( } dput(d_orphanage); - if (error) - return error; - - /* - * Do we need to update d_parent of the dentry for the file being - * repaired? There shouldn't be a hashed dentry with a parent since - * the file had nonzero nlink but wasn't connected to any parent dir. - */ - d_child = d_find_alias(VFS_I(adopt->sc->ip)); - if (!d_child) - return 0; - - trace_xrep_adoption_check_alias(adopt->sc->mp, d_child); - - if (d_child->d_parent && !d_unhashed(d_child)) { - ASSERT(d_child->d_parent == NULL || d_unhashed(d_child)); - error = -EFSCORRUPTED; - } - - dput(d_child); return error; } /* - * Remove all negative dentries from the dcache. There should not be any - * positive entries, since we've maintained our lock on the orphanage - * directory. + * Invalidate all dentries for the name that was added to the orphanage + * directory, and all dentries pointing to the child inode that was moved. + * + * There should not be any positive entries for the name, since we've + * maintained our lock on the orphanage directory. */ static void xrep_adoption_zap_dcache( @@ -488,15 +471,17 @@ xrep_adoption_zap_dcache( { struct qstr qname = QSTR_INIT(adopt->xname->name, adopt->xname->len); + struct xfs_scrub *sc = adopt->sc; struct dentry *d_orphanage, *d_child; - d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage)); + /* Invalidate all dentries for the adoption name */ + d_orphanage = d_find_alias(VFS_I(sc->orphanage)); if (!d_orphanage) return; d_child = d_hash_and_lookup(d_orphanage, &qname); while (d_child != NULL) { - trace_xrep_adoption_invalidate_child(adopt->sc->mp, d_child); + trace_xrep_adoption_invalidate_child(sc->mp, d_child); ASSERT(d_is_negative(d_child)); d_invalidate(d_child); @@ -505,6 +490,14 @@ xrep_adoption_zap_dcache( } dput(d_orphanage); + + /* Invalidate all the dentries pointing down to this file. */ + while ((d_child = d_find_alias(VFS_I(sc->ip))) != NULL) { + trace_xrep_adoption_invalidate_child(sc->mp, d_child); + + d_invalidate(d_child); + dput(d_child); + } } /* diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 4b945007ca6c..e27daa51cab6 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -3265,8 +3265,6 @@ DEFINE_EVENT(xrep_dentry_class, name, \ TP_PROTO(struct xfs_mount *mp, const struct dentry *dentry), \ TP_ARGS(mp, dentry)) DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_child); -DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_alias); -DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_dentry); DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_invalidate_child); DEFINE_REPAIR_DENTRY_EVENT(xrep_dirtree_delete_child); -- cgit v1.2.3