summaryrefslogtreecommitdiff
path: root/src/shutdown
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-08-24 11:23:41 +0200
committerLennart Poettering <lennart@poettering.net>2022-08-31 22:53:18 +0200
commitf11efcbeb17781a3e03596fe6b1016fbb5c31360 (patch)
treeb4f674bf55ba04c8ce0b18f1e277ef5207f69ac8 /src/shutdown
parentc905aaf68607754a2aa131854544f5b44a378874 (diff)
downloadsystemd-f11efcbeb17781a3e03596fe6b1016fbb5c31360.tar.gz
umount: unmount profcs/sysfs/.. lazily
Alternative for: df48b430a4a85f923eaecb3fadf9c514692d2082
Diffstat (limited to 'src/shutdown')
-rw-r--r--src/shutdown/umount.c25
-rw-r--r--src/shutdown/umount.h3
2 files changed, 13 insertions, 15 deletions
diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c
index 2fd1b464e4..7ddeb67e97 100644
--- a/src/shutdown/umount.c
+++ b/src/shutdown/umount.c
@@ -80,7 +80,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
struct libmnt_fs *fs;
const char *path, *fstype;
unsigned long remount_flags = 0u;
- bool try_remount_ro;
+ bool try_remount_ro, is_api_vfs;
_cleanup_free_ MountPoint *m = NULL;
r = mnt_table_next_fs(table, iter, &fs);
@@ -115,6 +115,8 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
PATH_STARTSWITH_SET(path, "/dev", "/sys", "/proc"))
continue;
+ 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
* benefits, but might confuse the host, as we remount the superblock here, not the bind
* mount.
@@ -124,7 +126,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
* careful and will not hang because of the network being down. */
try_remount_ro = detect_container() <= 0 &&
!fstype_is_network(fstype) &&
- !fstype_is_api_vfs(fstype) &&
+ !is_api_vfs &&
!fstype_is_ro(fstype) &&
!fstab_test_yes_no_option(options, "ro\0rw\0");
@@ -158,6 +160,10 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
.remount_options = remount_options,
.remount_flags = remount_flags,
.try_remount_ro = try_remount_ro,
+
+ /* 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,
};
m->path = strdup(path);
@@ -634,23 +640,14 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
* -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 than return EBUSY). */
- r = RET_NERRNO(umount2(m->path, MNT_FORCE));
+ r = RET_NERRNO(umount2(m->path,
+ UMOUNT_NOFOLLOW | /* Don't follow symlinks: this should never happen unless our mount list was wrong */
+ (m->umount_lazily ? MNT_DETACH : MNT_FORCE)));
if (r < 0) {
log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Failed to unmount %s: %m", m->path);
if (r == -EBUSY && last_try)
log_umount_blockers(m->path);
-
- /* If API filesystems under /oldroot cannot be unmounted we can still lazily unmount
- * them to unblock /oldroot. They serve no function to us anymore and should be
- * memory-only and hence safe to unmount like this. */
- if (in_initrd() &&
- PATH_STARTSWITH_SET(m->path, "/oldroot/dev", "/oldroot/proc", "/oldroot/sys")) {
- log_info("Lazily unmounting '%s' instead.", m->path);
- r = umount2(m->path, MNT_FORCE | MNT_DETACH);
- if (r < 0)
- log_error_errno(errno, "Failed to lazily unmount %s: %m", m->path);
- }
}
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
diff --git a/src/shutdown/umount.h b/src/shutdown/umount.h
index 618b754011..a4154c9099 100644
--- a/src/shutdown/umount.h
+++ b/src/shutdown/umount.h
@@ -18,7 +18,8 @@ typedef struct MountPoint {
char *path;
char *remount_options;
unsigned long remount_flags;
- bool try_remount_ro;
+ bool try_remount_ro:1;
+ bool umount_lazily:1;
dev_t devnum;
LIST_FIELDS(struct MountPoint, mount_point);
} MountPoint;