Yu Watanabe
2025-05-06 13:00:24 +09:00
committed by GitHub
7 changed files with 119 additions and 14 deletions
+2 -1
View File
@@ -1019,7 +1019,8 @@ static int lookup_block_device(const char *p, dev_t *ret) {
}
/* If this is a LUKS/DM device, recursively try to get the originating block device */
while (block_get_originating(*ret, ret) > 0);
while (block_get_originating(*ret, ret) >= 0)
;
/* If this is a partition, try to get the originating block device */
(void) block_get_whole_disk(*ret, ret);
@@ -143,13 +143,14 @@ static bool validate_efi_hibernate_location(EFIHibernateLocation *e) {
int get_efi_hibernate_location(EFIHibernateLocation **ret) {
#if ENABLE_EFI
static const sd_json_dispatch_field dispatch_table[] = {
{ "uuid", SD_JSON_VARIANT_STRING, sd_json_dispatch_id128, offsetof(EFIHibernateLocation, uuid), SD_JSON_MANDATORY },
{ "offset", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(EFIHibernateLocation, offset), SD_JSON_MANDATORY },
{ "kernelVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, kernel_version), SD_JSON_PERMISSIVE },
{ "osReleaseId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, id), SD_JSON_PERMISSIVE },
{ "osReleaseImageId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, image_id), SD_JSON_PERMISSIVE },
{ "osReleaseVersionId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, version_id), SD_JSON_PERMISSIVE|SD_JSON_DEBUG },
{ "osReleaseImageVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, image_version), SD_JSON_PERMISSIVE|SD_JSON_DEBUG },
{ "uuid", SD_JSON_VARIANT_STRING, sd_json_dispatch_id128, offsetof(EFIHibernateLocation, uuid), SD_JSON_MANDATORY },
{ "offset", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(EFIHibernateLocation, offset), SD_JSON_MANDATORY },
{ "autoSwap", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(EFIHibernateLocation, auto_swap), 0 },
{ "kernelVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, kernel_version), SD_JSON_PERMISSIVE },
{ "osReleaseId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, id), SD_JSON_PERMISSIVE },
{ "osReleaseImageId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, image_id), SD_JSON_PERMISSIVE },
{ "osReleaseVersionId", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, version_id), SD_JSON_PERMISSIVE|SD_JSON_DEBUG },
{ "osReleaseImageVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(EFIHibernateLocation, image_version), SD_JSON_PERMISSIVE|SD_JSON_DEBUG },
{},
};
@@ -16,6 +16,10 @@ typedef struct EFIHibernateLocation {
sd_id128_t uuid;
uint64_t offset;
/* Whether the device we hibernated into is the "auto" one, i.e. will show up as
* /dev/disk/by-designator/swap(-luks). */
bool auto_swap;
char *kernel_version;
char *id;
char *image_id;
@@ -2,6 +2,9 @@
#include "alloc-util.h"
#include "dropin.h"
#include "efi-loader.h"
#include "fd-util.h"
#include "fileio.h"
#include "generator.h"
#include "hibernate-resume-config.h"
#include "initrd-util.h"
@@ -15,6 +18,7 @@
#include "unit-name.h"
static const char *arg_dest = NULL;
static const char *arg_dest_late = NULL;
static char *arg_resume_options = NULL;
static char *arg_root_options = NULL;
static bool arg_noresume = false;
@@ -54,6 +58,58 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
}
#define DISSECTED_SWAP_LUKS_DEVICE "/dev/disk/by-designator/swap-luks"
#define DISSECTED_SWAP_LUKS_DEVICE_UNIT "dev-disk-by\\x2ddesignator-swap\\x2dluks.device"
static int add_dissected_swap_cryptsetup(void) {
#if HAVE_LIBCRYPTSETUP
_cleanup_fclose_ FILE *f = NULL;
int r;
/* Write out cryptsetup unit for the "auto" swap device (/dev/disk/by-designator/swap-luks), so that
* resume from hibernation can be automatically initiated there. This mostly follows what gpt-auto does,
* but operates in initrd. */
r = generator_open_unit_file(arg_dest_late, /* source = */ NULL, "systemd-cryptsetup@swap.service", &f);
if (r < 0)
return r;
r = generator_write_cryptsetup_unit_section(f, /* source = */ NULL);
if (r < 0)
return r;
fputs("Before=umount.target cryptsetup.target\n"
"Conflicts=umount.target\n"
"BindsTo="DISSECTED_SWAP_LUKS_DEVICE_UNIT"\n"
"After="DISSECTED_SWAP_LUKS_DEVICE_UNIT"\n",
f);
r = generator_write_cryptsetup_service_section(
f, "swap", DISSECTED_SWAP_LUKS_DEVICE,
/* key_file = */ NULL,
efi_measured_uki(LOG_DEBUG) > 0 ? "tpm2-device=auto" : NULL);
if (r < 0)
return r;
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write cryptsetup unit for " DISSECTED_SWAP_LUKS_DEVICE ": %m");
r = generator_write_device_timeout(arg_dest_late,
DISSECTED_SWAP_LUKS_DEVICE,
arg_resume_options ?: arg_root_options, /* filtered = */ NULL);
if (r < 0)
return r;
return generator_add_symlink(arg_dest_late, DISSECTED_SWAP_LUKS_DEVICE_UNIT, "wants", "systemd-cryptsetup@swap.service");
#else
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"systemd-hibernate-resume-generator was compiled without libcryptsetup support, "
"not generating cryptsetup unit for " DISSECTED_SWAP_LUKS_DEVICE ".");
#endif
}
static int process_resume(const HibernateInfo *info) {
_cleanup_free_ char *device_unit = NULL;
int r;
@@ -89,6 +145,12 @@ static int process_resume(const HibernateInfo *info) {
if (r < 0)
return log_error_errno(r, "Failed to write device dependency drop-in: %m");
/* Generate cryptsetup unit for /dev/disk/by-designator/swap-luks if we hibernated into it, but only
* if resume= is not specified, on the assumption that the user would have everything configured
* manually otherwise. */
if (!info->cmdline && info->efi->auto_swap)
(void) add_dissected_swap_cryptsetup();
return generator_add_symlink(arg_dest, SPECIAL_SYSINIT_TARGET, "wants", SPECIAL_HIBERNATE_RESUME_SERVICE);
}
@@ -97,6 +159,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
int r;
arg_dest = ASSERT_PTR(dest);
arg_dest_late = ASSERT_PTR(dest_late);
/* Don't even consider resuming outside of initrd. */
if (!in_initrd()) {
+4 -4
View File
@@ -138,7 +138,7 @@ int block_device_get_originating(sd_device *dev, sd_device **ret) {
return -ENOENT;
*ret = TAKE_PTR(first_found);
return 1; /* found */
return 0;
}
int block_device_new_from_fd(int fd, BlockDeviceLookupFlag flags, sd_device **ret) {
@@ -166,10 +166,10 @@ int block_device_new_from_fd(int fd, BlockDeviceLookupFlag flags, sd_device **re
return r;
r = block_device_get_originating(dev_whole_disk, &dev_origin);
if (r < 0 && r != -ENOENT)
return r;
if (r > 0)
if (r >= 0)
device_unref_and_replace(dev, dev_origin);
else if (r != -ENOENT)
return r;
}
if (FLAGS_SET(flags, BLOCK_DEVICE_LOOKUP_WHOLE_DISK)) {
+37 -1
View File
@@ -21,6 +21,7 @@
#include "battery-capacity.h"
#include "battery-util.h"
#include "blockdev-util.h"
#include "build.h"
#include "bus-error.h"
#include "bus-locator.h"
@@ -53,6 +54,35 @@
static SleepOperation arg_operation = _SLEEP_OPERATION_INVALID;
#if ENABLE_EFI
static int determine_auto_swap(sd_device *device) {
_cleanup_(sd_device_unrefp) sd_device *origin = NULL;
const char *part_designator;
int r;
/* Check if the selected hibernation device is the "auto" one. Specifically, trace to the partition
* block device and check if ID_DISSECT_PART_DESIGNATOR property is set to "swap" by udev
* dissect_image builtin. Later hibernate-resume-generator will generate cryptsetup unit based on
* this info. */
assert(device);
r = block_device_get_originating(device, &origin);
if (r < 0 && r != -ENOENT)
return r;
if (r >= 0)
device = origin;
r = sd_device_get_property_value(device, "ID_DISSECT_PART_DESIGNATOR", &part_designator);
if (r == -ENOENT)
return false;
if (r < 0)
return r;
return streq(part_designator, "swap");
}
#endif
static int write_efi_hibernate_location(const HibernationDevice *hibernation_device, bool required) {
int log_level = required ? LOG_ERR : LOG_DEBUG;
@@ -64,7 +94,7 @@ static int write_efi_hibernate_location(const HibernationDevice *hibernation_dev
const char *uuid_str;
sd_id128_t uuid;
struct utsname uts = {};
int r, log_level_ignore = required ? LOG_WARNING : LOG_DEBUG;
int r, auto_swap, log_level_ignore = required ? LOG_WARNING : LOG_DEBUG;
assert(hibernation_device);
@@ -87,6 +117,11 @@ static int write_efi_hibernate_location(const HibernationDevice *hibernation_dev
return log_full_errno(log_level, r, "Failed to parse ID_FS_UUID '%s' for device '%s': %m",
uuid_str, hibernation_device->path);
auto_swap = determine_auto_swap(device);
if (auto_swap < 0)
log_full_errno(log_level_ignore, auto_swap,
"Failed to get partition designator of '%s', ignoring: %m", hibernation_device->path);
if (uname(&uts) < 0)
log_full_errno(log_level_ignore, errno, "Failed to get kernel info, ignoring: %m");
@@ -102,6 +137,7 @@ static int write_efi_hibernate_location(const HibernationDevice *hibernation_dev
&v,
SD_JSON_BUILD_PAIR_UUID("uuid", uuid),
SD_JSON_BUILD_PAIR_UNSIGNED("offset", hibernation_device->offset),
SD_JSON_BUILD_PAIR_CONDITION(auto_swap >= 0, "autoSwap", SD_JSON_BUILD_BOOLEAN(auto_swap)),
SD_JSON_BUILD_PAIR_CONDITION(!isempty(uts.release), "kernelVersion", SD_JSON_BUILD_STRING(uts.release)),
SD_JSON_BUILD_PAIR_CONDITION(!!id, "osReleaseId", SD_JSON_BUILD_STRING(id)),
SD_JSON_BUILD_PAIR_CONDITION(!!image_id, "osReleaseImageId", SD_JSON_BUILD_STRING(image_id)),
+1 -1
View File
@@ -842,7 +842,7 @@ static void device_track_back(sd_device *d, sd_device **ret) {
_cleanup_(sd_device_unrefp) sd_device *d_originating = NULL;
r = block_device_get_originating(d, &d_originating);
if (r < 0)
if (r < 0 && r != -ENOENT)
log_device_debug_errno(d, r, "Failed to get originating device for '%s', ignoring: %m", strna(devname));
sd_device *d_whole = NULL;