]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/fscounters.c
2 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <sys/statvfs.h>
24 #include "platform_defs.h"
26 #include "xfs_format.h"
28 #include "workqueue.h"
29 #include "xfs_scrub.h"
31 #include "fscounters.h"
34 * Filesystem counter collection routines. We can count the number of
35 * inodes in the filesystem, and we can estimate the block counters.
38 /* Count the number of inodes in the filesystem. */
40 /* INUMBERS wrapper routines. */
41 struct xfs_count_inodes
{
47 * Count the number of inodes. Use INUMBERS to figure out how many inodes
48 * exist in the filesystem, assuming we've already scrubbed that.
51 xfs_count_inodes_range(
52 struct scrub_ctx
*ctx
,
58 struct xfs_fsop_bulkreq igrpreq
= {0};
59 struct xfs_inogrp inogrp
;
65 ASSERT(!(first_ino
& (XFS_INODES_PER_CHUNK
- 1)));
66 ASSERT((last_ino
& (XFS_INODES_PER_CHUNK
- 1)));
68 igrpreq
.lastip
= &igrp_ino
;
70 igrpreq
.ubuffer
= &inogrp
;
71 igrpreq
.ocount
= &igrplen
;
74 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSINUMBERS
, &igrpreq
);
75 while (!error
&& igrplen
&& inogrp
.xi_startino
< last_ino
) {
76 nr
+= inogrp
.xi_alloccount
;
77 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSINUMBERS
, &igrpreq
);
81 str_errno(ctx
, descr
);
89 /* Scan all the inodes in an AG. */
96 struct xfs_count_inodes
*ci
= arg
;
97 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
98 char descr
[DESCR_BUFSZ
];
100 uint64_t next_ag_ino
;
103 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d AG %u inodes"),
104 major(ctx
->fsinfo
.fs_datadev
),
105 minor(ctx
->fsinfo
.fs_datadev
),
108 ag_ino
= (__u64
)agno
<< (ctx
->inopblog
+ ctx
->agblklog
);
109 next_ag_ino
= (__u64
)(agno
+ 1) << (ctx
->inopblog
+ ctx
->agblklog
);
111 moveon
= xfs_count_inodes_range(ctx
, descr
, ag_ino
, next_ag_ino
- 1,
112 &ci
->counters
[agno
]);
117 /* Count all the inodes in a filesystem. */
119 xfs_count_all_inodes(
120 struct scrub_ctx
*ctx
,
123 struct xfs_count_inodes
*ci
;
129 ci
= calloc(1, sizeof(struct xfs_count_inodes
) +
130 (ctx
->geo
.agcount
* sizeof(uint64_t)));
135 ret
= workqueue_create(&wq
, (struct xfs_mount
*)ctx
,
136 scrub_nproc_workqueue(ctx
));
139 str_info(ctx
, ctx
->mntpoint
, _("Could not create workqueue."));
142 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++) {
143 ret
= workqueue_add(&wq
, xfs_count_ag_inodes
, agno
, ci
);
146 str_info(ctx
, ctx
->mntpoint
,
147 _("Could not queue AG %u icount work."), agno
);
151 workqueue_destroy(&wq
);
153 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++)
154 *count
+= ci
->counters
[agno
];
162 /* Estimate the number of blocks and inodes in the filesystem. */
164 xfs_scan_estimate_blocks(
165 struct scrub_ctx
*ctx
,
166 unsigned long long *d_blocks
,
167 unsigned long long *d_bfree
,
168 unsigned long long *r_blocks
,
169 unsigned long long *r_bfree
,
170 unsigned long long *f_files
,
171 unsigned long long *f_free
)
173 struct xfs_fsop_counts fc
;
174 struct xfs_fsop_resblks rb
;
178 /* Grab the fstatvfs counters, since it has to report accurately. */
179 error
= fstatvfs(ctx
->mnt_fd
, &sfs
);
181 str_errno(ctx
, ctx
->mntpoint
);
185 /* Fetch the filesystem counters. */
186 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSCOUNTS
, &fc
);
188 str_errno(ctx
, ctx
->mntpoint
);
193 * XFS reserves some blocks to prevent hard ENOSPC, so add those
194 * blocks back to the free data counts.
196 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_GET_RESBLKS
, &rb
);
198 str_errno(ctx
, ctx
->mntpoint
);
199 sfs
.f_bfree
+= rb
.resblks_avail
;
201 *d_blocks
= sfs
.f_blocks
+ (ctx
->geo
.logstart
? ctx
->geo
.logblocks
: 0);
202 *d_bfree
= sfs
.f_bfree
;
203 *r_blocks
= ctx
->geo
.rtblocks
;
204 *r_bfree
= fc
.freertx
;
205 *f_files
= sfs
.f_files
;
206 *f_free
= sfs
.f_ffree
;