]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: perform media scanning of the log region
authorDarrick J. Wong <djwong@kernel.org>
Sun, 22 Feb 2026 22:41:17 +0000 (14:41 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 9 Apr 2026 22:30:19 +0000 (15:30 -0700)
Scan the log area for media errors because a defect in a region could
prevent the user from being able to perform log recovery.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/fscounters.c
scrub/fscounters.h
scrub/phase6.c
scrub/phase7.c

index 098bf87465ea836c9175b0d2c459733c1b105827..8c054493b9889fd3d9cbc315c4db7c9868aa965a 100644 (file)
@@ -125,7 +125,8 @@ scrub_scan_estimate_blocks(
        unsigned long long              *d_bfree,
        unsigned long long              *r_blocks,
        unsigned long long              *r_bfree,
-       unsigned long long              *f_files_used)
+       unsigned long long              *f_files_used,
+       unsigned long long              *l_blocks)
 {
        struct xfs_fsop_counts          fc;
        int                             error;
@@ -140,6 +141,7 @@ scrub_scan_estimate_blocks(
        *r_blocks = ctx->mnt.fsgeom.rtblocks;
        *r_bfree = fc.freertx * ctx->mnt.fsgeom.rtextsize;
        *f_files_used = fc.allocino - fc.freeino;
+       *l_blocks = ctx->mnt.fsgeom.logblocks;
 
        return 0;
 }
index a3dd68837027edafc4cd0c527c2d1c78a6a3565e..e444c54d90252712ac99e524913fddf59fdf8cac 100644 (file)
@@ -9,7 +9,7 @@
 int scrub_scan_estimate_blocks(struct scrub_ctx *ctx,
                unsigned long long *d_blocks, unsigned long long *d_bfree,
                unsigned long long *r_blocks, unsigned long long *r_bfree,
-               unsigned long long *f_files_used);
+               unsigned long long *f_files_used, unsigned long long *l_blocks);
 int scrub_count_all_inodes(struct scrub_ctx *ctx, uint64_t *count);
 
 #endif /* XFS_SCRUB_FSCOUNTERS_H_ */
