]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shutdown: do not umount recursively before MS_MOVE
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 2 Aug 2023 19:19:14 +0000 (04:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 3 Aug 2023 18:58:10 +0000 (03:58 +0900)
Unmounting filesystem will be done gracefully by shutdown itself.

Follow-up for f2c1d491a539035d6cc1fa53a7cef0cbc8d52902 and
268d1244e87a35ff8dff56c92ef375ebf69d462e.

src/shared/switch-root.c
src/shared/switch-root.h
src/shutdown/shutdown.c

index 37395e02ad4cf8367dc25038bb562920d2c67817..99036c1364736195ce4d6edb8fff63331e61c22d 100644 (file)
@@ -166,7 +166,8 @@ int switch_root(const char *new_root,
                  * MS_MOVE won't magically unmount anything below it. Once the chroot() succeeds the mounts
                  * below would still be around but invisible to us, because not accessible via
                  * /proc/self/mountinfo. Hence, let's clean everything up first, as long as we still can. */
-                (void) umount_recursive_full(NULL, MNT_DETACH, STRV_MAKE(new_root));
+                if (!FLAGS_SET(flags, SWITCH_ROOT_SKIP_RECURSIVE_UMOUNT))
+                        (void) umount_recursive_full(NULL, MNT_DETACH, STRV_MAKE(new_root));
 
                 if (mount(".", "/", NULL, MS_MOVE, NULL) < 0)
                         return log_error_errno(errno, "Failed to move %s to /: %m", new_root);
index 78d62f28e04312a8ff93ce229e461802bf154e2a..20561fcee8bdd9b4c61757de952b1b49f5cb7c0b 100644 (file)
@@ -4,9 +4,11 @@
 #include <stdbool.h>
 
 typedef enum SwitchRootFlags {
-        SWITCH_ROOT_DESTROY_OLD_ROOT   = 1 << 0, /* rm -rf old root when switching – under the condition that it is backed by non-persistent tmpfs/ramfs/… */
-        SWITCH_ROOT_DONT_SYNC          = 1 << 1, /* don't call sync() immediately before switching root */
-        SWITCH_ROOT_SKIP_RECURSIVE_RUN = 1 << 2, /* move /run without MS_REC */
+        SWITCH_ROOT_DESTROY_OLD_ROOT      = 1 << 0, /* rm -rf old root when switching – under the condition
+                                                     * that it is backed by non-persistent tmpfs/ramfs/… */
+        SWITCH_ROOT_DONT_SYNC             = 1 << 1, /* don't call sync() immediately before switching root */
+        SWITCH_ROOT_SKIP_RECURSIVE_RUN    = 1 << 2, /* move /run without MS_REC */
+        SWITCH_ROOT_SKIP_RECURSIVE_UMOUNT = 1 << 3, /* do not umount recursively on move */
 } SwitchRootFlags;
 
 int switch_root(const char *new_root, const char *old_root_after, SwitchRootFlags flags);
index 97a4050ae91bf52321c0a31804b09a2448026508..ed873c61f1a4bc20e1b915c624c05ba280b7cf19 100644 (file)
@@ -168,12 +168,13 @@ static int switch_root_initramfs(void) {
          * Disable sync() during switch-root, we after all sync'ed here plenty, and a dumb sync (as opposed
          * to the "smart" sync() we did here that looks at progress parameters) would defeat much of our
          * efforts here. As the new root will be /run/initramfs/, it is not necessary to mount /run/
-         * recursively. */
+         * recursively. Also, do not umount filesystems before MS_MOVE, as that should be done by ourself. */
         return switch_root(
                         /* new_root= */ "/run/initramfs",
                         /* old_root_after= */ "/oldroot",
                         /* flags= */ SWITCH_ROOT_DONT_SYNC |
-                                     SWITCH_ROOT_SKIP_RECURSIVE_RUN);
+                                     SWITCH_ROOT_SKIP_RECURSIVE_RUN |
+                                     SWITCH_ROOT_SKIP_RECURSIVE_UMOUNT);
 }
 
 /* Read the following fields from /proc/meminfo: