1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2018 Dell Inc.
9 #include <linux/magic.h>
12 #include <sys/ioctl.h>
14 #include <sys/types.h>
18 #include "sd-device.h"
20 #include "alloc-util.h"
21 #include "battery-util.h"
22 #include "blockdev-util.h"
23 #include "btrfs-util.h"
24 #include "conf-parser.h"
25 #include "constants.h"
26 #include "device-private.h"
27 #include "device-util.h"
28 #include "devnum-util.h"
30 #include "errno-util.h"
33 #include "hexdecoct.h"
34 #include "id128-util.h"
37 #include "path-util.h"
38 #include "siphash24.h"
39 #include "sleep-util.h"
40 #include "stat-util.h"
41 #include "stdio-util.h"
42 #include "string-table.h"
43 #include "string-util.h"
45 #include "time-util.h"
47 #define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour"
48 #define BATTERY_DISCHARGE_RATE_HASH_KEY SD_ID128_MAKE(5f,9a,20,18,38,76,46,07,8d,36,58,0b,bb,c4,e0,63)
50 static void *CAPACITY_TO_PTR(int capacity
) {
51 assert(capacity
>= 0);
52 assert(capacity
<= 100);
53 return INT_TO_PTR(capacity
+ 1);
56 static int PTR_TO_CAPACITY(void *p
) {
57 int capacity
= PTR_TO_INT(p
) - 1;
58 assert(capacity
>= 0);
59 assert(capacity
<= 100);
63 int parse_sleep_config(SleepConfig
**ret_sleep_config
) {
64 _cleanup_(free_sleep_configp
) SleepConfig
*sc
= NULL
;
65 int allow_suspend
= -1, allow_hibernate
= -1,
66 allow_s2h
= -1, allow_hybrid_sleep
= -1;
68 sc
= new(SleepConfig
, 1);
73 .hibernate_delay_usec
= USEC_INFINITY
,
76 const ConfigTableItem items
[] = {
77 { "Sleep", "AllowSuspend", config_parse_tristate
, 0, &allow_suspend
},
78 { "Sleep", "AllowHibernation", config_parse_tristate
, 0, &allow_hibernate
},
79 { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate
, 0, &allow_s2h
},
80 { "Sleep", "AllowHybridSleep", config_parse_tristate
, 0, &allow_hybrid_sleep
},
82 { "Sleep", "SuspendMode", config_parse_strv
, 0, sc
->modes
+ SLEEP_SUSPEND
},
83 { "Sleep", "SuspendState", config_parse_strv
, 0, sc
->states
+ SLEEP_SUSPEND
},
84 { "Sleep", "HibernateMode", config_parse_strv
, 0, sc
->modes
+ SLEEP_HIBERNATE
},
85 { "Sleep", "HibernateState", config_parse_strv
, 0, sc
->states
+ SLEEP_HIBERNATE
},
86 { "Sleep", "HybridSleepMode", config_parse_strv
, 0, sc
->modes
+ SLEEP_HYBRID_SLEEP
},
87 { "Sleep", "HybridSleepState", config_parse_strv
, 0, sc
->states
+ SLEEP_HYBRID_SLEEP
},
89 { "Sleep", "HibernateDelaySec", config_parse_sec
, 0, &sc
->hibernate_delay_usec
},
90 { "Sleep", "SuspendEstimationSec", config_parse_sec
, 0, &sc
->suspend_estimation_usec
},
94 (void) config_parse_config_file("sleep.conf", "Sleep\0",
95 config_item_table_lookup
, items
,
96 CONFIG_PARSE_WARN
, NULL
);
98 /* use default values unless set */
99 sc
->allow
[SLEEP_SUSPEND
] = allow_suspend
!= 0;
100 sc
->allow
[SLEEP_HIBERNATE
] = allow_hibernate
!= 0;
101 sc
->allow
[SLEEP_HYBRID_SLEEP
] = allow_hybrid_sleep
>= 0 ? allow_hybrid_sleep
102 : (allow_suspend
!= 0 && allow_hibernate
!= 0);
103 sc
->allow
[SLEEP_SUSPEND_THEN_HIBERNATE
] = allow_s2h
>= 0 ? allow_s2h
104 : (allow_suspend
!= 0 && allow_hibernate
!= 0);
106 if (!sc
->states
[SLEEP_SUSPEND
])
107 sc
->states
[SLEEP_SUSPEND
] = strv_new("mem", "standby", "freeze");
108 if (!sc
->modes
[SLEEP_HIBERNATE
])
109 sc
->modes
[SLEEP_HIBERNATE
] = strv_new("platform", "shutdown");
110 if (!sc
->states
[SLEEP_HIBERNATE
])
111 sc
->states
[SLEEP_HIBERNATE
] = strv_new("disk");
112 if (!sc
->modes
[SLEEP_HYBRID_SLEEP
])
113 sc
->modes
[SLEEP_HYBRID_SLEEP
] = strv_new("suspend", "platform", "shutdown");
114 if (!sc
->states
[SLEEP_HYBRID_SLEEP
])
115 sc
->states
[SLEEP_HYBRID_SLEEP
] = strv_new("disk");
116 if (sc
->suspend_estimation_usec
== 0)
117 sc
->suspend_estimation_usec
= DEFAULT_SUSPEND_ESTIMATION_USEC
;
119 /* Ensure values set for all required fields */
120 if (!sc
->states
[SLEEP_SUSPEND
] || !sc
->modes
[SLEEP_HIBERNATE
]
121 || !sc
->states
[SLEEP_HIBERNATE
] || !sc
->modes
[SLEEP_HYBRID_SLEEP
] || !sc
->states
[SLEEP_HYBRID_SLEEP
])
124 *ret_sleep_config
= TAKE_PTR(sc
);
129 int get_capacity_by_name(Hashmap
*capacities_by_name
, const char *name
) {
132 assert(capacities_by_name
);
135 p
= hashmap_get(capacities_by_name
, name
);
139 return PTR_TO_CAPACITY(p
);
142 /* Store current capacity of each battery before suspension and timestamp */
143 int fetch_batteries_capacity_by_name(Hashmap
**ret
) {
144 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
145 _cleanup_hashmap_free_ Hashmap
*batteries_capacity_by_name
= NULL
;
150 batteries_capacity_by_name
= hashmap_new(&string_hash_ops_free
);
151 if (!batteries_capacity_by_name
)
152 return log_oom_debug();
154 r
= battery_enumerator_new(&e
);
156 return log_debug_errno(r
, "Failed to initialize battery enumerator: %m");
158 FOREACH_DEVICE(e
, dev
) {
159 _cleanup_free_
char *battery_name_copy
= NULL
;
160 const char *battery_name
;
161 int battery_capacity
;
163 battery_capacity
= r
= battery_read_capacity_percentage(dev
);
167 r
= sd_device_get_property_value(dev
, "POWER_SUPPLY_NAME", &battery_name
);
169 log_device_debug_errno(dev
, r
, "Failed to get POWER_SUPPLY_NAME property, ignoring: %m");
173 battery_name_copy
= strdup(battery_name
);
174 if (!battery_name_copy
)
175 return log_oom_debug();
177 r
= hashmap_put(batteries_capacity_by_name
, battery_name_copy
, CAPACITY_TO_PTR(battery_capacity
));
179 return log_device_debug_errno(dev
, r
, "Failed to store battery capacity: %m");
181 TAKE_PTR(battery_name_copy
);
184 *ret
= TAKE_PTR(batteries_capacity_by_name
);
189 static int siphash24_compress_device_sysattr(sd_device
*dev
, const char *attr
, struct siphash
*state
) {
197 r
= sd_device_get_sysattr_value(dev
, attr
, &x
);
199 return log_device_debug_errno(dev
, r
, "Failed to read '%s' attribute: %m", attr
);
202 siphash24_compress_string(x
, state
);
207 static int siphash24_compress_id128(int (*getter
)(sd_id128_t
*), const char *name
, struct siphash
*state
) {
216 return log_debug_errno(r
, "Failed to get %s ID: %m", name
);
218 siphash24_compress(&id
, sizeof(sd_id128_t
), state
);
222 /* Read system and battery identifier from specific location and generate hash of it */
223 static int get_system_battery_identifier_hash(sd_device
*dev
, uint64_t *ret
) {
224 struct siphash state
;
229 siphash24_init(&state
, BATTERY_DISCHARGE_RATE_HASH_KEY
.bytes
);
231 (void) siphash24_compress_device_sysattr(dev
, "manufacturer", &state
);
232 (void) siphash24_compress_device_sysattr(dev
, "model_name", &state
);
233 (void) siphash24_compress_device_sysattr(dev
, "serial_number", &state
);
234 (void) siphash24_compress_id128(sd_id128_get_machine
, "machine", &state
);
235 (void) siphash24_compress_id128(id128_get_product
, "product", &state
);
237 *ret
= siphash24_finalize(&state
);
241 /* Return success if battery percentage discharge rate per hour is in the range 1–199 */
242 static bool battery_discharge_rate_is_valid(int battery_discharge_rate
) {
243 return battery_discharge_rate
> 0 && battery_discharge_rate
< 200;
246 /* Battery percentage discharge rate per hour is read from specific file. It is stored along with system
247 * and battery identifier hash to maintain the integrity of discharge rate value */
248 static int get_battery_discharge_rate(sd_device
*dev
, int *ret
) {
249 _cleanup_fclose_
FILE *f
= NULL
;
250 uint64_t current_hash_id
;
257 f
= fopen(DISCHARGE_RATE_FILEPATH
, "re");
259 return log_debug_errno(errno
, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH
": %m");
261 r
= get_system_battery_identifier_hash(dev
, ¤t_hash_id
);
263 return log_device_debug_errno(dev
, r
, "Failed to generate system battery identifier hash: %m");
266 _cleanup_free_
char *stored_hash_id
= NULL
, *stored_discharge_rate
= NULL
, *line
= NULL
;
270 r
= read_line(f
, LONG_LINE_MAX
, &line
);
272 return log_debug_errno(r
, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH
": %m");
277 r
= extract_many_words(&p
, NULL
, 0, &stored_hash_id
, &stored_discharge_rate
, NULL
);
279 return log_debug_errno(r
, "Failed to parse hash_id and discharge_rate read from " DISCHARGE_RATE_FILEPATH
": %m");
281 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid number of items fetched from " DISCHARGE_RATE_FILEPATH
);
283 r
= safe_atou64(stored_hash_id
, &hash_id
);
285 return log_debug_errno(r
, "Failed to parse hash ID read from " DISCHARGE_RATE_FILEPATH
" location: %m");
287 if (current_hash_id
!= hash_id
)
288 /* matching device not found, move to next line */
291 r
= safe_atoi(stored_discharge_rate
, &discharge_rate
);
293 return log_device_debug_errno(dev
, r
, "Failed to parse discharge rate read from " DISCHARGE_RATE_FILEPATH
": %m");
295 if (!battery_discharge_rate_is_valid(discharge_rate
))
296 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ERANGE
), "Invalid battery discharge percentage rate per hour: %m");
298 *ret
= discharge_rate
;
299 return 0; /* matching device found, exit iteration */
305 /* Write battery percentage discharge rate per hour along with system and battery identifier hash to file */
306 static int put_battery_discharge_rate(int estimated_battery_discharge_rate
, uint64_t system_hash_id
, bool trunc
) {
309 if (!battery_discharge_rate_is_valid(estimated_battery_discharge_rate
))
310 return log_debug_errno(SYNTHETIC_ERRNO(ERANGE
),
311 "Invalid battery discharge rate %d%% per hour: %m",
312 estimated_battery_discharge_rate
);
314 r
= write_string_filef(
315 DISCHARGE_RATE_FILEPATH
,
316 WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_MKDIR_0755
| (trunc
? WRITE_STRING_FILE_TRUNCATE
: 0),
319 estimated_battery_discharge_rate
);
321 return log_debug_errno(r
, "Failed to update %s: %m", DISCHARGE_RATE_FILEPATH
);
323 log_debug("Estimated discharge rate %d%% per hour successfully saved to %s", estimated_battery_discharge_rate
, DISCHARGE_RATE_FILEPATH
);
328 /* Estimate battery discharge rate using stored previous and current capacity over timestamp difference */
329 int estimate_battery_discharge_rate_per_hour(
330 Hashmap
*last_capacity
,
331 Hashmap
*current_capacity
,
332 usec_t before_timestamp
,
333 usec_t after_timestamp
) {
335 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
339 assert(last_capacity
);
340 assert(current_capacity
);
341 assert(before_timestamp
< after_timestamp
);
343 r
= battery_enumerator_new(&e
);
345 return log_debug_errno(r
, "Failed to initialize battery enumerator: %m");
347 FOREACH_DEVICE(e
, dev
) {
348 int battery_last_capacity
, battery_current_capacity
, battery_discharge_rate
;
349 const char *battery_name
;
350 uint64_t system_hash_id
;
352 r
= sd_device_get_property_value(dev
, "POWER_SUPPLY_NAME", &battery_name
);
354 log_device_debug_errno(dev
, r
, "Failed to read battery name, ignoring: %m");
358 battery_last_capacity
= get_capacity_by_name(last_capacity
, battery_name
);
359 if (battery_last_capacity
< 0)
362 battery_current_capacity
= get_capacity_by_name(current_capacity
, battery_name
);
363 if (battery_current_capacity
< 0)
366 if (battery_current_capacity
>= battery_last_capacity
) {
367 log_device_debug(dev
, "Battery was not discharged during suspension");
371 r
= get_system_battery_identifier_hash(dev
, &system_hash_id
);
373 return log_device_debug_errno(dev
, r
, "Failed to generate system battery identifier hash: %m");
375 log_device_debug(dev
,
376 "%d%% was discharged in %s. Estimating discharge rate...",
377 battery_last_capacity
- battery_current_capacity
,
378 FORMAT_TIMESPAN(after_timestamp
- before_timestamp
, USEC_PER_SEC
));
380 battery_discharge_rate
= (battery_last_capacity
- battery_current_capacity
) * USEC_PER_HOUR
/ (after_timestamp
- before_timestamp
);
381 r
= put_battery_discharge_rate(battery_discharge_rate
, system_hash_id
, trunc
);
383 log_device_warning_errno(dev
, r
, "Failed to update battery discharge rate, ignoring: %m");
391 /* Calculate the suspend interval for each battery and then return their sum */
392 int get_total_suspend_interval(Hashmap
*last_capacity
, usec_t
*ret
) {
393 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
394 usec_t total_suspend_interval
= 0;
397 assert(last_capacity
);
400 r
= battery_enumerator_new(&e
);
402 return log_debug_errno(r
, "Failed to initialize battery enumerator: %m");
404 FOREACH_DEVICE(e
, dev
) {
405 int battery_last_capacity
, previous_discharge_rate
= 0;
406 const char *battery_name
;
407 usec_t suspend_interval
;
409 r
= sd_device_get_property_value(dev
, "POWER_SUPPLY_NAME", &battery_name
);
411 log_device_debug_errno(dev
, r
, "Failed to read battery name, ignoring: %m");
415 battery_last_capacity
= get_capacity_by_name(last_capacity
, battery_name
);
416 if (battery_last_capacity
<= 0)
419 r
= get_battery_discharge_rate(dev
, &previous_discharge_rate
);
421 log_device_debug_errno(dev
, r
, "Failed to get discharge rate, ignoring: %m");
425 if (previous_discharge_rate
== 0)
428 if (battery_last_capacity
* 2 <= previous_discharge_rate
) {
429 log_device_debug(dev
, "Current battery capacity percentage too low compared to discharge rate");
432 suspend_interval
= battery_last_capacity
* USEC_PER_HOUR
/ previous_discharge_rate
;
434 total_suspend_interval
= usec_add(total_suspend_interval
, suspend_interval
);
436 /* Previous discharge rate is stored in per hour basis converted to usec.
437 * Subtract 30 minutes from the result to keep a buffer of 30 minutes before battery gets critical */
438 total_suspend_interval
= usec_sub_unsigned(total_suspend_interval
, 30 * USEC_PER_MINUTE
);
439 if (total_suspend_interval
== 0)
442 *ret
= total_suspend_interval
;
447 /* Return true if all batteries have acpi_btp support */
448 int battery_trip_point_alarm_exists(void) {
449 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
452 r
= battery_enumerator_new(&e
);
454 return log_debug_errno(r
, "Failed to initialize battery enumerator: %m");
456 FOREACH_DEVICE(e
, dev
) {
460 r
= sd_device_get_sysattr_value(dev
, "alarm", &s
);
462 return log_device_debug_errno(dev
, r
, "Failed to read battery alarm: %m");
464 r
= safe_atoi(s
, &battery_alarm
);
466 return log_device_debug_errno(dev
, r
, "Failed to parse battery alarm: %m");
467 if (battery_alarm
<= 0)
474 /* Return true if wakeup type is APM timer */
475 int check_wakeup_type(void) {
476 static const char dmi_object_path
[] = "/sys/firmware/dmi/entries/1-0/raw";
477 uint8_t wakeup_type_byte
, tablesize
;
478 _cleanup_free_
char *buf
= NULL
;
482 /* implementation via dmi/entries */
483 r
= read_full_virtual_file(dmi_object_path
, &buf
, &bufsize
);
485 return log_debug_errno(r
, "Unable to read %s: %m", dmi_object_path
);
487 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Only read %zu bytes from %s (expected 25)", bufsize
, dmi_object_path
);
489 /* index 1 stores the size of table */
490 tablesize
= (uint8_t) buf
[1];
492 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Table size lesser than the index[0x18] where waketype byte is available.");
494 wakeup_type_byte
= (uint8_t) buf
[24];
495 /* 0 is Reserved and 8 is AC Power Restored. As per table 12 in
496 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf */
497 if (wakeup_type_byte
>= 128)
498 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Expected value in range 0-127");
500 if (wakeup_type_byte
== 3) {
501 log_debug("DMI BIOS System Information indicates wakeup type is APM Timer");
508 int can_sleep_state(char **requested_types
) {
509 _cleanup_free_
char *text
= NULL
;
512 if (strv_isempty(requested_types
))
515 /* If /sys is read-only we cannot sleep */
516 if (access("/sys/power/state", W_OK
) < 0) {
517 log_debug_errno(errno
, "/sys/power/state is not writable, cannot sleep: %m");
521 r
= read_one_line_file("/sys/power/state", &text
);
523 log_debug_errno(r
, "Failed to read /sys/power/state, cannot sleep: %m");
528 r
= string_contains_word_strv(text
, NULL
, requested_types
, &found
);
530 return log_debug_errno(r
, "Failed to parse /sys/power/state: %m");
532 log_debug("Sleep mode \"%s\" is supported by the kernel.", found
);
533 else if (DEBUG_LOGGING
) {
534 _cleanup_free_
char *t
= strv_join(requested_types
, "/");
535 log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t
));
540 int can_sleep_disk(char **types
) {
541 _cleanup_free_
char *text
= NULL
;
544 if (strv_isempty(types
))
547 /* If /sys is read-only we cannot sleep */
548 if (access("/sys/power/disk", W_OK
) < 0) {
549 log_debug_errno(errno
, "/sys/power/disk is not writable: %m");
553 r
= read_one_line_file("/sys/power/disk", &text
);
555 log_debug_errno(r
, "Couldn't read /sys/power/disk: %m");
559 for (const char *p
= text
;;) {
560 _cleanup_free_
char *word
= NULL
;
562 r
= extract_first_word(&p
, &word
, NULL
, 0);
564 return log_debug_errno(r
, "Failed to parse /sys/power/disk: %m");
569 size_t l
= strlen(s
);
570 if (s
[0] == '[' && s
[l
-1] == ']') {
575 if (strv_contains(types
, s
)) {
576 log_debug("Disk sleep mode \"%s\" is supported by the kernel.", s
);
582 _cleanup_free_
char *t
= strv_join(types
, "/");
583 log_debug("Disk sleep mode %s not supported by the kernel, sorry.", strnull(t
));
588 #define HIBERNATION_SWAP_THRESHOLD 0.98
590 SwapEntry
* swap_entry_free(SwapEntry
*se
) {
599 HibernateLocation
* hibernate_location_free(HibernateLocation
*hl
) {
603 swap_entry_free(hl
->swap
);
608 static int swap_device_to_devnum(const SwapEntry
*swap
, dev_t
*ret_dev
) {
609 _cleanup_close_
int fd
= -EBADF
;
616 fd
= open(swap
->path
, O_CLOEXEC
|O_PATH
);
620 if (fstat(fd
, &sb
) < 0)
623 if (swap
->type
== SWAP_BLOCK
) {
624 if (!S_ISBLK(sb
.st_mode
))
627 *ret_dev
= sb
.st_rdev
;
631 r
= stat_verify_regular(&sb
);
635 return get_block_device_fd(fd
, ret_dev
);
639 * Attempt to calculate the swap file offset on supported filesystems. On unsupported
640 * filesystems, a debug message is logged and ret_offset is set to UINT64_MAX.
642 static int calculate_swap_file_offset(const SwapEntry
*swap
, uint64_t *ret_offset
) {
643 _cleanup_close_
int fd
= -EBADF
;
644 _cleanup_free_
struct fiemap
*fiemap
= NULL
;
649 assert(swap
->type
== SWAP_FILE
);
652 fd
= open(swap
->path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
654 return log_debug_errno(errno
, "Failed to open swap file %s to determine on-disk offset: %m", swap
->path
);
656 r
= fd_verify_regular(fd
);
658 return log_debug_errno(r
, "Selected swap file is not a regular file.");
660 r
= fd_is_fs_type(fd
, BTRFS_SUPER_MAGIC
);
662 return log_debug_errno(r
, "Error checking %s for Btrfs filesystem: %m", swap
->path
);
664 log_debug("%s: detection of swap file offset on Btrfs is not supported", swap
->path
);
665 *ret_offset
= UINT64_MAX
;
669 r
= read_fiemap(fd
, &fiemap
);
671 return log_debug_errno(r
, "Unable to read extent map for '%s': %m", swap
->path
);
673 *ret_offset
= fiemap
->fm_extents
[0].fe_physical
/ page_size();
677 static int read_resume_files(dev_t
*ret_resume
, uint64_t *ret_resume_offset
) {
678 _cleanup_free_
char *resume_str
= NULL
, *resume_offset_str
= NULL
;
679 uint64_t resume_offset
;
684 assert(ret_resume_offset
);
686 r
= read_one_line_file("/sys/power/resume", &resume_str
);
688 return log_debug_errno(r
, "Error reading /sys/power/resume: %m");
690 r
= parse_devnum(resume_str
, &resume
);
692 return log_debug_errno(r
, "Error parsing /sys/power/resume device: %s: %m", resume_str
);
694 r
= read_one_line_file("/sys/power/resume_offset", &resume_offset_str
);
696 log_debug_errno(r
, "Kernel does not support resume_offset; swap file offset detection will be skipped.");
699 return log_debug_errno(r
, "Error reading /sys/power/resume_offset: %m");
701 r
= safe_atou64(resume_offset_str
, &resume_offset
);
703 return log_debug_errno(r
, "Failed to parse value in /sys/power/resume_offset \"%s\": %m", resume_offset_str
);
706 if (resume_offset
> 0 && resume
== 0)
707 log_debug("Warning: found /sys/power/resume_offset==%" PRIu64
", but /sys/power/resume unset. Misconfiguration?",
710 *ret_resume
= resume
;
711 *ret_resume_offset
= resume_offset
;
716 * Determine if the HibernateLocation matches the resume= (device) and resume_offset= (file).
718 static bool location_is_resume_device(const HibernateLocation
*location
, dev_t sys_resume
, uint64_t sys_offset
) {
722 return sys_resume
> 0 &&
723 sys_resume
== location
->devno
&&
724 (sys_offset
== location
->offset
|| (sys_offset
> 0 && location
->offset
== UINT64_MAX
));
728 * Attempt to find the hibernation location by parsing /proc/swaps, /sys/power/resume, and
729 * /sys/power/resume_offset.
732 * Never use a device or file as location that hasn't been somehow specified by a user that would also be
733 * entrusted with full system memory access (for example via /sys/power/resume) or that isn't an already
735 * Otherwise various security attacks might become possible, for example an attacker could silently attach
736 * such a device and circumvent full disk encryption when it would be automatically used for hibernation.
737 * Also, having a swap area on top of encryption is not per se enough to protect from all such attacks.
740 * 1 - Values are set in /sys/power/resume and /sys/power/resume_offset.
741 * ret_hibernate_location will represent matching /proc/swap entry if identified or NULL if not.
743 * 0 - No values are set in /sys/power/resume and /sys/power/resume_offset.
744 ret_hibernate_location will represent the highest priority swap with most remaining space discovered in /proc/swaps.
746 * Negative value in the case of error.
748 int find_hibernate_location(HibernateLocation
**ret_hibernate_location
) {
749 _cleanup_fclose_
FILE *f
= NULL
;
750 _cleanup_(hibernate_location_freep
) HibernateLocation
*hibernate_location
= NULL
;
751 dev_t sys_resume
= 0; /* Unnecessary initialization to appease gcc */
752 uint64_t sys_offset
= 0;
753 bool resume_match
= false;
756 /* read the /sys/power/resume & /sys/power/resume_offset values */
757 r
= read_resume_files(&sys_resume
, &sys_offset
);
761 f
= fopen("/proc/swaps", "re");
763 log_debug_errno(errno
, "Failed to open /proc/swaps: %m");
764 return errno
== ENOENT
? -EOPNOTSUPP
: -errno
; /* Convert swap not supported to a recognizable error */
767 (void) fscanf(f
, "%*s %*s %*s %*s %*s\n");
768 for (unsigned i
= 1;; i
++) {
769 _cleanup_(swap_entry_freep
) SwapEntry
*swap
= NULL
;
770 _cleanup_free_
char *type
= NULL
;
771 uint64_t swap_offset
= 0;
774 swap
= new(SwapEntry
, 1);
778 *swap
= (SwapEntry
) {
779 .type
= _SWAP_TYPE_INVALID
,
783 "%ms " /* device/file path */
784 "%ms " /* type of swap */
785 "%" PRIu64
/* swap size */
786 "%" PRIu64
/* used */
787 "%i\n", /* priority */
788 &swap
->path
, &type
, &swap
->size
, &swap
->used
, &swap
->priority
);
792 log_debug("Failed to parse /proc/swaps:%u, ignoring", i
);
796 if (streq(type
, "file")) {
798 if (endswith(swap
->path
, "\\040(deleted)")) {
799 log_debug("Ignoring deleted swap file '%s'.", swap
->path
);
803 swap
->type
= SWAP_FILE
;
805 r
= calculate_swap_file_offset(swap
, &swap_offset
);
809 } else if (streq(type
, "partition")) {
812 fn
= path_startswith(swap
->path
, "/dev/");
813 if (fn
&& startswith(fn
, "zram")) {
814 log_debug("%s: ignoring zram swap", swap
->path
);
818 swap
->type
= SWAP_BLOCK
;
821 log_debug("%s: swap type %s is unsupported for hibernation, ignoring", swap
->path
, type
);
825 /* prefer resume device or highest priority swap with most remaining space */
826 if (sys_resume
== 0) {
827 if (hibernate_location
&& swap
->priority
< hibernate_location
->swap
->priority
) {
828 log_debug("%s: ignoring device with lower priority", swap
->path
);
831 if (hibernate_location
&&
832 (swap
->priority
== hibernate_location
->swap
->priority
833 && swap
->size
- swap
->used
< hibernate_location
->swap
->size
- hibernate_location
->swap
->used
)) {
834 log_debug("%s: ignoring device with lower usable space", swap
->path
);
840 r
= swap_device_to_devnum(swap
, &swap_devno
);
842 return log_debug_errno(r
, "%s: failed to query device number: %m", swap
->path
);
844 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "%s: not backed by block device.", swap
->path
);
846 hibernate_location
= hibernate_location_free(hibernate_location
);
847 hibernate_location
= new(HibernateLocation
, 1);
848 if (!hibernate_location
)
851 *hibernate_location
= (HibernateLocation
) {
853 .offset
= swap_offset
,
854 .swap
= TAKE_PTR(swap
),
857 /* if the swap is the resume device, stop the loop */
858 if (location_is_resume_device(hibernate_location
, sys_resume
, sys_offset
)) {
859 log_debug("%s: device matches configured resume settings.", hibernate_location
->swap
->path
);
864 log_debug("%s: is a candidate device.", hibernate_location
->swap
->path
);
867 /* We found nothing at all */
868 if (!hibernate_location
)
869 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS
),
870 "No possible swap partitions or files suitable for hibernation were found in /proc/swaps.");
872 /* resume= is set but a matching /proc/swaps entry was not found */
873 if (sys_resume
!= 0 && !resume_match
)
874 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS
),
875 "No swap partitions or files matching resume config were found in /proc/swaps.");
877 if (hibernate_location
->offset
== UINT64_MAX
) {
879 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS
), "Offset detection failed and /sys/power/resume_offset is not set.");
881 hibernate_location
->offset
= sys_offset
;
885 log_debug("Hibernation will attempt to use swap entry with path: %s, device: %u:%u, offset: %" PRIu64
", priority: %i",
886 hibernate_location
->swap
->path
, major(hibernate_location
->devno
), minor(hibernate_location
->devno
),
887 hibernate_location
->offset
, hibernate_location
->swap
->priority
);
889 log_debug("/sys/power/resume is not configured; attempting to hibernate with path: %s, device: %u:%u, offset: %" PRIu64
", priority: %i",
890 hibernate_location
->swap
->path
, major(hibernate_location
->devno
), minor(hibernate_location
->devno
),
891 hibernate_location
->offset
, hibernate_location
->swap
->priority
);
893 *ret_hibernate_location
= TAKE_PTR(hibernate_location
);
901 static bool enough_swap_for_hibernation(void) {
902 _cleanup_free_
char *active
= NULL
;
903 _cleanup_(hibernate_location_freep
) HibernateLocation
*hibernate_location
= NULL
;
904 unsigned long long act
= 0;
907 if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
910 r
= find_hibernate_location(&hibernate_location
);
914 /* If /sys/power/{resume,resume_offset} is configured but a matching entry
915 * could not be identified in /proc/swaps, user is likely using Btrfs with a swapfile;
916 * return true and let the system attempt hibernation.
918 if (r
> 0 && !hibernate_location
) {
919 log_debug("Unable to determine remaining swap space; hibernation may fail");
923 if (!hibernate_location
)
926 r
= get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE
, &active
);
928 log_debug_errno(r
, "Failed to retrieve Active(anon) from /proc/meminfo: %m");
932 r
= safe_atollu(active
, &act
);
934 log_debug_errno(r
, "Failed to parse Active(anon) from /proc/meminfo: %s: %m", active
);
938 r
= act
<= (hibernate_location
->swap
->size
- hibernate_location
->swap
->used
) * HIBERNATION_SWAP_THRESHOLD
;
939 log_debug("%s swap for hibernation, Active(anon)=%llu kB, size=%" PRIu64
" kB, used=%" PRIu64
" kB, threshold=%.2g%%",
940 r
? "Enough" : "Not enough", act
, hibernate_location
->swap
->size
, hibernate_location
->swap
->used
, 100*HIBERNATION_SWAP_THRESHOLD
);
945 int read_fiemap(int fd
, struct fiemap
**ret
) {
946 _cleanup_free_
struct fiemap
*fiemap
= NULL
, *result_fiemap
= NULL
;
947 struct stat statinfo
;
948 uint32_t result_extents
= 0;
949 uint64_t fiemap_start
= 0, fiemap_length
;
950 const size_t n_extra
= DIV_ROUND_UP(sizeof(struct fiemap
), sizeof(struct fiemap_extent
));
952 if (fstat(fd
, &statinfo
) < 0)
953 return log_debug_errno(errno
, "Cannot determine file size: %m");
954 if (!S_ISREG(statinfo
.st_mode
))
956 fiemap_length
= statinfo
.st_size
;
958 /* Zero this out in case we run on a file with no extents */
959 fiemap
= calloc(n_extra
, sizeof(struct fiemap_extent
));
963 result_fiemap
= malloc_multiply(n_extra
, sizeof(struct fiemap_extent
));
967 /* XFS filesystem has incorrect implementation of fiemap ioctl and
968 * returns extents for only one block-group at a time, so we need
969 * to handle it manually, starting the next fiemap call from the end
972 while (fiemap_start
< fiemap_length
) {
973 *fiemap
= (struct fiemap
) {
974 .fm_start
= fiemap_start
,
975 .fm_length
= fiemap_length
,
976 .fm_flags
= FIEMAP_FLAG_SYNC
,
979 /* Find out how many extents there are */
980 if (ioctl(fd
, FS_IOC_FIEMAP
, fiemap
) < 0)
981 return log_debug_errno(errno
, "Failed to read extents: %m");
983 /* Nothing to process */
984 if (fiemap
->fm_mapped_extents
== 0)
987 /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
988 * the extents for the whole file. Add space for the initial struct fiemap. */
989 if (!greedy_realloc0((void**) &fiemap
, n_extra
+ fiemap
->fm_mapped_extents
, sizeof(struct fiemap_extent
)))
992 fiemap
->fm_extent_count
= fiemap
->fm_mapped_extents
;
993 fiemap
->fm_mapped_extents
= 0;
995 if (ioctl(fd
, FS_IOC_FIEMAP
, fiemap
) < 0)
996 return log_debug_errno(errno
, "Failed to read extents: %m");
998 /* Resize result_fiemap to allow us to copy in the extents */
999 if (!greedy_realloc((void**) &result_fiemap
,
1000 n_extra
+ result_extents
+ fiemap
->fm_mapped_extents
, sizeof(struct fiemap_extent
)))
1003 memcpy(result_fiemap
->fm_extents
+ result_extents
,
1005 sizeof(struct fiemap_extent
) * fiemap
->fm_mapped_extents
);
1007 result_extents
+= fiemap
->fm_mapped_extents
;
1009 /* Highly unlikely that it is zero */
1010 if (_likely_(fiemap
->fm_mapped_extents
> 0)) {
1011 uint32_t i
= fiemap
->fm_mapped_extents
- 1;
1013 fiemap_start
= fiemap
->fm_extents
[i
].fe_logical
+
1014 fiemap
->fm_extents
[i
].fe_length
;
1016 if (fiemap
->fm_extents
[i
].fe_flags
& FIEMAP_EXTENT_LAST
)
1021 memcpy(result_fiemap
, fiemap
, sizeof(struct fiemap
));
1022 result_fiemap
->fm_mapped_extents
= result_extents
;
1023 *ret
= TAKE_PTR(result_fiemap
);
1027 int write_resume_config(dev_t devno
, uint64_t offset
, const char *device
) {
1028 char offset_str
[DECIMAL_STR_MAX(uint64_t)];
1029 _cleanup_free_
char *path
= NULL
;
1030 const char *devno_str
;
1033 devno_str
= FORMAT_DEVNUM(devno
);
1034 xsprintf(offset_str
, "%" PRIu64
, offset
);
1037 r
= device_path_make_canonical(S_IFBLK
, devno
, &path
);
1039 return log_error_errno(r
,
1040 "Failed to format canonical device path for devno '" DEVNUM_FORMAT_STR
"': %m",
1041 DEVNUM_FORMAT_VAL(devno
));
1045 /* We write the offset first since it's safer. Note that this file is only available in 4.17+, so
1046 * fail gracefully if it doesn't exist and we're only overwriting it with 0. */
1047 r
= write_string_file("/sys/power/resume_offset", offset_str
, WRITE_STRING_FILE_DISABLE_BUFFER
);
1050 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1051 "Can't configure hibernation offset %" PRIu64
", kernel does not support /sys/power/resume_offset. Refusing.",
1054 log_warning_errno(r
, "/sys/power/resume_offset is unavailable, skipping writing swap file offset.");
1056 return log_error_errno(r
,
1057 "Failed to write swap file offset %s to /sys/power/resume_offset for device '%s': %m",
1058 offset_str
, device
);
1060 log_debug("Wrote resume_offset=%s for device '%s' to /sys/power/resume_offset.",
1061 offset_str
, device
);
1063 r
= write_string_file("/sys/power/resume", devno_str
, WRITE_STRING_FILE_DISABLE_BUFFER
);
1065 return log_error_errno(r
,
1066 "Failed to write device '%s' (%s) to /sys/power/resume: %m",
1068 log_debug("Wrote resume=%s for device '%s' to /sys/power/resume.", devno_str
, device
);
1073 static int can_sleep_internal(const SleepConfig
*sleep_config
, SleepOperation operation
, bool check_allowed
);
1075 static bool can_s2h(const SleepConfig
*sleep_config
) {
1077 static const SleepOperation operations
[] = {
1084 if (!clock_supported(CLOCK_BOOTTIME_ALARM
)) {
1085 log_debug("CLOCK_BOOTTIME_ALARM is not supported.");
1089 for (size_t i
= 0; i
< ELEMENTSOF(operations
); i
++) {
1090 r
= can_sleep_internal(sleep_config
, operations
[i
], false);
1091 if (IN_SET(r
, 0, -ENOSPC
)) {
1092 log_debug("Unable to %s system.", sleep_operation_to_string(operations
[i
]));
1096 return log_debug_errno(r
, "Failed to check if %s is possible: %m", sleep_operation_to_string(operations
[i
]));
1102 static int can_sleep_internal(
1103 const SleepConfig
*sleep_config
,
1104 SleepOperation operation
,
1105 bool check_allowed
) {
1107 assert(operation
>= 0);
1108 assert(operation
< _SLEEP_OPERATION_MAX
);
1110 if (check_allowed
&& !sleep_config
->allow
[operation
]) {
1111 log_debug("Sleep mode \"%s\" is disabled by configuration.", sleep_operation_to_string(operation
));
1115 if (operation
== SLEEP_SUSPEND_THEN_HIBERNATE
)
1116 return can_s2h(sleep_config
);
1118 if (can_sleep_state(sleep_config
->states
[operation
]) <= 0 ||
1119 can_sleep_disk(sleep_config
->modes
[operation
]) <= 0)
1122 if (operation
== SLEEP_SUSPEND
)
1125 if (!enough_swap_for_hibernation())
1131 int can_sleep(SleepOperation operation
) {
1132 _cleanup_(free_sleep_configp
) SleepConfig
*sleep_config
= NULL
;
1135 r
= parse_sleep_config(&sleep_config
);
1139 return can_sleep_internal(sleep_config
, operation
, true);
1142 SleepConfig
* free_sleep_config(SleepConfig
*sc
) {
1146 for (SleepOperation i
= 0; i
< _SLEEP_OPERATION_MAX
; i
++) {
1147 strv_free(sc
->modes
[i
]);
1148 strv_free(sc
->states
[i
]);
1154 static const char* const sleep_operation_table
[_SLEEP_OPERATION_MAX
] = {
1155 [SLEEP_SUSPEND
] = "suspend",
1156 [SLEEP_HIBERNATE
] = "hibernate",
1157 [SLEEP_HYBRID_SLEEP
] = "hybrid-sleep",
1158 [SLEEP_SUSPEND_THEN_HIBERNATE
] = "suspend-then-hibernate",
1161 DEFINE_STRING_TABLE_LOOKUP(sleep_operation
, SleepOperation
);