From: Darrick J. Wong <djwong@xxxxxxxxxx> Now that we have online fsck for directory tree structure problems, we need to find a place to call it. The scanner requires that parent pointers are enabled, that directory link counts are correct, and that every directory entry has a corresponding parent pointer. Therefore, we can only run it after phase 4 fixes every file, and phase 5 resets the link counts. In other words, we call it as part of the phase 5 file scan that we do to warn about weird looking file names. This has the added benefit that opening the directory by handle is less likely to fail if there are loops in the directory structure. For now, only plumb in enough to try to fix directory tree problems right away; the next patch will make phase 5 retry the dirloop scanner until the problems are fixed or we stop making forward progress. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- scrub/phase5.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/scrub/phase5.c b/scrub/phase5.c index b3719627755..6c8dee66e6e 100644 --- a/scrub/phase5.c +++ b/scrub/phase5.c @@ -252,6 +252,47 @@ render_ino_from_handle( bstat->bs_gen, NULL); } +/* + * Check the directory structure for problems that could cause open_by_handle + * not to work. Returns 0 for no problems; EADDRNOTAVAIL if the there are + * problems that would prevent name checking. + */ +static int +check_dir_connection( + struct scrub_ctx *ctx, + struct descr *dsc, + const struct xfs_bulkstat *bstat) +{ + struct scrub_item sri = { }; + int error; + + /* The dirtree scrubber only works when parent pointers are enabled */ + if (!(ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT)) + return 0; + + scrub_item_init_file(&sri, bstat); + scrub_item_schedule(&sri, XFS_SCRUB_TYPE_DIRTREE); + + error = scrub_item_check_file(ctx, &sri, -1); + if (error) { + str_liberror(ctx, error, _("checking directory loops")); + return error; + } + + error = repair_file_corruption(ctx, &sri, -1); + if (error) { + str_liberror(ctx, error, _("repairing directory loops")); + return error; + } + + /* No directory tree problems? Clear this inode if it was deferred. */ + if (repair_item_count_needsrepair(&sri) == 0) + return 0; + + str_corrupt(ctx, descr_render(dsc), _("directory loop uncorrected!")); + return EADDRNOTAVAIL; +} + /* * Verify the connectivity of the directory tree. * We know that the kernel's open-by-handle function will try to reconnect @@ -275,6 +316,20 @@ check_inode_names( descr_set(&dsc, bstat); background_sleep(); + /* + * Try to fix directory loops before we have problems opening files by + * handle. + */ + if (S_ISDIR(bstat->bs_mode)) { + error = check_dir_connection(ctx, &dsc, bstat); + if (error == EADDRNOTAVAIL) { + error = 0; + goto out; + } + if (error) + goto err; + } + /* Warn about naming problems in xattrs. */ if (bstat->bs_xflags & FS_XFLAG_HASATTR) { error = check_xattr_names(ctx, &dsc, handle, bstat); @@ -315,6 +370,7 @@ check_inode_names( err: if (error) *aborted = true; +out: if (!error && *aborted) error = ECANCELED;