Merge pull request #12760 from zachsmith/systemd-sleep_resume_offset

systemd-sleep: use resume_offset value if set
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-06-27 13:37:27 +02:00 committed by GitHub
commit dc2c231684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 6 deletions

4
TODO
View File

@ -56,10 +56,6 @@ Features:
with a nice speed-up on services that have many processes running in the same with a nice speed-up on services that have many processes running in the same
cgroup. cgroup.
* clean up sleep.c:
- Make sure resume= and resume_offset= on the kernel cmdline always take
precedence
* make MAINPID= message reception checks even stricter: if service uses User=, * make MAINPID= message reception checks even stricter: if service uses User=,
then check sending UID and ignore message if it doesn't match the user or then check sending UID and ignore message if it doesn't match the user or
root. root.

View File

@ -178,6 +178,7 @@ int find_hibernate_location(char **device, char **type, size_t *size, size_t *us
(void) fscanf(f, "%*s %*s %*s %*s %*s\n"); (void) fscanf(f, "%*s %*s %*s %*s %*s\n");
// TODO: sort swaps in priority order rather than using first successful option
for (i = 1;; i++) { for (i = 1;; i++) {
_cleanup_free_ char *dev_field = NULL, *type_field = NULL; _cleanup_free_ char *dev_field = NULL, *type_field = NULL;
size_t size_field, used_field; size_t size_field, used_field;

View File

@ -17,6 +17,7 @@
#include "sd-messages.h" #include "sd-messages.h"
#include "btrfs-util.h"
#include "def.h" #include "def.h"
#include "exec-util.h" #include "exec-util.h"
#include "fd-util.h" #include "fd-util.h"
@ -80,6 +81,14 @@ static int write_hibernate_location_info(void) {
if (r < 0) if (r < 0)
return log_debug_errno(errno, "Unable to stat %s: %m", device); return log_debug_errno(errno, "Unable to stat %s: %m", device);
r = btrfs_is_filesystem(fd);
if (r < 0)
return log_error_errno(r, "Error checking %s for Btrfs filesystem: %m", device);
if (r)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Unable to calculate swapfile offset when using Btrfs: %s", device);
r = read_fiemap(fd, &fiemap); r = read_fiemap(fd, &fiemap);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Unable to read extent map for '%s': %m", device); return log_debug_errno(r, "Unable to read extent map for '%s': %m", device);
@ -93,11 +102,15 @@ static int write_hibernate_location_info(void) {
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to write offset '%s': %m", offset_str); return log_debug_errno(r, "Failed to write offset '%s': %m", offset_str);
log_debug("Wrote calculated resume_offset value to /sys/power/resume_offset: %s", offset_str);
xsprintf(device_str, "%lx", (unsigned long)stb.st_dev); xsprintf(device_str, "%lx", (unsigned long)stb.st_dev);
r = write_string_file("/sys/power/resume", device_str, WRITE_STRING_FILE_DISABLE_BUFFER); r = write_string_file("/sys/power/resume", device_str, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to write device '%s': %m", device_str); return log_debug_errno(r, "Failed to write device '%s': %m", device_str);
log_debug("Wrote device id to /sys/power/resume: %s", device_str);
return 0; return 0;
} }
@ -143,6 +156,32 @@ static int write_state(FILE **f, char **states) {
return r; return r;
} }
static int configure_hibernation(void) {
_cleanup_free_ char *resume = NULL, *resume_offset = NULL;
int r;
/* check for proper hibernation configuration */
r = read_one_line_file("/sys/power/resume", &resume);
if (r < 0)
return log_debug_errno(r, "Error reading from /sys/power/resume: %m");
r = read_one_line_file("/sys/power/resume_offset", &resume_offset);
if (r < 0)
return log_debug_errno(r, "Error reading from /sys/power/resume_offset: %m");
if (!streq(resume_offset, "0") && !streq(resume, "0:0")) {
log_debug("Hibernating using device id and offset read from /sys/power/resume: %s and /sys/power/resume_offset: %s", resume, resume_offset);
return 0;
} else if (!streq(resume, "0:0")) {
log_debug("Hibernating using device id read from /sys/power/resume: %s", resume);
return 0;
} else if (!streq(resume_offset, "0"))
log_debug("Found offset in /sys/power/resume_offset: %s; no device id found in /sys/power/resume; ignoring offset", resume_offset);
/* if hibernation is not properly configured, attempt to calculate and write values */
return write_hibernate_location_info();
}
static int execute(char **modes, char **states) { static int execute(char **modes, char **states) {
char *arguments[] = { char *arguments[] = {
NULL, NULL,
@ -168,9 +207,10 @@ static int execute(char **modes, char **states) {
/* Configure the hibernation mode */ /* Configure the hibernation mode */
if (!strv_isempty(modes)) { if (!strv_isempty(modes)) {
r = write_hibernate_location_info(); r = configure_hibernation();
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write hibernation disk offset: %m"); return log_error_errno(r, "Failed to prepare for hibernation: %m");
r = write_mode(modes); r = write_mode(modes);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");; return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;