]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxcmd: add non-iterating user commands
authorDave Chinner <dchinner@redhat.com>
Thu, 12 Jan 2017 20:12:41 +0000 (14:12 -0600)
committerEric Sandeen <sandeen@redhat.com>
Thu, 12 Jan 2017 20:12:41 +0000 (14:12 -0600)
Right now command iteration is not directly controllable by the
user; it is controlled entirely by the application command flag
setup. Sometimes we don't want commands to iterate but only operate
on the currently selected object.

For example, the stat command iterates:

$ xfs_io -c "open -r foo" -c "open bar" -c "file" -c "stat" foo
 000  foo            (foreign,non-sync,non-direct,read-write)
 001  foo            (foreign,non-sync,non-direct,read-only)
[002] bar            (foreign,non-sync,non-direct,read-write)
fd.path = "foo"
fd.flags = non-sync,non-direct,read-write
stat.ino = 462399
stat.type = regular file
stat.size = 776508
stat.blocks = 1528
fd.path = "foo"
fd.flags = non-sync,non-direct,read-only
stat.ino = 462399
stat.type = regular file
stat.size = 776508
stat.blocks = 1528
fd.path = "bar"
fd.flags = non-sync,non-direct,read-write
stat.ino = 475227
stat.type = regular file
stat.size = 0
stat.blocks = 0
$

To do this, add a function to supply a "non-iterating" user command
that will execute an iterating-capable command as though it
CMD_FLAG_ONESHOT was set. Add a new command line option to xfs_io to
drive it (-C <command>) and connect it all up. Document it in the
xfs_io man page, too.

The result of "-C stat":

$ xfs_io -c "open -r foo" -c "open bar" -c "file" -C "stat" foo
 000  foo            (foreign,non-sync,non-direct,read-write)
 001  foo            (foreign,non-sync,non-direct,read-only)
[002] bar            (foreign,non-sync,non-direct,read-write)
fd.path = "bar"
fd.flags = non-sync,non-direct,read-write
stat.ino = 475227
stat.type = regular file
stat.size = 0
stat.blocks = 0
$

Is that we only see the stat output for the active open file
which is "bar".

[ sandeen: fix arg in command_loop printf ]

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/command.h
io/init.c
libxcmd/command.c
man/man8/xfs_io.8

index 348002cbe3eddca46f9f8d040fdfe353f683ccf6..fb3f5c79b9912e7df9c64c062d7ca460a55d1f12 100644 (file)
@@ -56,6 +56,7 @@ typedef int (*checkfunc_t)(const cmdinfo_t *ci);
 
 extern void            add_command(const cmdinfo_t *ci);
 extern void            add_user_command(char *optarg);
+extern void            add_oneshot_user_command(char *optarg);
 extern void            add_command_iterator(iterfunc_t func);
 extern void            add_check_command(checkfunc_t cf);
 
index 28a7d6005d49b1d5086bcb1a2dc2f531df69c888..61b0d698b8e0ba346bab889fa407e3baf0162d78 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -34,7 +34,7 @@ void
 usage(void)
 {
        fprintf(stderr,
-               _("Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [-c cmd]... file\n"),
+_("Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [[-c|-C] cmd]... file\n"),
                progname);
        exit(1);
 }
