]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/phase7.c
xfs_scrub: retry scrub (and repair) of items that are ok except for XFAIL
[thirdparty/xfsprogs-dev.git] / scrub / phase7.c
index 50d04ae6794b852f07547c31ef35c8bf7c265446..84546b1cb5cc2b29047f151cf892ef5b5e8038f0 100644 (file)
@@ -1,36 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2018 Oracle.  All Rights Reserved.
- *
  * Author: Darrick J. Wong <darrick.wong@oracle.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 #include "xfs.h"
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/statvfs.h>
-#include "path.h"
-#include "ptvar.h"
+#include <linux/fsmap.h>
+#include "libfrog/paths.h"
+#include "libfrog/ptvar.h"
+#include "list.h"
 #include "xfs_scrub.h"
 #include "common.h"
+#include "scrub.h"
 #include "fscounters.h"
 #include "spacemap.h"
+#include "repair.h"
 
 /* Phase 7: Check summary counters. */
 
-struct xfs_summary_counts {
+struct summary_counts {
        unsigned long long      dbytes;         /* data dev bytes */
        unsigned long long      rbytes;         /* rt dev bytes */
        unsigned long long      next_phys;      /* next phys bytes we see? */
@@ -38,22 +28,26 @@ struct xfs_summary_counts {
 };
 
 /* Record block usage. */
-static bool
-xfs_record_block_summary(
-       struct scrub_ctx                *ctx,
-       const char                      *descr,
-       struct fsmap                    *fsmap,
-       void                            *arg)
+static int
+count_block_summary(
+       struct scrub_ctx        *ctx,
+       struct fsmap            *fsmap,
+       void                    *arg)
 {
-       struct xfs_summary_counts       *counts;
-       unsigned long long              len;
+       struct summary_counts   *counts;
+       unsigned long long      len;
+       int                     ret;
 
-       counts = ptvar_get((struct ptvar *)arg);
+       counts = ptvar_get((struct ptvar *)arg, &ret);
+       if (ret) {
+               str_liberror(ctx, -ret, _("retrieving summary counts"));
+               return -ret;
+       }
        if (fsmap->fmr_device == ctx->fsinfo.fs_logdev)
-               return true;
+               return 0;
        if ((fsmap->fmr_flags & FMR_OF_SPECIAL_OWNER) &&
            fsmap->fmr_owner == XFS_FMR_OWN_FREE)
-               return true;
+               return 0;
 
        len = fsmap->fmr_length;
 
@@ -68,30 +62,30 @@ xfs_record_block_summary(
        } else {
                /* Count datadev extents. */
                if (counts->next_phys >= fsmap->fmr_physical + len)
-                       return true;
+                       return 0;
                else if (counts->next_phys > fsmap->fmr_physical)
                        len = counts->next_phys - fsmap->fmr_physical;
                counts->dbytes += len;
                counts->next_phys = fsmap->fmr_physical + fsmap->fmr_length;
        }
 
-       return true;
+       return 0;
 }
 
 /* Add all the summaries in the per-thread counter */
-static bool
-xfs_add_summaries(
-       struct ptvar                    *ptv,
-       void                            *data,
-       void                            *arg)
+static int
+add_summaries(
+       struct ptvar            *ptv,
+       void                    *data,
+       void                    *arg)
 {
-       struct xfs_summary_counts       *total = arg;
-       struct xfs_summary_counts       *item = data;
+       struct summary_counts   *total = arg;
+       struct summary_counts   *item = data;
 
        total->dbytes += item->dbytes;
        total->rbytes += item->rbytes;
        total->agbytes += item->agbytes;
-       return true;
+       return 0;
 }
 
 /*
@@ -100,60 +94,76 @@ xfs_add_summaries(
  * filesystem we'll be content if the summary counts are within 10% of
  * what we observed.
  */
-bool
-xfs_scan_summary(
-       struct scrub_ctx                *ctx)
+int
+phase7_func(
+       struct scrub_ctx        *ctx)
 {
-       struct xfs_summary_counts       totalcount = {0};
-       struct ptvar                    *ptvar;
-       unsigned long long              used_data;
-       unsigned long long              used_rt;
-       unsigned long long              used_files;
-       unsigned long long              stat_data;
-       unsigned long long              stat_rt;
-       uint64_t                        counted_inodes = 0;
-       unsigned long long              absdiff;
-       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;
-       unsigned long long              f_free;
-       bool                            moveon;
-       bool                            complain;
-       int                             error;
+       struct summary_counts   totalcount = {0};
+       struct action_list      alist;
+       struct ptvar            *ptvar;
+       unsigned long long      used_data;
+       unsigned long long      used_rt;
+       unsigned long long      used_files;
+       unsigned long long      stat_data;
+       unsigned long long      stat_rt;
+       uint64_t                counted_inodes = 0;
+       unsigned long long      absdiff;
+       unsigned long long      d_blocks;
+       unsigned long long      d_bfree;
+       unsigned long long      r_blocks;
+       unsigned long long      r_bfree;
+       bool                    complain;
+       int                     ip;
+       int                     error;
+
+       /* Check and fix the fs summary counters. */
+       action_list_init(&alist);
+       error = scrub_fs_summary(ctx, &alist);
+       if (error)
+               return error;
+       error = action_list_process(ctx, ctx->mnt.fd, &alist,
+                       ALP_COMPLAIN_IF_UNFIXED | ALP_NOPROGRESS);
+       if (error)
+               return error;
 
        /* Flush everything out to disk before we start counting. */
-       error = syncfs(ctx->mnt_fd);
+       error = syncfs(ctx->mnt.fd);
        if (error) {
                str_errno(ctx, ctx->mntpoint);
-               return false;
+               return error;
        }
 
-       ptvar = ptvar_init(scrub_nproc(ctx), sizeof(struct xfs_summary_counts));
-       if (!ptvar) {
-               str_errno(ctx, ctx->mntpoint);
-               return false;
+       error = -ptvar_alloc(scrub_nproc(ctx), sizeof(struct summary_counts),
+                       &ptvar);
+       if (error) {
+               str_liberror(ctx, error, _("setting up block counter"));
+               return error;
        }
 
        /* Use fsmap to count blocks. */
-       moveon = xfs_scan_all_spacemaps(ctx, xfs_record_block_summary, ptvar);
-       if (!moveon)
+       error = scrub_scan_all_spacemaps(ctx, count_block_summary, ptvar);
+       if (error)
                goto out_free;
-       moveon = ptvar_foreach(ptvar, xfs_add_summaries, &totalcount);
-       if (!moveon)
+       error = -ptvar_foreach(ptvar, add_summaries, &totalcount);
+       if (error) {
+               str_liberror(ctx, error, _("counting blocks"));
                goto out_free;
+       }
        ptvar_free(ptvar);
 
        /* Scan the whole fs. */
-       moveon = xfs_count_all_inodes(ctx, &counted_inodes);
-       if (!moveon)
-               goto out;
+       error = scrub_count_all_inodes(ctx, &counted_inodes);
+       if (error) {
+               str_liberror(ctx, error, _("counting inodes"));
+               return error;
+       }
 
-       moveon = xfs_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
-                       &r_bfree, &f_files, &f_free);
-       if (!moveon)
-               return moveon;
+       error = scrub_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
+                       &r_bfree, &used_files);
+       if (error) {
+               str_liberror(ctx, error, _("estimating verify work"));
+               return error;
+       }
 
        /*
         * If we counted blocks with fsmap, then dblocks includes
@@ -161,12 +171,11 @@ xfs_scan_summary(
         * filesystem treats them as "free", but since we scanned
         * them, we'll consider them used.
         */
-       d_bfree -= totalcount.agbytes >> ctx->blocklog;
+       d_bfree -= cvt_b_to_off_fsbt(&ctx->mnt, totalcount.agbytes);
 
        /* Report on what we found. */
-       used_data = (d_blocks - d_bfree) << ctx->blocklog;
-       used_rt = (r_blocks - r_bfree) << ctx->blocklog;
-       used_files = f_files - f_free;
+       used_data = cvt_off_fsb_to_b(&ctx->mnt, d_blocks - d_bfree);
+       used_rt = cvt_off_fsb_to_b(&ctx->mnt, r_blocks - r_bfree);
        stat_data = totalcount.dbytes;
        stat_rt = totalcount.rbytes;
 
@@ -190,27 +199,27 @@ xfs_scan_summary(
                if (used_rt || stat_rt) {
                        d = auto_space_units(used_data, &du);
                        r = auto_space_units(used_rt, &ru);
-                       i = auto_units(used_files, &iu);
+                       i = auto_units(used_files, &iu, &ip);
                        fprintf(stdout,
-_("%.1f%s data used;  %.1f%s realtime data used;  %.2f%s inodes used.\n"),
-                                       d, du, r, ru, i, iu);
+_("%.1f%s data used;  %.1f%s realtime data used;  %.*f%s inodes used.\n"),
+                                       d, du, r, ru, ip, i, iu);
                        d = auto_space_units(stat_data, &du);
                        r = auto_space_units(stat_rt, &ru);
-                       i = auto_units(counted_inodes, &iu);
+                       i = auto_units(counted_inodes, &iu, &ip);
                        fprintf(stdout,
-_("%.1f%s data found; %.1f%s realtime data found; %.2f%s inodes found.\n"),
-                                       d, du, r, ru, i, iu);
+_("%.1f%s data found; %.1f%s realtime data found; %.*f%s inodes found.\n"),
+                                       d, du, r, ru, ip, i, iu);
                } else {
                        d = auto_space_units(used_data, &du);
-                       i = auto_units(used_files, &iu);
+                       i = auto_units(used_files, &iu, &ip);
                        fprintf(stdout,
-_("%.1f%s data used;  %.1f%s inodes used.\n"),
-                                       d, du, i, iu);
+_("%.1f%s data used;  %.*f%s inodes used.\n"),
+                                       d, du, ip, i, iu);
                        d = auto_space_units(stat_data, &du);
-                       i = auto_units(counted_inodes, &iu);
+                       i = auto_units(counted_inodes, &iu, &ip);
                        fprintf(stdout,
-_("%.1f%s data found; %.1f%s inodes found.\n"),
-                                       d, du, i, iu);
+_("%.1f%s data found; %.*f%s inodes found.\n"),
+                                       d, du, ip, i, iu);
                }
                fflush(stdout);
        }
@@ -224,12 +233,13 @@ _("%.1f%s data found; %.1f%s inodes found.\n"),
                        _("checked inodes"))) {
                double          i1, i2;
                char            *i1u, *i2u;
+               int             i1p, i2p;
 
-               i1 = auto_units(counted_inodes, &i1u);
-               i2 = auto_units(ctx->inodes_checked, &i2u);
+               i1 = auto_units(counted_inodes, &i1u, &i1p);
+               i2 = auto_units(ctx->inodes_checked, &i2u, &i2p);
                fprintf(stdout,
-_("%.1f%s inodes counted; %.1f%s inodes checked.\n"),
-                               i1, i1u, i2, i2u);
+_("%.*f%s inodes counted; %.*f%s inodes checked.\n"),
+                               i1p, i1, i1u, i2p, i2, i2u);
                fflush(stdout);
        }
 
@@ -253,11 +263,8 @@ _("%.1f%s data counted; %.1f%s data verified.\n"),
                fflush(stdout);
        }
 
-       moveon = true;
-
-out:
-       return moveon;
+       return 0;
 out_free:
        ptvar_free(ptvar);
-       return moveon;
+       return error;
 }