]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
findmnt: filter filesystems and actions for --poll
authorKarel Zak <kzak@redhat.com>
Wed, 27 Apr 2011 20:39:44 +0000 (22:39 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 27 Apr 2011 20:59:00 +0000 (22:59 +0200)
The patch allows to filter by:

 * actions name:
$ findmnt --poll=umount

 * target, source, fstype, options:
$ findmnt --poll /mnt/test
$ findmnt --poll -O ro
$ findmnt --poll -t ext4

 * --first-only option to wait only for the first matching change:

$ findmnt --poll=umount --first-only /mnt/test

Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/findmnt.8
misc-utils/findmnt.c

index b99e7bc716661aa995b426955a800c51e8c991ee..4f47d09b4ce79ad9bfd2d89bd982ca18709183dc 100644 (file)
@@ -113,10 +113,17 @@ column contains tree formatting if the
 or
 .B \-\-raw
 options are not specified.
-.IP "\fB\-p, \-\-poll\fP"
-Monitor changes in the /proc/self/mountinfo file. The standard columns always
-use the new version of the information from the mountinfo file, except the
-umount action which is based on the original information cached by
+.IP "\fB\-p, \-\-poll[=list]\fP"
+Monitor changes in the /proc/self/mountinfo file. Supported actions are: mount,
+umount, remount and move. More than one action may be specified in a
+comma-separated list. All actions are monitored by default.
+
+The time for which --poll will block could be restricted by \fB\-\-timeout\fP
+or \fB\-\-first-only\fP options.
+
+The standard columns always use the new version of the information from the
+mountinfo file, except the umount action which is based on the original
+information cached by
 .BR findmnt (8) .
 The poll mode allows to use extra columns:
 .RS
@@ -171,8 +178,14 @@ filesystems where the mountpoint directory is /mnt/foo.
 Prints all
 .IR /etc/fstab
 filesystems and converts LABEL= and UUID= tags to the real device names.
-.IP "\fBfindmnt -n --raw --evaluate --output=target LABEL=/boot
+.IP "\fBfindmnt -n --raw --evaluate --output=target LABEL=/boot\fP"
 Prints only the mountpoint where the filesystem with label "/boot" is mounted.
+.IP "\fBfindmnt --poll --target /mnt/foo\fP"
+Monitors mount, umount, remount and move on /mnt/foo.
+.IP "\fBfindmnt --poll=umount --first-only --target /mnt/foo\fP"
+Waits for /mnt/foo umount.
+.IP "\fBfindmnt --poll=remount -t ext3 -O ro\fP"
+Monitors remounts to read-only mode on all ext3 filesystems.
 .SH AUTHORS
 .nf
 Karel Zak <kzak@redhat.com>
index 71a44f0011077b7c95f242a66443fe4753e05e30..4a209698277ebb4638adb03d37b84e82f5ece743 100644 (file)
@@ -102,6 +102,11 @@ int tt_flags = 0;
 int columns[__NCOLUMNS];
 int ncolumns;
 
+/* poll actions (parsed --poll=<list> */
+#define __NACTIONS     4               /* mount, umount, move, remount */
+int actions[__NACTIONS];
+int nactions;
+
 /* libmount cache */
 struct libmnt_cache *cache;
 
@@ -176,6 +181,39 @@ static int is_listall_mode(void)
                !get_match(COL_OPTIONS));
 }
 
