]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: add a bulkstat command
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 30 Sep 2019 20:17:02 +0000 (16:17 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Mon, 30 Sep 2019 20:17:02 +0000 (16:17 -0400)
Add a bulkstat command to xfs_io so that we can test our new xfrog code.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
io/Makefile
io/bulkstat.c [new file with mode: 0644]
io/init.c
io/io.h
libfrog/bulkstat.c
libfrog/bulkstat.h
man/man8/xfs_io.8

index 484e2b5af8164d78d235f7f239d1d27da6a63233..1112605e115ee993915a0de8c196109f70897eb1 100644 (file)
@@ -9,10 +9,11 @@ LTCOMMAND = xfs_io
 LSRCFILES = xfs_bmap.sh xfs_freeze.sh xfs_mkfile.sh
 HFILES = init.h io.h
 CFILES = init.c \
-       attr.c bmap.c crc32cselftest.c cowextsize.c encrypt.c file.c freeze.c \
-       fsync.c getrusage.c imap.c inject.c label.c link.c mmap.c open.c \
-       parent.c pread.c prealloc.c pwrite.c reflink.c resblks.c scrub.c \
-       seek.c shutdown.c stat.c swapext.c sync.c truncate.c utimes.c
+       attr.c bmap.c bulkstat.c crc32cselftest.c cowextsize.c encrypt.c \
+       file.c freeze.c fsync.c getrusage.c imap.c inject.c label.c link.c \
+       mmap.c open.c parent.c pread.c prealloc.c pwrite.c reflink.c \
+       resblks.c scrub.c seek.c shutdown.c stat.c swapext.c sync.c \
+       truncate.c utimes.c
 
 LLDLIBS = $(LIBXCMD) $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD)
 LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE) $(LIBFROG)
