#include <stdint.h>
#include <stdlib.h>
#include <sys/statvfs.h>
-#include "path.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. */
};
/* Record block usage. */
-static bool
-xfs_record_block_summary(
+static int
+count_block_summary(
struct scrub_ctx *ctx,
- const char *descr,
struct fsmap *fsmap,
void *arg)
{
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;
} 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
+static int
xfs_add_summaries(
struct ptvar *ptv,
void *data,
total->dbytes += item->dbytes;
total->rbytes += item->rbytes;
total->agbytes += item->agbytes;
- return true;
+ return 0;
}
/*
struct scrub_ctx *ctx)
{
struct summary_counts totalcount = {0};
+ struct xfs_action_list alist;
struct ptvar *ptvar;
unsigned long long used_data;
unsigned long long used_rt;
int ip;
int error;
+ /* Check and fix the fs summary counters. */
+ xfs_action_list_init(&alist);
+ moveon = xfs_scrub_fs_summary(ctx, &alist);
+ if (!moveon)
+ return false;
+ moveon = xfs_action_list_process(ctx, ctx->mnt.fd, &alist,
+ ALP_COMPLAIN_IF_UNFIXED | ALP_NOPROGRESS);
+ if (!moveon)
+ return moveon;
+
/* Flush everything out to disk before we start counting. */
error = syncfs(ctx->mnt.fd);
if (error) {
return false;
}
- ptvar = ptvar_init(scrub_nproc(ctx), sizeof(struct summary_counts));
- if (!ptvar) {
- str_errno(ctx, ctx->mntpoint);
+ error = ptvar_alloc(scrub_nproc(ctx), sizeof(struct summary_counts),
+ &ptvar);
+ if (error) {
+ str_liberror(ctx, error, _("setting up block counter"));
return false;
}
/* 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) {
+ moveon = false;
goto out_free;
- moveon = ptvar_foreach(ptvar, xfs_add_summaries, &totalcount);
- if (!moveon)
+ }
+ error = ptvar_foreach(ptvar, xfs_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)
+ error = scrub_count_all_inodes(ctx, &counted_inodes);
+ if (error) {
+ str_liberror(ctx, error, _("counting inodes"));
+ moveon = false;
goto out;
+ }
- moveon = xfs_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
+ error = scrub_scan_estimate_blocks(ctx, &d_blocks, &d_bfree, &r_blocks,
&r_bfree, &f_files, &f_free);
- if (!moveon)
- return moveon;
+ if (error) {
+ str_liberror(ctx, error, _("estimating verify work"));
+ return false;
+ }
/*
* If we counted blocks with fsmap, then dblocks includes