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