From 1795252caa681b6b16e575ae2e5bd24a48f4e376 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 May 2023 15:52:43 +0200 Subject: [PATCH] switch-root: disable sync() again when we switch root during shutdown 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 | 3 ++- src/shared/switch-root.h | 1 + src/shutdown/shutdown.c | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 333118f75f..17078c0490 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -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. diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h index 059b4603ea..79e47c67f4 100644 --- a/src/shared/switch-root.h +++ b/src/shared/switch-root.h @@ -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); diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index be4adb79d5..cdf828616e 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -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: