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