mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
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
This commit is contained in:
parent
a7c5865098
commit
2002d8cdae
4
TODO
4
TODO
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -80,6 +80,7 @@ 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);
|
||||||
|
|
||||||
|
// TODO check for btrfs and fail if offset is not provided; calculation will fail
|
||||||
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 +94,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 +148,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 +199,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");;
|
||||||
|
Loading…
Reference in New Issue
Block a user