]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/fscounters.c
xfs_scrub: update copyright years for scrub/ files
[thirdparty/xfsprogs-dev.git] / scrub / fscounters.c
index ac898764b7181da59bc92ad7a9a2a6c771d70080..098bf87465ea836c9175b0d2c459733c1b105827 100644 (file)
@@ -1,7 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * Copyright (C) 2018 Oracle.  All Rights Reserved.
- * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ * Copyright (C) 2018-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
  */
 #include "xfs.h"
 #include <stdint.h>
@@ -9,12 +9,12 @@
 #include <sys/statvfs.h>
 #include "platform_defs.h"
 #include "xfs_arch.h"
-#include "xfs_format.h"
-#include "path.h"
-#include "workqueue.h"
+#include "libfrog/paths.h"
+#include "libfrog/workqueue.h"
 #include "xfs_scrub.h"
 #include "common.h"
 #include "fscounters.h"
+#include "libfrog/bulkstat.h"
 
 /*
  * Filesystem counter collection routines.  We can count the number of
@@ -24,8 +24,8 @@
 /* Count the number of inodes in the filesystem. */
 
 /* INUMBERS wrapper routines. */
-struct xfs_count_inodes {
-       bool                    moveon;
+struct count_inodes {
+       int                     error;
        uint64_t                counters[0];
 };
 
@@ -33,165 +33,113 @@ struct xfs_count_inodes {
  * Count the number of inodes.  Use INUMBERS to figure out how many inodes
  * exist in the filesystem, assuming we've already scrubbed that.
  */
-static bool
-xfs_count_inodes_range(
-       struct scrub_ctx        *ctx,
-       const char              *descr,
-       uint64_t                first_ino,
-       uint64_t                last_ino,
-       uint64_t                *count)
+static void
+count_ag_inodes(
+       struct workqueue        *wq,
+       xfs_agnumber_t          agno,
+       void                    *arg)
 {
-       struct xfs_fsop_bulkreq igrpreq = {NULL};
-       struct xfs_inogrp       inogrp;
-       __u64                   igrp_ino;
+       struct count_inodes     *ci = arg;
+       struct scrub_ctx        *ctx = (struct scrub_ctx *)wq->wq_ctx;
+       struct xfs_inumbers_req *ireq;
        uint64_t                nr = 0;
-       __s32                   igrplen = 0;
+       unsigned int            i;
        int                     error;
 
-       ASSERT(!(first_ino & (XFS_INODES_PER_CHUNK - 1)));
-       ASSERT((last_ino & (XFS_INODES_PER_CHUNK - 1)));
-
-       igrpreq.lastip  = &igrp_ino;
-       igrpreq.icount  = 1;
-       igrpreq.ubuffer = &inogrp;
-       igrpreq.ocount  = &igrplen;
-
-       igrp_ino = first_ino;
-       error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
-       while (!error && igrplen && inogrp.xi_startino < last_ino) {
-               nr += inogrp.xi_alloccount;
-               error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
+       error = -xfrog_inumbers_alloc_req(64, 0, &ireq);
+       if (error) {
+               ci->error = error;
+               return;
        }
+       xfrog_inumbers_set_ag(ireq, agno);
 
-       if (error) {
-               str_errno(ctx, descr);
-               return false;
+       while (!ci->error && (error = -xfrog_inumbers(&ctx->mnt, ireq)) == 0) {
+               if (ireq->hdr.ocount == 0)
+                       break;
+               for (i = 0; i < ireq->hdr.ocount; i++)
+                       nr += ireq->inumbers[i].xi_alloccount;
        }
+       if (error)
+               ci->error = error;
 
-       *count = nr;
-       return true;
-}
+       free(ireq);
 
-/* Scan all the inodes in an AG. */
-static void
-xfs_count_ag_inodes(
-       struct workqueue        *wq,
-       xfs_agnumber_t          agno,
-       void                    *arg)
-{
-       struct xfs_count_inodes *ci = arg;
-       struct scrub_ctx        *ctx = (struct scrub_ctx *)wq->wq_ctx;
-       char                    descr[DESCR_BUFSZ];
-       uint64_t                ag_ino;
-       uint64_t                next_ag_ino;
-       bool                    moveon;
-
-       snprintf(descr, DESCR_BUFSZ, _("dev %d:%d AG %u inodes"),
-                               major(ctx->fsinfo.fs_datadev),
-                               minor(ctx->fsinfo.fs_datadev),
-                               agno);
-
-       ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
-       next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
-
-       moveon = xfs_count_inodes_range(ctx, descr, ag_ino, next_ag_ino - 1,
-                       &ci->counters[agno]);
-       if (!moveon)
-               ci->moveon = false;
+       ci->counters[agno] = nr;
 }
 
-/* Count all the inodes in a filesystem. */
-bool
-xfs_count_all_inodes(
+/*
+ * Count all the inodes in a filesystem.  Returns 0 or a positive error number.
+ */
+int
+scrub_count_all_inodes(
        struct scrub_ctx        *ctx,
        uint64_t                *count)
 {
-       struct xfs_count_inodes *ci;
+       struct count_inodes     *ci;
        xfs_agnumber_t          agno;
        struct workqueue        wq;
-       bool                    moveon;
-       int                     ret;
+       int                     ret, ret2;
 
-       ci = calloc(1, sizeof(struct xfs_count_inodes) +
+       ci = calloc(1, sizeof(struct count_inodes) +
                        (ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
        if (!ci)
-               return false;
-       ci->moveon = true;
+               return errno;
 
-       ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
+       ret = -workqueue_create(&wq, (struct xfs_mount *)ctx,
                        scrub_nproc_workqueue(ctx));
-       if (ret) {
-               moveon = false;
-               str_info(ctx, ctx->mntpoint, _("Could not create workqueue."));
+       if (ret)
                goto out_free;
-       }
-       for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
-               ret = workqueue_add(&wq, xfs_count_ag_inodes, agno, ci);
-               if (ret) {
-                       moveon = false;
-                       str_info(ctx, ctx->mntpoint,
-_("Could not queue AG %u icount work."), agno);
+
+       for (agno = 0; agno < ctx->mnt.fsgeom.agcount && !ci->error; agno++) {
+               ret = -workqueue_add(&wq, count_ag_inodes, agno, ci);
+               if (ret)
                        break;
-               }
        }
+
+       ret2 = -workqueue_terminate(&wq);
+       if (!ret && ret2)
+               ret = ret2;
        workqueue_destroy(&wq);
 
+       if (ci->error) {
+               ret = ci->error;
+               goto out_free;
+       }
+
        for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
                *count += ci->counters[agno];
-       moveon = ci->moveon;
 
 out_free:
        free(ci);
-       return moveon;
+       return ret;
 }
 
-/* Estimate the number of blocks and inodes in the filesystem. */
-bool
-xfs_scan_estimate_blocks(
+/*
+ * Estimate the number of blocks and used inodes in the filesystem.  Returns 0
+ * or a positive error number.
+ */
+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,
-       unsigned long long              *f_free)
+       unsigned long long              *f_files_used)
 {
        struct xfs_fsop_counts          fc;
-       struct xfs_fsop_resblks         rb;
-       struct statvfs                  sfs;
        int                             error;
 
-       /* Grab the fstatvfs counters, since it has to report accurately. */
-       error = fstatvfs(ctx->mnt.fd, &sfs);
-       if (error) {
-               str_errno(ctx, ctx->mntpoint);
-               return false;
-       }
-
        /* Fetch the filesystem counters. */
        error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
-       if (error) {
-               str_errno(ctx, ctx->mntpoint);
-               return false;
-       }
-
-       /*
-        * XFS reserves some blocks to prevent hard ENOSPC, so add those
-        * blocks back to the free data counts.
-        */
-       error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
        if (error)
-               str_errno(ctx, ctx->mntpoint);
-       sfs.f_bfree += rb.resblks_avail;
+               return errno;
 
-       *d_blocks = sfs.f_blocks;
-       if (ctx->mnt.fsgeom.logstart > 0)
-               *d_blocks += ctx->mnt.fsgeom.logblocks;
-       *d_bfree = sfs.f_bfree;
+       *d_blocks = ctx->mnt.fsgeom.datablocks;
+       *d_bfree = fc.freedata;
        *r_blocks = ctx->mnt.fsgeom.rtblocks;
-       *r_bfree = fc.freertx;
-       *f_files = sfs.f_files;
-       *f_free = sfs.f_ffree;
+       *r_bfree = fc.freertx * ctx->mnt.fsgeom.rtextsize;
+       *f_files_used = fc.allocino - fc.freeino;
 
-       return true;
+       return 0;
 }