1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
7 #include "platform_defs.h"
10 #include "libfrog/logging.h"
11 #include "libfrog/fsgeom.h"
12 #include "libfrog/bulkstat.h"
13 #include "libfrog/paths.h"
23 printf("\t%s = %"PRIu64
".%"PRIu32
"\n", tag
, sec
, nsec
);
28 struct xfs_bulkstat
*bstat
)
30 printf("bs_ino = %"PRIu64
"\n", bstat
->bs_ino
);
31 printf("\tbs_size = %"PRIu64
"\n", bstat
->bs_size
);
33 printf("\tbs_blocks = %"PRIu64
"\n", bstat
->bs_blocks
);
34 printf("\tbs_xflags = 0x%"PRIx64
"\n", bstat
->bs_xflags
);
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
);
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
);
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
);
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
);
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
);
66 "Bulk-queries the filesystem for inode stat information and prints it.\n"
68 " -a <agno> Only iterate this AG.\n"
69 " -d Print debugging output.\n"
70 " -e <ino> Stop after this inode.\n"
71 " -n <nr> Ask for this many results at once.\n"
72 " -s <ino> Inode to start with.\n"
73 " -v <ver> Use this version of the ioctl (1 or 5).\n"));
83 xfd
->flags
|= XFROG_FLAG_BULKSTAT_FORCE_V1
;
86 xfd
->flags
|= XFROG_FLAG_BULKSTAT_FORCE_V5
;
98 struct xfs_fd xfd
= XFS_FD_INIT(file
->fd
);
99 struct xfs_bulkstat_req
*breq
;
100 uint64_t startino
= 0;
101 uint64_t endino
= -1ULL;
102 uint32_t batch_size
= 4096;
105 bool has_agno
= false;
111 while ((c
= getopt(argc
, argv
, "a:de:n:s:v:")) != -1) {
114 agno
= cvt_u32(optarg
, 10);
125 endino
= cvt_u64(optarg
, 10);
132 batch_size
= cvt_u32(optarg
, 10);
139 startino
= cvt_u64(optarg
, 10);
146 ver
= cvt_u32(optarg
, 10);
151 if (ver
!= 1 && ver
!= 5) {
152 fprintf(stderr
, "version must be 1 or 5.\n");
161 if (optind
!= argc
) {
166 ret
= -xfd_prepare_geometry(&xfd
);
168 xfrog_perror(ret
, "xfd_prepare_geometry");
173 breq
= xfrog_bulkstat_alloc_req(batch_size
, startino
);
175 perror("alloc bulkreq");
181 xfrog_bulkstat_set_ag(breq
, agno
);
183 set_xfd_flags(&xfd
, ver
);
185 while ((ret
= xfrog_bulkstat(&xfd
, breq
)) == 0) {
188 _("bulkstat: startino=%lld flags=0x%x agno=%u ret=%d icount=%u ocount=%u\n"),
189 (long long)breq
->hdr
.ino
,
190 (unsigned int)breq
->hdr
.flags
,
191 (unsigned int)breq
->hdr
.agno
,
193 (unsigned int)breq
->hdr
.icount
,
194 (unsigned int)breq
->hdr
.ocount
);
195 if (breq
->hdr
.ocount
== 0)
198 for (i
= 0; i
< breq
->hdr
.ocount
; i
++) {
199 if (breq
->bulkstat
[i
].bs_ino
> endino
)
201 dump_bulkstat(&breq
->bulkstat
[i
]);
205 xfrog_perror(ret
, "xfrog_bulkstat");
214 bulkstat_single_help(void)
217 "Queries the filesystem for a single inode's stat information and prints it.\n"
218 "If a given inode is not allocated, information about the next allocated \n"
219 "inode will be printed instead.\n"
221 " -v (ver) Use this version of the ioctl (1 or 5).\n"
222 " -d Print debugging information.\n"
224 "Pass in inode numbers or a special inode name:\n"
225 " root Root directory.\n"));
233 struct single_map tags
[] = {
234 {"root", XFS_BULK_IREQ_SPECIAL_ROOT
},
243 struct xfs_fd xfd
= XFS_FD_INIT(file
->fd
);
244 struct xfs_bulkstat bulkstat
;
245 unsigned long ver
= 0;
251 while ((c
= getopt(argc
, argv
, "dv:")) != -1) {
258 ver
= strtoull(optarg
, NULL
, 10);
263 if (ver
!= 1 && ver
!= 5) {
264 fprintf(stderr
, "version must be 1 or 5.\n");
269 bulkstat_single_help();
274 ret
= -xfd_prepare_geometry(&xfd
);
276 xfrog_perror(ret
, "xfd_prepare_geometry");
281 set_xfd_flags(&xfd
, ver
);
283 for (i
= optind
; i
< argc
; i
++) {
284 struct single_map
*sm
= tags
;
286 unsigned int flags
= 0;
288 /* Try to look up our tag... */
289 for (sm
= tags
; sm
->tag
; sm
++) {
290 if (!strcmp(argv
[i
], sm
->tag
)) {
292 flags
|= XFS_BULK_IREQ_SPECIAL
;
297 /* ...or else it's an inode number. */
298 if (sm
->tag
== NULL
) {
300 ino
= strtoull(argv
[i
], NULL
, 10);
308 ret
= xfrog_bulkstat_single(&xfd
, ino
, flags
, &bulkstat
);
310 xfrog_perror(ret
, "xfrog_bulkstat_single");
316 _("bulkstat_single: startino=%"PRIu64
" flags=0x%"PRIx32
" ret=%d\n"),
319 dump_bulkstat(&bulkstat
);
327 struct xfs_inumbers
*inumbers
)
329 printf("xi_startino = %"PRIu64
"\n", inumbers
->xi_startino
);
330 printf("\txi_allocmask = 0x%"PRIx64
"\n", inumbers
->xi_allocmask
);
331 printf("\txi_alloccount = %"PRIu8
"\n", inumbers
->xi_alloccount
);
332 printf("\txi_version = %"PRIu8
"\n", inumbers
->xi_version
);
339 "Queries the filesystem for inode group information and prints it.\n"
341 " -a <agno> Only iterate this AG.\n"
342 " -d Print debugging output.\n"
343 " -e <ino> Stop after this inode.\n"
344 " -n <nr> Ask for this many results at once.\n"
345 " -s <ino> Inode to start with.\n"
346 " -v <ver> Use this version of the ioctl (1 or 5).\n"));
354 struct xfs_fd xfd
= XFS_FD_INIT(file
->fd
);
355 struct xfs_inumbers_req
*ireq
;
356 uint64_t startino
= 0;
357 uint64_t endino
= -1ULL;
358 uint32_t batch_size
= 4096;
361 bool has_agno
= false;
367 while ((c
= getopt(argc
, argv
, "a:de:n:s:v:")) != -1) {
370 agno
= cvt_u32(optarg
, 10);
381 endino
= cvt_u64(optarg
, 10);
388 batch_size
= cvt_u32(optarg
, 10);
395 startino
= cvt_u64(optarg
, 10);
402 ver
= cvt_u32(optarg
, 10);
407 if (ver
!= 1 && ver
!= 5) {
408 fprintf(stderr
, "version must be 1 or 5.\n");
417 if (optind
!= argc
) {
422 ret
= -xfd_prepare_geometry(&xfd
);
424 xfrog_perror(ret
, "xfd_prepare_geometry");
429 ireq
= xfrog_inumbers_alloc_req(batch_size
, startino
);
431 perror("alloc inumbersreq");
437 xfrog_inumbers_set_ag(ireq
, agno
);
439 set_xfd_flags(&xfd
, ver
);
441 while ((ret
= xfrog_inumbers(&xfd
, ireq
)) == 0) {
444 _("bulkstat: startino=%"PRIu64
" flags=0x%"PRIx32
" agno=%"PRIu32
" ret=%d icount=%"PRIu32
" ocount=%"PRIu32
"\n"),
451 if (ireq
->hdr
.ocount
== 0)
454 for (i
= 0; i
< ireq
->hdr
.ocount
; i
++) {
455 if (ireq
->inumbers
[i
].xi_startino
> endino
)
457 dump_inumbers(&ireq
->inumbers
[i
]);
461 xfrog_perror(ret
, "xfrog_inumbers");
469 static cmdinfo_t bulkstat_cmd
= {
474 .flags
= CMD_NOMAP_OK
| CMD_FLAG_ONESHOT
,
475 .help
= bulkstat_help
,
478 static cmdinfo_t bulkstat_single_cmd
= {
479 .name
= "bulkstat_single",
480 .cfunc
= bulkstat_single_f
,
483 .flags
= CMD_NOMAP_OK
| CMD_FLAG_ONESHOT
,
484 .help
= bulkstat_single_help
,
487 static cmdinfo_t inumbers_cmd
= {
492 .flags
= CMD_NOMAP_OK
| CMD_FLAG_ONESHOT
,
493 .help
= inumbers_help
,
500 _("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
501 bulkstat_cmd
.oneline
= _("Bulk stat of inodes in a filesystem");
503 bulkstat_single_cmd
.args
= _("[-d] [-v version] inum...");
504 bulkstat_single_cmd
.oneline
= _("Stat one inode in a filesystem");
507 _("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
508 inumbers_cmd
.oneline
= _("Query inode groups in a filesystem");
510 add_command(&bulkstat_cmd
);
511 add_command(&bulkstat_single_cmd
);
512 add_command(&inumbers_cmd
);