From 466646c4f936eb3387b76dcb9a41e7b8cfb98fe2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 18 May 2013 01:47:14 -0500 Subject: [PATCH] Add --lazy option to `wimlib-imagex unmount' This can be used to "fix" problems with testing WIM mounting on operating systems running GNOME. --- doc/imagex-mount.1.in | 9 +++++++-- include/wimlib.h | 3 +++ programs/imagex.c | 7 ++++++- src/mount_image.c | 23 +++++++++++++++++++---- tests/test-imagex-mount | 21 +++++++++++++++------ 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/doc/imagex-mount.1.in b/doc/imagex-mount.1.in index da3e97fb..b1c6fc42 100644 --- a/doc/imagex-mount.1.in +++ b/doc/imagex-mount.1.in @@ -147,8 +147,13 @@ Rebuild the entire WIM rather than appending any new data to the end of it. Rebuilding the WIM is slower, but will save a little bit of space that would otherwise be left as a hole in the WIM. Even more space will be saved if the read-write mount resulted in streams being deleted from the WIM. Also see -\fB@IMAGEX_PROGNAME@ optimize\fR. Has no effect if the mount is read-only or if -\fB--commit\fR was not specified. +.TP +\fB--lazy\fR +Pass the \fB-z\fR option to \fBfusermount\fR, which performs a "lazy" unmount +where the filesystme is detached immediately even if it is still busy. However, +even with this option, \fB@IMAGEX_PROGNAME@ unmount\fR still waits for the +filesystem to become unbusy; \fB--lazy\fR will only stop the unmount from +immediately failing. .SH IMPLEMENTATION DETAILS Since a WIM is an archive and not a filesystem, \fB@IMAGEX_PROGNAME@ mountrw\fR creates a temporary staging directory to contain files that are created or modified. This diff --git a/include/wimlib.h b/include/wimlib.h index 16f4ba9c..906a15c7 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -779,6 +779,9 @@ struct wimlib_capture_config { /** See ::WIMLIB_WRITE_FLAG_RECOMPRESS */ #define WIMLIB_UNMOUNT_FLAG_RECOMPRESS 0x00000008 +/** Do a "lazy" unmount (detach filesystem immediately, even if busy) */ +#define WIMLIB_UNMOUNT_FLAG_LAZY 0x00000010 + /****************************** * WIMLIB_WRITE_FLAG_* ******************************/ diff --git a/programs/imagex.c b/programs/imagex.c index 7dbbc8a4..854be037 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -168,7 +168,7 @@ IMAGEX_PROGNAME" split WIMFILE SPLIT_WIMFILE PART_SIZE_MB [--check]\n" ), [UNMOUNT] = T( -IMAGEX_PROGNAME" unmount DIRECTORY [--commit] [--check] [--rebuild]\n" +IMAGEX_PROGNAME" unmount DIRECTORY [--commit] [--check] [--rebuild] [--lazy]\n" ), [UPDATE] = T( @@ -208,6 +208,7 @@ enum { IMAGEX_FORCE_OPTION, IMAGEX_HARDLINK_OPTION, IMAGEX_HEADER_OPTION, + IMAGEX_LAZY_OPTION, IMAGEX_LOOKUP_TABLE_OPTION, IMAGEX_METADATA_OPTION, IMAGEX_NORPFIX_OPTION, @@ -335,6 +336,7 @@ static const struct option unmount_options[] = { {T("commit"), no_argument, NULL, IMAGEX_COMMIT_OPTION}, {T("check"), no_argument, NULL, IMAGEX_CHECK_OPTION}, {T("rebuild"), no_argument, NULL, IMAGEX_REBUILD_OPTION}, + {T("lazy"), no_argument, NULL, IMAGEX_LAZY_OPTION}, {NULL, 0, NULL, 0}, }; @@ -2888,6 +2890,9 @@ imagex_unmount(int argc, tchar **argv) case IMAGEX_REBUILD_OPTION: unmount_flags |= WIMLIB_UNMOUNT_FLAG_REBUILD; break; + case IMAGEX_LAZY_OPTION: + unmount_flags |= WIMLIB_UNMOUNT_FLAG_LAZY; + break; default: usage(UNMOUNT); return -1; diff --git a/src/mount_image.c b/src/mount_image.c index 3f1c5906..f3e0a427 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -1444,7 +1444,7 @@ message_loop(mqd_t mq, * daemon to finish writing the WIM file. */ static int -execute_fusermount(const char *dir) +execute_fusermount(const char *dir, bool lazy) { pid_t pid; int ret; @@ -1457,7 +1457,15 @@ execute_fusermount(const char *dir) } if (pid == 0) { /* Child */ - execlp("fusermount", "fusermount", "-u", dir, NULL); + char *argv[10]; + char **argp = argv; + *argp++ = "fusermount"; + if (lazy) + *argp++ = "-z"; + *argp++ = "-u"; + *argp++ = (char*)dir; + *argp = NULL; + execvp("fusermount", argv); ERROR_WITH_ERRNO("Failed to execute `fusermount'"); exit(WIMLIB_ERR_FUSERMOUNT); } @@ -1495,7 +1503,14 @@ execute_fusermount(const char *dir) } if (pid == 0) { /* Child */ - execlp("umount", "umount", dir, NULL); + char *argv[10]; + char **argp = argv; + *argp++ = "umount"; + if (lazy) + *argp++ = "-l"; + *argp++ = (char*)dir; + *argp = NULL; + execvp("umount", argv); ERROR_WITH_ERRNO("Failed to execute `umount'"); exit(WIMLIB_ERR_FUSERMOUNT); } @@ -2597,7 +2612,7 @@ wimlib_unmount_image(const char *dir, int unmount_flags, if (ret != 0) goto out_close_message_queues; - ret = execute_fusermount(dir); + ret = execute_fusermount(dir, (unmount_flags & WIMLIB_UNMOUNT_FLAG_LAZY) != 0); if (ret != 0) goto out_close_message_queues; diff --git a/tests/test-imagex-mount b/tests/test-imagex-mount index 13b4e0cd..bbe931ff 100755 --- a/tests/test-imagex-mount +++ b/tests/test-imagex-mount @@ -16,6 +16,15 @@ if [ ! -r /dev/fuse ]; then exit 0 fi +imagex_unmount() { + # Give the --lazy flag to work around a problem testing on Ubuntu and + # other OS's running Gnome, as they have a daemon + # "gvfs-gdu-volume-monitor" that apparently likes to randomly read + # filesystems that get mounted, thereby stopping them from being + # unmounted. + imagex unmount "$@" --lazy +} + cleanup() { fusermount -u $TEST_SUBDIR/tmp &> /dev/null || true fusermount -u $TEST_SUBDIR/tmp.mnt &> /dev/null || true @@ -85,14 +94,14 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do error "Recursive diff of read-only mounted WIM with original directory failed" fi echo "Testing unmount of read-only filesystem" - if ! imagex unmount tmp; then + if ! imagex_unmount tmp; then error "Unmounting read-only WIM failed" fi echo "Testing unmount of read-only filesystem with --commit given" if ! imagex mount dir.wim dir tmp; then error "Failed to re-mount WIM read-only" fi - if ! imagex unmount tmp --commit; then + if ! imagex_unmount tmp --commit; then error "Failed to unmount read-only WIM with --commit flag (should be ignored)" fi rm -rf tmp dir.wim @@ -108,14 +117,14 @@ if ! imagex mountrw dir.wim dir tmp; then error "Failed to mount test WIM read-write" fi echo "Testing unmounting WIM unmodified" -if ! imagex unmount tmp; then +if ! imagex_unmount tmp; then error "Failed to unmount test WIM unmodified" fi echo "Testing unmounting WIM unmodified with --commit and --check" if ! imagex mountrw dir.wim dir tmp; then error "Failed to re-mount test WIM read-write" fi -if ! imagex unmount tmp --commit --check; then +if ! imagex_unmount tmp --commit --check; then error "Failed to unmount read-write mounted WIM with changes commited (no changes made)" fi echo "Testing removing file from mounted WIM" @@ -156,7 +165,7 @@ if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then error "New files in mounted WIM not made correctly" fi echo "Unmounting WIM with changes committed and --check" -if ! imagex unmount tmp --commit --check; then +if ! imagex_unmount tmp --commit --check; then error "Failed to unmount read-write mounted WIM" fi if test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" != "yes"; then @@ -239,7 +248,7 @@ do_test() { # Unmount the WIM, apply it, and diff the original tree with the applied # tree - if ! imagex unmount tmp.mnt --commit; then + if ! imagex_unmount tmp.mnt --commit; then error "Failed to unmount WIM mounted read-write" fi if ! imagex apply test.wim tmp.apply; then -- 2.43.0