]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
umount: unmount profcs/sysfs/.. lazily
authorLennart Poettering <lennart@poettering.net>
Wed, 24 Aug 2022 09:23:41 +0000 (11:23 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 31 Aug 2022 20:53:18 +0000 (22:53 +0200)
Alternative for: df48b430a4a85f923eaecb3fadf9c514692d2082

src/shutdown/umount.c
src/shutdown/umount.h

index 2fd1b464e455a0be85d1832022d41159dae6f6ea..7ddeb67e977fe61d5d01f1a20eadda43e2fb73e8 100644 (file)
@@ -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);
index 618b754011445f4caa4dd49db5f8c5272b1b1c57..a4154c9099fcd7fdac5fdac8822f0d6bed99f73d 100644 (file)
@@ -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;