]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
sd-journal: add FORMAT_TIMESTAMP_SAFE()
[thirdparty/systemd.git] / src / core / swap.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
07b0b134
ML
2
3#include <errno.h>
07b0b134
ML
4#include <sys/epoll.h>
5#include <sys/stat.h>
4f5dd394 6#include <unistd.h>
07b0b134 7
4366e598 8#include "sd-device.h"
b4bbcaa9 9
b5efdb8a 10#include "alloc-util.h"
07b0b134 11#include "dbus-swap.h"
6fcbec6f 12#include "dbus-unit.h"
4366e598 13#include "device-util.h"
57b7a260 14#include "device.h"
4f5dd394 15#include "escape.h"
9a57c629 16#include "exit-status.h"
3ffd4af2 17#include "fd-util.h"
f97b34a6 18#include "format-util.h"
4f5dd394 19#include "fstab-util.h"
6bedfcbb 20#include "parse-util.h"
9eb977db 21#include "path-util.h"
7b3e062c 22#include "process-util.h"
d68c645b 23#include "serialize.h"
4f5dd394 24#include "special.h"
8b43440b 25#include "string-table.h"
07630cea 26#include "string-util.h"
3ffd4af2 27#include "swap.h"
4f5dd394
LP
28#include "unit-name.h"
29#include "unit.h"
30#include "virt.h"
07b0b134
ML
31
32static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
33 [SWAP_DEAD] = UNIT_INACTIVE,
e04aad61 34 [SWAP_ACTIVATING] = UNIT_ACTIVATING,
5bcb0f2b 35 [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
07b0b134 36 [SWAP_ACTIVE] = UNIT_ACTIVE,
e04aad61 37 [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
e04aad61
LP
38 [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
39 [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
a8b689b7
YW
40 [SWAP_FAILED] = UNIT_FAILED,
41 [SWAP_CLEANING] = UNIT_MAINTENANCE,
07b0b134
ML
42};
43
718db961
LP
44static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
45static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
bcce581d 46static int swap_process_proc_swaps(Manager *m);
718db961 47
dedf3719
LP
48static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
49 return IN_SET(state,
50 SWAP_ACTIVATING,
51 SWAP_ACTIVATING_DONE,
52 SWAP_DEACTIVATING,
53 SWAP_DEACTIVATING_SIGTERM,
a8b689b7
YW
54 SWAP_DEACTIVATING_SIGKILL,
55 SWAP_CLEANING);
dedf3719
LP
56}
57
39c79477
ZJS
58_pure_ static UnitActiveState swap_active_state(Unit *u) {
59 assert(u);
60
61 return state_translation_table[SWAP(u)->state];
62}
63
64_pure_ static const char *swap_sub_state_to_string(Unit *u) {
65 assert(u);
66
67 return swap_state_to_string(SWAP(u)->state);
68}
69
70_pure_ static bool swap_may_gc(Unit *u) {
71 Swap *s = SWAP(u);
72
73 assert(s);
74
75 if (s->from_proc_swaps)
76 return false;
77
78 return true;
79}
80
81_pure_ static bool swap_is_extrinsic(Unit *u) {
82 assert(SWAP(u));
83
84 return MANAGER_IS_USER(u->manager);
85}
86
e04aad61 87static void swap_unset_proc_swaps(Swap *s) {
9670d583
LP
88 assert(s);
89
90 if (!s->from_proc_swaps)
91 return;
92
a1e58e8e 93 s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what);
9670d583
LP
94 s->from_proc_swaps = false;
95}
96
97static int swap_set_devnode(Swap *s, const char *devnode) {
df326b84 98 Hashmap *swaps;
5bcb0f2b 99 Swap *first;
9670d583 100 int r;
e04aad61
LP
101
102 assert(s);
103
548f6937 104 r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &path_hash_ops);
9670d583
LP
105 if (r < 0)
106 return r;
e04aad61 107
9670d583 108 swaps = UNIT(s)->manager->swaps_by_devnode;
e04aad61 109
9670d583
LP
110 if (s->devnode) {
111 first = hashmap_get(swaps, s->devnode);
e04aad61 112
9670d583
LP
113 LIST_REMOVE(same_devnode, first, s);
114 if (first)
115 hashmap_replace(swaps, first->devnode, first);
116 else
117 hashmap_remove(swaps, s->devnode);
5bcb0f2b 118
a1e58e8e 119 s->devnode = mfree(s->devnode);
9670d583
LP
120 }
121
122 if (devnode) {
123 s->devnode = strdup(devnode);
124 if (!s->devnode)
125 return -ENOMEM;
126
127 first = hashmap_get(swaps, s->devnode);
128 LIST_PREPEND(same_devnode, first, s);
129
130 return hashmap_replace(swaps, first->devnode, first);
131 }
132
133 return 0;
e04aad61
LP
134}
135
f6cebb3b 136static void swap_init(Unit *u) {
6e620bec
LP
137 Swap *s = SWAP(u);
138
139 assert(s);
1124fe6f 140 assert(UNIT(s)->load_state == UNIT_STUB);
6e620bec 141
1f19a534 142 s->timeout_usec = u->manager->default_timeout_start_usec;
e04aad61 143
ac155bb8
MS
144 s->exec_context.std_output = u->manager->default_std_output;
145 s->exec_context.std_error = u->manager->default_std_error;
085afe36 146
e1770af8 147 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
c8f4d764 148
5bcb0f2b 149 u->ignore_on_isolate = true;
e04aad61
LP
150}
151
152static void swap_unwatch_control_pid(Swap *s) {
153 assert(s);
154
155 if (s->control_pid <= 0)
156 return;
157
158 unit_unwatch_pid(UNIT(s), s->control_pid);
159 s->control_pid = 0;
6e620bec
LP
160}
161
4e85aff4
LP
162static void swap_done(Unit *u) {
163 Swap *s = SWAP(u);
07b0b134 164
4e85aff4 165 assert(s);
07b0b134 166
e04aad61 167 swap_unset_proc_swaps(s);
9670d583 168 swap_set_devnode(s, NULL);
e04aad61 169
a1e58e8e
LP
170 s->what = mfree(s->what);
171 s->parameters_fragment.what = mfree(s->parameters_fragment.what);
172 s->parameters_fragment.options = mfree(s->parameters_fragment.options);
86b23b07 173
e8a565cb 174 s->exec_runtime = exec_runtime_unref(s->exec_runtime, false);
e04aad61
LP
175 exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
176 s->control_command = NULL;
177
29206d46
LP
178 dynamic_creds_unref(&s->dynamic_creds);
179
e04aad61
LP
180 swap_unwatch_control_pid(s);
181
5dcadb4c 182 s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
718db961
LP
183}
184
36c16a7c 185static int swap_arm_timer(Swap *s, usec_t usec) {
718db961
LP
186 int r;
187
188 assert(s);
189
718db961 190 if (s->timer_event_source) {
36c16a7c 191 r = sd_event_source_set_time(s->timer_event_source, usec);
718db961
LP
192 if (r < 0)
193 return r;
194
195 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
196 }
197
36c16a7c
LP
198 if (usec == USEC_INFINITY)
199 return 0;
200
7dfbe2e3 201 r = sd_event_add_time(
6a0f1f6d
LP
202 UNIT(s)->manager->event,
203 &s->timer_event_source,
204 CLOCK_MONOTONIC,
36c16a7c 205 usec, 0,
6a0f1f6d 206 swap_dispatch_timer, s);
7dfbe2e3
TG
207 if (r < 0)
208 return r;
209
210 (void) sd_event_source_set_description(s->timer_event_source, "swap-timer");
211
212 return 0;
07b0b134
ML
213}
214
61f9cf4e
LP
215static SwapParameters* swap_get_parameters(Swap *s) {
216 assert(s);
217
218 if (s->from_proc_swaps)
219 return &s->parameters_proc_swaps;
220
221 if (s->from_fragment)
222 return &s->parameters_fragment;
223
224 return NULL;
225}
226
eef85c4a 227static int swap_add_device_dependencies(Swap *s) {
61f9cf4e
LP
228 UnitDependencyMask mask;
229 SwapParameters *p;
44b0d1fd 230 int r;
61f9cf4e 231
173a8d04
LP
232 assert(s);
233
234 if (!s->what)
235 return 0;
236
61f9cf4e 237 p = swap_get_parameters(s);
d4a3494e 238 if (!p || !p->what)
f10af76d
LP
239 return 0;
240
61f9cf4e
LP
241 mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
242
44b0d1fd
LP
243 if (is_device_path(p->what)) {
244 r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
245 if (r < 0)
246 return r;
247
248 return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
249 }
9b88bb50 250
61f9cf4e
LP
251 /* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
252 * a writable file system. */
253 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, mask);
173a8d04
LP
254}
255
2edd4434 256static int swap_add_default_dependencies(Swap *s) {
8bf23dc7
FB
257 int r;
258
2edd4434
LP
259 assert(s);
260
4c9ea260
LP
261 if (!UNIT(s)->default_dependencies)
262 return 0;
263
463d0d15 264 if (!MANAGER_IS_SYSTEM(UNIT(s)->manager))
6b1dc2bd 265 return 0;
2edd4434 266
75f86906 267 if (detect_container() > 0)
c0387ebf
LP
268 return 0;
269
8bf23dc7
FB
270 /* swap units generated for the swap dev links are missing the
271 * ordering dep against the swap target. */
35d8c19a 272 r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
8bf23dc7
FB
273 if (r < 0)
274 return r;
275
5a724170 276 return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
2edd4434
LP
277}
278
4e85aff4 279static int swap_verify(Swap *s) {
7fd1b19b 280 _cleanup_free_ char *e = NULL;
7410616c 281 int r;
4e85aff4 282
75193d41 283 assert(UNIT(s)->load_state == UNIT_LOADED);
4e85aff4 284
7410616c
LP
285 r = unit_name_from_path(s->what, ".swap", &e);
286 if (r < 0)
f2341e0a 287 return log_unit_error_errno(UNIT(s), r, "Failed to generate unit name from path: %m");
4e85aff4 288
d85ff944
YW
289 if (!unit_has_name(UNIT(s), e))
290 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Value of What= and unit name do not match, not loading.");
4e85aff4 291
d85ff944
YW
292 if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP)
293 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.");
e04aad61 294
4e85aff4
LP
295 return 0;
296}
297
9670d583 298static int swap_load_devnode(Swap *s) {
4366e598 299 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
9670d583
LP
300 struct stat st;
301 const char *p;
e5ca27b7 302 int r;
9670d583
LP
303
304 assert(s);
305
306 if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
307 return 0;
308
a1130022 309 r = sd_device_new_from_stat_rdev(&d, &st);
e5ca27b7 310 if (r < 0) {
8ed6f81b
YW
311 log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
312 "Failed to allocate device for swap %s: %m", s->what);
9670d583 313 return 0;
e5ca27b7 314 }
9670d583 315
4366e598 316 if (sd_device_get_devname(d, &p) < 0)
9670d583
LP
317 return 0;
318
319 return swap_set_devnode(s, p);
320}
321
15332d73 322static int swap_add_extras(Swap *s) {
07b0b134 323 int r;
07b0b134
ML
324
325 assert(s);
07b0b134 326
15332d73
LP
327 if (UNIT(s)->fragment_path)
328 s->from_fragment = true;
07b0b134 329
15332d73
LP
330 if (!s->what) {
331 if (s->parameters_fragment.what)
332 s->what = strdup(s->parameters_fragment.what);
333 else if (s->parameters_proc_swaps.what)
334 s->what = strdup(s->parameters_proc_swaps.what);
335 else {
336 r = unit_name_to_path(UNIT(s)->id, &s->what);
5bcb0f2b 337 if (r < 0)
4e85aff4 338 return r;
5bcb0f2b 339 }
4e85aff4 340
15332d73
LP
341 if (!s->what)
342 return -ENOMEM;
343 }
07b0b134 344
4ff361cc 345 path_simplify(s->what);
07b0b134 346
15332d73
LP
347 if (!UNIT(s)->description) {
348 r = unit_set_description(UNIT(s), s->what);
9670d583
LP
349 if (r < 0)
350 return r;
15332d73 351 }
9670d583 352
15332d73
LP
353 r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
354 if (r < 0)
355 return r;
598459ce 356
15332d73
LP
357 r = swap_add_device_dependencies(s);
358 if (r < 0)
359 return r;
598459ce 360
15332d73
LP
361 r = swap_load_devnode(s);
362 if (r < 0)
363 return r;
a016b922 364
15332d73
LP
365 r = unit_patch_contexts(UNIT(s));
366 if (r < 0)
367 return r;
368
369 r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
370 if (r < 0)
371 return r;
372
373 r = unit_set_default_slice(UNIT(s));
374 if (r < 0)
375 return r;
376
377 r = swap_add_default_dependencies(s);
378 if (r < 0)
379 return r;
380
381 return 0;
382}
383
384static int swap_load(Unit *u) {
385 Swap *s = SWAP(u);
75193d41 386 int r, q = 0;
15332d73
LP
387
388 assert(s);
389 assert(u->load_state == UNIT_STUB);
390
391 /* Load a .swap file */
c3620770
ZJS
392 bool fragment_optional = s->from_proc_swaps;
393 r = unit_load_fragment_and_dropin(u, !fragment_optional);
15332d73 394
75193d41
ZJS
395 /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is
396 * already active. */
06721f39
LP
397 if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
398 q = swap_add_extras(s);
15332d73 399
06721f39
LP
400 if (r < 0)
401 return r;
402 if (q < 0)
403 return q;
75193d41
ZJS
404 if (u->load_state != UNIT_LOADED)
405 return 0;
07b0b134
ML
406
407 return swap_verify(s);
408}
409
628c89cc 410static int swap_setup_unit(
4e85aff4
LP
411 Manager *m,
412 const char *what,
e04aad61 413 const char *what_proc_swaps,
4e85aff4 414 int priority,
e04aad61
LP
415 bool set_flags) {
416
7fd1b19b 417 _cleanup_free_ char *e = NULL;
2c7c6144 418 bool delete = false;
5bcb0f2b 419 Unit *u = NULL;
07b0b134 420 int r;
4e85aff4
LP
421 SwapParameters *p;
422
423 assert(m);
424 assert(what);
6b1dc2bd 425 assert(what_proc_swaps);
07b0b134 426
7410616c
LP
427 r = unit_name_from_path(what, ".swap", &e);
428 if (r < 0)
f2341e0a 429 return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
07b0b134 430
e04aad61 431 u = manager_get_unit(m, e);
6b1dc2bd 432 if (u &&
e04aad61 433 SWAP(u)->from_proc_swaps &&
baaa35ad
ZJS
434 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
435 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
436 "Swap %s appeared twice with different device paths %s and %s",
437 e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
4e85aff4
LP
438
439 if (!u) {
07b0b134
ML
440 delete = true;
441
a581e45a 442 r = unit_new_for_name(m, sizeof(Swap), e, &u);
7d17cfbc 443 if (r < 0)
e04aad61
LP
444 goto fail;
445
7d17cfbc
MS
446 SWAP(u)->what = strdup(what);
447 if (!SWAP(u)->what) {
628c89cc 448 r = -ENOMEM;
e04aad61
LP
449 goto fail;
450 }
451
452 unit_add_to_load_queue(u);
4e85aff4
LP
453 } else
454 delete = false;
07b0b134 455
6b1dc2bd 456 p = &SWAP(u)->parameters_proc_swaps;
07b0b134 457
6b1dc2bd 458 if (!p->what) {
5bcb0f2b
LP
459 p->what = strdup(what_proc_swaps);
460 if (!p->what) {
461 r = -ENOMEM;
6b1dc2bd
LP
462 goto fail;
463 }
6b1dc2bd 464 }
e04aad61 465
46f94480
LP
466 /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
467 * loaded. After all we can load it now, from the data in /proc/swaps. */
468 if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
469 u->load_state = UNIT_LOADED;
470 u->load_error = 0;
471 }
472
6b1dc2bd
LP
473 if (set_flags) {
474 SWAP(u)->is_active = true;
475 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
4e85aff4 476 }
07b0b134 477
6b1dc2bd
LP
478 SWAP(u)->from_proc_swaps = true;
479
4e85aff4 480 p->priority = priority;
7477451b 481 p->priority_set = true;
07b0b134 482
4e85aff4 483 unit_add_to_dbus_queue(u);
07b0b134
ML
484 return 0;
485
486fail:
f2341e0a 487 log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
e04aad61 488
c9d5c9c0 489 if (delete)
07b0b134
ML
490 unit_free(u);
491
4e85aff4 492 return r;
07b0b134
ML
493}
494
6aeb8c89 495static void swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
4366e598
YW
496 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
497 const char *dn, *devlink;
498 struct stat st, st_link;
5bcb0f2b 499 int r;
e04aad61
LP
500
501 assert(m);
502
6aeb8c89
LP
503 if (swap_setup_unit(m, device, device, prio, set_flags) < 0)
504 return;
e04aad61 505
5bcb0f2b
LP
506 /* If this is a block device, then let's add duplicates for
507 * all other names of this block device */
508 if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
6aeb8c89 509 return;
e04aad61 510
a1130022 511 r = sd_device_new_from_stat_rdev(&d, &st);
6aeb8c89
LP
512 if (r < 0)
513 return (void) log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
514 "Failed to allocate device for swap %s: %m", device);
e04aad61 515
5bcb0f2b 516 /* Add the main device node */
4366e598 517 if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device))
6aeb8c89 518 (void) swap_setup_unit(m, dn, device, prio, set_flags);
e04aad61 519
5bcb0f2b 520 /* Add additional units for all symlinks */
4366e598 521 FOREACH_DEVICE_DEVLINK(d, devlink) {
e04aad61 522
5bcb0f2b 523 /* Don't bother with the /dev/block links */
4366e598 524 if (streq(devlink, device))
5bcb0f2b 525 continue;
e04aad61 526
4366e598 527 if (path_startswith(devlink, "/dev/block/"))
5bcb0f2b 528 continue;
e04aad61 529
4366e598
YW
530 if (stat(devlink, &st_link) >= 0 &&
531 (!S_ISBLK(st_link.st_mode) ||
532 st_link.st_rdev != st.st_rdev))
533 continue;
e04aad61 534
6aeb8c89 535 (void) swap_setup_unit(m, devlink, device, prio, set_flags);
e04aad61 536 }
e04aad61
LP
537}
538
07b0b134
ML
539static void swap_set_state(Swap *s, SwapState state) {
540 SwapState old_state;
37cf8fee 541 Swap *other;
e04aad61 542
07b0b134
ML
543 assert(s);
544
6fcbec6f
LP
545 if (s->state != state)
546 bus_unit_send_pending_change_signal(UNIT(s), false);
547
07b0b134
ML
548 old_state = s->state;
549 s->state = state;
550
dedf3719 551 if (!SWAP_STATE_WITH_PROCESS(state)) {
5dcadb4c 552 s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
e04aad61
LP
553 swap_unwatch_control_pid(s);
554 s->control_command = NULL;
555 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
556 }
557
07b0b134 558 if (state != old_state)
f2341e0a 559 log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
07b0b134 560
2ad2e41a 561 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
37cf8fee
LP
562
563 /* If there other units for the same device node have a job
564 queued it might be worth checking again if it is runnable
565 now. This is necessary, since swap_start() refuses
566 operation with EAGAIN if there's already another job for
567 the same device node queued. */
568 LIST_FOREACH_OTHERS(same_devnode, other, s)
569 if (UNIT(other)->job)
570 job_add_to_run_queue(UNIT(other)->job);
07b0b134
ML
571}
572
be847e82 573static int swap_coldplug(Unit *u) {
07b0b134
ML
574 Swap *s = SWAP(u);
575 SwapState new_state = SWAP_DEAD;
e04aad61 576 int r;
07b0b134
ML
577
578 assert(s);
579 assert(s->state == SWAP_DEAD);
580
581 if (s->deserialized_state != s->state)
582 new_state = s->deserialized_state;
4e85aff4 583 else if (s->from_proc_swaps)
07b0b134
ML
584 new_state = SWAP_ACTIVE;
585
5bcb0f2b
LP
586 if (new_state == s->state)
587 return 0;
e04aad61 588
c386f588
LP
589 if (s->control_pid > 0 &&
590 pid_is_unwaited(s->control_pid) &&
dedf3719 591 SWAP_STATE_WITH_PROCESS(new_state)) {
e04aad61 592
f75f613d 593 r = unit_watch_pid(UNIT(s), s->control_pid, false);
5bcb0f2b
LP
594 if (r < 0)
595 return r;
e04aad61 596
36c16a7c 597 r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
5bcb0f2b
LP
598 if (r < 0)
599 return r;
e04aad61 600 }
07b0b134 601
e8a565cb 602 if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) {
29206d46 603 (void) unit_setup_dynamic_creds(u);
e8a565cb
YW
604 (void) unit_setup_exec_runtime(u);
605 }
29206d46 606
5bcb0f2b 607 swap_set_state(s, new_state);
07b0b134
ML
608 return 0;
609}
610
611static void swap_dump(Unit *u, FILE *f, const char *prefix) {
f2e18ef1 612 char buf[FORMAT_TIMESPAN_MAX];
07b0b134 613 Swap *s = SWAP(u);
4e85aff4 614 SwapParameters *p;
07b0b134
ML
615
616 assert(s);
4e85aff4
LP
617 assert(f);
618
619 if (s->from_proc_swaps)
620 p = &s->parameters_proc_swaps;
621 else if (s->from_fragment)
622 p = &s->parameters_fragment;
b6bfc7bb
LP
623 else
624 p = NULL;
07b0b134
ML
625
626 fprintf(f,
4e85aff4 627 "%sSwap State: %s\n"
e1770af8 628 "%sResult: %s\n"
a8b689b7 629 "%sClean Result: %s\n"
07b0b134 630 "%sWhat: %s\n"
4e85aff4 631 "%sFrom /proc/swaps: %s\n"
39c79477
ZJS
632 "%sFrom fragment: %s\n"
633 "%sExtrinsic: %s\n",
07b0b134 634 prefix, swap_state_to_string(s->state),
e1770af8 635 prefix, swap_result_to_string(s->result),
a8b689b7 636 prefix, swap_result_to_string(s->clean_result),
07b0b134 637 prefix, s->what,
4e85aff4 638 prefix, yes_no(s->from_proc_swaps),
39c79477
ZJS
639 prefix, yes_no(s->from_fragment),
640 prefix, yes_no(swap_is_extrinsic(u)));
e04aad61 641
9670d583
LP
642 if (s->devnode)
643 fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
644
b6bfc7bb
LP
645 if (p)
646 fprintf(f,
647 "%sPriority: %i\n"
47cb901e 648 "%sOptions: %s\n",
b6bfc7bb 649 prefix, p->priority,
47cb901e 650 prefix, strempty(p->options));
b6bfc7bb 651
9bd0e1b8
YW
652 fprintf(f,
653 "%sTimeoutSec: %s\n",
654 prefix, format_timespan(buf, sizeof(buf), s->timeout_usec, USEC_PER_SEC));
655
e04aad61
LP
656 if (s->control_pid > 0)
657 fprintf(f,
de0671ee
ZJS
658 "%sControl PID: "PID_FMT"\n",
659 prefix, s->control_pid);
e04aad61
LP
660
661 exec_context_dump(&s->exec_context, f, prefix);
4819ff03 662 kill_context_dump(&s->kill_context, f, prefix);
bc0623df 663 cgroup_context_dump(UNIT(s), f, prefix);
e04aad61
LP
664}
665
666static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
3c7416b6 667
b9c04eaf 668 _cleanup_(exec_params_clear) ExecParameters exec_params = {
1703fa41 669 .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
c39f1ce2
LP
670 .stdin_fd = -1,
671 .stdout_fd = -1,
672 .stderr_fd = -1,
5686391b 673 .exec_fd = -1,
9fa95f85 674 };
3c7416b6
LP
675 pid_t pid;
676 int r;
e04aad61
LP
677
678 assert(s);
679 assert(c);
680 assert(_pid);
681
3c7416b6 682 r = unit_prepare_exec(UNIT(s));
29206d46 683 if (r < 0)
3c7416b6 684 return r;
29206d46 685
36c16a7c 686 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
646134dc 687 if (r < 0)
e04aad61
LP
688 goto fail;
689
1ad6e8b3
LP
690 r = unit_set_exec_params(UNIT(s), &exec_params);
691 if (r < 0)
692 goto fail;
9fa95f85 693
f2341e0a
LP
694 r = exec_spawn(UNIT(s),
695 c,
646134dc 696 &s->exec_context,
9fa95f85 697 &exec_params,
613b411c 698 s->exec_runtime,
29206d46 699 &s->dynamic_creds,
646134dc
ZJS
700 &pid);
701 if (r < 0)
e04aad61
LP
702 goto fail;
703
f75f613d 704 r = unit_watch_pid(UNIT(s), pid, true);
646134dc 705 if (r < 0)
e04aad61
LP
706 goto fail;
707
708 *_pid = pid;
709
710 return 0;
711
712fail:
5dcadb4c 713 s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
3536f49e 714
e04aad61 715 return r;
07b0b134
ML
716}
717
e1770af8 718static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
719 assert(s);
720
a0fef983 721 if (s->result == SWAP_SUCCESS)
e1770af8 722 s->result = f;
e04aad61 723
aac99f30 724 unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result));
4c425434 725 unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
29206d46
LP
726 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
727
e8a565cb 728 s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
613b411c 729
bb0c0d6f 730 unit_destroy_runtime_data(UNIT(s), &s->exec_context);
e66cf1a3 731
00d9ef85
LP
732 unit_unref_uid_gid(UNIT(s), true);
733
29206d46 734 dynamic_creds_destroy(&s->dynamic_creds);
07b0b134
ML
735}
736
e1770af8 737static void swap_enter_active(Swap *s, SwapResult f) {
e04aad61
LP
738 assert(s);
739
a0fef983 740 if (s->result == SWAP_SUCCESS)
e1770af8 741 s->result = f;
e04aad61
LP
742
743 swap_set_state(s, SWAP_ACTIVE);
744}
745
50864457
LP
746static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
747 assert(s);
748
9c1f969d
HD
749 if (s->from_proc_swaps) {
750 Swap *other;
751
50864457 752 swap_enter_active(s, f);
9c1f969d
HD
753
754 LIST_FOREACH_OTHERS(same_devnode, other, s)
755 if (UNIT(other)->job)
756 swap_enter_dead_or_active(other, f);
757 } else
50864457
LP
758 swap_enter_dead(s, f);
759}
760
a232ebcc
ZJS
761static int state_to_kill_operation(Swap *s, SwapState state) {
762 if (state == SWAP_DEACTIVATING_SIGTERM) {
763 if (unit_has_job_type(UNIT(s), JOB_RESTART))
764 return KILL_RESTART;
765 else
766 return KILL_TERMINATE;
767 }
768
769 return KILL_KILL;
770}
771
e1770af8 772static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
07b0b134
ML
773 int r;
774
775 assert(s);
e04aad61 776
a0fef983 777 if (s->result == SWAP_SUCCESS)
e1770af8 778 s->result = f;
e04aad61 779
a232ebcc
ZJS
780 r = unit_kill_context(UNIT(s),
781 &s->kill_context,
782 state_to_kill_operation(s, state),
783 -1,
784 s->control_pid,
785 false);
cd2086fe
LP
786 if (r < 0)
787 goto fail;
e04aad61 788
cd2086fe 789 if (r > 0) {
36c16a7c 790 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
646134dc 791 if (r < 0)
e04aad61
LP
792 goto fail;
793
794 swap_set_state(s, state);
50864457 795 } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
ac84d1fb
LP
796 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
797 else
50864457 798 swap_enter_dead_or_active(s, SWAP_SUCCESS);
e04aad61
LP
799
800 return;
801
802fail:
f2341e0a 803 log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
50864457 804 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
805}
806
807static void swap_enter_activating(Swap *s) {
bf1d7ba7
KZ
808 _cleanup_free_ char *opts = NULL;
809 int r;
e04aad61
LP
810
811 assert(s);
812
4c425434 813 unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
a4634b21 814
e04aad61
LP
815 s->control_command_id = SWAP_EXEC_ACTIVATE;
816 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 817
86b23b07 818 if (s->from_fragment) {
7477451b 819 int priority = 0;
47cb901e 820
bf1d7ba7
KZ
821 r = fstab_find_pri(s->parameters_fragment.options, &priority);
822 if (r < 0)
af4454cb
LP
823 log_unit_warning_errno(UNIT(s), r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options);
824 else if (r > 0 && s->parameters_fragment.priority_set)
825 log_unit_warning(UNIT(s), "Duplicate swap priority configuration by Priority= and Options= fields.");
bf1d7ba7 826
7477451b 827 if (r <= 0 && s->parameters_fragment.priority_set) {
bf1d7ba7
KZ
828 if (s->parameters_fragment.options)
829 r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority);
830 else
831 r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority);
6fca66a7
LP
832 if (r < 0) {
833 r = -ENOMEM;
bf1d7ba7 834 goto fail;
6fca66a7 835 }
e64d5235 836 }
86b23b07
JS
837 }
838
839 r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
840 if (r < 0)
841 goto fail;
4e85aff4 842
bf1d7ba7
KZ
843 if (s->parameters_fragment.options || opts) {
844 r = exec_command_append(s->control_command, "-o",
af4454cb 845 opts ?: s->parameters_fragment.options, NULL);
86b23b07
JS
846 if (r < 0)
847 goto fail;
848 }
e04aad61 849
86b23b07 850 r = exec_command_append(s->control_command, s->what, NULL);
e04aad61
LP
851 if (r < 0)
852 goto fail;
853
854 swap_unwatch_control_pid(s);
855
646134dc
ZJS
856 r = swap_spawn(s, s->control_command, &s->control_pid);
857 if (r < 0)
e04aad61
LP
858 goto fail;
859
860 swap_set_state(s, SWAP_ACTIVATING);
e04aad61
LP
861 return;
862
863fail:
f2341e0a 864 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
50864457 865 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
866}
867
e1770af8 868static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
869 int r;
870
871 assert(s);
872
e04aad61
LP
873 s->control_command_id = SWAP_EXEC_DEACTIVATE;
874 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
875
646134dc 876 r = exec_command_set(s->control_command,
e04aad61
LP
877 "/sbin/swapoff",
878 s->what,
646134dc
ZJS
879 NULL);
880 if (r < 0)
e04aad61
LP
881 goto fail;
882
883 swap_unwatch_control_pid(s);
884
646134dc
ZJS
885 r = swap_spawn(s, s->control_command, &s->control_pid);
886 if (r < 0)
e04aad61
LP
887 goto fail;
888
889 swap_set_state(s, SWAP_DEACTIVATING);
890
891 return;
892
893fail:
f2341e0a 894 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
50864457 895 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
896}
897
31135818
LP
898static void swap_cycle_clear(Swap *s) {
899 assert(s);
900
901 s->result = SWAP_SUCCESS;
902 exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
903 UNIT(s)->reset_accounting = true;
904}
905
e04aad61 906static int swap_start(Unit *u) {
37cf8fee 907 Swap *s = SWAP(u), *other;
07299350 908 int r;
e04aad61
LP
909
910 assert(s);
911
50864457 912 /* We cannot fulfill this request right now, try again later please! */
d31ae548
FB
913 if (IN_SET(s->state,
914 SWAP_DEACTIVATING,
915 SWAP_DEACTIVATING_SIGTERM,
a8b689b7
YW
916 SWAP_DEACTIVATING_SIGKILL,
917 SWAP_CLEANING))
e04aad61
LP
918 return -EAGAIN;
919
50864457 920 /* Already on it! */
e04aad61
LP
921 if (s->state == SWAP_ACTIVATING)
922 return 0;
923
d31ae548 924 assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
e04aad61 925
75f86906 926 if (detect_container() > 0)
a5c3034f
LP
927 return -EPERM;
928
37cf8fee
LP
929 /* If there's a job for another swap unit for the same node
930 * running, then let's not dispatch this one for now, and wait
931 * until that other job has finished. */
932 LIST_FOREACH_OTHERS(same_devnode, other, s)
933 if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
934 return -EAGAIN;
935
97a3f4ee 936 r = unit_test_start_limit(u);
07299350
LP
937 if (r < 0) {
938 swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
939 return r;
940 }
941
4b58153d
LP
942 r = unit_acquire_invocation_id(u);
943 if (r < 0)
944 return r;
945
31135818 946 swap_cycle_clear(s);
e04aad61 947 swap_enter_activating(s);
82a2b6bb 948 return 1;
07b0b134
ML
949}
950
951static int swap_stop(Unit *u) {
952 Swap *s = SWAP(u);
07b0b134
ML
953
954 assert(s);
955
50864457
LP
956 switch (s->state) {
957
958 case SWAP_DEACTIVATING:
959 case SWAP_DEACTIVATING_SIGTERM:
960 case SWAP_DEACTIVATING_SIGKILL:
961 /* Already on it */
e04aad61 962 return 0;
07b0b134 963
50864457
LP
964 case SWAP_ACTIVATING:
965 case SWAP_ACTIVATING_DONE:
966 /* There's a control process pending, directly enter kill mode */
967 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
968 return 0;
07b0b134 969
50864457
LP
970 case SWAP_ACTIVE:
971 if (detect_container() > 0)
972 return -EPERM;
a5c3034f 973
50864457
LP
974 swap_enter_deactivating(s);
975 return 1;
976
a8b689b7
YW
977 case SWAP_CLEANING:
978 /* If we are currently cleaning, then abort it, brutally. */
979 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
980 return 0;
981
50864457
LP
982 default:
983 assert_not_reached("Unexpected state.");
984 }
07b0b134
ML
985}
986
987static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
988 Swap *s = SWAP(u);
989
990 assert(s);
991 assert(f);
992 assert(fds);
993
d68c645b
LP
994 (void) serialize_item(f, "state", swap_state_to_string(s->state));
995 (void) serialize_item(f, "result", swap_result_to_string(s->result));
e04aad61
LP
996
997 if (s->control_pid > 0)
d68c645b 998 (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
e04aad61
LP
999
1000 if (s->control_command_id >= 0)
d68c645b 1001 (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
1002
1003 return 0;
1004}
1005
1006static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1007 Swap *s = SWAP(u);
1008
1009 assert(s);
1010 assert(fds);
1011
1012 if (streq(key, "state")) {
1013 SwapState state;
1014
646134dc
ZJS
1015 state = swap_state_from_string(value);
1016 if (state < 0)
f2341e0a 1017 log_unit_debug(u, "Failed to parse state value: %s", value);
07b0b134
ML
1018 else
1019 s->deserialized_state = state;
e1770af8
LP
1020 } else if (streq(key, "result")) {
1021 SwapResult f;
1022
1023 f = swap_result_from_string(value);
1024 if (f < 0)
f2341e0a 1025 log_unit_debug(u, "Failed to parse result value: %s", value);
e1770af8
LP
1026 else if (f != SWAP_SUCCESS)
1027 s->result = f;
e04aad61
LP
1028 } else if (streq(key, "control-pid")) {
1029 pid_t pid;
1030
1031 if (parse_pid(value, &pid) < 0)
f2341e0a 1032 log_unit_debug(u, "Failed to parse control-pid value: %s", value);
e04aad61
LP
1033 else
1034 s->control_pid = pid;
1035
1036 } else if (streq(key, "control-command")) {
1037 SwapExecCommand id;
1038
646134dc
ZJS
1039 id = swap_exec_command_from_string(value);
1040 if (id < 0)
f2341e0a 1041 log_unit_debug(u, "Failed to parse exec-command value: %s", value);
e04aad61
LP
1042 else {
1043 s->control_command_id = id;
1044 s->control_command = s->exec_command + id;
1045 }
07b0b134 1046 } else
f2341e0a 1047 log_unit_debug(u, "Unknown serialization key: %s", key);
07b0b134
ML
1048
1049 return 0;
1050}
1051
e04aad61
LP
1052static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1053 Swap *s = SWAP(u);
e1770af8 1054 SwapResult f;
e04aad61
LP
1055
1056 assert(s);
1057 assert(pid >= 0);
1058
1059 if (pid != s->control_pid)
1060 return;
1061
bcce581d
LP
1062 /* Let's scan /proc/swaps before we process SIGCHLD. For the reasoning see the similar code in
1063 * mount.c */
1064 (void) swap_process_proc_swaps(u->manager);
1065
e04aad61
LP
1066 s->control_pid = 0;
1067
1f0958f6 1068 if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
e1770af8
LP
1069 f = SWAP_SUCCESS;
1070 else if (code == CLD_EXITED)
1071 f = SWAP_FAILURE_EXIT_CODE;
1072 else if (code == CLD_KILLED)
1073 f = SWAP_FAILURE_SIGNAL;
1074 else if (code == CLD_DUMPED)
1075 f = SWAP_FAILURE_CORE_DUMP;
1076 else
1077 assert_not_reached("Unknown code");
1078
a0fef983 1079 if (s->result == SWAP_SUCCESS)
e1770af8 1080 s->result = f;
e04aad61
LP
1081
1082 if (s->control_command) {
6ea832a2 1083 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 1084
e04aad61
LP
1085 s->control_command = NULL;
1086 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
1087 }
1088
91bbd9b7 1089 unit_log_process_exit(
5cc2cd1c 1090 u,
91bbd9b7
LP
1091 "Swap process",
1092 swap_exec_command_to_string(s->control_command_id),
5cc2cd1c 1093 f == SWAP_SUCCESS,
91bbd9b7 1094 code, status);
e04aad61
LP
1095
1096 switch (s->state) {
1097
1098 case SWAP_ACTIVATING:
5bcb0f2b 1099 case SWAP_ACTIVATING_DONE:
e04aad61 1100
50864457 1101 if (f == SWAP_SUCCESS || s->from_proc_swaps)
e1770af8 1102 swap_enter_active(s, f);
e04aad61 1103 else
e1770af8 1104 swap_enter_dead(s, f);
e04aad61
LP
1105 break;
1106
1107 case SWAP_DEACTIVATING:
1108 case SWAP_DEACTIVATING_SIGKILL:
1109 case SWAP_DEACTIVATING_SIGTERM:
1110
50864457 1111 swap_enter_dead_or_active(s, f);
e04aad61
LP
1112 break;
1113
a8b689b7
YW
1114 case SWAP_CLEANING:
1115 if (s->clean_result == SWAP_SUCCESS)
1116 s->clean_result = f;
1117
1118 swap_enter_dead(s, SWAP_SUCCESS);
1119 break;
1120
e04aad61
LP
1121 default:
1122 assert_not_reached("Uh, control process died at wrong time.");
1123 }
1124
1125 /* Notify clients about changed exit status */
1126 unit_add_to_dbus_queue(u);
e04aad61
LP
1127}
1128
718db961
LP
1129static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1130 Swap *s = SWAP(userdata);
e04aad61
LP
1131
1132 assert(s);
718db961 1133 assert(s->timer_event_source == source);
e04aad61
LP
1134
1135 switch (s->state) {
1136
1137 case SWAP_ACTIVATING:
5bcb0f2b 1138 case SWAP_ACTIVATING_DONE:
f2341e0a 1139 log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
50864457 1140 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1141 break;
1142
1143 case SWAP_DEACTIVATING:
f2341e0a 1144 log_unit_warning(UNIT(s), "Deactivation timed out. Stopping.");
e1770af8 1145 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1146 break;
1147
e04aad61 1148 case SWAP_DEACTIVATING_SIGTERM:
4819ff03 1149 if (s->kill_context.send_sigkill) {
50864457 1150 log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
e1770af8 1151 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1152 } else {
50864457
LP
1153 log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
1154 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1155 }
e04aad61
LP
1156 break;
1157
e04aad61 1158 case SWAP_DEACTIVATING_SIGKILL:
f2341e0a 1159 log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
50864457 1160 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1161 break;
1162
a8b689b7
YW
1163 case SWAP_CLEANING:
1164 log_unit_warning(UNIT(s), "Cleaning timed out. killing.");
1165
1166 if (s->clean_result == SWAP_SUCCESS)
1167 s->clean_result = SWAP_FAILURE_TIMEOUT;
1168
1169 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, 0);
1170 break;
1171
e04aad61
LP
1172 default:
1173 assert_not_reached("Timeout at wrong time.");
1174 }
718db961
LP
1175
1176 return 0;
e04aad61
LP
1177}
1178
1179static int swap_load_proc_swaps(Manager *m, bool set_flags) {
e04aad61
LP
1180 assert(m);
1181
07b0b134 1182 rewind(m->proc_swaps);
bab45044 1183
4e85aff4 1184 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1185
fe96c0f8 1186 for (unsigned i = 1;; i++) {
9fb3675e 1187 _cleanup_free_ char *dev = NULL, *d = NULL;
07b0b134
ML
1188 int prio = 0, k;
1189
646134dc
ZJS
1190 k = fscanf(m->proc_swaps,
1191 "%ms " /* device/file */
1192 "%*s " /* type of swap */
1193 "%*s " /* swap size */
1194 "%*s " /* used */
1195 "%i\n", /* priority */
1196 &dev, &prio);
1197 if (k != 2) {
07b0b134 1198 if (k == EOF)
4e85aff4 1199 break;
07b0b134 1200
628c89cc 1201 log_warning("Failed to parse /proc/swaps:%u.", i);
e04aad61 1202 continue;
07b0b134 1203 }
07b0b134 1204
527b7a42 1205 if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
628c89cc
LP
1206 return log_oom();
1207
485ae697 1208 device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
4e85aff4 1209
eb04385d 1210 (void) swap_process_new(m, d, prio, set_flags);
07b0b134
ML
1211 }
1212
eb04385d 1213 return 0;
e04aad61
LP
1214}
1215
bcce581d 1216static int swap_process_proc_swaps(Manager *m) {
595ed347 1217 Unit *u;
4e434314
LP
1218 int r;
1219
1220 assert(m);
4e434314 1221
646134dc
ZJS
1222 r = swap_load_proc_swaps(m, true);
1223 if (r < 0) {
da927ba9 1224 log_error_errno(r, "Failed to reread /proc/swaps: %m");
e04aad61
LP
1225
1226 /* Reset flags, just in case, for late calls */
595ed347
MS
1227 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1228 Swap *swap = SWAP(u);
e04aad61
LP
1229
1230 swap->is_active = swap->just_activated = false;
1231 }
1232
1233 return 0;
1234 }
1235
1236 manager_dispatch_load_queue(m);
1237
595ed347
MS
1238 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1239 Swap *swap = SWAP(u);
e04aad61
LP
1240
1241 if (!swap->is_active) {
e04aad61 1242
e04aad61
LP
1243 swap_unset_proc_swaps(swap);
1244
1245 switch (swap->state) {
1246
1247 case SWAP_ACTIVE:
ba6fbb2c 1248 /* This has just been deactivated */
e1770af8 1249 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1250 break;
1251
1252 default:
5bcb0f2b 1253 /* Fire again */
e04aad61
LP
1254 swap_set_state(swap, swap->state);
1255 break;
1256 }
1257
628c89cc 1258 if (swap->what)
485ae697 1259 device_found_node(m, swap->what, 0, DEVICE_FOUND_SWAP);
628c89cc 1260
e04aad61
LP
1261 } else if (swap->just_activated) {
1262
1263 /* New swap entry */
1264
1265 switch (swap->state) {
1266
1267 case SWAP_DEAD:
1268 case SWAP_FAILED:
31135818
LP
1269 (void) unit_acquire_invocation_id(u);
1270 swap_cycle_clear(swap);
e1770af8 1271 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1272 break;
1273
5bcb0f2b
LP
1274 case SWAP_ACTIVATING:
1275 swap_set_state(swap, SWAP_ACTIVATING_DONE);
1276 break;
1277
e04aad61
LP
1278 default:
1279 /* Nothing really changed, but let's
1280 * issue an notification call
1281 * nonetheless, in case somebody is
1282 * waiting for this. */
1283 swap_set_state(swap, swap->state);
1284 break;
1285 }
1286 }
1287
1288 /* Reset the flags for later calls */
1289 swap->is_active = swap->just_activated = false;
1290 }
1291
1292 return 1;
1293}
1294
bcce581d
LP
1295static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1296 Manager *m = userdata;
1297
1298 assert(m);
1299 assert(revents & EPOLLPRI);
1300
1301 return swap_process_proc_swaps(m);
1302}
1303
e04aad61
LP
1304static Unit *swap_following(Unit *u) {
1305 Swap *s = SWAP(u);
1306 Swap *other, *first = NULL;
1307
1308 assert(s);
1309
cdc89820
ZJS
1310 /* If the user configured the swap through /etc/fstab or
1311 * a device unit, follow that. */
1312
1313 if (s->from_fragment)
e04aad61
LP
1314 return NULL;
1315
caac2704 1316 LIST_FOREACH_OTHERS(same_devnode, other, s)
cdc89820
ZJS
1317 if (other->from_fragment)
1318 return UNIT(other);
1319
b938cb90 1320 /* Otherwise, make everybody follow the unit that's named after
cdc89820
ZJS
1321 * the swap device in the kernel */
1322
1323 if (streq_ptr(s->what, s->devnode))
1324 return NULL;
e04aad61 1325
9670d583
LP
1326 LIST_FOREACH_AFTER(same_devnode, other, s)
1327 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1328 return UNIT(other);
1329
9670d583
LP
1330 LIST_FOREACH_BEFORE(same_devnode, other, s) {
1331 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1332 return UNIT(other);
1333
1334 first = other;
1335 }
1336
cdc89820 1337 /* Fall back to the first on the list */
e04aad61 1338 return UNIT(first);
07b0b134
ML
1339}
1340
6210e7fc 1341static int swap_following_set(Unit *u, Set **_set) {
5bcb0f2b 1342 Swap *s = SWAP(u), *other;
af4fa99d 1343 _cleanup_set_free_ Set *set = NULL;
6210e7fc
LP
1344 int r;
1345
1346 assert(s);
1347 assert(_set);
1348
9670d583 1349 if (LIST_JUST_US(same_devnode, s)) {
6210e7fc
LP
1350 *_set = NULL;
1351 return 0;
1352 }
1353
d5099efc 1354 set = set_new(NULL);
5bcb0f2b 1355 if (!set)
6210e7fc
LP
1356 return -ENOMEM;
1357
caac2704 1358 LIST_FOREACH_OTHERS(same_devnode, other, s) {
5bcb0f2b
LP
1359 r = set_put(set, other);
1360 if (r < 0)
95f14a3e 1361 return r;
5bcb0f2b 1362 }
6210e7fc 1363
95f14a3e 1364 *_set = TAKE_PTR(set);
6210e7fc 1365 return 1;
6210e7fc
LP
1366}
1367
07b0b134
ML
1368static void swap_shutdown(Manager *m) {
1369 assert(m);
1370
5dcadb4c 1371 m->swap_event_source = sd_event_source_disable_unref(m->swap_event_source);
74ca738f 1372 m->proc_swaps = safe_fclose(m->proc_swaps);
525d3cc7 1373 m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
07b0b134
ML
1374}
1375
ba64af90 1376static void swap_enumerate(Manager *m) {
07b0b134 1377 int r;
9670d583 1378
07b0b134
ML
1379 assert(m);
1380
4e434314 1381 if (!m->proc_swaps) {
646134dc 1382 m->proc_swaps = fopen("/proc/swaps", "re");
ba64af90
LP
1383 if (!m->proc_swaps) {
1384 if (errno == ENOENT)
cb209a04 1385 log_debug_errno(errno, "Not swap enabled, skipping enumeration.");
ba64af90 1386 else
cb209a04 1387 log_warning_errno(errno, "Failed to open /proc/swaps, ignoring: %m");
ba64af90
LP
1388
1389 return;
1390 }
4e434314 1391
151b9b96 1392 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
ba64af90
LP
1393 if (r < 0) {
1394 log_error_errno(r, "Failed to watch /proc/swaps: %m");
29083707 1395 goto fail;
ba64af90 1396 }
29083707
LP
1397
1398 /* Dispatch this before we dispatch SIGCHLD, so that
1399 * we always get the events from /proc/swaps before
1400 * the SIGCHLD of /sbin/swapon. */
83231637 1401 r = sd_event_source_set_priority(m->swap_event_source, SD_EVENT_PRIORITY_NORMAL-10);
ba64af90
LP
1402 if (r < 0) {
1403 log_error_errno(r, "Failed to change /proc/swaps priority: %m");
718db961 1404 goto fail;
ba64af90 1405 }
7dfbe2e3
TG
1406
1407 (void) sd_event_source_set_description(m->swap_event_source, "swap-proc");
4e434314
LP
1408 }
1409
646134dc
ZJS
1410 r = swap_load_proc_swaps(m, false);
1411 if (r < 0)
718db961
LP
1412 goto fail;
1413
ba64af90 1414 return;
07b0b134 1415
718db961
LP
1416fail:
1417 swap_shutdown(m);
07b0b134
ML
1418}
1419
4366e598 1420int swap_process_device_new(Manager *m, sd_device *dev) {
9670d583 1421 _cleanup_free_ char *e = NULL;
4366e598 1422 const char *dn, *devlink;
cabf58b2 1423 Unit *u;
c53aafb7 1424 int r;
9670d583
LP
1425
1426 assert(m);
1427 assert(dev);
1428
e82c6e8b 1429 if (sd_device_get_devname(dev, &dn) < 0)
9670d583
LP
1430 return 0;
1431
7410616c 1432 r = unit_name_from_path(dn, ".swap", &e);
e82c6e8b
LP
1433 if (r < 0) {
1434 log_debug_errno(r, "Cannot convert device name '%s' to unit name, ignoring: %m", dn);
1435 return 0;
1436 }
9670d583 1437
cabf58b2
FB
1438 u = manager_get_unit(m, e);
1439 if (u)
1440 r = swap_set_devnode(SWAP(u), dn);
9670d583 1441
4366e598 1442 FOREACH_DEVICE_DEVLINK(dev, devlink) {
9670d583 1443 _cleanup_free_ char *n = NULL;
7410616c 1444 int q;
9670d583 1445
4366e598 1446 q = unit_name_from_path(devlink, ".swap", &n);
598a6a84
LP
1447 if (IN_SET(q, -EINVAL, -ENAMETOOLONG)) /* If name too long or otherwise not convertible to
1448 * unit name, we can't manage it */
1449 continue;
7410616c
LP
1450 if (q < 0)
1451 return q;
9670d583 1452
cabf58b2
FB
1453 u = manager_get_unit(m, n);
1454 if (u) {
1455 q = swap_set_devnode(SWAP(u), dn);
9670d583
LP
1456 if (q < 0)
1457 r = q;
1458 }
1459 }
1460
1461 return r;
1462}
1463
4366e598 1464int swap_process_device_remove(Manager *m, sd_device *dev) {
9670d583 1465 const char *dn;
c53aafb7 1466 int r;
9670d583
LP
1467 Swap *s;
1468
4366e598
YW
1469 r = sd_device_get_devname(dev, &dn);
1470 if (r < 0)
9670d583
LP
1471 return 0;
1472
1473 while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
1474 int q;
1475
1476 q = swap_set_devnode(s, NULL);
1477 if (q < 0)
1478 r = q;
1479 }
1480
1481 return r;
1482}
1483
fdf20a31 1484static void swap_reset_failed(Unit *u) {
5632e374
LP
1485 Swap *s = SWAP(u);
1486
1487 assert(s);
1488
fdf20a31 1489 if (s->state == SWAP_FAILED)
5632e374 1490 swap_set_state(s, SWAP_DEAD);
e04aad61 1491
e1770af8 1492 s->result = SWAP_SUCCESS;
a8b689b7 1493 s->clean_result = SWAP_SUCCESS;
5632e374
LP
1494}
1495
718db961 1496static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1497 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
8a0867d6
LP
1498}
1499
7a7821c8 1500static int swap_get_timeout(Unit *u, usec_t *timeout) {
68db7a3b 1501 Swap *s = SWAP(u);
7a7821c8 1502 usec_t t;
68db7a3b
ZJS
1503 int r;
1504
1505 if (!s->timer_event_source)
1506 return 0;
1507
7a7821c8 1508 r = sd_event_source_get_time(s->timer_event_source, &t);
68db7a3b
ZJS
1509 if (r < 0)
1510 return r;
7a7821c8
LP
1511 if (t == USEC_INFINITY)
1512 return 0;
68db7a3b 1513
7a7821c8 1514 *timeout = t;
68db7a3b
ZJS
1515 return 1;
1516}
1517
1c2e9646 1518static bool swap_supported(void) {
0faacd47
LP
1519 static int supported = -1;
1520
1521 /* If swap support is not available in the kernel, or we are
1522 * running in a container we don't support swap units, and any
1523 * attempts to starting one should fail immediately. */
1524
1525 if (supported < 0)
1526 supported =
1527 access("/proc/swaps", F_OK) >= 0 &&
75f86906 1528 detect_container() <= 0;
0faacd47
LP
1529
1530 return supported;
1531}
1532
291d565a
LP
1533static int swap_control_pid(Unit *u) {
1534 Swap *s = SWAP(u);
1535
1536 assert(s);
1537
1538 return s->control_pid;
1539}
1540
a8b689b7
YW
1541static int swap_clean(Unit *u, ExecCleanMask mask) {
1542 _cleanup_strv_free_ char **l = NULL;
1543 Swap *s = SWAP(u);
1544 int r;
1545
1546 assert(s);
1547 assert(mask != 0);
1548
1549 if (s->state != SWAP_DEAD)
1550 return -EBUSY;
1551
1552 r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
1553 if (r < 0)
1554 return r;
1555
1556 if (strv_isempty(l))
1557 return -EUNATCH;
1558
1559 swap_unwatch_control_pid(s);
1560 s->clean_result = SWAP_SUCCESS;
1561 s->control_command = NULL;
1562 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
1563
1564 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
1565 if (r < 0)
1566 goto fail;
1567
1568 r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
1569 if (r < 0)
1570 goto fail;
1571
1572 swap_set_state(s, SWAP_CLEANING);
1573
1574 return 0;
1575
1576fail:
1577 log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
1578 s->clean_result = SWAP_FAILURE_RESOURCES;
5dcadb4c 1579 s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
a8b689b7
YW
1580 return r;
1581}
1582
1583static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
1584 Swap *s = SWAP(u);
1585
1586 assert(s);
1587
1588 return exec_context_get_clean_mask(&s->exec_context, ret);
1589}
1590
e04aad61
LP
1591static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1592 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1593 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1594};
1595
1596DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1597
e1770af8
LP
1598static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1599 [SWAP_SUCCESS] = "success",
1600 [SWAP_FAILURE_RESOURCES] = "resources",
1601 [SWAP_FAILURE_TIMEOUT] = "timeout",
1602 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1603 [SWAP_FAILURE_SIGNAL] = "signal",
07299350
LP
1604 [SWAP_FAILURE_CORE_DUMP] = "core-dump",
1605 [SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
e1770af8
LP
1606};
1607
1608DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1609
07b0b134 1610const UnitVTable swap_vtable = {
7d17cfbc 1611 .object_size = sizeof(Swap),
718db961
LP
1612 .exec_context_offset = offsetof(Swap, exec_context),
1613 .cgroup_context_offset = offsetof(Swap, cgroup_context),
1614 .kill_context_offset = offsetof(Swap, kill_context),
613b411c 1615 .exec_runtime_offset = offsetof(Swap, exec_runtime),
29206d46 1616 .dynamic_creds_offset = offsetof(Swap, dynamic_creds),
3ef63c31 1617
f975e971
LP
1618 .sections =
1619 "Unit\0"
1620 "Swap\0"
1621 "Install\0",
4ad49000 1622 .private_section = "Swap",
71645aca 1623
c80a9a33
LP
1624 .can_fail = true,
1625
4e85aff4 1626 .init = swap_init,
07b0b134 1627 .load = swap_load,
6e620bec 1628 .done = swap_done,
07b0b134
ML
1629
1630 .coldplug = swap_coldplug,
1631
1632 .dump = swap_dump,
1633
1634 .start = swap_start,
1635 .stop = swap_stop,
1636
8a0867d6 1637 .kill = swap_kill,
a8b689b7
YW
1638 .clean = swap_clean,
1639 .can_clean = swap_can_clean,
8a0867d6 1640
68db7a3b
ZJS
1641 .get_timeout = swap_get_timeout,
1642
07b0b134
ML
1643 .serialize = swap_serialize,
1644 .deserialize_item = swap_deserialize_item,
1645
1646 .active_state = swap_active_state,
1647 .sub_state_to_string = swap_sub_state_to_string,
1648
52a12341
YW
1649 .will_restart = unit_will_restart_default,
1650
f2f725e5 1651 .may_gc = swap_may_gc,
39c79477 1652 .is_extrinsic = swap_is_extrinsic,
07b0b134 1653
e04aad61 1654 .sigchld_event = swap_sigchld_event,
e04aad61
LP
1655
1656 .reset_failed = swap_reset_failed,
1657
291d565a
LP
1658 .control_pid = swap_control_pid,
1659
74c964d3
LP
1660 .bus_set_property = bus_swap_set_property,
1661 .bus_commit_properties = bus_swap_commit_properties,
07b0b134 1662
e04aad61 1663 .following = swap_following,
6210e7fc 1664 .following_set = swap_following_set,
5632e374 1665
6e620bec 1666 .enumerate = swap_enumerate,
c6918296 1667 .shutdown = swap_shutdown,
0faacd47 1668 .supported = swap_supported,
c6918296
MS
1669
1670 .status_message_formats = {
1671 .starting_stopping = {
1672 [0] = "Activating swap %s...",
1673 [1] = "Deactivating swap %s...",
1674 },
1675 .finished_start_job = {
1676 [JOB_DONE] = "Activated swap %s.",
1677 [JOB_FAILED] = "Failed to activate swap %s.",
c6918296
MS
1678 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1679 },
1680 .finished_stop_job = {
1681 [JOB_DONE] = "Deactivated swap %s.",
1682 [JOB_FAILED] = "Failed deactivating swap %s.",
1683 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1684 },
1685 },
07b0b134 1686};