shutdown: clean up sync_with_progress a bit

Also, ignore the error on caller's side.
This commit is contained in:
Mike Yuan 2024-06-05 17:53:27 +02:00
parent c1bf0571c0
commit 758760a361
No known key found for this signature in database
GPG key ID: 417471C0A40F58B3

View file

@ -188,7 +188,9 @@ static int switch_root_initramfs(void) {
static int sync_making_progress(unsigned long long *prev_dirty) { static int sync_making_progress(unsigned long long *prev_dirty) {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
unsigned long long val = 0; unsigned long long val = 0;
int ret; int r;
assert(prev_dirty);
f = fopen("/proc/meminfo", "re"); f = fopen("/proc/meminfo", "re");
if (!f) if (!f)
@ -196,13 +198,12 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
for (;;) { for (;;) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
unsigned long long ull = 0; unsigned long long ull;
int q;
q = read_line(f, LONG_LINE_MAX, &line); r = read_line(f, LONG_LINE_MAX, &line);
if (q < 0) if (r < 0)
return log_warning_errno(q, "Failed to parse /proc/meminfo: %m"); return log_warning_errno(r, "Failed to parse /proc/meminfo: %m");
if (q == 0) if (r == 0)
break; break;
if (!first_word(line, "NFS_Unstable:") && !first_word(line, "Writeback:") && !first_word(line, "Dirty:")) 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; errno = 0;
if (sscanf(line, "%*s %llu %*s", &ull) != 1) { if (sscanf(line, "%*s %llu %*s", &ull) != 1) {
if (errno != 0) log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m");
log_warning_errno(errno, "Failed to parse /proc/meminfo: %m");
else
log_warning("Failed to parse /proc/meminfo");
return false; return false;
} }
val += ull; val += ull;
} }
ret = *prev_dirty > val; r = *prev_dirty > val;
*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 long long dirty = ULLONG_MAX;
unsigned checks;
pid_t pid; pid_t pid;
int r; 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. */ * the progress. If the timeout lapses, the assumption is that the particular sync stalled. */
r = asynchronous_sync(&pid); r = asynchronous_sync(&pid);
if (r < 0) { if (r < 0)
log_error_errno(r, "Failed to fork sync(): %m"); return log_error_errno(r, "Failed to fork sync(): %m");
return;
}
log_info("Syncing filesystems and block devices."); log_info("Syncing filesystems and block devices.");
/* Start monitoring the sync operation. If more than /* Start monitoring the sync operation. If more than
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made, * SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
* we assume that the sync is stalled */ * 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); r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC);
if (r == 0) if (r == 0)
/* Sync finished without error. /* Sync finished without error (sync() call itself does not return an error code) */
* (The sync itself does not return an error code) */ return 0;
return; if (r != -ETIMEDOUT)
else if (r == -ETIMEDOUT) { return log_error_errno(r, "Failed to sync filesystems and block devices: %m");
/* Reset the check counter if the "Dirty" value is
* decreasing */ /* Reset the check counter if we made some progress */
if (sync_making_progress(&dirty) > 0) if (sync_making_progress(&dirty) > 0)
checks = 0; checks = 0;
} else {
log_error_errno(r, "Failed to sync filesystems and block devices: %m");
return;
}
} }
/* Only reached in the event of a timeout. We should issue a kill /* Only reached in the event of a timeout. We should issue a kill to the stray process. */
* to the stray process. */
log_error("Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", pid);
(void) kill(pid, SIGKILL); (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) { 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 * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will
* result. */ * result. */
if (!in_container) if (!in_container)
sync_with_progress(); (void) sync_with_progress();
disable_coredumps(); disable_coredumps();
disable_binfmt(); 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 * which might have caused IO, hence let's do it once more. Do not remove this sync, data corruption
* will result. */ * will result. */
if (!in_container) if (!in_container)
sync_with_progress(); (void) sync_with_progress();
notify_supervisor(); notify_supervisor();