switch-root: disable sync() again when we switch root during shutdown
authorLennart Poettering <lennart@poettering.net>
Fri, 19 May 2023 13:52:43 +0000 (15:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 2 Jun 2023 14:49:39 +0000 (16:49 +0200)
Our shutdown binary that takes over as PID 1 when shutting down puts
great efforts into a sync() that comes with a time-out once sync'ing
process stops. If we'd add another dumb sync() here, we kinda defeat all
it is good for. Hence, let's keep the sync() in for most codepats, but
let's disable it for the final shutdown logic when we transition back
into the exitrd. After all we sync()ed more than enough here, no need to
sync() even more.

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

index 333118f75fc7bd79a3cb23863246eda49a4b7598..17078c049035a1f15ed8428cd406f75244af3052 100644 (file)
@@ -89,7 +89,8 @@ int switch_root(const char *new_root,
          * all while making them invisible/inaccessible in the file system tree for later code. That makes
          * sync'ing them then difficult. Let's hence issue a manual sync() here, so that we at least can
          * guarantee all file systems are an a good state before entering this state. */
-        sync();
+        if (!FLAGS_SET(flags, SWITCH_ROOT_DONT_SYNC))
+                sync();
 
         /* Work-around for kernel design: the kernel refuses MS_MOVE if any file systems are mounted
          * MS_SHARED. Hence remount them MS_PRIVATE here as a work-around.
index 059b4603ea5dc12a8bbfef928367ba0d65aef32e..79e47c67f471ba3f96c192d66caf39df9ffc60eb 100644 (file)
@@ -5,6 +5,7 @@
 
 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 */
 } SwitchRootFlags;
 
 int switch_root(const char *new_root, const char *old_root_after, SwitchRootFlags flags);
index be4adb79d578fcd9a7bef83460eac64b0b9a5c6a..cdf828616ea7dd426877d7d22ca80358703d4ea8 100644 (file)
@@ -165,11 +165,15 @@ static int switch_root_initramfs(void) {
         if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0)
                 return log_error_errno(errno, "Failed to make /run/initramfs private mount: %m");
 
-        /* Do not detach the old root, because /run/initramfs/shutdown needs to access it. */
+        /* Do not detach the old root, because /run/initramfs/shutdown needs to access it.
+         *
+         * 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. */
         return switch_root(
                         /* new_root= */ "/run/initramfs",
                         /* old_root_after= */ "/oldroot",
-                        /* flags= */ 0);
+                        /* flags= */ SWITCH_ROOT_DONT_SYNC);
 }
 
 /* Read the following fields from /proc/meminfo: