]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/sleep-util.c
d7277399fba17734a8f09b75d82489245a2462ee
[thirdparty/systemd.git] / src / shared / sleep-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2018 Dell Inc.
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/fs.h>
9 #include <linux/magic.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <syslog.h>
16 #include <unistd.h>
17
18 #include "sd-device.h"
19
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"
29 #include "env-util.h"
30 #include "errno-util.h"
31 #include "fd-util.h"
32 #include "fileio.h"
33 #include "hexdecoct.h"
34 #include "id128-util.h"
35 #include "log.h"
36 #include "macro.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"
44 #include "strv.h"
45 #include "time-util.h"
46
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)
49
50 static void *CAPACITY_TO_PTR(int capacity) {
51 assert(capacity >= 0);
52 assert(capacity <= 100);
53 return INT_TO_PTR(capacity + 1);
54 }
55
56 static int PTR_TO_CAPACITY(void *p) {
57 int capacity = PTR_TO_INT(p) - 1;
58 assert(capacity >= 0);
59 assert(capacity <= 100);
60 return capacity;
61 }
62
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;
67
68 sc = new(SleepConfig, 1);
69 if (!sc)
70 return log_oom();
71
72 *sc = (SleepConfig) {
73 .hibernate_delay_usec = USEC_INFINITY,
74 };
75
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 },
81
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 },
88
89 { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
90 { "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
91 {}
92 };
93
94 (void) config_parse_config_file("sleep.conf", "Sleep\0",
95 config_item_table_lookup, items,
96 CONFIG_PARSE_WARN, NULL);
97
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);
105
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;
118
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])
122 return log_oom();
123
124 *ret_sleep_config = TAKE_PTR(sc);
125
126 return 0;
127 }
128
129 int get_capacity_by_name(Hashmap *capacities_by_name, const char *name) {
130 void *p;
131
132 assert(capacities_by_name);
133 assert(name);
134
135 p = hashmap_get(capacities_by_name, name);
136 if (!p)
137 return -ENOENT;
138
139 return PTR_TO_CAPACITY(p);
140 }
141
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;
146 int r;
147
148 assert(ret);
149
150 batteries_capacity_by_name = hashmap_new(&string_hash_ops_free);
151 if (!batteries_capacity_by_name)
152 return log_oom_debug();
153
154 r = battery_enumerator_new(&e);
155 if (r < 0)
156 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
157
158 FOREACH_DEVICE(e, dev) {
159 _cleanup_free_ char *battery_name_copy = NULL;
160 const char *battery_name;
161 int battery_capacity;
162
163 battery_capacity = r = battery_read_capacity_percentage(dev);
164 if (r < 0)
165 continue;
166
167 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
168 if (r < 0) {
169 log_device_debug_errno(dev, r, "Failed to get POWER_SUPPLY_NAME property, ignoring: %m");
170 continue;
171 }
172
173 battery_name_copy = strdup(battery_name);
174 if (!battery_name_copy)
175 return log_oom_debug();
176
177 r = hashmap_put(batteries_capacity_by_name, battery_name_copy, CAPACITY_TO_PTR(battery_capacity));
178 if (r < 0)
179 return log_device_debug_errno(dev, r, "Failed to store battery capacity: %m");
180
181 TAKE_PTR(battery_name_copy);
182 }
183
184 *ret = TAKE_PTR(batteries_capacity_by_name);
185
186 return 0;
187 }
188
189 static int siphash24_compress_device_sysattr(sd_device *dev, const char *attr, struct siphash *state) {
190 const char *x;
191 int r;
192
193 assert(dev);
194 assert(attr);
195 assert(state);
196
197 r = sd_device_get_sysattr_value(dev, attr, &x);
198 if (r < 0)
199 return log_device_debug_errno(dev, r, "Failed to read '%s' attribute: %m", attr);
200
201 if (!isempty(x))
202 siphash24_compress_string(x, state);
203
204 return 0;
205 }
206
207 static int siphash24_compress_id128(int (*getter)(sd_id128_t*), const char *name, struct siphash *state) {
208 sd_id128_t id;
209 int r;
210
211 assert(getter);
212 assert(state);
213
214 r = getter(&id);
215 if (r < 0)
216 return log_debug_errno(r, "Failed to get %s ID: %m", name);
217
218 siphash24_compress(&id, sizeof(sd_id128_t), state);
219 return 0;
220 }
221
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;
225
226 assert(ret);
227 assert(dev);
228
229 siphash24_init(&state, BATTERY_DISCHARGE_RATE_HASH_KEY.bytes);
230
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);
236
237 *ret = siphash24_finalize(&state);
238 return 0;
239 }
240
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;
244 }
245
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;
251 const char *p;
252 int r;
253
254 assert(dev);
255 assert(ret);
256
257 f = fopen(DISCHARGE_RATE_FILEPATH, "re");
258 if (!f)
259 return log_debug_errno(errno, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
260
261 r = get_system_battery_identifier_hash(dev, &current_hash_id);
262 if (r < 0)
263 return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
264
265 for (;;) {
266 _cleanup_free_ char *stored_hash_id = NULL, *stored_discharge_rate = NULL, *line = NULL;
267 uint64_t hash_id;
268 int discharge_rate;
269
270 r = read_line(f, LONG_LINE_MAX, &line);
271 if (r < 0)
272 return log_debug_errno(r, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
273 if (r == 0)
274 break;
275
276 p = line;
277 r = extract_many_words(&p, NULL, 0, &stored_hash_id, &stored_discharge_rate, NULL);
278 if (r < 0)
279 return log_debug_errno(r, "Failed to parse hash_id and discharge_rate read from " DISCHARGE_RATE_FILEPATH ": %m");
280 if (r != 2)
281 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid number of items fetched from " DISCHARGE_RATE_FILEPATH);
282
283 r = safe_atou64(stored_hash_id, &hash_id);
284 if (r < 0)
285 return log_debug_errno(r, "Failed to parse hash ID read from " DISCHARGE_RATE_FILEPATH " location: %m");
286
287 if (current_hash_id != hash_id)
288 /* matching device not found, move to next line */
289 continue;
290
291 r = safe_atoi(stored_discharge_rate, &discharge_rate);
292 if (r < 0)
293 return log_device_debug_errno(dev, r, "Failed to parse discharge rate read from " DISCHARGE_RATE_FILEPATH ": %m");
294
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");
297
298 *ret = discharge_rate;
299 return 0; /* matching device found, exit iteration */
300 }
301
302 return -ENOENT;
303 }
304
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) {
307 int r;
308
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);
313
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),
317 "%"PRIu64" %d",
318 system_hash_id,
319 estimated_battery_discharge_rate);
320 if (r < 0)
321 return log_debug_errno(r, "Failed to update %s: %m", DISCHARGE_RATE_FILEPATH);
322
323 log_debug("Estimated discharge rate %d%% per hour successfully saved to %s", estimated_battery_discharge_rate, DISCHARGE_RATE_FILEPATH);
324
325 return 0;
326 }
327
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) {
334
335 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
336 bool trunc = true;
337 int r;
338
339 assert(last_capacity);
340 assert(current_capacity);
341 assert(before_timestamp < after_timestamp);
342
343 r = battery_enumerator_new(&e);
344 if (r < 0)
345 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
346
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;
351
352 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
353 if (r < 0) {
354 log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
355 continue;
356 }
357
358 battery_last_capacity = get_capacity_by_name(last_capacity, battery_name);
359 if (battery_last_capacity < 0)
360 continue;
361
362 battery_current_capacity = get_capacity_by_name(current_capacity, battery_name);
363 if (battery_current_capacity < 0)
364 continue;
365
366 if (battery_current_capacity >= battery_last_capacity) {
367 log_device_debug(dev, "Battery was not discharged during suspension");
368 continue;
369 }
370
371 r = get_system_battery_identifier_hash(dev, &system_hash_id);
372 if (r < 0)
373 return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
374
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));
379
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);
382 if (r < 0)
383 log_device_warning_errno(dev, r, "Failed to update battery discharge rate, ignoring: %m");
384 else
385 trunc = false;
386 }
387
388 return 0;
389 }
390
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;
395 int r;
396
397 assert(last_capacity);
398 assert(ret);
399
400 r = battery_enumerator_new(&e);
401 if (r < 0)
402 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
403
404 FOREACH_DEVICE(e, dev) {
405 int battery_last_capacity, previous_discharge_rate = 0;
406 const char *battery_name;
407 usec_t suspend_interval;
408
409 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
410 if (r < 0) {
411 log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
412 continue;
413 }
414
415 battery_last_capacity = get_capacity_by_name(last_capacity, battery_name);
416 if (battery_last_capacity <= 0)
417 continue;
418
419 r = get_battery_discharge_rate(dev, &previous_discharge_rate);
420 if (r < 0) {
421 log_device_debug_errno(dev, r, "Failed to get discharge rate, ignoring: %m");
422 continue;
423 }
424
425 if (previous_discharge_rate == 0)
426 continue;
427
428 if (battery_last_capacity * 2 <= previous_discharge_rate) {
429 log_device_debug(dev, "Current battery capacity percentage too low compared to discharge rate");
430 continue;
431 }
432 suspend_interval = battery_last_capacity * USEC_PER_HOUR / previous_discharge_rate;
433
434 total_suspend_interval = usec_add(total_suspend_interval, suspend_interval);
435 }
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)
440 return -ENOENT;
441
442 *ret = total_suspend_interval;
443
444 return 0;
445 }
446
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;
450 int r;
451
452 r = battery_enumerator_new(&e);
453 if (r < 0)
454 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
455
456 FOREACH_DEVICE(e, dev) {
457 int battery_alarm;
458 const char *s;
459
460 r = sd_device_get_sysattr_value(dev, "alarm", &s);
461 if (r < 0)
462 return log_device_debug_errno(dev, r, "Failed to read battery alarm: %m");
463
464 r = safe_atoi(s, &battery_alarm);
465 if (r < 0)
466 return log_device_debug_errno(dev, r, "Failed to parse battery alarm: %m");
467 if (battery_alarm <= 0)
468 return false;
469 }
470
471 return true;
472 }
473
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;
479 size_t bufsize;
480 int r;
481
482 /* implementation via dmi/entries */
483 r = read_full_virtual_file(dmi_object_path, &buf, &bufsize);
484 if (r < 0)
485 return log_debug_errno(r, "Unable to read %s: %m", dmi_object_path);
486 if (bufsize < 25)
487 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Only read %zu bytes from %s (expected 25)", bufsize, dmi_object_path);
488
489 /* index 1 stores the size of table */
490 tablesize = (uint8_t) buf[1];
491 if (tablesize < 25)
492 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Table size lesser than the index[0x18] where waketype byte is available.");
493
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");
499
500 if (wakeup_type_byte == 3) {
501 log_debug("DMI BIOS System Information indicates wakeup type is APM Timer");
502 return true;
503 }
504
505 return false;
506 }
507
508 int can_sleep_state(char **requested_types) {
509 _cleanup_free_ char *text = NULL;
510 int r;
511
512 if (strv_isempty(requested_types))
513 return true;
514
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");
518 return false;
519 }
520
521 r = read_one_line_file("/sys/power/state", &text);
522 if (r < 0) {
523 log_debug_errno(r, "Failed to read /sys/power/state, cannot sleep: %m");
524 return false;
525 }
526
527 const char *found;
528 r = string_contains_word_strv(text, NULL, requested_types, &found);
529 if (r < 0)
530 return log_debug_errno(r, "Failed to parse /sys/power/state: %m");
531 if (r > 0)
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));
536 }
537 return r;
538 }
539
540 int can_sleep_disk(char **types) {
541 _cleanup_free_ char *text = NULL;
542 int r;
543
544 if (strv_isempty(types))
545 return true;
546
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");
550 return false;
551 }
552
553 r = read_one_line_file("/sys/power/disk", &text);
554 if (r < 0) {
555 log_debug_errno(r, "Couldn't read /sys/power/disk: %m");
556 return false;
557 }
558
559 for (const char *p = text;;) {
560 _cleanup_free_ char *word = NULL;
561
562 r = extract_first_word(&p, &word, NULL, 0);
563 if (r < 0)
564 return log_debug_errno(r, "Failed to parse /sys/power/disk: %m");
565 if (r == 0)
566 break;
567
568 char *s = word;
569 size_t l = strlen(s);
570 if (s[0] == '[' && s[l-1] == ']') {
571 s[l-1] = '\0';
572 s++;
573 }
574
575 if (strv_contains(types, s)) {
576 log_debug("Disk sleep mode \"%s\" is supported by the kernel.", s);
577 return true;
578 }
579 }
580
581 if (DEBUG_LOGGING) {
582 _cleanup_free_ char *t = strv_join(types, "/");
583 log_debug("Disk sleep mode %s not supported by the kernel, sorry.", strnull(t));
584 }
585 return false;
586 }
587
588 #define HIBERNATION_SWAP_THRESHOLD 0.98
589
590 SwapEntry* swap_entry_free(SwapEntry *se) {
591 if (!se)
592 return NULL;
593
594 free(se->path);
595
596 return mfree(se);
597 }
598
599 HibernateLocation* hibernate_location_free(HibernateLocation *hl) {
600 if (!hl)
601 return NULL;
602
603 swap_entry_free(hl->swap);
604
605 return mfree(hl);
606 }
607
608 static int swap_device_to_devnum(const SwapEntry *swap, dev_t *ret_dev) {
609 _cleanup_close_ int fd = -EBADF;
610 struct stat sb;
611 int r;
612
613 assert(swap);
614 assert(swap->path);
615
616 fd = open(swap->path, O_CLOEXEC|O_PATH);
617 if (fd < 0)
618 return -errno;
619
620 if (fstat(fd, &sb) < 0)
621 return -errno;
622
623 if (swap->type == SWAP_BLOCK) {
624 if (!S_ISBLK(sb.st_mode))
625 return -ENOTBLK;
626
627 *ret_dev = sb.st_rdev;
628 return 0;
629 }
630
631 r = stat_verify_regular(&sb);
632 if (r < 0)
633 return r;
634
635 return get_block_device_fd(fd, ret_dev);
636 }
637
638 /*
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.
641 */
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;
645 int r;
646
647 assert(swap);
648 assert(swap->path);
649 assert(swap->type == SWAP_FILE);
650 assert(ret_offset);
651
652 fd = open(swap->path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
653 if (fd < 0)
654 return log_debug_errno(errno, "Failed to open swap file %s to determine on-disk offset: %m", swap->path);
655
656 r = fd_verify_regular(fd);
657 if (r < 0)
658 return log_debug_errno(r, "Selected swap file is not a regular file.");
659
660 r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
661 if (r < 0)
662 return log_debug_errno(r, "Error checking %s for Btrfs filesystem: %m", swap->path);
663 if (r > 0) {
664 log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->path);
665 *ret_offset = UINT64_MAX;
666 return 0;
667 }
668
669 r = read_fiemap(fd, &fiemap);
670 if (r < 0)
671 return log_debug_errno(r, "Unable to read extent map for '%s': %m", swap->path);
672
673 *ret_offset = fiemap->fm_extents[0].fe_physical / page_size();
674 return 0;
675 }
676
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;
680 dev_t resume;
681 int r;
682
683 assert(ret_resume);
684 assert(ret_resume_offset);
685
686 r = read_one_line_file("/sys/power/resume", &resume_str);
687 if (r < 0)
688 return log_debug_errno(r, "Error reading /sys/power/resume: %m");
689
690 r = parse_devnum(resume_str, &resume);
691 if (r < 0)
692 return log_debug_errno(r, "Error parsing /sys/power/resume device: %s: %m", resume_str);
693
694 r = read_one_line_file("/sys/power/resume_offset", &resume_offset_str);
695 if (r == -ENOENT) {
696 log_debug_errno(r, "Kernel does not support resume_offset; swap file offset detection will be skipped.");
697 resume_offset = 0;
698 } else if (r < 0)
699 return log_debug_errno(r, "Error reading /sys/power/resume_offset: %m");
700 else {
701 r = safe_atou64(resume_offset_str, &resume_offset);
702 if (r < 0)
703 return log_debug_errno(r, "Failed to parse value in /sys/power/resume_offset \"%s\": %m", resume_offset_str);
704 }
705
706 if (resume_offset > 0 && resume == 0)
707 log_debug("Warning: found /sys/power/resume_offset==%" PRIu64 ", but /sys/power/resume unset. Misconfiguration?",
708 resume_offset);
709
710 *ret_resume = resume;
711 *ret_resume_offset = resume_offset;
712 return 0;
713 }
714
715 /*
716 * Determine if the HibernateLocation matches the resume= (device) and resume_offset= (file).
717 */
718 static bool location_is_resume_device(const HibernateLocation *location, dev_t sys_resume, uint64_t sys_offset) {
719 if (!location)
720 return false;
721
722 return sys_resume > 0 &&
723 sys_resume == location->devno &&
724 (sys_offset == location->offset || (sys_offset > 0 && location->offset == UINT64_MAX));
725 }
726
727 /*
728 * Attempt to find the hibernation location by parsing /proc/swaps, /sys/power/resume, and
729 * /sys/power/resume_offset.
730 *
731 * Beware:
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
734 * active swap area!
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.
738 *
739 * Returns:
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.
742 *
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.
745 *
746 * Negative value in the case of error.
747 */
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;
754 int r;
755
756 /* read the /sys/power/resume & /sys/power/resume_offset values */
757 r = read_resume_files(&sys_resume, &sys_offset);
758 if (r < 0)
759 return r;
760
761 f = fopen("/proc/swaps", "re");
762 if (!f) {
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 */
765 }
766
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;
772 int k;
773
774 swap = new(SwapEntry, 1);
775 if (!swap)
776 return -ENOMEM;
777
778 *swap = (SwapEntry) {
779 .type = _SWAP_TYPE_INVALID,
780 };
781
782 k = fscanf(f,
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);
789 if (k == EOF)
790 break;
791 if (k != 5) {
792 log_debug("Failed to parse /proc/swaps:%u, ignoring", i);
793 continue;
794 }
795
796 if (streq(type, "file")) {
797
798 if (endswith(swap->path, "\\040(deleted)")) {
799 log_debug("Ignoring deleted swap file '%s'.", swap->path);
800 continue;
801 }
802
803 swap->type = SWAP_FILE;
804
805 r = calculate_swap_file_offset(swap, &swap_offset);
806 if (r < 0)
807 return r;
808
809 } else if (streq(type, "partition")) {
810 const char *fn;
811
812 fn = path_startswith(swap->path, "/dev/");
813 if (fn && startswith(fn, "zram")) {
814 log_debug("%s: ignoring zram swap", swap->path);
815 continue;
816 }
817
818 swap->type = SWAP_BLOCK;
819
820 } else {
821 log_debug("%s: swap type %s is unsupported for hibernation, ignoring", swap->path, type);
822 continue;
823 }
824
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);
829 continue;
830 }
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);
835 continue;
836 }
837 }
838
839 dev_t swap_devno;
840 r = swap_device_to_devnum(swap, &swap_devno);
841 if (r < 0)
842 return log_debug_errno(r, "%s: failed to query device number: %m", swap->path);
843 if (swap_devno == 0)
844 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "%s: not backed by block device.", swap->path);
845
846 hibernate_location = hibernate_location_free(hibernate_location);
847 hibernate_location = new(HibernateLocation, 1);
848 if (!hibernate_location)
849 return -ENOMEM;
850
851 *hibernate_location = (HibernateLocation) {
852 .devno = swap_devno,
853 .offset = swap_offset,
854 .swap = TAKE_PTR(swap),
855 };
856
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);
860 resume_match = true;
861 break;
862 }
863
864 log_debug("%s: is a candidate device.", hibernate_location->swap->path);
865 }
866
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.");
871
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.");
876
877 if (hibernate_location->offset == UINT64_MAX) {
878 if (sys_offset == 0)
879 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS), "Offset detection failed and /sys/power/resume_offset is not set.");
880
881 hibernate_location->offset = sys_offset;
882 }
883
884 if (resume_match)
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);
888 else
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);
892
893 *ret_hibernate_location = TAKE_PTR(hibernate_location);
894
895 if (resume_match)
896 return 1;
897
898 return 0;
899 }
900
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;
905 int r;
906
907 if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
908 return true;
909
910 r = find_hibernate_location(&hibernate_location);
911 if (r < 0)
912 return false;
913
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.
917 */
918 if (r > 0 && !hibernate_location) {
919 log_debug("Unable to determine remaining swap space; hibernation may fail");
920 return true;
921 }
922
923 if (!hibernate_location)
924 return false;
925
926 r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active);
927 if (r < 0) {
928 log_debug_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m");
929 return false;
930 }
931
932 r = safe_atollu(active, &act);
933 if (r < 0) {
934 log_debug_errno(r, "Failed to parse Active(anon) from /proc/meminfo: %s: %m", active);
935 return false;
936 }
937
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);
941
942 return r;
943 }
944
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));
951
952 if (fstat(fd, &statinfo) < 0)
953 return log_debug_errno(errno, "Cannot determine file size: %m");
954 if (!S_ISREG(statinfo.st_mode))
955 return -ENOTTY;
956 fiemap_length = statinfo.st_size;
957
958 /* Zero this out in case we run on a file with no extents */
959 fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
960 if (!fiemap)
961 return -ENOMEM;
962
963 result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
964 if (!result_fiemap)
965 return -ENOMEM;
966
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
970 * of the last extent
971 */
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,
977 };
978
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");
982
983 /* Nothing to process */
984 if (fiemap->fm_mapped_extents == 0)
985 break;
986
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)))
990 return -ENOMEM;
991
992 fiemap->fm_extent_count = fiemap->fm_mapped_extents;
993 fiemap->fm_mapped_extents = 0;
994
995 if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
996 return log_debug_errno(errno, "Failed to read extents: %m");
997
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)))
1001 return -ENOMEM;
1002
1003 memcpy(result_fiemap->fm_extents + result_extents,
1004 fiemap->fm_extents,
1005 sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents);
1006
1007 result_extents += fiemap->fm_mapped_extents;
1008
1009 /* Highly unlikely that it is zero */
1010 if (_likely_(fiemap->fm_mapped_extents > 0)) {
1011 uint32_t i = fiemap->fm_mapped_extents - 1;
1012
1013 fiemap_start = fiemap->fm_extents[i].fe_logical +
1014 fiemap->fm_extents[i].fe_length;
1015
1016 if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST)
1017 break;
1018 }
1019 }
1020
1021 memcpy(result_fiemap, fiemap, sizeof(struct fiemap));
1022 result_fiemap->fm_mapped_extents = result_extents;
1023 *ret = TAKE_PTR(result_fiemap);
1024 return 0;
1025 }
1026
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;
1031 int r;
1032
1033 devno_str = FORMAT_DEVNUM(devno);
1034 xsprintf(offset_str, "%" PRIu64, offset);
1035
1036 if (!device) {
1037 r = device_path_make_canonical(S_IFBLK, devno, &path);
1038 if (r < 0)
1039 return log_error_errno(r,
1040 "Failed to format canonical device path for devno '" DEVNUM_FORMAT_STR "': %m",
1041 DEVNUM_FORMAT_VAL(devno));
1042 device = path;
1043 }
1044
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);
1048 if (r == -ENOENT) {
1049 if (offset != 0)
1050 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1051 "Can't configure hibernation offset %" PRIu64 ", kernel does not support /sys/power/resume_offset. Refusing.",
1052 offset);
1053
1054 log_warning_errno(r, "/sys/power/resume_offset is unavailable, skipping writing swap file offset.");
1055 } else if (r < 0)
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);
1059 else
1060 log_debug("Wrote resume_offset=%s for device '%s' to /sys/power/resume_offset.",
1061 offset_str, device);
1062
1063 r = write_string_file("/sys/power/resume", devno_str, WRITE_STRING_FILE_DISABLE_BUFFER);
1064 if (r < 0)
1065 return log_error_errno(r,
1066 "Failed to write device '%s' (%s) to /sys/power/resume: %m",
1067 device, devno_str);
1068 log_debug("Wrote resume=%s for device '%s' to /sys/power/resume.", devno_str, device);
1069
1070 return 0;
1071 }
1072
1073 static int can_sleep_internal(const SleepConfig *sleep_config, SleepOperation operation, bool check_allowed);
1074
1075 static bool can_s2h(const SleepConfig *sleep_config) {
1076
1077 static const SleepOperation operations[] = {
1078 SLEEP_SUSPEND,
1079 SLEEP_HIBERNATE,
1080 };
1081
1082 int r;
1083
1084 if (!clock_supported(CLOCK_BOOTTIME_ALARM)) {
1085 log_debug("CLOCK_BOOTTIME_ALARM is not supported.");
1086 return false;
1087 }
1088
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]));
1093 return false;
1094 }
1095 if (r < 0)
1096 return log_debug_errno(r, "Failed to check if %s is possible: %m", sleep_operation_to_string(operations[i]));
1097 }
1098
1099 return true;
1100 }
1101
1102 static int can_sleep_internal(
1103 const SleepConfig *sleep_config,
1104 SleepOperation operation,
1105 bool check_allowed) {
1106
1107 assert(operation >= 0);
1108 assert(operation < _SLEEP_OPERATION_MAX);
1109
1110 if (check_allowed && !sleep_config->allow[operation]) {
1111 log_debug("Sleep mode \"%s\" is disabled by configuration.", sleep_operation_to_string(operation));
1112 return false;
1113 }
1114
1115 if (operation == SLEEP_SUSPEND_THEN_HIBERNATE)
1116 return can_s2h(sleep_config);
1117
1118 if (can_sleep_state(sleep_config->states[operation]) <= 0 ||
1119 can_sleep_disk(sleep_config->modes[operation]) <= 0)
1120 return false;
1121
1122 if (operation == SLEEP_SUSPEND)
1123 return true;
1124
1125 if (!enough_swap_for_hibernation())
1126 return -ENOSPC;
1127
1128 return true;
1129 }
1130
1131 int can_sleep(SleepOperation operation) {
1132 _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
1133 int r;
1134
1135 r = parse_sleep_config(&sleep_config);
1136 if (r < 0)
1137 return r;
1138
1139 return can_sleep_internal(sleep_config, operation, true);
1140 }
1141
1142 SleepConfig* free_sleep_config(SleepConfig *sc) {
1143 if (!sc)
1144 return NULL;
1145
1146 for (SleepOperation i = 0; i < _SLEEP_OPERATION_MAX; i++) {
1147 strv_free(sc->modes[i]);
1148 strv_free(sc->states[i]);
1149 }
1150
1151 return mfree(sc);
1152 }
1153
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",
1159 };
1160
1161 DEFINE_STRING_TABLE_LOOKUP(sleep_operation, SleepOperation);