mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
umount: do not move busy network mounts
If a network mount returns EBUSY on umount, the logic introduced in6dc68a00cfcauses shutdown to hang indefinitely on `fstatat()` (i.e., within `is_dir(m->path, true)`). Hence, skip this logic for network mounts (following the same motivation we use to skip read-only mounts in this kind of file systems). Fixes6dc68a00cf
This commit is contained in:
committed by
Yu Watanabe
parent
63b331517e
commit
cef2181cda
@@ -63,7 +63,7 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
||||
struct libmnt_fs *fs;
|
||||
const char *path, *fstype;
|
||||
unsigned long remount_flags = 0u;
|
||||
bool try_remount_ro, is_api_vfs;
|
||||
bool try_remount_ro, is_api_vfs, is_network;
|
||||
_cleanup_free_ MountPoint *m = NULL;
|
||||
|
||||
r = mnt_table_next_fs(table, iter, &fs);
|
||||
@@ -98,6 +98,7 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
||||
path_below_api_vfs(path))
|
||||
continue;
|
||||
|
||||
is_network = fstype_is_network(fstype);
|
||||
is_api_vfs = fstype_is_api_vfs(fstype);
|
||||
|
||||
/* If we are in a container, don't attempt to read-only mount anything as that brings no real
|
||||
@@ -108,7 +109,7 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
||||
* leave 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. */
|
||||
try_remount_ro = detect_container() <= 0 &&
|
||||
!fstype_is_network(fstype) &&
|
||||
!is_network &&
|
||||
!is_api_vfs &&
|
||||
!fstype_is_ro(fstype) &&
|
||||
!fstab_test_yes_no_option(options, "ro\0rw\0");
|
||||
@@ -152,7 +153,11 @@ int mount_points_list_get(FILE *f, MountPoint **head) {
|
||||
/* Unmount sysfs/procfs/… lazily, since syncing doesn't matter there, and it's OK if
|
||||
* something keeps an fd open to it. */
|
||||
.umount_lazily = is_api_vfs,
|
||||
.leaf = leaf,
|
||||
|
||||
/* If a mount point is not a leaf, moving it would invalidate our mount table.
|
||||
* If a mount point is on the network and the network is down, it can hang and block
|
||||
* the shutdown. */
|
||||
.umount_move_if_busy = leaf && !is_network,
|
||||
};
|
||||
|
||||
m->path = strdup(path);
|
||||
@@ -403,10 +408,9 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool last_
|
||||
*changed = true;
|
||||
|
||||
/* If a mount is busy, we move it to not keep parent mount points busy.
|
||||
* If a mount point is not a leaf, moving it would invalidate our mount table.
|
||||
* More moving will occur in next iteration with a fresh mount table.
|
||||
*/
|
||||
if (r != -EBUSY || !m->leaf)
|
||||
if (r != -EBUSY || !m->umount_move_if_busy)
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char *dirname = NULL;
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct MountPoint {
|
||||
unsigned long remount_flags;
|
||||
bool try_remount_ro;
|
||||
bool umount_lazily;
|
||||
bool leaf;
|
||||
bool umount_move_if_busy;
|
||||
LIST_FIELDS(struct MountPoint, mount_point);
|
||||
} MountPoint;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user