]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_scrub: collect free space histograms during phase 7
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:21:14 +0000 (14:21 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:36:59 +0000 (15:36 -0700)
Collect a histogram of free space observed during phase 7.  We'll put
this information to use in the next patch.

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

index 59d46363c1da869d82a1efe1220ff690a1a18dcc..543c8a63646225f41c52fcec7d7e4c9b2ec9a5cd 100644 (file)
@@ -230,3 +230,41 @@ hist_summarize(
        printf("%s %g\n", hstr->averages,
                        (double)hs->tot_sum / (double)hs->tot_obs);
 }
+
+/* Copy the contents of src to dest. */
+void
+hist_import(
+       struct histogram        *dest,
+       const struct histogram  *src)
+{
+       unsigned int            i;
+
+       ASSERT(dest->nr_buckets == src->nr_buckets);
+
+       dest->tot_sum += src->tot_sum;
+       dest->tot_obs += src->tot_obs;
+
+       for (i = 0; i < dest->nr_buckets; i++) {
+               ASSERT(dest->buckets[i].low == src->buckets[i].low);
+               ASSERT(dest->buckets[i].high == src->buckets[i].high);
+
+               dest->buckets[i].nr_obs += src->buckets[i].nr_obs;
+               dest->buckets[i].sum += src->buckets[i].sum;
+       }
+}
+
+/*
+ * Move the contents of src to dest and reinitialize src.  dst must not
+ * contain any observations or buckets.
+ */
+void
+hist_move(
+       struct histogram        *dest,
+       struct histogram        *src)
+{
+       ASSERT(dest->nr_buckets == 0);
+       ASSERT(dest->tot_obs == 0);
+
+       memcpy(dest, src, sizeof(struct histogram));
+       hist_init(src);
+}
index 0c534f65dd9ad7c50b68ca16f97860f9481edf35..002ad78ca426e8e88253bfb70a0b8016d6fd9eeb 100644 (file)
@@ -68,4 +68,7 @@ static inline unsigned int hist_buckets(const struct histogram *hs)
        return hs->nr_buckets;
 }
 
+void hist_import(struct histogram *dest, const struct histogram *src);
+void hist_move(struct histogram *dest, struct histogram *src);
+
 #endif /* __LIBFROG_HISTOGRAM_H__ */
index cce5ede00122a5c39c85ad0d445d82583e9310a3..475d8f157eeccae4c157fec977709cfa3cc24c07 100644 (file)
@@ -12,6 +12,7 @@
 #include "libfrog/ptvar.h"
 #include "libfrog/fsgeom.h"
 #include "libfrog/scrub.h"
+#include "libfrog/histogram.h"
 #include "list.h"
 #include "xfs_scrub.h"
 #include "common.h"
@@ -27,8 +28,36 @@ struct summary_counts {
        unsigned long long      rbytes;         /* rt dev bytes */
        unsigned long long      next_phys;      /* next phys bytes we see? */
        unsigned long long      agbytes;        /* freespace bytes */
+
+       /* Free space histogram, in fsb */
+       struct histogram        datadev_hist;
 };
 
+/*
+ * Initialize a free space histogram.  Unsharded realtime volumes can be up to
+ * 2^52 blocks long, so we allocate enough buckets to handle that.
+ */
+static inline void
+init_freesp_hist(
+       struct histogram        *hs)
+{
+       unsigned int            i;
+
+       hist_init(hs);
+       for (i = 0; i < 53; i++)
+               hist_add_bucket(hs, 1ULL << i);
+       hist_prepare(hs, 1ULL << 53);
+}
+
+static void
+summary_count_init(
+       void                    *data)
+{
+       struct summary_counts   *counts = data;
+
+       init_freesp_hist(&counts->datadev_hist);
+}
+
 /* Record block usage. */
 static int
 count_block_summary(
@@ -48,8 +77,14 @@ count_block_summary(
        if (fsmap->fmr_device == ctx->fsinfo.fs_logdev)
                return 0;
        if ((fsmap->fmr_flags & FMR_OF_SPECIAL_OWNER) &&
-           fsmap->fmr_owner == XFS_FMR_OWN_FREE)
+           fsmap->fmr_owner == XFS_FMR_OWN_FREE) {
+               uint64_t        blocks;
+
+               blocks = cvt_b_to_off_fsbt(&ctx->mnt, fsmap->fmr_length);
+               if (fsmap->fmr_device == ctx->fsinfo.fs_datadev)
+                       hist_add(&counts->datadev_hist, blocks);
                return 0;
+       }
 
        len = fsmap->fmr_length;
 
@@ -87,6 +122,9 @@ add_summaries(
        total->dbytes += item->dbytes;
        total->rbytes += item->rbytes;
        total->agbytes += item->agbytes;
+
+       hist_import(&total->datadev_hist, &item->datadev_hist);
+       hist_free(&item->datadev_hist);
        return 0;
 }
 
@@ -118,6 +156,8 @@ phase7_func(
        int                     ip;
        int                     error;
 
+       summary_count_init(&totalcount);
+
        /* Check and fix the summary metadata. */
        scrub_item_init_fs(&sri);
        scrub_item_schedule_group(&sri, XFROG_SCRUB_GROUP_SUMMARY);
@@ -136,7 +176,7 @@ phase7_func(
        }
 
        error = -ptvar_alloc(scrub_nproc(ctx), sizeof(struct summary_counts),
-                       NULL, &ptvar);
+                       summary_count_init, &ptvar);
        if (error) {
                str_liberror(ctx, error, _("setting up block counter"));
                return error;
@@ -153,6 +193,9 @@ phase7_func(
        }
        ptvar_free(ptvar);
 
+       /* Preserve free space histograms for phase 8. */
+       hist_move(&ctx->datadev_hist, &totalcount.datadev_hist);
+
        /* Scan the whole fs. */
        error = scrub_count_all_inodes(ctx, &counted_inodes);
        if (error) {
index adf9d13e5090825ae067d6c0d4d6e098a4c75f70..2894f6148e100692fe20f2ebd55e4c9cb5f9525b 100644 (file)
@@ -18,6 +18,7 @@
 #include "descr.h"
 #include "unicrash.h"
 #include "progress.h"
+#include "libfrog/histogram.h"
 
 /*
  * XFS Online Metadata Scrub (and Repair)
@@ -669,6 +670,8 @@ main(
        int                     ret = SCRUB_RET_SUCCESS;
        int                     error;
 
+       hist_init(&ctx.datadev_hist);
+
        fprintf(stdout, "EXPERIMENTAL xfs_scrub program in use! Use at your own risk!\n");
        fflush(stdout);
 
@@ -883,6 +886,8 @@ out:
 out_unicrash:
        unicrash_unload();
 
+       hist_free(&ctx.datadev_hist);
+
        /*
         * If we're being run as a service, the return code must fit the LSB
         * init script action error guidelines, which is to say that we
index 6272a36879e7f1cccea020c6b5d884bf0ef63250..1a28f0cc847e9c5b9a207a729c027712aa26684f 100644 (file)
@@ -7,6 +7,7 @@
 #define XFS_SCRUB_XFS_SCRUB_H_
 
 #include "libfrog/fsgeom.h"
+#include "libfrog/histogram.h"
 
 extern char *progname;
 
@@ -86,6 +87,9 @@ struct scrub_ctx {
        unsigned long long      preens;
        bool                    scrub_setup_succeeded;
        bool                    preen_triggers[XFS_SCRUB_TYPE_NR];
+
+       /* Free space histograms, in fsb */
+       struct histogram        datadev_hist;
 };
 
 /* Phase helper functions */