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