]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/fscounters.c
xfs_scrub: remove moveon from unicode name collision helpers
[thirdparty/xfsprogs-dev.git] / scrub / fscounters.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 #include "xfs.h"
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <sys/statvfs.h>
10 #include "platform_defs.h"
11 #include "xfs_arch.h"
12 #include "xfs_format.h"
13 #include "libfrog/paths.h"
14 #include "libfrog/workqueue.h"
15 #include "xfs_scrub.h"
16 #include "common.h"
17 #include "fscounters.h"
18 #include "libfrog/bulkstat.h"
19
20 /*
21 * Filesystem counter collection routines. We can count the number of
22 * inodes in the filesystem, and we can estimate the block counters.
23 */
24
25 /* Count the number of inodes in the filesystem. */
26
27 /* INUMBERS wrapper routines. */
28 struct count_inodes {
29 int error;
30 uint64_t counters[0];
31 };
32
33 /*
34 * Count the number of inodes. Use INUMBERS to figure out how many inodes
35 * exist in the filesystem, assuming we've already scrubbed that.
36 */
37 static void
38 count_ag_inodes(
39 struct workqueue *wq,
40 xfs_agnumber_t agno,
41 void *arg)
42 {
43 struct count_inodes *ci = arg;
44 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
45 struct xfs_inumbers_req *ireq;
46 uint64_t nr = 0;
47 unsigned int i;
48 int error;
49
50 ireq = xfrog_inumbers_alloc_req(64, 0);
51 if (!ireq) {
52 ci->error = errno;
53 return;
54 }
55 xfrog_inumbers_set_ag(ireq, agno);
56
57 while (!ci->error && (error = xfrog_inumbers(&ctx->mnt, ireq)) == 0) {
58 if (ireq->hdr.ocount == 0)
59 break;
60 for (i = 0; i < ireq->hdr.ocount; i++)
61 nr += ireq->inumbers[i].xi_alloccount;
62 }
63 if (error)
64 ci->error = error;
65
66 free(ireq);
67
68 ci->counters[agno] = nr;
69 }
70
71 /*
72 * Count all the inodes in a filesystem. Returns 0 or a positive error number.
73 */
74 int
75 scrub_count_all_inodes(
76 struct scrub_ctx *ctx,
77 uint64_t *count)
78 {
79 struct count_inodes *ci;
80 xfs_agnumber_t agno;
81 struct workqueue wq;
82 int ret, ret2;
83
84 ci = calloc(1, sizeof(struct count_inodes) +
85 (ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
86 if (!ci)
87 return errno;
88
89 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
90 scrub_nproc_workqueue(ctx));
91 if (ret)
92 goto out_free;
93
94 for (agno = 0; agno < ctx->mnt.fsgeom.agcount && !ci->error; agno++) {
95 ret = workqueue_add(&wq, count_ag_inodes, agno, ci);
96 if (ret)
97 break;
98 }
99
100 ret2 = workqueue_terminate(&wq);
101 if (!ret && ret2)
102 ret = ret2;
103 workqueue_destroy(&wq);
104
105 if (ci->error) {
106 ret = ci->error;
107 goto out_free;
108 }
109
110 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
111 *count += ci->counters[agno];
112
113 out_free:
114 free(ci);
115 return ret;
116 }
117
118 /*
119 * Estimate the number of blocks and inodes in the filesystem. Returns 0
120 * or a positive error number.
121 */
122 int
123 scrub_scan_estimate_blocks(
124 struct scrub_ctx *ctx,
125 unsigned long long *d_blocks,
126 unsigned long long *d_bfree,
127 unsigned long long *r_blocks,
128 unsigned long long *r_bfree,
129 unsigned long long *f_files,
130 unsigned long long *f_free)
131 {
132 struct xfs_fsop_counts fc;
133 struct xfs_fsop_resblks rb;
134 struct statvfs sfs;
135 int error;
136
137 /* Grab the fstatvfs counters, since it has to report accurately. */
138 error = fstatvfs(ctx->mnt.fd, &sfs);
139 if (error)
140 return errno;
141
142 /* Fetch the filesystem counters. */
143 error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
144 if (error)
145 return errno;
146
147 /*
148 * XFS reserves some blocks to prevent hard ENOSPC, so add those
149 * blocks back to the free data counts.
150 */
151 error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
152 if (error)
153 return errno;
154
155 sfs.f_bfree += rb.resblks_avail;
156
157 *d_blocks = sfs.f_blocks;
158 if (ctx->mnt.fsgeom.logstart > 0)
159 *d_blocks += ctx->mnt.fsgeom.logblocks;
160 *d_bfree = sfs.f_bfree;
161 *r_blocks = ctx->mnt.fsgeom.rtblocks;
162 *r_bfree = fc.freertx;
163 *f_files = sfs.f_files;
164 *f_free = sfs.f_ffree;
165
166 return 0;
167 }