Implements a new xfs_io command, named 'inode', which is supposed to be used to query information about inode's existence and its physical size in the filesystem. Supported options: Default: -- Return true(1) or false(0) if any inode greater than 32bits has been found in the filesystem -v -- verbose mode Display the number and the physical size (in bits) of the largest inode in the filesystem [num] -- Return true(1) or false(0) if the inode [num] is in use -n [num] -- Return the next valid inode after [num] No manpage sent because there were changes in the supported options and its descriptions. I'll send the manpage after the options and descriptions are reviewed. - Changelog V3: - Merge all 3 patches from the V2 together in a single patch - Rework of '-n [num]' and 'num' only arguments algorithm - Argument -n now relies on bulkreq.count to check for next inodes, not on bstat.bs_ino anymore. - for loop in ret_lsize or ret_largest case, now relies on count being 0 to break the loop V4: - Refactor inode_f function to reduce its size and easier logic - Implement error handlers for invalid command combination (hopefully all invalid combinations). - use a single xfs_inogrp array for keep track of inodes - Fix missing newline in inode_help() - Rewrite help message in inode_help() - Fix indentation V5: - Reduce the amount of options - remove igrp_rec variable, and use igroup[lastgrp] directly to get information from the last inode groups returned by ioctl Signed-off-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx> --- io/open.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/io/open.c b/io/open.c index ac5a5e0..1e38ea8 100644 --- a/io/open.c +++ b/io/open.c @@ -20,6 +20,7 @@ #include "input.h" #include "init.h" #include "io.h" +#include "libxfs.h" #ifndef __O_TMPFILE #if defined __alpha__ @@ -44,6 +45,7 @@ static cmdinfo_t statfs_cmd; static cmdinfo_t chproj_cmd; static cmdinfo_t lsproj_cmd; static cmdinfo_t extsize_cmd; +static cmdinfo_t inode_cmd; static prid_t prid; static long extsize; @@ -750,6 +752,136 @@ statfs_f( return 0; } +static void +inode_help(void) +{ + printf(_( +"\n" +"Query physical information about the inode" +"\n" +" Default: -- Return true(1) or false(0) if any inode greater than\n" +" 32bits has been found in the filesystem\n" +" -v -- verbose mode\n" +" Display the number and the physical size (in bits)\n" +" of the largest inode in the filesystem\n" +"[num] -- Return true(1) or false(0) if the inode [num] is in use\n" +" -n [num] -- Return the next valid inode after [num]\n" +"\n")); +} + +static int +inode_f( + int argc, + char **argv) +{ + __s32 count = 0; + __s32 lastgrp = 0; + __u64 last = 0; + __u64 lastino = 0; + __u64 userino = 0; + char *p; + int c; + int verbose = 0; + int ret_next = 0; + int cmd = 0; + struct xfs_inogrp igroup[1024]; + struct xfs_fsop_bulkreq bulkreq; + struct xfs_bstat bstat; + + while ((c = getopt(argc, argv, "nv")) != EOF) { + switch (c) { + case 'v': + verbose = 1; + break; + case 'n': + ret_next = 1; + break; + default: + return command_usage(&inode_cmd); + } + } + + if (ret_next && verbose) + return command_usage(&inode_cmd); + + if (optind < argc) { + if (verbose) + return command_usage(&inode_cmd); + + if (ret_next) { + cmd = XFS_IOC_FSBULKSTAT; + } else { + if (argc > 2) + return command_usage(&inode_cmd); + else + cmd = XFS_IOC_FSBULKSTAT_SINGLE; + } + + userino = strtoull(argv[optind], &p, 10); + if ((*p != '\0')) { + printf(_("[num] must be a numeric value\n")); + exitcode = 1; + return 0; + } + + bulkreq.lastip = &userino; + bulkreq.icount = 1; + bulkreq.ubuffer = &bstat; + bulkreq.ocount = &count; + + if (xfsctl(file->name, file->fd, cmd, &bulkreq)) { + if (errno == EINVAL) { + if (!ret_next) + printf("0\n"); + } else { + perror("xfsctl"); + } + exitcode = 1; + return 0; + } + + if (ret_next) { + printf("%llu\n", bstat.bs_ino); + return 0; + } else { + /* Inode number used*/ + printf("1\n"); + return 0; + } + } + + bulkreq.lastip = &last; + bulkreq.icount = 1024; /* User-defined maybe!? */ + bulkreq.ubuffer = &igroup; + bulkreq.ocount = &count; + + for (;;) { + if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, + &bulkreq)) { + perror("XFS_IOC_FSINUMBERS"); + exitcode = 1; + return 0; + } + + if (count == 0) + break; + + lastgrp = count; + } + + lastgrp--; + lastino = igroup[lastgrp].xi_startino + + xfs_highbit64(igroup[lastgrp].xi_allocmask); + + if (verbose) + printf("%llu:%d\n", lastino, + lastino > XFS_MAXINUMBER_32 ? 64 : 32); + else + printf("%d\n", lastino > XFS_MAXINUMBER_32 ? 1 : 0); + + return 0; +} + void open_init(void) { @@ -815,6 +947,16 @@ open_init(void) _("get/set preferred extent size (in bytes) for the open file"); extsize_cmd.help = extsize_help; + inode_cmd.name = "inode"; + inode_cmd.cfunc = inode_f; + inode_cmd.args = _("[-n | -v] [num]"); + inode_cmd.argmin = 0; + inode_cmd.argmax = 2; + inode_cmd.flags = CMD_NOMAP_OK; + inode_cmd.oneline = + _("Query inode number usage in the filesystem"); + inode_cmd.help = inode_help; + add_command(&open_cmd); add_command(&stat_cmd); add_command(&close_cmd); @@ -822,4 +964,5 @@ open_init(void) add_command(&chproj_cmd); add_command(&lsproj_cmd); add_command(&extsize_cmd); + add_command(&inode_cmd); } -- 2.4.3 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs