From: Darrick J. Wong <djwong@xxxxxxxxxx> Teach the online fsck file adoption code how to create parent pointers for files that are moved to /lost+found. In addition to the parent pointer creation itself, we must also turn on logged xattrs during scrub setup. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/scrub/orphanage.c | 66 +++++++++++++++++++++++++++++++++++++++++++--- fs/xfs/scrub/orphanage.h | 2 + fs/xfs/scrub/scrub.c | 6 ++++ fs/xfs/scrub/scrub.h | 8 +++--- fs/xfs/scrub/trace.h | 1 + 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/fs/xfs/scrub/orphanage.c b/fs/xfs/scrub/orphanage.c index 8285d129db9e..c574ae5a23ec 100644 --- a/fs/xfs/scrub/orphanage.c +++ b/fs/xfs/scrub/orphanage.c @@ -19,6 +19,10 @@ #include "xfs_icache.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" +#include "xfs_parent.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_xattr.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/repair.h" @@ -97,6 +101,31 @@ xrep_chown_orphanage( return error; } +/* + * Enable logged extended attributes for parent pointers. This must get done + * before we create transactions and start making changes. + */ +STATIC int +xrep_adoption_grab_log_assist( + struct xfs_scrub *sc) +{ + int error; + + if (!xfs_has_parent(sc->mp)) + return 0; + + ASSERT(!(sc->flags & XREP_FSGATES_LARP)); + + error = xfs_attr_grab_log_assist(sc->mp); + if (error) + return error; + + trace_xchk_fsgates_enable(sc, XREP_FSGATES_LARP); + + sc->flags |= XREP_FSGATES_LARP; + return 0; +} + #define ORPHANAGE "lost+found" /* Create the orphanage directory, and set sc->orphanage to it. */ @@ -188,6 +217,12 @@ xrep_orphanage_create( out_dput_root: dput(root_dentry); out: + /* + * Turn on whatever log features are required for an adoption to be + * committed correctly. + */ + if (!error) + error = xrep_adoption_grab_log_assist(sc); return error; } @@ -267,6 +302,14 @@ xrep_adoption_init( child_blkres = xfs_rename_space_res(mp, 0, false, xfs_name_dotdot.len, false); adopt->child_blkres = child_blkres; + + if (xfs_has_parent(mp)) { + ASSERT(sc->flags & XREP_FSGATES_LARP); + return xfs_parent_start_locked(mp, &adopt->parent); + } else { + adopt->parent = NULL; + } + return 0; } @@ -466,7 +509,7 @@ xrep_adoption_commit( error = xrep_orphanage_check_dcache(adopt); if (error) - return error; + goto out_parent; /* * Create the new name in the orphanage, and bump the link count of @@ -475,7 +518,7 @@ xrep_adoption_commit( error = xfs_dir_createname(sc->tp, sc->orphanage, xname, sc->ip->i_ino, adopt->orphanage_blkres); if (error) - return error; + goto out_parent; xfs_trans_ichgtime(sc->tp, sc->orphanage, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -488,7 +531,15 @@ xrep_adoption_commit( error = xfs_dir_replace(sc->tp, sc->ip, &xfs_name_dotdot, sc->orphanage->i_ino, adopt->child_blkres); if (error) - return error; + goto out_parent; + } + + /* Add a parent pointer from the file back to the lost+found. */ + if (adopt->parent) { + error = xfs_parent_add(sc->tp, adopt->parent, sc->orphanage, + xname, sc->ip); + if (error) + goto out_parent; } /* @@ -499,11 +550,14 @@ xrep_adoption_commit( xfs_dir_update_hook(sc->orphanage, sc->ip, 1, xname); error = xrep_defer_finish(sc); if (error) - return error; + goto out_parent; /* Remove negative dentries from the lost+found's dcache */ xrep_orphanage_zap_dcache(adopt); - return 0; +out_parent: + xfs_parent_finish(sc->mp, adopt->parent); + adopt->parent = NULL; + return error; } /* Cancel a proposed relocation of a file to the orphanage. */ @@ -521,6 +575,8 @@ xrep_adoption_cancel( * state to manage, we'll need to give that back. */ trace_xrep_adoption_cancel(sc->orphanage, sc->ip, error); + xfs_parent_finish(sc->mp, adopt->parent); + adopt->parent = NULL; } /* Release the orphanage. */ diff --git a/fs/xfs/scrub/orphanage.h b/fs/xfs/scrub/orphanage.h index 31f068198c8a..382c061e2fb6 100644 --- a/fs/xfs/scrub/orphanage.h +++ b/fs/xfs/scrub/orphanage.h @@ -47,6 +47,8 @@ struct xrep_adoption { struct xfs_scrub *sc; + struct xfs_parent_defer *parent; + /* Block reservations for orphanage and child (if directory). */ unsigned int orphanage_blkres; unsigned int child_blkres; diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index b5bd7125ca34..70010b111d9a 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -21,6 +21,9 @@ #include "xfs_rmap.h" #include "xfs_xchgrange.h" #include "xfs_swapext.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_xattr.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" @@ -177,6 +180,9 @@ xchk_fsgates_disable( if (sc->flags & XREP_FSGATES_ATOMIC_XCHG) xfs_xchg_range_rele_log_assist(sc->mp); + if (sc->flags & XREP_FSGATES_LARP) + xfs_attr_rele_log_assist(sc->mp); + sc->flags &= ~FSGATES_MASK; } #undef FSGATES_MASK diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 6f23edcac5cd..638c69e1fed9 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -135,6 +135,7 @@ struct xfs_scrub { #define XCHK_FSGATES_QUOTA (1 << 4) /* quota live update enabled */ #define XCHK_FSGATES_DIRENTS (1 << 5) /* directory live update enabled */ #define XCHK_FSGATES_RMAP (1 << 6) /* rmapbt live update enabled */ +#define XREP_FSGATES_LARP (1 << 28) /* logged xattr updates */ #define XREP_FSGATES_ATOMIC_XCHG (1 << 29) /* uses atomic file content exchange */ #define XREP_RESET_PERAG_RESV (1 << 30) /* must reset AG space reservation */ #define XREP_ALREADY_FIXED (1 << 31) /* checking our repair work */ @@ -151,10 +152,11 @@ struct xfs_scrub { XCHK_FSGATES_RMAP) /* - * The sole XREP_FSGATES* flag reflects a log intent item that is protected - * by a log-incompat feature flag. No code patching in use here. + * The sole XREP_FSGATES* flag reflects log intent items protected by + * log-incompat feature flags. No code patching in use here. */ -#define XREP_FSGATES_ALL (XREP_FSGATES_ATOMIC_XCHG) +#define XREP_FSGATES_ALL (XREP_FSGATES_ATOMIC_XCHG | \ + XREP_FSGATES_LARP) /* Metadata scrubbers */ int xchk_tester(struct xfs_scrub *sc); diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index c64594f20f73..96c88f4419d7 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -124,6 +124,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY); { XCHK_FSGATES_QUOTA, "fsgates_quota" }, \ { XCHK_FSGATES_DIRENTS, "fsgates_dirents" }, \ { XCHK_FSGATES_RMAP, "fsgates_rmap" }, \ + { XREP_FSGATES_LARP, "fsgates_larp" }, \ { XREP_FSGATES_ATOMIC_XCHG, "fsgates_atomic_swapext" }, \ { XREP_RESET_PERAG_RESV, "reset_perag_resv" }, \ { XREP_ALREADY_FIXED, "already_fixed" }