]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/fscounters.c
xfs_scrub_all: fix argument passing when invoking xfs_scrub manually
[thirdparty/xfsprogs-dev.git] / scrub / fscounters.c
CommitLineData
8d318d62 1// SPDX-License-Identifier: GPL-2.0-or-later
604dd334 2/*
52520522 3 * Copyright (C) 2018-2024 Oracle. All Rights Reserved.
8d318d62 4 * Author: Darrick J. Wong <djwong@kernel.org>
604dd334 5 */
a440f877 6#include "xfs.h"
604dd334
DW
7#include <stdint.h>
8#include <stdlib.h>
9#include <sys/statvfs.h>
10#include "platform_defs.h"
604dd334 11#include "xfs_arch.h"
42b4c8e8 12#include "libfrog/paths.h"
56598728 13#include "libfrog/workqueue.h"
604dd334
DW
14#include "xfs_scrub.h"
15#include "common.h"
16#include "fscounters.h"
621f3374 17#include "libfrog/bulkstat.h"
604dd334
DW
18
19/*
20 * Filesystem counter collection routines. We can count the number of
21 * inodes in the filesystem, and we can estimate the block counters.
22 */
23
24/* Count the number of inodes in the filesystem. */
25
26/* INUMBERS wrapper routines. */
934d8d3a
DW
27struct count_inodes {
28 int error;
604dd334
DW
29 uint64_t counters[0];
30};
31
32/*
33 * Count the number of inodes. Use INUMBERS to figure out how many inodes
34 * exist in the filesystem, assuming we've already scrubbed that.
35 */
934d8d3a
DW
36static void
37count_ag_inodes(
38 struct workqueue *wq,
39 xfs_agnumber_t agno,
40 void *arg)
604dd334 41{
934d8d3a
DW
42 struct count_inodes *ci = arg;
43 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
b94a69ac 44 struct xfs_inumbers_req *ireq;
604dd334 45 uint64_t nr = 0;
6040b5d5 46 unsigned int i;
604dd334
DW
47 int error;
48
e6542132
DW
49 error = -xfrog_inumbers_alloc_req(64, 0, &ireq);
50 if (error) {
51 ci->error = error;
934d8d3a 52 return;
b94a69ac 53 }
23ea9841 54 xfrog_inumbers_set_ag(ireq, agno);
b94a69ac 55
e6542132 56 while (!ci->error && (error = -xfrog_inumbers(&ctx->mnt, ireq)) == 0) {
23ea9841 57 if (ireq->hdr.ocount == 0)
621f3374 58 break;
6040b5d5
DW
59 for (i = 0; i < ireq->hdr.ocount; i++)
60 nr += ireq->inumbers[i].xi_alloccount;
604dd334 61 }
934d8d3a
DW
62 if (error)
63 ci->error = error;
604dd334 64
b94a69ac
DW
65 free(ireq);
66
934d8d3a 67 ci->counters[agno] = nr;
604dd334
DW
68}
69
934d8d3a
DW
70/*
71 * Count all the inodes in a filesystem. Returns 0 or a positive error number.
72 */
73int
74scrub_count_all_inodes(
604dd334
DW
75 struct scrub_ctx *ctx,
76 uint64_t *count)
77{
934d8d3a 78 struct count_inodes *ci;
604dd334
DW
79 xfs_agnumber_t agno;
80 struct workqueue wq;
934d8d3a 81 int ret, ret2;
604dd334 82
934d8d3a 83 ci = calloc(1, sizeof(struct count_inodes) +
3f9efb2e 84 (ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
604dd334 85 if (!ci)
934d8d3a 86 return errno;
604dd334 87
baed134d 88 ret = -workqueue_create(&wq, (struct xfs_mount *)ctx,
604dd334 89 scrub_nproc_workqueue(ctx));
934d8d3a 90 if (ret)
604dd334 91 goto out_free;
934d8d3a
DW
92
93 for (agno = 0; agno < ctx->mnt.fsgeom.agcount && !ci->error; agno++) {
baed134d 94 ret = -workqueue_add(&wq, count_ag_inodes, agno, ci);
934d8d3a 95 if (ret)
604dd334 96 break;
604dd334 97 }
71296cf8 98
baed134d 99 ret2 = -workqueue_terminate(&wq);
934d8d3a
DW
100 if (!ret && ret2)
101 ret = ret2;
604dd334
DW
102 workqueue_destroy(&wq);
103
934d8d3a
DW
104 if (ci->error) {
105 ret = ci->error;
71296cf8 106 goto out_free;
934d8d3a 107 }
71296cf8 108
3f9efb2e 109 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
604dd334 110 *count += ci->counters[agno];
604dd334
DW
111
112out_free:
113 free(ci);
934d8d3a 114 return ret;
604dd334
DW
115}
116
934d8d3a 117/*
0b78ac05 118 * Estimate the number of blocks and used inodes in the filesystem. Returns 0
934d8d3a
DW
119 * or a positive error number.
120 */
121int
122scrub_scan_estimate_blocks(
604dd334
DW
123 struct scrub_ctx *ctx,
124 unsigned long long *d_blocks,
125 unsigned long long *d_bfree,
126 unsigned long long *r_blocks,
127 unsigned long long *r_bfree,
0b78ac05 128 unsigned long long *f_files_used)
604dd334
DW
129{
130 struct xfs_fsop_counts fc;
604dd334
DW
131 int error;
132
604dd334 133 /* Fetch the filesystem counters. */
3f9efb2e 134 error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
934d8d3a
DW
135 if (error)
136 return errno;
604dd334 137
2b9857cd
DW
138 *d_blocks = ctx->mnt.fsgeom.datablocks;
139 *d_bfree = fc.freedata;
3f9efb2e 140 *r_blocks = ctx->mnt.fsgeom.rtblocks;
085fce0b 141 *r_bfree = fc.freertx * ctx->mnt.fsgeom.rtextsize;
0b78ac05 142 *f_files_used = fc.allocino - fc.freeino;
604dd334 143
934d8d3a 144 return 0;
604dd334 145}