+/*
+ * Returns 1 if the @act is in the --poll=<list>
+ */
+static int has_poll_action(int act)
+{
+       int i;
+
+       if (!nactions)
+               return 1;       /* all actions enabled */
+       for (i = 0; i < nactions; i++)
+               if (actions[i] == act)
+                       return 1;
+       return 0;
+}
+
+static int poll_action_name_to_id(const char *name, size_t namesz)
+{
+       int id = -1;
+
+       if (strncasecmp(name, "move", namesz) == 0 && namesz == 4)
+               id = MNT_TABDIFF_MOVE;
+       else if (strncasecmp(name, "mount", namesz) == 0 && namesz == 5)
+               id = MNT_TABDIFF_MOUNT;
+       else if (strncasecmp(name, "umount", namesz) == 0 && namesz == 6)
+               id = MNT_TABDIFF_UMOUNT;
+       else if (strncasecmp(name, "remount", namesz) == 0 && namesz == 7)
+               id = MNT_TABDIFF_REMOUNT;
+       else
+               warnx(_("unknown action: %s"), name);
+
+       return id;
+}
+
 /*
  * findmnt --first-only <devname|TAG=|mountpoint>
  *
@@ -586,6 +624,30 @@ done:
        return rc;
 }
 
+static int poll_match(struct libmnt_fs *fs)
+{
+       int rc = match_func(fs, NULL);
+
+       if (rc == 0 && !(flags & FL_NOSWAPMATCH) &&
+           get_match(COL_SOURCE) && !get_match(COL_TARGET)) {
+               /*
+                * findmnt --poll /foo
+                * The '/foo' source as well as target.
+                */
+               const char *str = get_match(COL_SOURCE);
+
+               set_match(COL_TARGET, str);     /* swap */
+               set_match(COL_SOURCE, NULL);
+
+               rc = match_func(fs, NULL);
+
+               set_match(COL_TARGET, NULL);    /* restore */
+               set_match(COL_SOURCE, str);
+
+       }
+       return rc;
+}
+
 static int poll_table(struct libmnt_table *tb, const char *tabfile,
                  int timeout, struct tt *tt, int direction)
 {
@@ -632,12 +694,12 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile,
        while (1) {
                struct libmnt_table *tmp;
                struct libmnt_fs *old, *new;
-               int change, x;
+               int change, count;
 
-               x = poll(fds, 1, timeout);
-               if (x == 0)
+               count = poll(fds, 1, timeout);
+               if (count == 0)
                        break;  /* timeout */
-               if (x < 0) {
+               if (count < 0) {
                        warn(_("poll() failed"));
                        goto done;
                }
@@ -649,10 +711,16 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile,
                if (rc < 0)
                        goto done;
 
+               count = 0;
                mnt_reset_iter(itr, direction);
                while(mnt_tabdiff_next_change(
                                diff, itr, &old, &new, &change) == 0) {
 
+                       if (!has_poll_action(change))
+                               continue;
+                       if (!poll_match(new ? new : old))
+                               continue;
+                       count++;
                        rc = !add_tabdiff_line(tt, new, old, change);
                        if (rc)
                                goto done;
@@ -660,9 +728,11 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile,
                                break;
                }
 
-               rc = tt_print_table(tt);
-               if (rc)
-                       goto done;
+               if (count) {
+                       rc = tt_print_table(tt);
+                       if (rc)
+                               goto done;
+               }
 
                /* swap tables */
                tmp = tb;
@@ -671,6 +741,9 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile,
 
                tt_remove_lines(tt);
                mnt_reset_table(tb_new);
+
+               if (count && (flags & FL_FIRSTONLY))
+                       break;
        }
 
        rc = 0;
@@ -700,7 +773,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
        " -k, --kernel           search in kernel table of mounted \n"
         "                        filesystems (default)\n\n"
 
-       " -p, --poll             monitor changes in table of mounted filesystems\n"
+       " -p, --poll[=<list>]    monitor changes in table of mounted filesystems\n"
        " -w, --timeout <num>    upper limit in millisecods which --poll will block\n\n"
 
        " -c, --canonicalize     canonicalize printed paths\n"
@@ -771,7 +844,7 @@ int main(int argc, char *argv[])
            { "notruncate",   0, 0, 'u' },
            { "options",      1, 0, 'O' },
            { "output",       1, 0, 'o' },
-           { "poll",         0, 0, 'p' },
+           { "poll",         2, 0, 'p' },
            { "raw",          0, 0, 'r' },
            { "types",        1, 0, 't' },
            { "fsroot",       0, 0, 'v' },
@@ -793,7 +866,7 @@ int main(int argc, char *argv[])
        tt_flags |= TT_FL_TREE;
 
        while ((c = getopt_long(argc, argv,
-                               "acd:ehifo:O:pklmnrst:uvRS:T:w:", longopts, NULL)) != -1) {
+                               "acd:ehifo:O:p::klmnrst:uvRS:T:w:", longopts, NULL)) != -1) {
                switch(c) {
                case 'a':
                        tt_flags |= TT_FL_ASCII;
@@ -834,6 +907,11 @@ int main(int argc, char *argv[])
                        set_match(COL_OPTIONS, optarg);
                        break;
                case 'p':
+                       if (optarg &&
+                           tt_parse_columns_list(optarg, actions, &nactions,
+                                               poll_action_name_to_id))
+                               exit(EXIT_FAILURE);
+
                        flags |= FL_POLL;
                        tt_flags &= ~TT_FL_TREE;
                        break;