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