* [PATCH] umount: add -R, --recursive option
@ 2012-11-07 18:02 Dave Reisner
2012-11-13 15:53 ` Karel Zak
0 siblings, 1 reply; 2+ messages in thread
From: Dave Reisner @ 2012-11-07 18:02 UTC (permalink / raw)
To: util-linux; +Cc: Lukas Jirkovsky, Dave Reisner
This allows unmounting of an entire tree of filesystems, which might be
of particular interest for a shutdown initramfs.
Signed-off-by: Dave Reisner <dreisner@archlinux.org>
---
sys-utils/umount.8 | 4 +++
sys-utils/umount.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/sys-utils/umount.8 b/sys-utils/umount.8
index bdd10a5..b8d4358 100644
--- a/sys-utils/umount.8
+++ b/sys-utils/umount.8
@@ -109,6 +109,10 @@ Each option can be prefixed with
.B no
to specify options for which no action should be taken.
.TP
+\fB\-R\fR, \fB\-\-recursive\fR
+Recursively unmount each directory specified. Recursion for each directory will
+stop if any unmount operation in the chain fails for any reason.
+.TP
\fB\-r\fR, \fB\-\-read\-only\fR
In case unmounting fails, try to remount read-only.
.TP
diff --git a/sys-utils/umount.c b/sys-utils/umount.c
index 38a2fc8..d107a49 100644
--- a/sys-utils/umount.c
+++ b/sys-utils/umount.c
@@ -88,6 +88,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
" -l, --lazy detach the filesystem now, and cleanup all later\n"));
fprintf(out, _(
" -O, --test-opts <list> limit the set of filesystems (use with -a)\n"
+ " -R, --recursive recursively unmount a target with all its children\n"
" -r, --read-only In case unmounting fails, try to remount read-only\n"
" -t, --types <list> limit the set of filesystem types\n"
" -v, --verbose say what is being done\n"));
@@ -300,9 +301,71 @@ static int umount_one(struct libmnt_context *cxt, const char *spec)
return rc;
}
+static int umount_do_recurse(struct libmnt_context *cxt,
+ struct libmnt_table *mountinfo, struct libmnt_fs *parent)
+{
+ int rc;
+ struct libmnt_fs *child;
+ const char *target = mnt_fs_get_target(parent);
+ struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
+
+ if (itr == NULL)
+ err(MOUNT_EX_SYSERR, _("libmount iterator allocation failed"));
+
+ for (;;) {
+ rc = mnt_table_next_child_fs(mountinfo, itr, parent, &child);
+ if (rc == -1)
+ warn(_("failed to get child fs of %s"), target);
+
+ if (rc != 0)
+ break;
+
+ rc = umount_do_recurse(cxt, mountinfo, child);
+ if (rc != 0)
+ break;
+ }
+
+ /* stop on any hard failure */
+ if (rc != -1 && rc != 32)
+ rc = umount_one(cxt, target);
+
+ mnt_free_iter(itr);
+
+ return rc;
+}
+
+static int umount_recursive(struct libmnt_context *cxt, const char *spec)
+{
+ struct libmnt_table *mountinfo;
+ struct libmnt_fs *fs;
+ int rc = 32; /* ENOENT */
+
+ mountinfo = mnt_new_table();
+ if (mountinfo == NULL)
+ err(MOUNT_EX_SYSERR, _("libmount table allocation failed"));
+
+ if (mnt_table_parse_mtab(mountinfo, "/proc/self/mountifo") < 0) {
+ warn("failed to parse /proc/self/mountifo");
+ goto finish;
+ }
+
+ fs = mnt_table_find_target(mountinfo, spec, MNT_ITER_BACKWARD);
+ if (fs)
+ rc = umount_do_recurse(cxt, mountinfo, fs);
+ else
+ warnx(access(spec, F_OK) == 0 ?
+ _("%s: not mounted") :
+ _("%s: not found"), spec);
+
+finish:
+ mnt_free_table(mountinfo);
+
+ return rc;
+}
+
int main(int argc, char **argv)
{
- int c, rc = 0, all = 0;
+ int c, rc = 0, all = 0, recursive = 0;
struct libmnt_context *cxt;
char *types = NULL;
@@ -321,6 +384,7 @@ int main(int argc, char **argv)
{ "no-canonicalize", 0, 0, 'c' },
{ "no-mtab", 0, 0, 'n' },
{ "read-only", 0, 0, 'r' },
+ { "recursive", 0, 0, 'R' },
{ "test-opts", 1, 0, 'O' },
{ "types", 1, 0, 't' },
{ "verbose", 0, 0, 'v' },
@@ -341,7 +405,7 @@ int main(int argc, char **argv)
mnt_context_set_tables_errcb(cxt, table_parser_errcb);
- while ((c = getopt_long(argc, argv, "acdfhilnrO:t:vV",
+ while ((c = getopt_long(argc, argv, "acdfhilnRrO:t:vV",
longopts, NULL)) != -1) {
@@ -380,6 +444,9 @@ int main(int argc, char **argv)
case 'r':
mnt_context_enable_rdonly_umount(cxt, TRUE);
break;
+ case 'R':
+ recursive = TRUE;
+ break;
case 'O':
if (mnt_context_set_options_pattern(cxt, optarg))
err(MOUNT_EX_SYSERR, _("failed to set options pattern"));
@@ -412,8 +479,14 @@ int main(int argc, char **argv)
} else if (argc < 1) {
usage(stderr);
- } else while (argc--)
- rc += umount_one(cxt, *argv++);
+ } else if (recursive) {
+ while (argc--)
+ rc += umount_recursive(cxt, *argv++);
+
+ } else {
+ while (argc--)
+ rc += umount_one(cxt, *argv++);
+ }
mnt_free_context(cxt);
return rc;
--
1.8.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] umount: add -R, --recursive option
2012-11-07 18:02 [PATCH] umount: add -R, --recursive option Dave Reisner
@ 2012-11-13 15:53 ` Karel Zak
0 siblings, 0 replies; 2+ messages in thread
From: Karel Zak @ 2012-11-13 15:53 UTC (permalink / raw)
To: Dave Reisner; +Cc: util-linux, Lukas Jirkovsky
On Wed, Nov 07, 2012 at 01:02:28PM -0500, Dave Reisner wrote:
> sys-utils/umount.8 | 4 +++
> sys-utils/umount.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 81 insertions(+), 4 deletions(-)
Applied (with some small changes), thanks!
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-11-13 15:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-07 18:02 [PATCH] umount: add -R, --recursive option Dave Reisner
2012-11-13 15:53 ` Karel Zak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).