]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hibernate-util,logind: emit a clear error if the specified resume dev is missing
authorMike Yuan <me@yhndnzj.com>
Wed, 8 May 2024 04:42:40 +0000 (12:42 +0800)
committerMike Yuan <me@yhndnzj.com>
Wed, 8 May 2024 04:54:13 +0000 (12:54 +0800)
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
src/shared/hibernate-util.c
src/shared/sleep-config.c
src/shared/sleep-config.h

index 38bfaa56be259c25d744ea1fc05e52629cb951da..ef8cad0a316b3ede68de9589cdf99be059150876 100644 (file)
@@ -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");
index cb26a9ab272ec798e718b974a1e165e0a3bcc928..ce49344debd550761f8f842722f41eb6cbd6d459 100644 (file)
@@ -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;
index aac145836b6c9f62072ef6476b5f71016836398d..0a4303f3eb599e57d9aaecb8921c07d6c55b9c87 100644 (file)
@@ -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]);
 
index 75d9c4a6221efdda50733993875a2a0392a3393e..be0287e2e494daff8a5067dac20cae62705cfec3 100644 (file)
@@ -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;