@@ -146,7 +146,7 @@ init(
        pagesize = getpagesize();
        gettimeofday(&stopwatch, NULL);
 
-       while ((c = getopt(argc, argv, "ac:dFfim:p:nrRstTVx")) != EOF) {
+       while ((c = getopt(argc, argv, "ac:C:dFfim:p:nrRstTVx")) != EOF) {
                switch (c) {
                case 'a':
                        flags |= IO_APPEND;
@@ -154,6 +154,9 @@ init(
                case 'c':
                        add_user_command(optarg);
                        break;
+               case 'C':
+                       add_oneshot_user_command(optarg);
+                       break;
                case 'd':
                        flags |= IO_DIRECT;
                        break;
index ce434479c15e2ae63009982daeb1e95803e49a97..5803734707814196f172a856c387c1ee82e11536 100644 (file)
@@ -25,8 +25,14 @@ int          ncmds;
 
 static iterfunc_t      iter_func;
 static checkfunc_t     check_func;
-static int             ncmdline;
-static char            **cmdline;
+
+struct cmdline {
+       char    *cmdline;
+       bool    iterate;
+};
+
+static int     ncmdline;
+struct cmdline *cmdline;
 
 static int
 compare(const void *a, const void *b)
@@ -120,12 +126,27 @@ void
 add_user_command(char *optarg)
 {
        ncmdline++;
-       cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
+       cmdline = realloc(cmdline, sizeof(struct cmdline) * (ncmdline));
+       if (!cmdline) {
+               perror("realloc");
+               exit(1);
+       }
+       cmdline[ncmdline-1].cmdline = optarg;
+       cmdline[ncmdline-1].iterate = true;
+
+}
+
+void
+add_oneshot_user_command(char *optarg)
+{
+       ncmdline++;
+       cmdline = realloc(cmdline, sizeof(struct cmdline) * (ncmdline));
        if (!cmdline) {
                perror("realloc");
                exit(1);
        }
-       cmdline[ncmdline-1] = optarg;
+       cmdline[ncmdline-1].cmdline = optarg;
+       cmdline[ncmdline-1].iterate = false;
 }
 
 /*
@@ -212,14 +233,14 @@ command_loop(void)
 
        /* command line mode */
        for (i = 0; !done && i < ncmdline; i++) {
-               input = strdup(cmdline[i]);
+               input = strdup(cmdline[i].cmdline);
                if (!input) {
                        fprintf(stderr,
                                _("cannot strdup command '%s': %s\n"),
-                               cmdline[i], strerror(errno));
+                               cmdline[i].cmdline, strerror(errno));
                        exit(1);
                }
-               done = process_input(input, true);
+               done = process_input(input, cmdline[i].iterate);
        }
        free(cmdline);
        return;
index db7fa904f16e495e590ec6dc3680ad33245846e3..2c3ea9d4f5b03e3d4662211a627e8c44ba3fb361 100644 (file)
@@ -9,10 +9,13 @@ xfs_io \- debug the I/O path of an XFS filesystem
 .B \-c
 .I cmd
 ] ... [
+.B \-C
+.I cmd
+] ... [
 .B \-p
 .I prog
 ]
-.I file
+.I [ file ]
 .br
 .B xfs_io \-V
 .SH DESCRIPTION
@@ -25,14 +28,39 @@ These code paths include not only the obvious read/write/mmap interfaces
 for manipulating files, but also cover all of the XFS extensions (such
 as space preallocation, additional inode flags, etc).
 .SH OPTIONS
+.B xfs_io
+commands may be run interactively (the default) or as arguments on the
+command line.
+Interactive mode always runs commands on the current open file, whilst commands
+run from the command line may be repeated on all open files rather than just the current
+open file.
+In general, open file iteration will occur for commands that operate on file
+content or state. In contrast, commands that operate on filesystem or
+system-wide state will only be run on the current file regardless of how many
+files are currently open.
+Multiple arguments may be given on the command line and they are run in the
+sequence given. The program exits one all commands have
+been run.
 .TP 1.0i
 .BI \-c " cmd"
-.B xfs_io
-commands may be run interactively (the default) or as arguments on
-the command line. Multiple
+Run the specified command on all currently open files.
+To maintain compatibility with historical usage, commands that can not be run on
+all open files will still be run but only execute once on the current open file.
+Multiple
+.B \-c
+arguments may be given and may be interleaved on the command line in any order
+with
+.B \-C
+commands.
+.TP
+.BI \-C " cmd"
+Run the specified command only on the current open file. 
+Multiple
+.B \-C
+arguments may be given and may be interleaved on the command line in any order
+with
 .B \-c
-arguments may be given. The commands are run in the sequence given,
-then the program exits.
+commands.
 .TP
 .BI \-p " prog"
 Set the program name for prompts and some error messages,