umount: always use umount2 syscall with specified flags
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 1 Oct 2015 16:50:06 +0000 (18:50 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 1 Oct 2015 16:50:06 +0000 (18:50 +0200)
Make umount -f more compatible with util-linux 2.22.2.

Before:
  * 'umount -f': calls umount syscall,
        if it fails calls umount2 with 'MNT_FORCE'
  * 'mount -f -l': calls umount syscall,
        if it fails calls umount2 with 'MNT_LAZY'. 'MNT_FORCE' dropped
After:
  * 'umount -f': calls umount2 syscall with 'MNT_FORCE'
  * 'mount -f -l': calls umount2 syscall with 'MNT_LAZY' and 'MNT_FORCE'

function                                             old     new   delta
umount                                                45       -     -45
umount_main                                          610     555     -55

Signed-off-by: Anton Bondarenko <anton.bondarenko@axis.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
util-linux/umount.c

index 4c2e8821e6adf5d806491c4f47af32b0e23c9fb5..c6c7441b86706060ccdcf4022fb21485ddb69d80 100644 (file)
@@ -81,8 +81,13 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
        argv += optind;
 
        // MNT_FORCE and MNT_DETACH (from linux/fs.h) must match
-       // OPT_FORCE and OPT_LAZY, otherwise this trick won't work:
-       doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY));
+       // OPT_FORCE and OPT_LAZY.
+       {
+               typedef char bug[
+                       (OPT_FORCE != MNT_FORCE || OPT_LAZY != MNT_DETACH) ? -1 : 1
+               ];
+       }
+       doForce = opt & (OPT_FORCE|OPT_LAZY);
 
        /* Get a list of mount points from mtab.  We read them all in now mostly
         * for umount -a (so we don't have to worry about the list changing while
@@ -147,11 +152,18 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
                // umount the directory even if we were given the block device.
                if (m) zapit = m->dir;
 
+// umount from util-linux 2.22.2 does not do this:
+// umount -f uses umount2(MNT_FORCE) immediately,
+// not trying umount() first.
+// (Strangely, umount -fl ignores -f: it is equivalent to umount -l.
+// We do pass both flags in this case)
+#if 0
                // Let's ask the thing nicely to unmount.
                curstat = umount(zapit);
 
-               // Force the unmount, if necessary.
+               // Unmount with force and/or lazy flags, if necessary.
                if (curstat && doForce)
+#endif
                        curstat = umount2(zapit, doForce);
 
                // If still can't umount, maybe remount read-only?
@@ -168,7 +180,7 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
                                bb_error_msg(msg, m->device);
                        } else {
                                status = EXIT_FAILURE;
-                               bb_perror_msg("can't %sumount %s", (doForce ? "forcibly " : ""), zapit);
+                               bb_perror_msg("can't unmount %s", zapit);
                        }
                } else {
                        // De-allocate the loop device.  This ioctl should be ignored on