]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/fscounters.c
libfrog: convert workqueue.c functions to negative error codes
[thirdparty/xfsprogs-dev.git] / scrub / fscounters.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0+
604dd334
DW
2/*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
604dd334 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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"
604dd334 12#include "xfs_format.h"
42b4c8e8 13#include "libfrog/paths.h"
56598728 14#include "libfrog/workqueue.h"
604dd334
DW
15#include "xfs_scrub.h"
16#include "common.h"
17#include "fscounters.h"
621f3374 18#include "libfrog/bulkstat.h"
604dd334
DW
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. */
934d8d3a
DW
28struct count_inodes {
29 int error;
604dd334
DW
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 */
934d8d3a
DW
37static void
38count_ag_inodes(
39 struct workqueue *wq,
40 xfs_agnumber_t agno,
41 void *arg)
604dd334 42{
934d8d3a
DW
43 struct count_inodes *ci = arg;
44 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
b94a69ac 45 struct xfs_inumbers_req *ireq;
604dd334 46 uint64_t nr = 0;
6040b5d5 47 unsigned int i;
604dd334
DW
48 int error;
49
e6542132
DW
50 error = -xfrog_inumbers_alloc_req(64, 0, &ireq);
51 if (error) {
52 ci->error = error;
934d8d3a 53 return;
b94a69ac 54 }
23ea9841 55 xfrog_inumbers_set_ag(ireq, agno);
b94a69ac 56
e6542132 57 while (!ci->error && (error = -xfrog_inumbers(&ctx->mnt, ireq)) == 0) {
23ea9841 58 if (ireq->hdr.ocount == 0)
621f3374 59 break;
6040b5d5
DW
60 for (i = 0; i < ireq->hdr.ocount; i++)
61 nr += ireq->inumbers[i].xi_alloccount;
604dd334 62 }
934d8d3a
DW
63 if (error)
64 ci->error = error;
604dd334 65
b94a69ac
DW
66 free(ireq);
67
934d8d3a 68 ci->counters[agno] = nr;
604dd334
DW
69}
70
934d8d3a
DW
71/*
72 * Count all the inodes in a filesystem. Returns 0 or a positive error number.
73 */
74int
75scrub_count_all_inodes(
604dd334
DW
76 struct scrub_ctx *ctx,
77 uint64_t *count)
78{
934d8d3a 79 struct count_inodes *ci;
604dd334
DW
80 xfs_agnumber_t agno;
81 struct workqueue wq;
934d8d3a 82 int ret, ret2;
604dd334 83
934d8d3a 84 ci = calloc(1, sizeof(struct count_inodes) +
3f9efb2e 85 (ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
604dd334 86 if (!ci)
934d8d3a 87 return errno;
604dd334 88
baed134d 89 ret = -workqueue_create(&wq, (struct xfs_mount *)ctx,
604dd334 90 scrub_nproc_workqueue(ctx));
934d8d3a 91 if (ret)
604dd334 92 goto out_free;
934d8d3a
DW
93
94 for (agno = 0; agno < ctx->mnt.fsgeom.agcount && !ci->error; agno++) {
baed134d 95 ret = -workqueue_add(&wq, count_ag_inodes, agno, ci);
934d8d3a 96 if (ret)
604dd334 97 break;
604dd334 98 }
71296cf8 99
baed134d 100 ret2 = -workqueue_terminate(&wq);
934d8d3a
DW
101 if (!ret && ret2)
102 ret = ret2;
604dd334
DW
103 workqueue_destroy(&wq);
104
934d8d3a
DW
105 if (ci->error) {
106 ret = ci->error;
71296cf8 107 goto out_free;
934d8d3a 108 }
71296cf8 109
3f9efb2e 110 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
604dd334 111 *count += ci->counters[agno];
604dd334
DW
112
113out_free:
114 free(ci);
934d8d3a 115 return ret;
604dd334
DW
116}
117
934d8d3a
DW
118/*
119 * Estimate the number of blocks and inodes in the filesystem. Returns 0
120 * or a positive error number.
121 */
122int
123scrub_scan_estimate_blocks(
604dd334
DW
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. */
3f9efb2e 138 error = fstatvfs(ctx->mnt.fd, &sfs);
934d8d3a
DW
139 if (error)
140 return errno;
604dd334
DW
141
142 /* Fetch the filesystem counters. */
3f9efb2e 143 error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
934d8d3a
DW
144 if (error)
145 return errno;
604dd334
DW
146
147 /*
148 * XFS reserves some blocks to prevent hard ENOSPC, so add those
149 * blocks back to the free data counts.
150 */
3f9efb2e 151 error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
604dd334 152 if (error)
934d8d3a
DW
153 return errno;
154
604dd334
DW
155 sfs.f_bfree += rb.resblks_avail;
156
3f9efb2e
DW
157 *d_blocks = sfs.f_blocks;
158 if (ctx->mnt.fsgeom.logstart > 0)
159 *d_blocks += ctx->mnt.fsgeom.logblocks;
604dd334 160 *d_bfree = sfs.f_bfree;
3f9efb2e 161 *r_blocks = ctx->mnt.fsgeom.rtblocks;
604dd334
DW
162 *r_bfree = fc.freertx;
163 *f_files = sfs.f_files;
164 *f_free = sfs.f_ffree;
165
934d8d3a 166 return 0;
604dd334 167}