]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/bulkstat.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / io / bulkstat.c
CommitLineData
3c8276c4
DW
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6#include "xfs.h"
7#include "platform_defs.h"
8#include "command.h"
9#include "init.h"
9fc3ef62 10#include "libfrog/logging.h"
3c8276c4
DW
11#include "libfrog/fsgeom.h"
12#include "libfrog/bulkstat.h"
13#include "libfrog/paths.h"
14#include "io.h"
15#include "input.h"
16
17static void
18dump_bulkstat_time(
19 const char *tag,
20 uint64_t sec,
21 uint32_t nsec)
22{
23 printf("\t%s = %"PRIu64".%"PRIu32"\n", tag, sec, nsec);
24}
25
26static void
27dump_bulkstat(
28 struct xfs_bulkstat *bstat)
29{
30 printf("bs_ino = %"PRIu64"\n", bstat->bs_ino);
31 printf("\tbs_size = %"PRIu64"\n", bstat->bs_size);
32
33 printf("\tbs_blocks = %"PRIu64"\n", bstat->bs_blocks);
34 printf("\tbs_xflags = 0x%"PRIx64"\n", bstat->bs_xflags);
35
36 dump_bulkstat_time("bs_atime", bstat->bs_atime, bstat->bs_atime_nsec);
37 dump_bulkstat_time("bs_ctime", bstat->bs_ctime, bstat->bs_ctime_nsec);
38 dump_bulkstat_time("bs_mtime", bstat->bs_mtime, bstat->bs_mtime_nsec);
39 dump_bulkstat_time("bs_btime", bstat->bs_btime, bstat->bs_btime_nsec);
40
41 printf("\tbs_gen = 0x%"PRIx32"\n", bstat->bs_gen);
42 printf("\tbs_uid = %"PRIu32"\n", bstat->bs_uid);
43 printf("\tbs_gid = %"PRIu32"\n", bstat->bs_gid);
44 printf("\tbs_projectid = %"PRIu32"\n", bstat->bs_projectid);
45
46 printf("\tbs_blksize = %"PRIu32"\n", bstat->bs_blksize);
47 printf("\tbs_rdev = %"PRIu32"\n", bstat->bs_rdev);
48 printf("\tbs_cowextsize_blks = %"PRIu32"\n", bstat->bs_cowextsize_blks);
49 printf("\tbs_extsize_blks = %"PRIu32"\n", bstat->bs_extsize_blks);
50
51 printf("\tbs_nlink = %"PRIu32"\n", bstat->bs_nlink);
52 printf("\tbs_extents = %"PRIu32"\n", bstat->bs_extents);
53 printf("\tbs_aextents = %"PRIu32"\n", bstat->bs_aextents);
54 printf("\tbs_version = %"PRIu16"\n", bstat->bs_version);
55 printf("\tbs_forkoff = %"PRIu16"\n", bstat->bs_forkoff);
56
57 printf("\tbs_sick = 0x%"PRIx16"\n", bstat->bs_sick);
58 printf("\tbs_checked = 0x%"PRIx16"\n", bstat->bs_checked);
59 printf("\tbs_mode = 0%"PRIo16"\n", bstat->bs_mode);
ac87307e 60 printf("\tbs_extents64 = %"PRIu64"\n", bstat->bs_extents64);
3c8276c4
DW
61};
62
63static void
64bulkstat_help(void)
65{
66 printf(_(
67"Bulk-queries the filesystem for inode stat information and prints it.\n"
68"\n"
69" -a <agno> Only iterate this AG.\n"
70" -d Print debugging output.\n"
7f6791f7 71" -q Be quiet, no output.\n"
3c8276c4
DW
72" -e <ino> Stop after this inode.\n"
73" -n <nr> Ask for this many results at once.\n"
74" -s <ino> Inode to start with.\n"
75" -v <ver> Use this version of the ioctl (1 or 5).\n"));
76}
77
78static void
79set_xfd_flags(
80 struct xfs_fd *xfd,
81 uint32_t ver)
82{
83 switch (ver) {
84 case 1:
85 xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V1;
86 break;
87 case 5:
88 xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V5;
89 break;
90 default:
91 break;
92 }
93}
94
95static int
96bulkstat_f(
97 int argc,
98 char **argv)
99{
100 struct xfs_fd xfd = XFS_FD_INIT(file->fd);
101 struct xfs_bulkstat_req *breq;
102 uint64_t startino = 0;
103 uint64_t endino = -1ULL;
104 uint32_t batch_size = 4096;
105 uint32_t agno = 0;
106 uint32_t ver = 0;
107 bool has_agno = false;
108 bool debug = false;
7f6791f7 109 bool quiet = false;
3c8276c4
DW
110 unsigned int i;
111 int c;
112 int ret;
113
7f6791f7 114 while ((c = getopt(argc, argv, "a:de:n:qs:v:")) != -1) {
3c8276c4
DW
115 switch (c) {
116 case 'a':
117 agno = cvt_u32(optarg, 10);
118 if (errno) {
119 perror(optarg);
120 return 1;
121 }
122 has_agno = true;
123 break;
124 case 'd':
125 debug = true;
126 break;
127 case 'e':
128 endino = cvt_u64(optarg, 10);
129 if (errno) {
130 perror(optarg);
131 return 1;
132 }
133 break;
134 case 'n':
135 batch_size = cvt_u32(optarg, 10);
136 if (errno) {
137 perror(optarg);
138 return 1;
139 }
140 break;
7f6791f7
DC
141 case 'q':
142 quiet = true;
143 break;
3c8276c4
DW
144 case 's':
145 startino = cvt_u64(optarg, 10);
146 if (errno) {
147 perror(optarg);
148 return 1;
149 }
150 break;
151 case 'v':
152 ver = cvt_u32(optarg, 10);
153 if (errno) {
154 perror(optarg);
155 return 1;
156 }
157 if (ver != 1 && ver != 5) {
158 fprintf(stderr, "version must be 1 or 5.\n");
159 return 1;
160 }
161 break;
162 default:
163 bulkstat_help();
164 return 0;
165 }
166 }
167 if (optind != argc) {
168 bulkstat_help();
169 return 0;
170 }
171
03d96c64 172 ret = -xfd_prepare_geometry(&xfd);
3c8276c4 173 if (ret) {
9fc3ef62 174 xfrog_perror(ret, "xfd_prepare_geometry");
3c8276c4
DW
175 exitcode = 1;
176 return 0;
177 }
178
e6542132
DW
179 ret = -xfrog_bulkstat_alloc_req(batch_size, startino, &breq);
180 if (ret) {
181 xfrog_perror(ret, "alloc bulkreq");
3c8276c4
DW
182 exitcode = 1;
183 return 0;
184 }
185
186 if (has_agno)
187 xfrog_bulkstat_set_ag(breq, agno);
188
189 set_xfd_flags(&xfd, ver);
190
e6542132 191 while ((ret = -xfrog_bulkstat(&xfd, breq)) == 0) {
3c8276c4
DW
192 if (debug)
193 printf(
194_("bulkstat: startino=%lld flags=0x%x agno=%u ret=%d icount=%u ocount=%u\n"),
195 (long long)breq->hdr.ino,
196 (unsigned int)breq->hdr.flags,
197 (unsigned int)breq->hdr.agno,
198 ret,
199 (unsigned int)breq->hdr.icount,
200 (unsigned int)breq->hdr.ocount);
201 if (breq->hdr.ocount == 0)
202 break;
203
204 for (i = 0; i < breq->hdr.ocount; i++) {
205 if (breq->bulkstat[i].bs_ino > endino)
206 break;
7f6791f7
DC
207 if (quiet)
208 continue;
3c8276c4
DW
209 dump_bulkstat(&breq->bulkstat[i]);
210 }
211 }
212 if (ret) {
9fc3ef62 213 xfrog_perror(ret, "xfrog_bulkstat");
3c8276c4
DW
214 exitcode = 1;
215 }
216
217 free(breq);
218 return 0;
219}
220
221static void
222bulkstat_single_help(void)
223{
224 printf(_(
225"Queries the filesystem for a single inode's stat information and prints it.\n"
226"If a given inode is not allocated, information about the next allocated \n"
227"inode will be printed instead.\n"
228"\n"
229" -v (ver) Use this version of the ioctl (1 or 5).\n"
230" -d Print debugging information.\n"
231"\n"
232"Pass in inode numbers or a special inode name:\n"
233" root Root directory.\n"));
234}
235
236struct single_map {
237 const char *tag;
238 uint64_t code;
239};
240
241struct single_map tags[] = {
242 {"root", XFS_BULK_IREQ_SPECIAL_ROOT},
243 {NULL, 0},
244};
245
246static int
247bulkstat_single_f(
248 int argc,
249 char **argv)
250{
251 struct xfs_fd xfd = XFS_FD_INIT(file->fd);
252 struct xfs_bulkstat bulkstat;
253 unsigned long ver = 0;
254 unsigned int i;
255 bool debug = false;
256 int c;
257 int ret;
258
259 while ((c = getopt(argc, argv, "dv:")) != -1) {
260 switch (c) {
261 case 'd':
262 debug = true;
263 break;
264 case 'v':
265 errno = 0;
266 ver = strtoull(optarg, NULL, 10);
267 if (errno) {
268 perror(optarg);
269 return 1;
270 }
271 if (ver != 1 && ver != 5) {
272 fprintf(stderr, "version must be 1 or 5.\n");
273 return 1;
274 }
275 break;
276 default:
277 bulkstat_single_help();
278 return 0;
279 }
280 }
281
03d96c64 282 ret = -xfd_prepare_geometry(&xfd);
3c8276c4 283 if (ret) {
9fc3ef62 284 xfrog_perror(ret, "xfd_prepare_geometry");
3c8276c4
DW
285 exitcode = 1;
286 return 0;
287 }
288
289 set_xfd_flags(&xfd, ver);
290
291 for (i = optind; i < argc; i++) {
292 struct single_map *sm = tags;
293 uint64_t ino;
294 unsigned int flags = 0;
295
296 /* Try to look up our tag... */
297 for (sm = tags; sm->tag; sm++) {
298 if (!strcmp(argv[i], sm->tag)) {
299 ino = sm->code;
300 flags |= XFS_BULK_IREQ_SPECIAL;
301 break;
302 }
303 }
304
305 /* ...or else it's an inode number. */
306 if (sm->tag == NULL) {
307 errno = 0;
308 ino = strtoull(argv[i], NULL, 10);
309 if (errno) {
310 perror(argv[i]);
311 exitcode = 1;
312 return 0;
313 }
314 }
315
e6542132 316 ret = -xfrog_bulkstat_single(&xfd, ino, flags, &bulkstat);
3c8276c4 317 if (ret) {
9fc3ef62 318 xfrog_perror(ret, "xfrog_bulkstat_single");
3c8276c4
DW
319 continue;
320 }
321
322 if (debug)
323 printf(
324_("bulkstat_single: startino=%"PRIu64" flags=0x%"PRIx32" ret=%d\n"),
325 ino, flags, ret);
326
327 dump_bulkstat(&bulkstat);
328 }
329
330 return 0;
331}
332
333static void
334dump_inumbers(
335 struct xfs_inumbers *inumbers)
336{
337 printf("xi_startino = %"PRIu64"\n", inumbers->xi_startino);
338 printf("\txi_allocmask = 0x%"PRIx64"\n", inumbers->xi_allocmask);
339 printf("\txi_alloccount = %"PRIu8"\n", inumbers->xi_alloccount);
340 printf("\txi_version = %"PRIu8"\n", inumbers->xi_version);
341}
342
343static void
344inumbers_help(void)
345{
346 printf(_(
347"Queries the filesystem for inode group information and prints it.\n"
348"\n"
349" -a <agno> Only iterate this AG.\n"
350" -d Print debugging output.\n"
351" -e <ino> Stop after this inode.\n"
352" -n <nr> Ask for this many results at once.\n"
353" -s <ino> Inode to start with.\n"
354" -v <ver> Use this version of the ioctl (1 or 5).\n"));
355}
356
357static int
358inumbers_f(
359 int argc,
360 char **argv)
361{
362 struct xfs_fd xfd = XFS_FD_INIT(file->fd);
363 struct xfs_inumbers_req *ireq;
364 uint64_t startino = 0;
365 uint64_t endino = -1ULL;
366 uint32_t batch_size = 4096;
367 uint32_t agno = 0;
368 uint32_t ver = 0;
369 bool has_agno = false;
370 bool debug = false;
371 unsigned int i;
372 int c;
373 int ret;
374
375 while ((c = getopt(argc, argv, "a:de:n:s:v:")) != -1) {
376 switch (c) {
377 case 'a':
378 agno = cvt_u32(optarg, 10);
379 if (errno) {
380 perror(optarg);
381 return 1;
382 }
383 has_agno = true;
384 break;
385 case 'd':
386 debug = true;
387 break;
388 case 'e':
389 endino = cvt_u64(optarg, 10);
390 if (errno) {
391 perror(optarg);
392 return 1;
393 }
394 break;
395 case 'n':
396 batch_size = cvt_u32(optarg, 10);
397 if (errno) {
398 perror(optarg);
399 return 1;
400 }
401 break;
402 case 's':
403 startino = cvt_u64(optarg, 10);
404 if (errno) {
405 perror(optarg);
406 return 1;
407 }
408 break;
409 case 'v':
410 ver = cvt_u32(optarg, 10);
411 if (errno) {
412 perror(optarg);
413 return 1;
414 }
415 if (ver != 1 && ver != 5) {
416 fprintf(stderr, "version must be 1 or 5.\n");
417 return 1;
418 }
419 break;
420 default:
421 bulkstat_help();
422 return 0;
423 }
424 }
425 if (optind != argc) {
426 bulkstat_help();
427 return 0;
428 }
429
03d96c64 430 ret = -xfd_prepare_geometry(&xfd);
3c8276c4 431 if (ret) {
9fc3ef62 432 xfrog_perror(ret, "xfd_prepare_geometry");
3c8276c4
DW
433 exitcode = 1;
434 return 0;
435 }
436
e6542132
DW
437 ret = -xfrog_inumbers_alloc_req(batch_size, startino, &ireq);
438 if (ret) {
439 xfrog_perror(ret, "alloc inumbersreq");
3c8276c4
DW
440 exitcode = 1;
441 return 0;
442 }
443
444 if (has_agno)
445 xfrog_inumbers_set_ag(ireq, agno);
446
447 set_xfd_flags(&xfd, ver);
448
e6542132 449 while ((ret = -xfrog_inumbers(&xfd, ireq)) == 0) {
3c8276c4
DW
450 if (debug)
451 printf(
452_("bulkstat: startino=%"PRIu64" flags=0x%"PRIx32" agno=%"PRIu32" ret=%d icount=%"PRIu32" ocount=%"PRIu32"\n"),
453 ireq->hdr.ino,
454 ireq->hdr.flags,
455 ireq->hdr.agno,
456 ret,
457 ireq->hdr.icount,
458 ireq->hdr.ocount);
459 if (ireq->hdr.ocount == 0)
460 break;
461
462 for (i = 0; i < ireq->hdr.ocount; i++) {
463 if (ireq->inumbers[i].xi_startino > endino)
464 break;
465 dump_inumbers(&ireq->inumbers[i]);
466 }
467 }
468 if (ret) {
9fc3ef62 469 xfrog_perror(ret, "xfrog_inumbers");
3c8276c4
DW
470 exitcode = 1;
471 }
472
473 free(ireq);
474 return 0;
475}
476
477static cmdinfo_t bulkstat_cmd = {
478 .name = "bulkstat",
479 .cfunc = bulkstat_f,
480 .argmin = 0,
481 .argmax = -1,
482 .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
483 .help = bulkstat_help,
484};
485
486static cmdinfo_t bulkstat_single_cmd = {
487 .name = "bulkstat_single",
488 .cfunc = bulkstat_single_f,
489 .argmin = 1,
490 .argmax = -1,
491 .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
492 .help = bulkstat_single_help,
493};
494
495static cmdinfo_t inumbers_cmd = {
496 .name = "inumbers",
497 .cfunc = inumbers_f,
498 .argmin = 0,
499 .argmax = -1,
500 .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
501 .help = inumbers_help,
502};
503
504void
505bulkstat_init(void)
506{
507 bulkstat_cmd.args =
508_("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
509 bulkstat_cmd.oneline = _("Bulk stat of inodes in a filesystem");
510
511 bulkstat_single_cmd.args = _("[-d] [-v version] inum...");
512 bulkstat_single_cmd.oneline = _("Stat one inode in a filesystem");
513
514 inumbers_cmd.args =
515_("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
516 inumbers_cmd.oneline = _("Query inode groups in a filesystem");
517
518 add_command(&bulkstat_cmd);
519 add_command(&bulkstat_single_cmd);
520 add_command(&inumbers_cmd);
521}