summaryrefslogtreecommitdiff
path: root/src/sleep/sleep.c
diff options
context:
space:
mode:
authorZach Smith <z@zxmth.us>2019-06-08 20:44:34 -0700
committerZach Smith <z@zxmth.us>2019-06-26 22:04:59 -0700
commit2002d8cdaee105a7ab6bc89d480a9ded2198247a (patch)
tree74a508b4559902b1cd554273e1dfdb5ddd4493de /src/sleep/sleep.c
parenta7c5865098bac384f47a141f7d96b3e635afacdc (diff)
downloadsystemd-2002d8cdaee105a7ab6bc89d480a9ded2198247a.tar.gz
systemd-sleep: (bug) use resume_offset value if set
Use hibernation configuration as defined in /sys/power/resume and /sys/power/resume_offset if present before inspecting /proc/swaps and attempting to calculate swapfile offset
Diffstat (limited to 'src/sleep/sleep.c')
-rw-r--r--src/sleep/sleep.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index c38aa4ccf6..435e5592e6 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -80,6 +80,7 @@ static int write_hibernate_location_info(void) {
if (r < 0)
return log_debug_errno(errno, "Unable to stat %s: %m", device);
+ // TODO check for btrfs and fail if offset is not provided; calculation will fail
r = read_fiemap(fd, &fiemap);
if (r < 0)
return log_debug_errno(r, "Unable to read extent map for '%s': %m", device);
@@ -93,11 +94,15 @@ static int write_hibernate_location_info(void) {
if (r < 0)
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);
r = write_string_file("/sys/power/resume", device_str, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
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;
}
@@ -143,6 +148,32 @@ static int write_state(FILE **f, char **states) {
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) {
char *arguments[] = {
NULL,
@@ -168,9 +199,10 @@ static int execute(char **modes, char **states) {
/* Configure the hibernation mode */
if (!strv_isempty(modes)) {
- r = write_hibernate_location_info();
+ r = configure_hibernation();
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);
if (r < 0)
return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;