From 40eb83a8fe535897b17760988849fa061a8f4929 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 8 May 2024 12:42:40 +0800 Subject: [PATCH] hibernate-util,logind: emit a clear error if the specified resume dev is missing Currently, SLEEP_NOT_ENOUGH_SWAP_SPACE (ENOSPC) is returned on all sorts of error conditions. But one important case that's worth differentiating from that is when the resume device is manually specified yet missing. Closes #32644 --- src/login/logind-dbus.c | 4 ++++ src/shared/hibernate-util.c | 12 ++++++------ src/shared/sleep-config.c | 18 +++++++++++++----- src/shared/sleep-config.h | 1 + 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 38bfaa56be2..ef8cad0a316 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2156,6 +2156,10 @@ static int method_do_shutdown_or_sleep( return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Not running on EFI and resume= is not set, or noresume is set. No available method to resume from hibernation"); + case SLEEP_RESUME_DEVICE_MISSING: + return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, + "Specified resume device is missing or is not an active swap device"); + case SLEEP_NOT_ENOUGH_SWAP_SPACE: return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Not enough suitable swap space for hibernation available on compatible block devices and file systems"); diff --git a/src/shared/hibernate-util.c b/src/shared/hibernate-util.c index cb26a9ab272..ce49344debd 100644 --- a/src/shared/hibernate-util.c +++ b/src/shared/hibernate-util.c @@ -394,7 +394,7 @@ int find_suitable_hibernation_device_full(HibernationDevice *ret_device, uint64_ if (!entry) { /* No need to check n_swaps == 0, since it's rejected early */ assert(resume_config_devno > 0); - return log_debug_errno(SYNTHETIC_ERRNO(ENOSPC), "Cannot find swap entry corresponding to /sys/power/resume."); + return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Cannot find swap entry corresponding to /sys/power/resume."); } if (ret_device) { @@ -452,11 +452,11 @@ int hibernation_is_safe(void) { bypass_space_check = getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0; r = find_suitable_hibernation_device_full(NULL, &size, &used); - if (r == -ENOSPC && bypass_space_check) - /* If we don't have any available swap space at all, and SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK - * is set, skip all remaining checks since we can't do that properly anyway. It is quite - * possible that the user is using a setup similar to #30083. When we actually perform - * hibernation in sleep.c we'll check everything again. */ + if (IN_SET(r, -ENOSPC, -ESTALE) && bypass_space_check) + /* If we don't have any available swap space at all, or the specified resume device is missing, + * and $SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK is set, skip all remaining checks since + * we can't do that properly anyway. It is quite possible that the user is using a setup + * similar to #30083. When we actually perform hibernation in sleep.c we'll check everything again. */ return 0; if (r < 0) return r; diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index aac145836b6..0a4303f3eb5 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -368,16 +368,24 @@ static int sleep_supported_internal( } r = hibernation_is_safe(); - if (r == -ENOTRECOVERABLE) { + switch (r) { + + case -ENOTRECOVERABLE: *ret_support = SLEEP_RESUME_NOT_SUPPORTED; return false; - } - if (r == -ENOSPC) { + + case -ESTALE: + *ret_support = SLEEP_RESUME_DEVICE_MISSING; + return false; + + case -ENOSPC: *ret_support = SLEEP_NOT_ENOUGH_SWAP_SPACE; return false; + + default: + if (r < 0) + return r; } - if (r < 0) - return r; } else assert(!sleep_config->modes[operation]); diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h index 75d9c4a6221..be0287e2e49 100644 --- a/src/shared/sleep-config.h +++ b/src/shared/sleep-config.h @@ -59,6 +59,7 @@ typedef enum SleepSupport { SLEEP_NOT_CONFIGURED, /* SleepConfig.states is not configured */ SLEEP_STATE_OR_MODE_NOT_SUPPORTED, /* SleepConfig.states/modes are not supported by kernel */ SLEEP_RESUME_NOT_SUPPORTED, + SLEEP_RESUME_DEVICE_MISSING, /* resume= is specified, but the device cannot be found in /proc/swaps */ SLEEP_NOT_ENOUGH_SWAP_SPACE, SLEEP_ALARM_NOT_SUPPORTED, /* CLOCK_BOOTTIME_ALARM is unsupported by kernel (only used by s2h) */ } SleepSupport; -- 2.39.2