From: Karel Zak Date: Wed, 27 Apr 2011 20:39:44 +0000 (+0200) Subject: findmnt: filter filesystems and actions for --poll X-Git-Tag: v2.20-rc1~312 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=582a5006d4ccac6131ad9e3eb3f391f4904bf4e3;p=thirdparty%2Futil-linux.git findmnt: filter filesystems and actions for --poll 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 --- diff --git a/misc-utils/findmnt.8 b/misc-utils/findmnt.8 index b99e7bc716..4f47d09b4c 100644 --- a/misc-utils/findmnt.8 +++ b/misc-utils/findmnt.8 @@ -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 diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index 71a44f0011..4a20969827 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -102,6 +102,11 @@ int tt_flags = 0; int columns[__NCOLUMNS]; int ncolumns; +/* poll actions (parsed --poll= */ +#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= + */ +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 * @@ -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[=] monitor changes in table of mounted filesystems\n" " -w, --timeout 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;