diff --git a/backport-shutdown-clean-up-sync_with_progress-a-bit.patch b/backport-shutdown-clean-up-sync_with_progress-a-bit.patch new file mode 100644 index 0000000000000000000000000000000000000000..dae8534e14a64b77d3a7db6f574905f7d5df7a10 --- /dev/null +++ b/backport-shutdown-clean-up-sync_with_progress-a-bit.patch @@ -0,0 +1,152 @@ +From 758760a3610e3c6674de8a1d51b12b991eafef7c Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Wed, 5 Jun 2024 17:53:27 +0200 +Subject: [PATCH] shutdown: clean up sync_with_progress a bit + +Also, ignore the error on caller's side. + +Conflict:context adaption. +Reference:https://github.com/systemd/systemd/commit/758760a3610e3c6674de8a1d51b12b991eafef7c + +--- + src/shutdown/shutdown.c | 67 ++++++++++++++++++----------------------- + 1 file changed, 29 insertions(+), 38 deletions(-) + +diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c +index 46f22cfc..8e11e353 100644 +--- a/src/shutdown/shutdown.c ++++ b/src/shutdown/shutdown.c +@@ -188,7 +188,9 @@ static int switch_root_initramfs(void) { + static int sync_making_progress(unsigned long long *prev_dirty) { + _cleanup_fclose_ FILE *f = NULL; + unsigned long long val = 0; +- int ret; ++ int r; ++ ++ assert(prev_dirty); + + f = fopen("/proc/meminfo", "re"); + if (!f) +@@ -196,13 +198,12 @@ static int sync_making_progress(unsigned long long *prev_dirty) { + + for (;;) { + _cleanup_free_ char *line = NULL; +- unsigned long long ull = 0; +- int q; ++ unsigned long long ull; + +- q = read_line(f, LONG_LINE_MAX, &line); +- if (q < 0) +- return log_warning_errno(q, "Failed to parse /proc/meminfo: %m"); +- if (q == 0) ++ r = read_line(f, LONG_LINE_MAX, &line); ++ if (r < 0) ++ return log_warning_errno(r, "Failed to parse /proc/meminfo: %m"); ++ if (r == 0) + break; + + if (!first_word(line, "NFS_Unstable:") && !first_word(line, "Writeback:") && !first_word(line, "Dirty:")) +@@ -210,25 +211,20 @@ static int sync_making_progress(unsigned long long *prev_dirty) { + + errno = 0; + if (sscanf(line, "%*s %llu %*s", &ull) != 1) { +- if (errno != 0) +- log_warning_errno(errno, "Failed to parse /proc/meminfo: %m"); +- else +- log_warning("Failed to parse /proc/meminfo"); +- ++ log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m"); + return false; + } + + val += ull; + } + +- ret = *prev_dirty > val; ++ r = *prev_dirty > val; + *prev_dirty = val; +- return ret; ++ return r; + } + +-static void sync_with_progress(void) { ++static int sync_with_progress(void) { + unsigned long long dirty = ULLONG_MAX; +- unsigned checks; + pid_t pid; + int r; + +@@ -238,37 +234,32 @@ static void sync_with_progress(void) { + * the progress. If the timeout lapses, the assumption is that the particular sync stalled. */ + + r = asynchronous_sync(&pid); +- if (r < 0) { +- log_error_errno(r, "Failed to fork sync(): %m"); +- return; +- } ++ if (r < 0) ++ return log_error_errno(r, "Failed to fork sync(): %m"); + + log_info("Syncing filesystems and block devices."); + + /* Start monitoring the sync operation. If more than + * SYNC_PROGRESS_ATTEMPTS lapse without progress being made, + * we assume that the sync is stalled */ +- for (checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) { ++ for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) { + r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC); + if (r == 0) +- /* Sync finished without error. +- * (The sync itself does not return an error code) */ +- return; +- else if (r == -ETIMEDOUT) { +- /* Reset the check counter if the "Dirty" value is +- * decreasing */ +- if (sync_making_progress(&dirty) > 0) +- checks = 0; +- } else { +- log_error_errno(r, "Failed to sync filesystems and block devices: %m"); +- return; +- } ++ /* Sync finished without error (sync() call itself does not return an error code) */ ++ return 0; ++ if (r != -ETIMEDOUT) ++ return log_error_errno(r, "Failed to sync filesystems and block devices: %m"); ++ ++ /* Reset the check counter if we made some progress */ ++ if (sync_making_progress(&dirty) > 0) ++ checks = 0; + } + +- /* Only reached in the event of a timeout. We should issue a kill +- * to the stray process. */ +- log_error("Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", pid); ++ /* Only reached in the event of a timeout. We should issue a kill to the stray process. */ + (void) kill(pid, SIGKILL); ++ return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), ++ "Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", ++ pid); + } + + static int read_current_sysctl_printk_log_level(void) { +@@ -436,7 +427,7 @@ int main(int argc, char *argv[]) { + * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will + * result. */ + if (!in_container) +- sync_with_progress(); ++ (void) sync_with_progress(); + + disable_coredumps(); + disable_binfmt(); +@@ -604,7 +595,7 @@ int main(int argc, char *argv[]) { + * which might have caused IO, hence let's do it once more. Do not remove this sync, data corruption + * will result. */ + if (!in_container) +- sync_with_progress(); ++ (void) sync_with_progress(); + + /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with + * a mechanism to pick up systemd's exit status in the VM. */ +-- +2.43.0 + diff --git a/backport-shutdown-replace-unbounded-fsync-with-bounded-sync_w.patch b/backport-shutdown-replace-unbounded-fsync-with-bounded-sync_w.patch new file mode 100644 index 0000000000000000000000000000000000000000..29021868be5f212ba2c90b33e7c8a7dcf223fb29 --- /dev/null +++ b/backport-shutdown-replace-unbounded-fsync-with-bounded-sync_w.patch @@ -0,0 +1,102 @@ +From b4b66b26620bfaf5818c95d5cffafd85207694e7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 9 Sep 2024 17:53:03 +0200 +Subject: [PATCH] shutdown: replace unbounded fsync() with bounded + sync_with_progress() + +Let's put a time-out on this syncing. + +Inspired-by: #34289 #34283 + +Conflict:NA +Reference:https://github.com/systemd/systemd/pull/34330/commits/b4b66b26620bfaf5818c95d5cffafd85207694e7 + +--- + src/shutdown/detach-dm.c | 11 ++++++----- + src/shutdown/detach-loopback.c | 4 ++-- + src/shutdown/detach-md.c | 4 ++-- + 3 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/shutdown/detach-dm.c b/src/shutdown/detach-dm.c +index f6f672c7..bddd748d 100644 +--- a/src/shutdown/detach-dm.c ++++ b/src/shutdown/detach-dm.c +@@ -15,7 +15,7 @@ + #include "devnum-util.h" + #include "errno-util.h" + #include "fd-util.h" +-#include "sync-util.h" ++#include "shutdown.h" + + typedef struct DeviceMapper { + char *path; +@@ -93,7 +93,6 @@ static int dm_list_get(DeviceMapper **head) { + + static int delete_dm(DeviceMapper *m) { + _cleanup_close_ int fd = -EBADF; +- int r; + + assert(m); + assert(major(m->devnum) != 0); +@@ -103,9 +102,11 @@ static int delete_dm(DeviceMapper *m) { + if (fd < 0) + return -errno; + +- r = fsync_path_at(AT_FDCWD, m->path); +- if (r < 0) +- log_debug_errno(r, "Failed to sync DM block device %s, ignoring: %m", m->path); ++ _cleanup_close_ int block_fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); ++ if (block_fd < 0) ++ log_debug_errno(errno, "Failed to open DM block device %s for syncing, ignoring: %m", m->path); ++ else ++ (void) sync_with_progress(block_fd); + + return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) { + .version = { +diff --git a/src/shutdown/detach-loopback.c b/src/shutdown/detach-loopback.c +index 267509f7..8778a9e0 100644 +--- a/src/shutdown/detach-loopback.c ++++ b/src/shutdown/detach-loopback.c +@@ -18,6 +18,7 @@ + #include "detach-loopback.h" + #include "device-util.h" + #include "fd-util.h" ++#include "shutdown.h" + + typedef struct LoopbackDevice { + char *path; +@@ -111,8 +112,7 @@ static int delete_loopback(const char *device) { + + /* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly + * first */ +- if (fsync(fd) < 0) +- log_debug_errno(errno, "Failed to sync loop block device %s, ignoring: %m", device); ++ (void) sync_with_progress(fd); + + if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { + if (errno == ENXIO) /* Nothing bound, didn't do anything */ +diff --git a/src/shutdown/detach-md.c b/src/shutdown/detach-md.c +index ac46670f..b1aad976 100644 +--- a/src/shutdown/detach-md.c ++++ b/src/shutdown/detach-md.c +@@ -17,6 +17,7 @@ + #include "devnum-util.h" + #include "errno-util.h" + #include "fd-util.h" ++#include "shutdown.h" + #include "string-util.h" + + typedef struct RaidDevice { +@@ -133,8 +134,7 @@ static int delete_md(RaidDevice *m) { + if (fd < 0) + return -errno; + +- if (fsync(fd) < 0) +- log_debug_errno(errno, "Failed to sync MD block device %s, ignoring: %m", m->path); ++ (void) sync_with_progress(fd); + + return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL)); + } +-- +2.43.0 + diff --git a/backport-shutdown-teach-sync_with_progress-to-optionally-sync.patch b/backport-shutdown-teach-sync_with_progress-to-optionally-sync.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d7aea0ef5bd5b6d78488edb9c93567811210422 --- /dev/null +++ b/backport-shutdown-teach-sync_with_progress-to-optionally-sync.patch @@ -0,0 +1,164 @@ +From 13b5225d6278af15e84ebd1889f04cfe81b47787 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 9 Sep 2024 17:49:33 +0200 +Subject: [PATCH] shutdown: teach sync_with_progress() to optionally sync a + specific fd only + +This is preparation for reusing the logic for syncing DM and other +devices with a timeout applied. + +Conflict:context adaption. +Reference:https://github.com/systemd/systemd/pull/34330/commits/13b5225d6278af15e84ebd1889f04cfe81b47787 + +--- + src/shared/async.c | 22 ++++++++++++++++++++++ + src/shared/async.h | 1 + + src/shutdown/shutdown.c | 31 ++++++++++++++++++++++--------- + src/shutdown/shutdown.h | 4 ++++ + 4 files changed, 49 insertions(+), 9 deletions(-) + create mode 100644 src/shutdown/shutdown.h + +diff --git a/src/shared/async.c b/src/shared/async.c +index bbb8b810..bd043c84 100644 +--- a/src/shared/async.c ++++ b/src/shared/async.c +@@ -34,6 +34,28 @@ int asynchronous_sync(pid_t *ret_pid) { + return 0; + } + ++int asynchronous_fsync(int fd, pid_t *ret_pid) { ++ int r; ++ ++ assert(fd >= 0); ++ /* Same as asynchronous_sync() above, but calls fsync() on a specific fd */ ++ ++ r = safe_fork_full("(sd-fsync)", ++ /* stdio_fds= */ NULL, ++ /* except_fds= */ &fd, ++ /* n_except_fds= */ 1, ++ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH), ret_pid); ++ if (r < 0) ++ return r; ++ if (r == 0) { ++ /* Child process */ ++ fsync(fd); ++ _exit(EXIT_SUCCESS); ++ } ++ ++ return 0; ++} ++ + /* We encode the fd to close in the userdata pointer as an unsigned value. The highest bit indicates whether + * we need to fork again */ + #define NEED_DOUBLE_FORK (1U << (sizeof(unsigned) * 8 - 1)) +diff --git a/src/shared/async.h b/src/shared/async.h +index 96148f90..2f5bbd51 100644 +--- a/src/shared/async.h ++++ b/src/shared/async.h +@@ -20,6 +20,7 @@ + * for avoiding threads. */ + + int asynchronous_sync(pid_t *ret_pid); ++int asynchronous_fsync(int fd, pid_t *ret_pid); + int asynchronous_close(int fd); + int asynchronous_rm_rf(const char *p, RemoveFlags flags); + +diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c +index 03e6e70f..e6c9e0f8 100644 +--- a/src/shutdown/shutdown.c ++++ b/src/shutdown/shutdown.c +@@ -40,6 +40,7 @@ + #include "process-util.h" + #include "reboot-util.h" + #include "rlimit-util.h" ++#include "shutdown.h" + #include "signal-util.h" + #include "string-util.h" + #include "switch-root.h" +@@ -223,8 +224,10 @@ static int sync_making_progress(unsigned long long *prev_dirty) { + return r; + } + +-static int sync_with_progress(void) { ++int sync_with_progress(int fd) { + unsigned long long dirty = ULLONG_MAX; ++ _cleanup_free_ char *path = NULL; ++ const char *what; + pid_t pid; + int r; + +@@ -233,11 +236,20 @@ static int sync_with_progress(void) { + /* Due to the possibility of the sync operation hanging, we fork a child process and monitor + * the progress. If the timeout lapses, the assumption is that the particular sync stalled. */ + +- r = asynchronous_sync(&pid); +- if (r < 0) +- return log_error_errno(r, "Failed to fork sync(): %m"); ++ if (fd >= 0) { ++ r = asynchronous_fsync(fd, &pid); ++ if (r < 0) ++ return log_error_errno(r, "Failed to fork fsync(): %m"); ++ ++ (void) fd_get_path(fd, &path); ++ } else { ++ r = asynchronous_sync(&pid); ++ if (r < 0) ++ return log_error_errno(r, "Failed to fork sync(): %m"); ++ } + +- log_info("Syncing filesystems and block devices."); ++ what = path ?: "filesystems and block devices"; ++ log_info("Syncing %s.", what); + + /* Start monitoring the sync operation. If more than + * SYNC_PROGRESS_ATTEMPTS lapse without progress being made, +@@ -248,7 +260,7 @@ static int sync_with_progress(void) { + /* Sync finished without error (sync() call itself does not return an error code) */ + return 0; + if (r != -ETIMEDOUT) +- return log_error_errno(r, "Failed to sync filesystems and block devices: %m"); ++ return log_error_errno(r, "Failed to sync %s: %m", what); + + /* Reset the check counter if we made some progress */ + if (sync_making_progress(&dirty) > 0) +@@ -258,7 +270,8 @@ static int sync_with_progress(void) { + /* Only reached in the event of a timeout. We should issue a kill to the stray process. */ + (void) kill(pid, SIGKILL); + return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), +- "Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", ++ "Syncing %s - timed out, issuing SIGKILL to PID "PID_FMT".", ++ what, + pid); + } + +@@ -432,7 +445,7 @@ int main(int argc, char *argv[]) { + * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will + * result. */ + if (!in_container) +- (void) sync_with_progress(); ++ (void) sync_with_progress(-EBADF); + + disable_coredumps(); + disable_binfmt(); +@@ -600,7 +613,7 @@ int main(int argc, char *argv[]) { + * which might have caused IO, hence let's do it once more. Do not remove this sync, data corruption + * will result. */ + if (!in_container) +- (void) sync_with_progress(); ++ (void) sync_with_progress(-EBADF); + + /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with + * a mechanism to pick up systemd's exit status in the VM. */ +diff --git a/src/shutdown/shutdown.h b/src/shutdown/shutdown.h +new file mode 100644 +index 00000000..99aaec69 +--- /dev/null ++++ b/src/shutdown/shutdown.h +@@ -0,0 +1,4 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++#pragma once ++ ++int sync_with_progress(int fd); +-- +2.43.0 + diff --git a/shutdown-reboot-when-recieve-crash-signal.patch b/shutdown-reboot-when-recieve-crash-signal.patch index 1081e8ca0dc5d715a5270ad4aad01027ec00e13d..7a4019c31dde50363739da6c6de3e280c5789fad 100644 --- a/shutdown-reboot-when-recieve-crash-signal.patch +++ b/shutdown-reboot-when-recieve-crash-signal.patch @@ -28,7 +28,7 @@ index d6beb2d..ed1ce93 100644 + broadcast_signal(SIGKILL, true, false, arg_timeout); + + if (!in_container) -+ sync_with_progress(); ++ (void) sync_with_progress(-EBADF); + + log_info("Rebooting now."); + (void) reboot(RB_AUTOBOOT); diff --git a/systemd.spec b/systemd.spec index cc287df5f6a802e067d3c652944b8ec9bff12e5f..3e661d192b7390e7246aef12c3eb7cba7dffc0b3 100644 --- a/systemd.spec +++ b/systemd.spec @@ -25,7 +25,7 @@ Name: systemd Url: https://systemd.io/ Version: 255 -Release: 32 +Release: 33 License: LGPL-2.1-or-later AND MIT AND GPL-2.0-or-later Summary: System and Service Manager @@ -78,6 +78,9 @@ Patch6022: backport-mount-optimize-mountinfo-traversal-by-decoupling-dev.pa Patch6023: backport-systemctl-fix-printing-of-RootImageOptions.patch Patch6024: backport-pid1-add-env-var-to-override-default-mount-rate-limit-interval.patch Patch6025: backport-install-allow-removing-symlinks-even-for-units-that-.patch +Patch6026: backport-shutdown-clean-up-sync_with_progress-a-bit.patch +Patch6027: backport-shutdown-replace-unbounded-fsync-with-bounded-sync_w.patch +Patch6028: backport-shutdown-teach-sync_with_progress-to-optionally-sync.patch Patch9008: update-rtc-with-system-clock-when-shutdown.patch Patch9009: udev-add-actions-while-rename-netif-failed.patch @@ -1686,6 +1689,9 @@ fi %{_unitdir}/veritysetup.target %changelog +* Thu Dec 19 2024 Linux_zhang - 255-33 +- backport upstream patch to solve systemd-shutdown hang all the time caused by fsync blocked by absence of DM mapping table + * Tue Nov 26 2024 zhangyao - 255-32 - fix the systemctl disable cannot delete residuals symlink after the unit is deleted