Add --lazy option to `wimlib-imagex unmount'
authorEric Biggers <ebiggers3@gmail.com>
Sat, 18 May 2013 06:47:14 +0000 (01:47 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sat, 18 May 2013 06:47:14 +0000 (01:47 -0500)
This can be used to "fix" problems with testing WIM mounting on operating
systems running GNOME.

doc/imagex-mount.1.in
include/wimlib.h
programs/imagex.c
src/mount_image.c
tests/test-imagex-mount

index da3e97f..b1c6fc4 100644 (file)
@@ -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
index 16f4ba9..906a15c 100644 (file)
@@ -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_*
  ******************************/
index 7dbbc8a..854be03 100644 (file)
@@ -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;
index 3f1c590..f3e0a42 100644 (file)
@@ -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;
 
index 13b4e0c..bbe931f 100755 (executable)
@@ -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