a9339c
From 5bace483dedc9098da8191f39c823649948a7a3c Mon Sep 17 00:00:00 2001
2be57e
From: NeilBrown <neil@brown.name>
2be57e
Date: Wed, 8 Nov 2017 19:29:32 +1100
2be57e
Subject: [PATCH] umount: always use MNT_FORCE in umount_all() (#7213)
2be57e
2be57e
The linux umount2() systemcall accepts a MNT_FORCE flags
2be57e
which some filesystems honor, particularly FUSE and various
2be57e
network filesystems such as NFS.
2be57e
These filesystems can sometimes wait for an indefinite period
2be57e
for a response from an external service, and the wait if
2be57e
sometimes "uninterruptible" meaning that the process cannot be
2be57e
killed.
2be57e
Using MNT_FORCE causes any such request that are outstanding to
2be57e
be aborted.  This normally allows the waiting process to
2be57e
be killed.  It will then realease and reference it has to the
2be57e
filesytem, this allowing the filesystem to be unmounted.
2be57e
2be57e
If there remain active references to the filesystem, MNT_FORCE
2be57e
is *not* forcefull enough to unmount the filesystem anyway.
2be57e
2be57e
By the time that umount_all() is run by systemd-shutdown, all
2be57e
filesystems *should* be unmounted, and sync() will have been
2be57e
called.  Anything that remains cannot be unmounted in a
2be57e
completely clean manner and just nees to be dealt with as firmly
2be57e
as possible.  So use MNT_FORCE and try to explain why in the
2be57e
comment.
2be57e
2be57e
Also enhance an earlier comment to explain why umount2() is
2be57e
safe even though mount(MNT_REMOUNT) isn't.
2be57e
2be57e
(cherry picked from commit c44cac7c6c43407d28bd8daebff39f6145a2a33e)
2be57e
2be57e
Resolves: #1571098
2be57e
---
2be57e
 src/core/umount.c | 16 +++++++++++-----
2be57e
 1 file changed, 11 insertions(+), 5 deletions(-)
2be57e
2be57e
diff --git a/src/core/umount.c b/src/core/umount.c
2be57e
index 3eec0d459..91d67c06c 100644
2be57e
--- a/src/core/umount.c
2be57e
+++ b/src/core/umount.c
2be57e
@@ -377,7 +377,9 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
2be57e
                    the superblock here, not the bind mount.
2be57e
                    If the filesystem is a network fs, also skip the
2be57e
                    remount.  It brings no value (we cannot leave
2be57e
-                   a "dirty fs") and could hang if the network is down.  */
2be57e
+                   a "dirty fs") and could hang if the network is down.
2be57e
+                   Note that umount2() is more careful and will not
2be57e
+                   hang because of the network being down. */
2be57e
                 if (detect_container(NULL) <= 0 &&
2be57e
                     !fstype_is_network(m->type)) {
2be57e
                         _cleanup_free_ char *options = NULL;
2be57e
@@ -418,11 +420,15 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
2be57e
                 )
2be57e
                         continue;
2be57e
 
2be57e
-                /* Trying to umount. We don't force here since we rely
2be57e
-                 * on busy NFS and FUSE file systems to return EBUSY
2be57e
-                 * until we closed everything on top of them. */
2be57e
+                /* Trying to umount. Using MNT_FORCE causes some
2be57e
+                 * filesystems (e.g. FUSE and NFS and other network
2be57e
+                 * filesystems) to abort any pending requests and
2be57e
+                 * return -EIO rather than blocking indefinitely.
2be57e
+                 * If the filesysten is "busy", this may allow processes
2be57e
+                 * to die, thus making the filesystem less busy so
2be57e
+                 * the unmount might succeed (rather then return EBUSY).*/
2be57e
                 log_info("Unmounting %s.", m->path);
2be57e
-                if (umount2(m->path, 0) == 0) {
2be57e
+                if (umount2(m->path, MNT_FORCE) == 0) {
2be57e
                         if (changed)
2be57e
                                 *changed = true;
2be57e