]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/fscounters.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
9 #include <sys/statvfs.h>
10 #include "platform_defs.h"
12 #include "xfs_format.h"
14 #include "workqueue.h"
15 #include "xfs_scrub.h"
17 #include "fscounters.h"
20 * Filesystem counter collection routines. We can count the number of
21 * inodes in the filesystem, and we can estimate the block counters.
24 /* Count the number of inodes in the filesystem. */
26 /* INUMBERS wrapper routines. */
27 struct xfs_count_inodes
{
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.
37 xfs_count_inodes_range(
38 struct scrub_ctx
*ctx
,
44 struct xfs_fsop_bulkreq igrpreq
= {0};
45 struct xfs_inogrp inogrp
;
51 ASSERT(!(first_ino
& (XFS_INODES_PER_CHUNK
- 1)));
52 ASSERT((last_ino
& (XFS_INODES_PER_CHUNK
- 1)));
54 igrpreq
.lastip
= &igrp_ino
;
56 igrpreq
.ubuffer
= &inogrp
;
57 igrpreq
.ocount
= &igrplen
;
60 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSINUMBERS
, &igrpreq
);
61 while (!error
&& igrplen
&& inogrp
.xi_startino
< last_ino
) {
62 nr
+= inogrp
.xi_alloccount
;
63 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSINUMBERS
, &igrpreq
);
67 str_errno(ctx
, descr
);
75 /* Scan all the inodes in an AG. */
82 struct xfs_count_inodes
*ci
= arg
;
83 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
84 char descr
[DESCR_BUFSZ
];
89 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d AG %u inodes"),
90 major(ctx
->fsinfo
.fs_datadev
),
91 minor(ctx
->fsinfo
.fs_datadev
),
94 ag_ino
= (__u64
)agno
<< (ctx
->inopblog
+ ctx
->agblklog
);
95 next_ag_ino
= (__u64
)(agno
+ 1) << (ctx
->inopblog
+ ctx
->agblklog
);
97 moveon
= xfs_count_inodes_range(ctx
, descr
, ag_ino
, next_ag_ino
- 1,
103 /* Count all the inodes in a filesystem. */
105 xfs_count_all_inodes(
106 struct scrub_ctx
*ctx
,
109 struct xfs_count_inodes
*ci
;
115 ci
= calloc(1, sizeof(struct xfs_count_inodes
) +
116 (ctx
->geo
.agcount
* sizeof(uint64_t)));
121 ret
= workqueue_create(&wq
, (struct xfs_mount
*)ctx
,
122 scrub_nproc_workqueue(ctx
));
125 str_info(ctx
, ctx
->mntpoint
, _("Could not create workqueue."));
128 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++) {
129 ret
= workqueue_add(&wq
, xfs_count_ag_inodes
, agno
, ci
);
132 str_info(ctx
, ctx
->mntpoint
,
133 _("Could not queue AG %u icount work."), agno
);
137 workqueue_destroy(&wq
);
139 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++)
140 *count
+= ci
->counters
[agno
];
148 /* Estimate the number of blocks and inodes in the filesystem. */
150 xfs_scan_estimate_blocks(
151 struct scrub_ctx
*ctx
,
152 unsigned long long *d_blocks
,
153 unsigned long long *d_bfree
,
154 unsigned long long *r_blocks
,
155 unsigned long long *r_bfree
,
156 unsigned long long *f_files
,
157 unsigned long long *f_free
)
159 struct xfs_fsop_counts fc
;
160 struct xfs_fsop_resblks rb
;
164 /* Grab the fstatvfs counters, since it has to report accurately. */
165 error
= fstatvfs(ctx
->mnt_fd
, &sfs
);
167 str_errno(ctx
, ctx
->mntpoint
);
171 /* Fetch the filesystem counters. */
172 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSCOUNTS
, &fc
);
174 str_errno(ctx
, ctx
->mntpoint
);
179 * XFS reserves some blocks to prevent hard ENOSPC, so add those
180 * blocks back to the free data counts.
182 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_GET_RESBLKS
, &rb
);
184 str_errno(ctx
, ctx
->mntpoint
);
185 sfs
.f_bfree
+= rb
.resblks_avail
;
187 *d_blocks
= sfs
.f_blocks
+ (ctx
->geo
.logstart
? ctx
->geo
.logblocks
: 0);
188 *d_bfree
= sfs
.f_bfree
;
189 *r_blocks
= ctx
->geo
.rtblocks
;
190 *r_bfree
= fc
.freertx
;
191 *f_files
= sfs
.f_files
;
192 *f_free
= sfs
.f_ffree
;