index 266a2bf0e453ae49cf5ab803a1f8152f36a7645d..e130d7783888c3aa1671c4e7169ddfdad17ee61a 100644 (file)
@@ -47,6 +47,7 @@ struct media_verify_state {
        struct read_verify_pool *rvp_realtime;
        struct bitmap           *d_bad;         /* bytes */
        struct bitmap           *r_bad;         /* bytes */
+       struct bitmap           *l_bad;         /* bytes */
        bool                    d_trunc:1;
        bool                    r_trunc:1;
        bool                    l_trunc:1;
@@ -109,6 +110,8 @@ bitmap_for_disk(
                return vs->d_bad;
        case XFS_DEV_RT:
                return vs->r_bad;
+       case XFS_DEV_LOG:
+               return vs->l_bad;
        default:
                return NULL;
        }
@@ -571,6 +574,12 @@ report_all_media_errors(
                return ret;
        }
 
+       ret = report_disk_ioerrs(ctx, vs, XFS_DEV_LOG);
+       if (ret) {
+               str_liberror(ctx, ret, _("walking log device io errors"));
+               return ret;
+       }
+
        ret = report_disk_ioerrs(ctx, vs, XFS_DEV_RT);
        if (ret) {
                str_liberror(ctx, ret, _("walking rtdev io errors"));
@@ -617,9 +626,14 @@ check_rmap(
                        map->fmr_flags);
 
        /* "Unknown" extents should be verified; they could be data. */
-       if ((map->fmr_flags & FMR_OF_SPECIAL_OWNER) &&
-                       map->fmr_owner == XFS_FMR_OWN_UNKNOWN)
-               map->fmr_flags &= ~FMR_OF_SPECIAL_OWNER;
+       if ((map->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
+               switch (map->fmr_owner) {
+               case XFS_FMR_OWN_UNKNOWN:
+               case XFS_FMR_OWN_LOG:
+                       map->fmr_flags &= ~FMR_OF_SPECIAL_OWNER;
+                       break;
+               }
+       }
 
        /*
         * We only care about read-verifying data extents that have been
@@ -762,11 +776,17 @@ phase6_func(
                goto out_dbad;
        }
 
+       ret = -bitmap_alloc(&vs.l_bad);
+       if (ret) {
+               str_liberror(ctx, ret, _("creating log badblock bitmap"));
+               goto out_rbad;
+       }
+
        ret = read_verify_pool_alloc(ctx, XFS_DEV_DATA, remember_ioerr, &vs,
                        &vs.rvp_data);
        if (ret) {
                str_liberror(ctx, ret, _("creating datadev media verifier"));
-               goto out_rbad;
+               goto out_lbad;
        }
        if (ctx->fsinfo.fs_log) {
                ret = read_verify_pool_alloc(ctx, XFS_DEV_LOG, remember_ioerr,
@@ -823,16 +843,17 @@ phase6_func(
         */
        if (ret || ret2 || ret3) {
                ret |= ret2 | ret3; /* caller only cares about non-zero/zero */
-               goto out_rbad;
+               goto out_lbad;
        }
        if (bitmap_empty(vs.d_bad) && !vs.d_trunc &&
            bitmap_empty(vs.r_bad) && !vs.r_trunc &&
-           !vs.l_trunc)
-               goto out_rbad;
+           bitmap_empty(vs.l_bad) && !vs.l_trunc)
+               goto out_lbad;
 
        /* Scan the whole dir tree to see what matches the bad extents. */
        ret = report_all_media_errors(ctx, &vs);
 
+       bitmap_free(&vs.l_bad);
        bitmap_free(&vs.r_bad);
        bitmap_free(&vs.d_bad);
        return ret;
@@ -852,6 +873,8 @@ out_logpool:
 out_datapool:
        read_verify_pool_abort(vs.rvp_data);
        read_verify_pool_destroy(vs.rvp_data);
+out_lbad:
+       bitmap_free(&vs.l_bad);
 out_rbad:
        bitmap_free(&vs.r_bad);
 out_dbad:
@@ -872,10 +895,11 @@ phase6_estimate(
        unsigned long long      r_blocks;
        unsigned long long      r_bfree;
        unsigned long long      dontcare;
+       unsigned long long      l_blocks;
        int                     ret;
 
        ret = scrub_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
-                       &r_bfree, &dontcare);
+                       &r_bfree, &dontcare, &l_blocks);
        if (ret) {
                str_liberror(ctx, ret, _("estimating verify work"));
                return ret;
@@ -884,6 +908,10 @@ phase6_estimate(
        *items = cvt_off_fsb_to_b(&ctx->mnt,
                        (d_blocks - d_bfree) + (r_blocks - r_bfree));
 
+       /* count external logs now that we scan them */
+       if (ctx->fsinfo.fs_log)
+               *items += cvt_off_fsb_to_b(&ctx->mnt, l_blocks);
+
        /*
         * Each read-verify pool starts a thread pool, and each worker thread
         * can contribute to the progress counter.  Hence we need to set
index e25502668b1c41c59bf1d4f83fe9004ca259a651..d52c142cc36114bcec3ac6de10892d489f0a156c 100644 (file)
@@ -170,6 +170,7 @@ phase7_func(
        unsigned long long      d_bfree;
        unsigned long long      r_blocks;
        unsigned long long      r_bfree;
+       unsigned long long      l_blocks;
        bool                    complain;
        int                     ip;
        int                     error;
@@ -223,7 +224,7 @@ phase7_func(
        }
 
        error = scrub_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
-                       &r_bfree, &used_files);
+                       &r_bfree, &used_files, &l_blocks);
        if (error) {
                str_liberror(ctx, error, _("estimating verify work"));
                return error;
@@ -243,6 +244,10 @@ phase7_func(
        stat_data = totalcount.dbytes;
        stat_rt = totalcount.rbytes;
 
+       /* only count internal logs for data device summary */
+       if (!ctx->fsinfo.fs_log)
+               used_data += cvt_off_fsb_to_b(&ctx->mnt, l_blocks);
+
        /*
         * Complain if the counts are off by more than 10% unless
         * the inaccuracy is less than 32MB worth of blocks or 100 inodes.