diff options
Diffstat (limited to 'src/shared/hibernate-util.c')
-rw-r--r-- | src/shared/hibernate-util.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/src/shared/hibernate-util.c b/src/shared/hibernate-util.c index c3991cf..7c21157 100644 --- a/src/shared/hibernate-util.c +++ b/src/shared/hibernate-util.c @@ -159,8 +159,9 @@ static int read_resume_config(dev_t *ret_devno, uint64_t *ret_offset) { } if (devno == 0 && offset > 0 && offset != UINT64_MAX) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "Found resume_offset=%" PRIu64 " but resume= is unset, refusing.", offset); + return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), + "Found populated /sys/power/resume_offset (%" PRIu64 ") but /sys/power/resume is not set, refusing.", + offset); *ret_devno = devno; *ret_offset = offset; @@ -393,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) { @@ -451,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; @@ -466,7 +467,7 @@ int hibernation_is_safe(void) { "Not running on EFI and resume= is not set. Hibernation is not safe."); if (bypass_space_check) - return true; + return 0; r = get_proc_meminfo_active(&active); if (r < 0) @@ -483,30 +484,23 @@ int hibernation_is_safe(void) { int write_resume_config(dev_t devno, uint64_t offset, const char *device) { char offset_str[DECIMAL_STR_MAX(uint64_t)]; - _cleanup_free_ char *path = NULL; const char *devno_str; int r; + assert(devno > 0); + assert(device); + devno_str = FORMAT_DEVNUM(devno); xsprintf(offset_str, "%" PRIu64, offset); - if (!device) { - r = device_path_make_canonical(S_IFBLK, devno, &path); - if (r < 0) - return log_error_errno(r, - "Failed to format canonical device path for devno '" DEVNUM_FORMAT_STR "': %m", - DEVNUM_FORMAT_VAL(devno)); - device = path; - } - /* We write the offset first since it's safer. Note that this file is only available in 4.17+, so * fail gracefully if it doesn't exist and we're only overwriting it with 0. */ r = write_string_file("/sys/power/resume_offset", offset_str, WRITE_STRING_FILE_DISABLE_BUFFER); if (r == -ENOENT) { if (offset != 0) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Can't configure hibernation offset %" PRIu64 ", kernel does not support /sys/power/resume_offset. Refusing.", - offset); + "Can't configure swap file offset %s, kernel does not support /sys/power/resume_offset. Refusing.", + offset_str); log_warning_errno(r, "/sys/power/resume_offset is unavailable, skipping writing swap file offset."); } else if (r < 0) @@ -526,3 +520,18 @@ int write_resume_config(dev_t devno, uint64_t offset, const char *device) { return 0; } + +int clear_efi_hibernate_location_and_warn(void) { + int r; + + if (!is_efi_boot()) + return 0; + + r = efi_set_variable(EFI_SYSTEMD_VARIABLE(HibernateLocation), NULL, 0); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_warning_errno(r, "Failed to clear HibernateLocation EFI variable: %m"); + + return 1; +} |