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