diff --git a/io/bulkstat.c b/io/bulkstat.c
new file mode 100644 (file)
index 0000000..ab84468
--- /dev/null
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "xfs.h"
+#include "platform_defs.h"
+#include "command.h"
+#include "init.h"
+#include "libfrog/fsgeom.h"
+#include "libfrog/bulkstat.h"
+#include "libfrog/paths.h"
+#include "io.h"
+#include "input.h"
+
+static void
+dump_bulkstat_time(
+       const char              *tag,
+       uint64_t                sec,
+       uint32_t                nsec)
+{
+       printf("\t%s = %"PRIu64".%"PRIu32"\n", tag, sec, nsec);
+}
+
+static void
+dump_bulkstat(
+       struct xfs_bulkstat     *bstat)
+{
+       printf("bs_ino = %"PRIu64"\n", bstat->bs_ino);
+       printf("\tbs_size = %"PRIu64"\n", bstat->bs_size);
+
+       printf("\tbs_blocks = %"PRIu64"\n", bstat->bs_blocks);
+       printf("\tbs_xflags = 0x%"PRIx64"\n", bstat->bs_xflags);
+
+       dump_bulkstat_time("bs_atime", bstat->bs_atime, bstat->bs_atime_nsec);
+       dump_bulkstat_time("bs_ctime", bstat->bs_ctime, bstat->bs_ctime_nsec);
+       dump_bulkstat_time("bs_mtime", bstat->bs_mtime, bstat->bs_mtime_nsec);
+       dump_bulkstat_time("bs_btime", bstat->bs_btime, bstat->bs_btime_nsec);
+
+       printf("\tbs_gen = 0x%"PRIx32"\n", bstat->bs_gen);
+       printf("\tbs_uid = %"PRIu32"\n", bstat->bs_uid);
+       printf("\tbs_gid = %"PRIu32"\n", bstat->bs_gid);
+       printf("\tbs_projectid = %"PRIu32"\n", bstat->bs_projectid);
+
+       printf("\tbs_blksize = %"PRIu32"\n", bstat->bs_blksize);
+       printf("\tbs_rdev = %"PRIu32"\n", bstat->bs_rdev);
+       printf("\tbs_cowextsize_blks = %"PRIu32"\n", bstat->bs_cowextsize_blks);
+       printf("\tbs_extsize_blks = %"PRIu32"\n", bstat->bs_extsize_blks);
+
+       printf("\tbs_nlink = %"PRIu32"\n", bstat->bs_nlink);
+       printf("\tbs_extents = %"PRIu32"\n", bstat->bs_extents);
+       printf("\tbs_aextents = %"PRIu32"\n", bstat->bs_aextents);
+       printf("\tbs_version = %"PRIu16"\n", bstat->bs_version);
+       printf("\tbs_forkoff = %"PRIu16"\n", bstat->bs_forkoff);
+
+       printf("\tbs_sick = 0x%"PRIx16"\n", bstat->bs_sick);
+       printf("\tbs_checked = 0x%"PRIx16"\n", bstat->bs_checked);
+       printf("\tbs_mode = 0%"PRIo16"\n", bstat->bs_mode);
+};
+
+static void
+bulkstat_help(void)
+{
+       printf(_(
+"Bulk-queries the filesystem for inode stat information and prints it.\n"
+"\n"
+"   -a <agno>  Only iterate this AG.\n"
+"   -d         Print debugging output.\n"
+"   -e <ino>   Stop after this inode.\n"
+"   -n <nr>    Ask for this many results at once.\n"
+"   -s <ino>   Inode to start with.\n"
+"   -v <ver>   Use this version of the ioctl (1 or 5).\n"));
+}
+
+static void
+set_xfd_flags(
+       struct xfs_fd   *xfd,
+       uint32_t        ver)
+{
+       switch (ver) {
+       case 1:
+               xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V1;
+               break;
+       case 5:
+               xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V5;
+               break;
+       default:
+               break;
+       }
+}
+
+static int
+bulkstat_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct xfs_fd           xfd = XFS_FD_INIT(file->fd);
+       struct xfs_bulkstat_req *breq;
+       uint64_t                startino = 0;
+       uint64_t                endino = -1ULL;
+       uint32_t                batch_size = 4096;
+       uint32_t                agno = 0;
+       uint32_t                ver = 0;
+       bool                    has_agno = false;
+       bool                    debug = false;
+       unsigned int            i;
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "a:de:n:s:v:")) != -1) {
+               switch (c) {
+               case 'a':
+                       agno = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       has_agno = true;
+                       break;
+               case 'd':
+                       debug = true;
+                       break;
+               case 'e':
+                       endino = cvt_u64(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 'n':
+                       batch_size = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 's':
+                       startino = cvt_u64(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 'v':
+                       ver = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       if (ver != 1 && ver != 5) {
+                               fprintf(stderr, "version must be 1 or 5.\n");
+                               return 1;
+                       }
+                       break;
+               default:
+                       bulkstat_help();
+                       return 0;
+               }
+       }
+       if (optind != argc) {
+               bulkstat_help();
+               return 0;
+       }
+
+       ret = xfd_prepare_geometry(&xfd);
+       if (ret) {
+               errno = ret;
+               perror("xfd_prepare_geometry");
+               exitcode = 1;
+               return 0;
+       }
+
+       breq = xfrog_bulkstat_alloc_req(batch_size, startino);
+       if (!breq) {
+               perror("alloc bulkreq");
+               exitcode = 1;
+               return 0;
+       }
+
+       if (has_agno)
+               xfrog_bulkstat_set_ag(breq, agno);
+
+       set_xfd_flags(&xfd, ver);
+
+       while ((ret = xfrog_bulkstat(&xfd, breq)) == 0) {
+               if (debug)
+                       printf(
+_("bulkstat: startino=%lld flags=0x%x agno=%u ret=%d icount=%u ocount=%u\n"),
+                               (long long)breq->hdr.ino,
+                               (unsigned int)breq->hdr.flags,
+                               (unsigned int)breq->hdr.agno,
+                               ret,
+                               (unsigned int)breq->hdr.icount,
+                               (unsigned int)breq->hdr.ocount);
+               if (breq->hdr.ocount == 0)
+                       break;
+
+               for (i = 0; i < breq->hdr.ocount; i++) {
+                       if (breq->bulkstat[i].bs_ino > endino)
+                               break;
+                       dump_bulkstat(&breq->bulkstat[i]);
+               }
+       }
+       if (ret) {
+               errno = ret;
+               perror("xfrog_bulkstat");
+               exitcode = 1;
+       }
+
+       free(breq);
+       return 0;
+}
+
+static void
+bulkstat_single_help(void)
+{
+       printf(_(
+"Queries the filesystem for a single inode's stat information and prints it.\n"
+"If a given inode is not allocated, information about the next allocated \n"
+"inode will be printed instead.\n"
+"\n"
+"   -v (ver)  Use this version of the ioctl (1 or 5).\n"
+"   -d        Print debugging information.\n"
+"\n"
+"Pass in inode numbers or a special inode name:\n"
+"    root     Root directory.\n"));
+}
+
+struct single_map {
+       const char              *tag;
+       uint64_t                code;
+};
+
+struct single_map tags[] = {
+       {"root", XFS_BULK_IREQ_SPECIAL_ROOT},
+       {NULL, 0},
+};
+
+static int
+bulkstat_single_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct xfs_fd           xfd = XFS_FD_INIT(file->fd);
+       struct xfs_bulkstat     bulkstat;
+       unsigned long           ver = 0;
+       unsigned int            i;
+       bool                    debug = false;
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "dv:")) != -1) {
+               switch (c) {
+               case 'd':
+                       debug = true;
+                       break;
+               case 'v':
+                       errno = 0;
+                       ver = strtoull(optarg, NULL, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       if (ver != 1 && ver != 5) {
+                               fprintf(stderr, "version must be 1 or 5.\n");
+                               return 1;
+                       }
+                       break;
+               default:
+                       bulkstat_single_help();
+                       return 0;
+               }
+       }
+
+       ret = xfd_prepare_geometry(&xfd);
+       if (ret) {
+               errno = ret;
+               perror("xfd_prepare_geometry");
+               exitcode = 1;
+               return 0;
+       }
+
+       set_xfd_flags(&xfd, ver);
+
+       for (i = optind; i < argc; i++) {
+               struct single_map       *sm = tags;
+               uint64_t                ino;
+               unsigned int            flags = 0;
+
+               /* Try to look up our tag... */
+               for (sm = tags; sm->tag; sm++) {
+                       if (!strcmp(argv[i], sm->tag)) {
+                               ino = sm->code;
+                               flags |= XFS_BULK_IREQ_SPECIAL;
+                               break;
+                       }
+               }
+
+               /* ...or else it's an inode number. */
+               if (sm->tag == NULL) {
+                       errno = 0;
+                       ino = strtoull(argv[i], NULL, 10);
+                       if (errno) {
+                               perror(argv[i]);
+                               exitcode = 1;
+                               return 0;
+                       }
+               }
+
+               ret = xfrog_bulkstat_single(&xfd, ino, flags, &bulkstat);
+               if (ret) {
+                       errno = ret;
+                       perror("xfrog_bulkstat_single");
+                       continue;
+               }
+
+               if (debug)
+                       printf(
+_("bulkstat_single: startino=%"PRIu64" flags=0x%"PRIx32" ret=%d\n"),
+                               ino, flags, ret);
+
+               dump_bulkstat(&bulkstat);
+       }
+
+       return 0;
+}
+
+static void
+dump_inumbers(
+       struct xfs_inumbers     *inumbers)
+{
+       printf("xi_startino = %"PRIu64"\n", inumbers->xi_startino);
+       printf("\txi_allocmask = 0x%"PRIx64"\n", inumbers->xi_allocmask);
+       printf("\txi_alloccount = %"PRIu8"\n", inumbers->xi_alloccount);
+       printf("\txi_version = %"PRIu8"\n", inumbers->xi_version);
+}
+
+static void
+inumbers_help(void)
+{
+       printf(_(
+"Queries the filesystem for inode group information and prints it.\n"
+"\n"
+"   -a <agno>  Only iterate this AG.\n"
+"   -d         Print debugging output.\n"
+"   -e <ino>   Stop after this inode.\n"
+"   -n <nr>    Ask for this many results at once.\n"
+"   -s <ino>   Inode to start with.\n"
+"   -v <ver>   Use this version of the ioctl (1 or 5).\n"));
+}
+
+static int
+inumbers_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct xfs_fd           xfd = XFS_FD_INIT(file->fd);
+       struct xfs_inumbers_req *ireq;
+       uint64_t                startino = 0;
+       uint64_t                endino = -1ULL;
+       uint32_t                batch_size = 4096;
+       uint32_t                agno = 0;
+       uint32_t                ver = 0;
+       bool                    has_agno = false;
+       bool                    debug = false;
+       unsigned int            i;
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "a:de:n:s:v:")) != -1) {
+               switch (c) {
+               case 'a':
+                       agno = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       has_agno = true;
+                       break;
+               case 'd':
+                       debug = true;
+                       break;
+               case 'e':
+                       endino = cvt_u64(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 'n':
+                       batch_size = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 's':
+                       startino = cvt_u64(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
+               case 'v':
+                       ver = cvt_u32(optarg, 10);
+                       if (errno) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       if (ver != 1 && ver != 5) {
+                               fprintf(stderr, "version must be 1 or 5.\n");
+                               return 1;
+                       }
+                       break;
+               default:
+                       bulkstat_help();
+                       return 0;
+               }
+       }
+       if (optind != argc) {
+               bulkstat_help();
+               return 0;
+       }
+
+       ret = xfd_prepare_geometry(&xfd);
+       if (ret) {
+               errno = ret;
+               perror("xfd_prepare_geometry");
+               exitcode = 1;
+               return 0;
+       }
+
+       ireq = xfrog_inumbers_alloc_req(batch_size, startino);
+       if (!ireq) {
+               perror("alloc inumbersreq");
+               exitcode = 1;
+               return 0;
+       }
+
+       if (has_agno)
+               xfrog_inumbers_set_ag(ireq, agno);
+
+       set_xfd_flags(&xfd, ver);
+
+       while ((ret = xfrog_inumbers(&xfd, ireq)) == 0) {
+               if (debug)
+                       printf(
+_("bulkstat: startino=%"PRIu64" flags=0x%"PRIx32" agno=%"PRIu32" ret=%d icount=%"PRIu32" ocount=%"PRIu32"\n"),
+                               ireq->hdr.ino,
+                               ireq->hdr.flags,
+                               ireq->hdr.agno,
+                               ret,
+                               ireq->hdr.icount,
+                               ireq->hdr.ocount);
+               if (ireq->hdr.ocount == 0)
+                       break;
+
+               for (i = 0; i < ireq->hdr.ocount; i++) {
+                       if (ireq->inumbers[i].xi_startino > endino)
+                               break;
+                       dump_inumbers(&ireq->inumbers[i]);
+               }
+       }
+       if (ret) {
+               errno = ret;
+               perror("xfrog_inumbers");
+               exitcode = 1;
+       }
+
+       free(ireq);
+       return 0;
+}
+
+static cmdinfo_t       bulkstat_cmd = {
+       .name = "bulkstat",
+       .cfunc = bulkstat_f,
+       .argmin = 0,
+       .argmax = -1,
+       .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
+       .help = bulkstat_help,
+};
+
+static cmdinfo_t       bulkstat_single_cmd = {
+       .name = "bulkstat_single",
+       .cfunc = bulkstat_single_f,
+       .argmin = 1,
+       .argmax = -1,
+       .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
+       .help = bulkstat_single_help,
+};
+
+static cmdinfo_t       inumbers_cmd = {
+       .name = "inumbers",
+       .cfunc = inumbers_f,
+       .argmin = 0,
+       .argmax = -1,
+       .flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT,
+       .help = inumbers_help,
+};
+
+void
+bulkstat_init(void)
+{
+       bulkstat_cmd.args =
+_("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
+       bulkstat_cmd.oneline = _("Bulk stat of inodes in a filesystem");
+
+       bulkstat_single_cmd.args = _("[-d] [-v version] inum...");
+       bulkstat_single_cmd.oneline = _("Stat one inode in a filesystem");
+
+       inumbers_cmd.args =
+_("[-a agno] [-d] [-e endino] [-n batchsize] [-s startino] [-v version]");
+       inumbers_cmd.oneline = _("Query inode groups in a filesystem");
+
+       add_command(&bulkstat_cmd);
+       add_command(&bulkstat_single_cmd);
+       add_command(&inumbers_cmd);
+}
index 7025aea5f77b227882b50e832eac8d4f3402028b..033ed67d455f11bd1a8143657914bafbd6a38809 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -46,6 +46,7 @@ init_commands(void)
 {
        attr_init();
        bmap_init();
+       bulkstat_init();
        copy_range_init();
        cowextsize_init();
        encrypt_init();
diff --git a/io/io.h b/io/io.h
index 00dff2b700ee6f197211ab618a0b541c48207982..49db902fc44fea6c22dc60c05d33e9bf62b03890 100644 (file)
--- a/io/io.h
+++ b/io/io.h
@@ -183,3 +183,4 @@ extern void         log_writes_init(void);
 extern void            scrub_init(void);
 extern void            repair_init(void);
 extern void            crc32cselftest_init(void);
+extern void            bulkstat_init(void);
index 85594e5eb69f0136ec8aa4894bbec80f942394a4..538b5197039a122ad2b4218427b4e95c03dd9dd5 100644 (file)
@@ -435,6 +435,16 @@ xfrog_bulkstat_alloc_req(
        return breq;
 }
 
+/* Set a bulkstat cursor to iterate only a particular AG. */
+void
+xfrog_bulkstat_set_ag(
+       struct xfs_bulkstat_req *req,
+       uint32_t                agno)
+{
+       req->hdr.agno = agno;
+       req->hdr.flags |= XFS_BULK_IREQ_AGNO;
+}
+
 /* Convert a inumbers data from v5 format to v1 format. */
 void
 xfrog_inumbers_v5_to_v1(
@@ -562,3 +572,13 @@ xfrog_inumbers_alloc_req(
 
        return ireq;
 }
+
+/* Set an inumbers cursor to iterate only a particular AG. */
+void
+xfrog_inumbers_set_ag(
+       struct xfs_inumbers_req *req,
+       uint32_t                agno)
+{
+       req->hdr.agno = agno;
+       req->hdr.flags |= XFS_BULK_IREQ_AGNO;
+}
index a085da3d373a4c55340962dc7ad86b5e59a2ae76..133a99b85bfcd8d27df03a7cedde8d77bb85f670 100644 (file)
@@ -19,11 +19,14 @@ int xfrog_bulkstat_v5_to_v1(struct xfs_fd *xfd, struct xfs_bstat *bs1,
 void xfrog_bulkstat_v1_to_v5(struct xfs_fd *xfd, struct xfs_bulkstat *bstat,
                const struct xfs_bstat *bs1);
 
+void xfrog_bulkstat_set_ag(struct xfs_bulkstat_req *req, uint32_t agno);
+
 struct xfs_inogrp;
 int xfrog_inumbers(struct xfs_fd *xfd, struct xfs_inumbers_req *req);
 
 struct xfs_inumbers_req *xfrog_inumbers_alloc_req(uint32_t nr,
                uint64_t startino);
+void xfrog_inumbers_set_ag(struct xfs_inumbers_req *req, uint32_t agno);
 void xfrog_inumbers_v5_to_v1(struct xfs_inogrp *ig1,
                const struct xfs_inumbers *ig);
 void xfrog_inumbers_v1_to_v5(struct xfs_inumbers *ig,
index 9d70c159c22705a767746cf0c2f03d111e0d6dac..c69b295d70c852864c291b895452f33d42c2fd26 100644 (file)
@@ -1052,6 +1052,57 @@ for the current memory mapping.
 
 .SH FILESYSTEM COMMANDS
 .TP
+.BI "bulkstat [ \-a " agno " ] [ \-d ] [ \-e " endino " ] [ \-n " batchsize " ] [ \-s " startino " ] [ \-v " version" ]
+Display raw stat information about a bunch of inodes in an XFS filesystem.
+Options are as follows:
+.RS 1.0i
+.PD 0
+.TP
+.BI \-a " agno"
+Display only results from the given allocation group.
+If not specified, all results returned will be displayed.
+.TP
+.BI \-d
+Print debugging information about call results.
+.TP
+.BI \-e " endino"
+Stop displaying records when this inode number is reached.
+Defaults to stopping when the system call stops returning results.
+.TP
+.BI \-n " batchsize"
+Retrieve at most this many records per call.
+Defaults to 4,096.
+.TP
+.BI \-s " startino"
+Display inode allocation records starting with this inode.
+Defaults to the first inode in the filesystem.
+If the given inode is not allocated, results will begin with the next allocated
+inode in the filesystem.
+.TP
+.BI \-v " version"
+Use a particular version of the kernel interface.
+Currently supported versions are 1 and 5.
+.RE
+.PD
+.TP
+.BI "bulkstat_single [ \-d ] [ \-v " version " ] [ " inum... " | " special... " ]
+Display raw stat information about individual inodes in an XFS filesystem.
+The
+.B \-d
+and
+.B \-v
+options are the same as the
+.B bulkstat
+command.
+Arguments must be inode numbers or any of the special values:
+.RS 1.0i
+.PD 0
+.TP
+.B root
+Display information about the root directory inode.
+.RE
+.PD
+.TP
 .B freeze
 Suspend all write I/O requests to the filesystem of the current file.
 Only available in expert mode and requires privileges.
@@ -1123,6 +1174,40 @@ was specified on the command line, the maximum possible inode number in
 the system will be printed along with its size.
 .PD
 .TP
+.BI "inumbers [ \-a " agno " ] [ \-d ] [ \-e " endino " ] [ \-n " batchsize " ] [ \-s " startino " ] [ \-v " version " ]
+Prints allocation information about groups of inodes in an XFS filesystem.
+Callers can use this information to figure out which inodes are allocated.
+Options are as follows:
+.RS 1.0i
+.PD 0
+.TP
+.BI \-a " agno"
+Display only results from the given allocation group.
+If not specified, all results returned will be displayed.
+.TP
+.BI \-d
+Print debugging information about call results.
+.TP
+.BI \-e " endino"
+Stop displaying records when this inode number is reached.
+Defaults to stopping when the system call stops returning results.
+.TP
+.BI \-n " batchsize"
+Retrieve at most this many records per call.
+Defaults to 4,096.
+.TP
+.BI \-s " startino"
+Display inode allocation records starting with this inode.
+Defaults to the first inode in the filesystem.
+If the given inode is not allocated, results will begin with the next allocated
+inode in the filesystem.
+.TP
+.BI \-v " version"
+Use a particular version of the kernel interface.
+Currently supported versions are 1 and 5.
+.RE
+.PD
+.TP
 .BI "scrub " type " [ " agnumber " | " "ino" " " "gen" " ]"
 Scrub internal XFS filesystem metadata.  The
 .BI type