]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
core: make ExecRuntime be manager managed object
[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
e8a565cb 160 s->exec_runtime = exec_runtime_unref(s->exec_runtime, false);
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
e8a565cb 552 if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) {
29206d46 553 (void) unit_setup_dynamic_creds(u);
e8a565cb
YW
554 (void) unit_setup_exec_runtime(u);
555 }
29206d46 556
5bcb0f2b 557 swap_set_state(s, new_state);
07b0b134
ML
558 return 0;
559}
560
561static void swap_dump(Unit *u, FILE *f, const char *prefix) {
9bd0e1b8 562 char buf[FORMAT_TIMESPAN_MAX] = {};
07b0b134 563 Swap *s = SWAP(u);
4e85aff4 564 SwapParameters *p;
07b0b134
ML
565
566 assert(s);
4e85aff4
LP
567 assert(f);
568
569 if (s->from_proc_swaps)
570 p = &s->parameters_proc_swaps;
571 else if (s->from_fragment)
572 p = &s->parameters_fragment;
b6bfc7bb
LP
573 else
574 p = NULL;
07b0b134
ML
575
576 fprintf(f,
4e85aff4 577 "%sSwap State: %s\n"
e1770af8 578 "%sResult: %s\n"
07b0b134 579 "%sWhat: %s\n"
4e85aff4
LP
580 "%sFrom /proc/swaps: %s\n"
581 "%sFrom fragment: %s\n",
07b0b134 582 prefix, swap_state_to_string(s->state),
e1770af8 583 prefix, swap_result_to_string(s->result),
07b0b134 584 prefix, s->what,
4e85aff4
LP
585 prefix, yes_no(s->from_proc_swaps),
586 prefix, yes_no(s->from_fragment));
e04aad61 587
9670d583
LP
588 if (s->devnode)
589 fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode);
590
b6bfc7bb
LP
591 if (p)
592 fprintf(f,
593 "%sPriority: %i\n"
47cb901e 594 "%sOptions: %s\n",
b6bfc7bb 595 prefix, p->priority,
47cb901e 596 prefix, strempty(p->options));
b6bfc7bb 597
9bd0e1b8
YW
598 fprintf(f,
599 "%sTimeoutSec: %s\n",
600 prefix, format_timespan(buf, sizeof(buf), s->timeout_usec, USEC_PER_SEC));
601
e04aad61
LP
602 if (s->control_pid > 0)
603 fprintf(f,
de0671ee
ZJS
604 "%sControl PID: "PID_FMT"\n",
605 prefix, s->control_pid);
e04aad61
LP
606
607 exec_context_dump(&s->exec_context, f, prefix);
4819ff03 608 kill_context_dump(&s->kill_context, f, prefix);
18f573aa 609 cgroup_context_dump(&s->cgroup_context, f, prefix);
e04aad61
LP
610}
611
612static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
3c7416b6 613
9fa95f85 614 ExecParameters exec_params = {
1703fa41 615 .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
c39f1ce2
LP
616 .stdin_fd = -1,
617 .stdout_fd = -1,
618 .stderr_fd = -1,
9fa95f85 619 };
3c7416b6
LP
620 pid_t pid;
621 int r;
e04aad61
LP
622
623 assert(s);
624 assert(c);
625 assert(_pid);
626
3c7416b6 627 r = unit_prepare_exec(UNIT(s));
29206d46 628 if (r < 0)
3c7416b6 629 return r;
29206d46 630
36c16a7c 631 r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
646134dc 632 if (r < 0)
e04aad61
LP
633 goto fail;
634
19bbdd98 635 manager_set_exec_params(UNIT(s)->manager, &exec_params);
f0d47797 636 unit_set_exec_params(UNIT(s), &exec_params);
9fa95f85 637
f2341e0a
LP
638 r = exec_spawn(UNIT(s),
639 c,
646134dc 640 &s->exec_context,
9fa95f85 641 &exec_params,
613b411c 642 s->exec_runtime,
29206d46 643 &s->dynamic_creds,
646134dc
ZJS
644 &pid);
645 if (r < 0)
e04aad61
LP
646 goto fail;
647
646134dc
ZJS
648 r = unit_watch_pid(UNIT(s), pid);
649 if (r < 0)
e04aad61
LP
650 /* FIXME: we need to do something here */
651 goto fail;
652
653 *_pid = pid;
654
655 return 0;
656
657fail:
718db961 658 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
3536f49e 659
e04aad61 660 return r;
07b0b134
ML
661}
662
e1770af8 663static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
664 assert(s);
665
a0fef983 666 if (s->result == SWAP_SUCCESS)
e1770af8 667 s->result = f;
e04aad61 668
ed77d407
LP
669 if (s->result != SWAP_SUCCESS)
670 log_unit_warning(UNIT(s), "Failed with result '%s'.", swap_result_to_string(s->result));
671
29206d46
LP
672 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
673
e8a565cb 674 s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
613b411c 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
a4634b21
LP
743 unit_warn_leftover_processes(UNIT(s));
744
e04aad61
LP
745 s->control_command_id = SWAP_EXEC_ACTIVATE;
746 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 747
86b23b07 748 if (s->from_fragment) {
bf1d7ba7 749 int priority = -1;
47cb901e 750
bf1d7ba7
KZ
751 r = fstab_find_pri(s->parameters_fragment.options, &priority);
752 if (r < 0)
753 log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options);
754 else if (r == 1 && s->parameters_fragment.priority >= 0)
755 log_warning("Duplicate swap priority configuration by Priority and Options fields.");
756
757 if (r <= 0 && s->parameters_fragment.priority >= 0) {
758 if (s->parameters_fragment.options)
759 r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority);
760 else
761 r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority);
e64d5235 762 if (r < 0)
bf1d7ba7 763 goto fail;
e64d5235 764 }
86b23b07
JS
765 }
766
767 r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
768 if (r < 0)
769 goto fail;
4e85aff4 770
bf1d7ba7
KZ
771 if (s->parameters_fragment.options || opts) {
772 r = exec_command_append(s->control_command, "-o",
773 opts ? : s->parameters_fragment.options, NULL);
86b23b07
JS
774 if (r < 0)
775 goto fail;
776 }
e04aad61 777
86b23b07 778 r = exec_command_append(s->control_command, s->what, NULL);
e04aad61
LP
779 if (r < 0)
780 goto fail;
781
782 swap_unwatch_control_pid(s);
783
646134dc
ZJS
784 r = swap_spawn(s, s->control_command, &s->control_pid);
785 if (r < 0)
e04aad61
LP
786 goto fail;
787
788 swap_set_state(s, SWAP_ACTIVATING);
789
790 return;
791
792fail:
f2341e0a 793 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
50864457 794 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
795}
796
e1770af8 797static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
798 int r;
799
800 assert(s);
801
e04aad61
LP
802 s->control_command_id = SWAP_EXEC_DEACTIVATE;
803 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
804
646134dc 805 r = exec_command_set(s->control_command,
e04aad61
LP
806 "/sbin/swapoff",
807 s->what,
646134dc
ZJS
808 NULL);
809 if (r < 0)
e04aad61
LP
810 goto fail;
811
812 swap_unwatch_control_pid(s);
813
646134dc
ZJS
814 r = swap_spawn(s, s->control_command, &s->control_pid);
815 if (r < 0)
e04aad61
LP
816 goto fail;
817
818 swap_set_state(s, SWAP_DEACTIVATING);
819
820 return;
821
822fail:
f2341e0a 823 log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
50864457 824 swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
825}
826
827static int swap_start(Unit *u) {
37cf8fee 828 Swap *s = SWAP(u), *other;
07299350 829 int r;
e04aad61
LP
830
831 assert(s);
832
50864457 833 /* We cannot fulfill this request right now, try again later please! */
d31ae548
FB
834 if (IN_SET(s->state,
835 SWAP_DEACTIVATING,
836 SWAP_DEACTIVATING_SIGTERM,
50864457 837 SWAP_DEACTIVATING_SIGKILL))
e04aad61
LP
838 return -EAGAIN;
839
50864457 840 /* Already on it! */
e04aad61
LP
841 if (s->state == SWAP_ACTIVATING)
842 return 0;
843
d31ae548 844 assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
e04aad61 845
75f86906 846 if (detect_container() > 0)
a5c3034f
LP
847 return -EPERM;
848
37cf8fee
LP
849 /* If there's a job for another swap unit for the same node
850 * running, then let's not dispatch this one for now, and wait
851 * until that other job has finished. */
852 LIST_FOREACH_OTHERS(same_devnode, other, s)
853 if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
854 return -EAGAIN;
855
07299350
LP
856 r = unit_start_limit_test(u);
857 if (r < 0) {
858 swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
859 return r;
860 }
861
4b58153d
LP
862 r = unit_acquire_invocation_id(u);
863 if (r < 0)
864 return r;
865
e1770af8 866 s->result = SWAP_SUCCESS;
3c7416b6
LP
867
868 u->reset_accounting = true;
5ad096b3 869
e04aad61 870 swap_enter_activating(s);
82a2b6bb 871 return 1;
07b0b134
ML
872}
873
874static int swap_stop(Unit *u) {
875 Swap *s = SWAP(u);
07b0b134
ML
876
877 assert(s);
878
50864457
LP
879 switch (s->state) {
880
881 case SWAP_DEACTIVATING:
882 case SWAP_DEACTIVATING_SIGTERM:
883 case SWAP_DEACTIVATING_SIGKILL:
884 /* Already on it */
e04aad61 885 return 0;
07b0b134 886
50864457
LP
887 case SWAP_ACTIVATING:
888 case SWAP_ACTIVATING_DONE:
889 /* There's a control process pending, directly enter kill mode */
890 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
891 return 0;
07b0b134 892
50864457
LP
893 case SWAP_ACTIVE:
894 if (detect_container() > 0)
895 return -EPERM;
a5c3034f 896
50864457
LP
897 swap_enter_deactivating(s);
898 return 1;
899
900 default:
901 assert_not_reached("Unexpected state.");
902 }
07b0b134
ML
903}
904
905static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
906 Swap *s = SWAP(u);
907
908 assert(s);
909 assert(f);
910 assert(fds);
911
912 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
e1770af8 913 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
e04aad61
LP
914
915 if (s->control_pid > 0)
de0671ee 916 unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
e04aad61
LP
917
918 if (s->control_command_id >= 0)
919 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
920
921 return 0;
922}
923
924static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
925 Swap *s = SWAP(u);
926
927 assert(s);
928 assert(fds);
929
930 if (streq(key, "state")) {
931 SwapState state;
932
646134dc
ZJS
933 state = swap_state_from_string(value);
934 if (state < 0)
f2341e0a 935 log_unit_debug(u, "Failed to parse state value: %s", value);
07b0b134
ML
936 else
937 s->deserialized_state = state;
e1770af8
LP
938 } else if (streq(key, "result")) {
939 SwapResult f;
940
941 f = swap_result_from_string(value);
942 if (f < 0)
f2341e0a 943 log_unit_debug(u, "Failed to parse result value: %s", value);
e1770af8
LP
944 else if (f != SWAP_SUCCESS)
945 s->result = f;
e04aad61
LP
946 } else if (streq(key, "control-pid")) {
947 pid_t pid;
948
949 if (parse_pid(value, &pid) < 0)
f2341e0a 950 log_unit_debug(u, "Failed to parse control-pid value: %s", value);
e04aad61
LP
951 else
952 s->control_pid = pid;
953
954 } else if (streq(key, "control-command")) {
955 SwapExecCommand id;
956
646134dc
ZJS
957 id = swap_exec_command_from_string(value);
958 if (id < 0)
f2341e0a 959 log_unit_debug(u, "Failed to parse exec-command value: %s", value);
e04aad61
LP
960 else {
961 s->control_command_id = id;
962 s->control_command = s->exec_command + id;
963 }
07b0b134 964 } else
f2341e0a 965 log_unit_debug(u, "Unknown serialization key: %s", key);
07b0b134
ML
966
967 return 0;
968}
969
44a6b1b6 970_pure_ static UnitActiveState swap_active_state(Unit *u) {
07b0b134
ML
971 assert(u);
972
973 return state_translation_table[SWAP(u)->state];
974}
975
44a6b1b6 976_pure_ static const char *swap_sub_state_to_string(Unit *u) {
07b0b134
ML
977 assert(u);
978
979 return swap_state_to_string(SWAP(u)->state);
980}
981
44a6b1b6 982_pure_ static bool swap_check_gc(Unit *u) {
07b0b134
ML
983 Swap *s = SWAP(u);
984
985 assert(s);
986
6b1dc2bd 987 return s->from_proc_swaps;
07b0b134
ML
988}
989
e04aad61
LP
990static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
991 Swap *s = SWAP(u);
e1770af8 992 SwapResult f;
e04aad61
LP
993
994 assert(s);
995 assert(pid >= 0);
996
997 if (pid != s->control_pid)
998 return;
999
1000 s->control_pid = 0;
1001
1f0958f6 1002 if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
e1770af8
LP
1003 f = SWAP_SUCCESS;
1004 else if (code == CLD_EXITED)
1005 f = SWAP_FAILURE_EXIT_CODE;
1006 else if (code == CLD_KILLED)
1007 f = SWAP_FAILURE_SIGNAL;
1008 else if (code == CLD_DUMPED)
1009 f = SWAP_FAILURE_CORE_DUMP;
1010 else
1011 assert_not_reached("Unknown code");
1012
a0fef983 1013 if (s->result == SWAP_SUCCESS)
e1770af8 1014 s->result = f;
e04aad61
LP
1015
1016 if (s->control_command) {
6ea832a2 1017 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 1018
e04aad61
LP
1019 s->control_command = NULL;
1020 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
1021 }
1022
f2341e0a
LP
1023 log_unit_full(u, f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
1024 "Swap process exited, code=%s status=%i", sigchld_code_to_string(code), status);
e04aad61
LP
1025
1026 switch (s->state) {
1027
1028 case SWAP_ACTIVATING:
5bcb0f2b 1029 case SWAP_ACTIVATING_DONE:
e04aad61 1030
50864457 1031 if (f == SWAP_SUCCESS || s->from_proc_swaps)
e1770af8 1032 swap_enter_active(s, f);
e04aad61 1033 else
e1770af8 1034 swap_enter_dead(s, f);
e04aad61
LP
1035 break;
1036
1037 case SWAP_DEACTIVATING:
1038 case SWAP_DEACTIVATING_SIGKILL:
1039 case SWAP_DEACTIVATING_SIGTERM:
1040
50864457 1041 swap_enter_dead_or_active(s, f);
e04aad61
LP
1042 break;
1043
1044 default:
1045 assert_not_reached("Uh, control process died at wrong time.");
1046 }
1047
1048 /* Notify clients about changed exit status */
1049 unit_add_to_dbus_queue(u);
e04aad61
LP
1050}
1051
718db961
LP
1052static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1053 Swap *s = SWAP(userdata);
e04aad61
LP
1054
1055 assert(s);
718db961 1056 assert(s->timer_event_source == source);
e04aad61
LP
1057
1058 switch (s->state) {
1059
1060 case SWAP_ACTIVATING:
5bcb0f2b 1061 case SWAP_ACTIVATING_DONE:
f2341e0a 1062 log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
50864457 1063 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1064 break;
1065
1066 case SWAP_DEACTIVATING:
f2341e0a 1067 log_unit_warning(UNIT(s), "Deactivation timed out. Stopping.");
e1770af8 1068 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1069 break;
1070
e04aad61 1071 case SWAP_DEACTIVATING_SIGTERM:
4819ff03 1072 if (s->kill_context.send_sigkill) {
50864457 1073 log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
e1770af8 1074 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1075 } else {
50864457
LP
1076 log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
1077 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1078 }
e04aad61
LP
1079 break;
1080
e04aad61 1081 case SWAP_DEACTIVATING_SIGKILL:
f2341e0a 1082 log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
50864457 1083 swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1084 break;
1085
1086 default:
1087 assert_not_reached("Timeout at wrong time.");
1088 }
718db961
LP
1089
1090 return 0;
e04aad61
LP
1091}
1092
1093static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1094 unsigned i;
1095 int r = 0;
1096
1097 assert(m);
1098
07b0b134 1099 rewind(m->proc_swaps);
bab45044 1100
4e85aff4 1101 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1102
e04aad61 1103 for (i = 1;; i++) {
9fb3675e 1104 _cleanup_free_ char *dev = NULL, *d = NULL;
07b0b134
ML
1105 int prio = 0, k;
1106
646134dc
ZJS
1107 k = fscanf(m->proc_swaps,
1108 "%ms " /* device/file */
1109 "%*s " /* type of swap */
1110 "%*s " /* swap size */
1111 "%*s " /* used */
1112 "%i\n", /* priority */
1113 &dev, &prio);
1114 if (k != 2) {
07b0b134 1115 if (k == EOF)
4e85aff4 1116 break;
07b0b134 1117
628c89cc 1118 log_warning("Failed to parse /proc/swaps:%u.", i);
e04aad61 1119 continue;
07b0b134 1120 }
07b0b134 1121
527b7a42 1122 if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
628c89cc
LP
1123 return log_oom();
1124
1125 device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
4e85aff4 1126
628c89cc 1127 k = swap_process_new(m, d, prio, set_flags);
07b0b134 1128 if (k < 0)
e04aad61 1129 r = k;
07b0b134
ML
1130 }
1131
e04aad61
LP
1132 return r;
1133}
1134
718db961
LP
1135static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1136 Manager *m = userdata;
595ed347 1137 Unit *u;
4e434314
LP
1138 int r;
1139
1140 assert(m);
718db961 1141 assert(revents & EPOLLPRI);
4e434314 1142
646134dc
ZJS
1143 r = swap_load_proc_swaps(m, true);
1144 if (r < 0) {
da927ba9 1145 log_error_errno(r, "Failed to reread /proc/swaps: %m");
e04aad61
LP
1146
1147 /* Reset flags, just in case, for late calls */
595ed347
MS
1148 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1149 Swap *swap = SWAP(u);
e04aad61
LP
1150
1151 swap->is_active = swap->just_activated = false;
1152 }
1153
1154 return 0;
1155 }
1156
1157 manager_dispatch_load_queue(m);
1158
595ed347
MS
1159 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1160 Swap *swap = SWAP(u);
e04aad61
LP
1161
1162 if (!swap->is_active) {
1163 /* This has just been deactivated */
1164
e04aad61
LP
1165 swap_unset_proc_swaps(swap);
1166
1167 switch (swap->state) {
1168
1169 case SWAP_ACTIVE:
e1770af8 1170 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1171 break;
1172
1173 default:
5bcb0f2b 1174 /* Fire again */
e04aad61
LP
1175 swap_set_state(swap, swap->state);
1176 break;
1177 }
1178
628c89cc
LP
1179 if (swap->what)
1180 device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
1181
e04aad61
LP
1182 } else if (swap->just_activated) {
1183
1184 /* New swap entry */
1185
1186 switch (swap->state) {
1187
1188 case SWAP_DEAD:
1189 case SWAP_FAILED:
4b58153d 1190 (void) unit_acquire_invocation_id(UNIT(swap));
e1770af8 1191 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1192 break;
1193
5bcb0f2b
LP
1194 case SWAP_ACTIVATING:
1195 swap_set_state(swap, SWAP_ACTIVATING_DONE);
1196 break;
1197
e04aad61
LP
1198 default:
1199 /* Nothing really changed, but let's
1200 * issue an notification call
1201 * nonetheless, in case somebody is
1202 * waiting for this. */
1203 swap_set_state(swap, swap->state);
1204 break;
1205 }
1206 }
1207
1208 /* Reset the flags for later calls */
1209 swap->is_active = swap->just_activated = false;
1210 }
1211
1212 return 1;
1213}
1214
1215static Unit *swap_following(Unit *u) {
1216 Swap *s = SWAP(u);
1217 Swap *other, *first = NULL;
1218
1219 assert(s);
1220
cdc89820
ZJS
1221 /* If the user configured the swap through /etc/fstab or
1222 * a device unit, follow that. */
1223
1224 if (s->from_fragment)
e04aad61
LP
1225 return NULL;
1226
caac2704 1227 LIST_FOREACH_OTHERS(same_devnode, other, s)
cdc89820
ZJS
1228 if (other->from_fragment)
1229 return UNIT(other);
1230
b938cb90 1231 /* Otherwise, make everybody follow the unit that's named after
cdc89820
ZJS
1232 * the swap device in the kernel */
1233
1234 if (streq_ptr(s->what, s->devnode))
1235 return NULL;
e04aad61 1236
9670d583
LP
1237 LIST_FOREACH_AFTER(same_devnode, other, s)
1238 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1239 return UNIT(other);
1240
9670d583
LP
1241 LIST_FOREACH_BEFORE(same_devnode, other, s) {
1242 if (streq_ptr(other->what, other->devnode))
e04aad61
LP
1243 return UNIT(other);
1244
1245 first = other;
1246 }
1247
cdc89820 1248 /* Fall back to the first on the list */
e04aad61 1249 return UNIT(first);
07b0b134
ML
1250}
1251
6210e7fc 1252static int swap_following_set(Unit *u, Set **_set) {
5bcb0f2b 1253 Swap *s = SWAP(u), *other;
6210e7fc
LP
1254 Set *set;
1255 int r;
1256
1257 assert(s);
1258 assert(_set);
1259
9670d583 1260 if (LIST_JUST_US(same_devnode, s)) {
6210e7fc
LP
1261 *_set = NULL;
1262 return 0;
1263 }
1264
d5099efc 1265 set = set_new(NULL);
5bcb0f2b 1266 if (!set)
6210e7fc
LP
1267 return -ENOMEM;
1268
caac2704 1269 LIST_FOREACH_OTHERS(same_devnode, other, s) {
5bcb0f2b
LP
1270 r = set_put(set, other);
1271 if (r < 0)
6210e7fc 1272 goto fail;
5bcb0f2b 1273 }
6210e7fc
LP
1274
1275 *_set = set;
1276 return 1;
1277
1278fail:
1279 set_free(set);
1280 return r;
1281}
1282
07b0b134
ML
1283static void swap_shutdown(Manager *m) {
1284 assert(m);
1285
718db961
LP
1286 m->swap_event_source = sd_event_source_unref(m->swap_event_source);
1287
74ca738f 1288 m->proc_swaps = safe_fclose(m->proc_swaps);
e04aad61 1289
525d3cc7 1290 m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
07b0b134
ML
1291}
1292
ba64af90 1293static void swap_enumerate(Manager *m) {
07b0b134 1294 int r;
9670d583 1295
07b0b134
ML
1296 assert(m);
1297
4e434314 1298 if (!m->proc_swaps) {
646134dc 1299 m->proc_swaps = fopen("/proc/swaps", "re");
ba64af90
LP
1300 if (!m->proc_swaps) {
1301 if (errno == ENOENT)
1302 log_debug("Not swap enabled, skipping enumeration");
1303 else
1304 log_error_errno(errno, "Failed to open /proc/swaps: %m");
1305
1306 return;
1307 }
4e434314 1308
151b9b96 1309 r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m);
ba64af90
LP
1310 if (r < 0) {
1311 log_error_errno(r, "Failed to watch /proc/swaps: %m");
29083707 1312 goto fail;
ba64af90 1313 }
29083707
LP
1314
1315 /* Dispatch this before we dispatch SIGCHLD, so that
1316 * we always get the events from /proc/swaps before
1317 * the SIGCHLD of /sbin/swapon. */
83231637 1318 r = sd_event_source_set_priority(m->swap_event_source, SD_EVENT_PRIORITY_NORMAL-10);
ba64af90
LP
1319 if (r < 0) {
1320 log_error_errno(r, "Failed to change /proc/swaps priority: %m");
718db961 1321 goto fail;
ba64af90 1322 }
7dfbe2e3
TG
1323
1324 (void) sd_event_source_set_description(m->swap_event_source, "swap-proc");
4e434314
LP
1325 }
1326
646134dc
ZJS
1327 r = swap_load_proc_swaps(m, false);
1328 if (r < 0)
718db961
LP
1329 goto fail;
1330
ba64af90 1331 return;
07b0b134 1332
718db961
LP
1333fail:
1334 swap_shutdown(m);
07b0b134
ML
1335}
1336
628c89cc 1337int swap_process_device_new(Manager *m, struct udev_device *dev) {
9670d583
LP
1338 struct udev_list_entry *item = NULL, *first = NULL;
1339 _cleanup_free_ char *e = NULL;
1340 const char *dn;
cabf58b2 1341 Unit *u;
9670d583
LP
1342 int r = 0;
1343
1344 assert(m);
1345 assert(dev);
1346
1347 dn = udev_device_get_devnode(dev);
1348 if (!dn)
1349 return 0;
1350
7410616c
LP
1351 r = unit_name_from_path(dn, ".swap", &e);
1352 if (r < 0)
1353 return r;
9670d583 1354
cabf58b2
FB
1355 u = manager_get_unit(m, e);
1356 if (u)
1357 r = swap_set_devnode(SWAP(u), dn);
9670d583
LP
1358
1359 first = udev_device_get_devlinks_list_entry(dev);
1360 udev_list_entry_foreach(item, first) {
1361 _cleanup_free_ char *n = NULL;
7410616c 1362 int q;
9670d583 1363
7410616c
LP
1364 q = unit_name_from_path(udev_list_entry_get_name(item), ".swap", &n);
1365 if (q < 0)
1366 return q;
9670d583 1367
cabf58b2
FB
1368 u = manager_get_unit(m, n);
1369 if (u) {
1370 q = swap_set_devnode(SWAP(u), dn);
9670d583
LP
1371 if (q < 0)
1372 r = q;
1373 }
1374 }
1375
1376 return r;
1377}
1378
628c89cc 1379int swap_process_device_remove(Manager *m, struct udev_device *dev) {
9670d583
LP
1380 const char *dn;
1381 int r = 0;
1382 Swap *s;
1383
1384 dn = udev_device_get_devnode(dev);
1385 if (!dn)
1386 return 0;
1387
1388 while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
1389 int q;
1390
1391 q = swap_set_devnode(s, NULL);
1392 if (q < 0)
1393 r = q;
1394 }
1395
1396 return r;
1397}
1398
fdf20a31 1399static void swap_reset_failed(Unit *u) {
5632e374
LP
1400 Swap *s = SWAP(u);
1401
1402 assert(s);
1403
fdf20a31 1404 if (s->state == SWAP_FAILED)
5632e374 1405 swap_set_state(s, SWAP_DEAD);
e04aad61 1406
e1770af8 1407 s->result = SWAP_SUCCESS;
5632e374
LP
1408}
1409
718db961 1410static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1411 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
8a0867d6
LP
1412}
1413
7a7821c8 1414static int swap_get_timeout(Unit *u, usec_t *timeout) {
68db7a3b 1415 Swap *s = SWAP(u);
7a7821c8 1416 usec_t t;
68db7a3b
ZJS
1417 int r;
1418
1419 if (!s->timer_event_source)
1420 return 0;
1421
7a7821c8 1422 r = sd_event_source_get_time(s->timer_event_source, &t);
68db7a3b
ZJS
1423 if (r < 0)
1424 return r;
7a7821c8
LP
1425 if (t == USEC_INFINITY)
1426 return 0;
68db7a3b 1427
7a7821c8 1428 *timeout = t;
68db7a3b
ZJS
1429 return 1;
1430}
1431
1c2e9646 1432static bool swap_supported(void) {
0faacd47
LP
1433 static int supported = -1;
1434
1435 /* If swap support is not available in the kernel, or we are
1436 * running in a container we don't support swap units, and any
1437 * attempts to starting one should fail immediately. */
1438
1439 if (supported < 0)
1440 supported =
1441 access("/proc/swaps", F_OK) >= 0 &&
75f86906 1442 detect_container() <= 0;
0faacd47
LP
1443
1444 return supported;
1445}
1446
291d565a
LP
1447static int swap_control_pid(Unit *u) {
1448 Swap *s = SWAP(u);
1449
1450 assert(s);
1451
1452 return s->control_pid;
1453}
1454
e04aad61
LP
1455static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1456 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1457 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1458};
1459
1460DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1461
e1770af8
LP
1462static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1463 [SWAP_SUCCESS] = "success",
1464 [SWAP_FAILURE_RESOURCES] = "resources",
1465 [SWAP_FAILURE_TIMEOUT] = "timeout",
1466 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1467 [SWAP_FAILURE_SIGNAL] = "signal",
07299350
LP
1468 [SWAP_FAILURE_CORE_DUMP] = "core-dump",
1469 [SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
e1770af8
LP
1470};
1471
1472DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1473
07b0b134 1474const UnitVTable swap_vtable = {
7d17cfbc 1475 .object_size = sizeof(Swap),
718db961
LP
1476 .exec_context_offset = offsetof(Swap, exec_context),
1477 .cgroup_context_offset = offsetof(Swap, cgroup_context),
1478 .kill_context_offset = offsetof(Swap, kill_context),
613b411c 1479 .exec_runtime_offset = offsetof(Swap, exec_runtime),
29206d46 1480 .dynamic_creds_offset = offsetof(Swap, dynamic_creds),
3ef63c31 1481
f975e971
LP
1482 .sections =
1483 "Unit\0"
1484 "Swap\0"
1485 "Install\0",
4ad49000 1486 .private_section = "Swap",
71645aca 1487
4e85aff4 1488 .init = swap_init,
07b0b134 1489 .load = swap_load,
6e620bec 1490 .done = swap_done,
07b0b134
ML
1491
1492 .coldplug = swap_coldplug,
1493
1494 .dump = swap_dump,
1495
1496 .start = swap_start,
1497 .stop = swap_stop,
1498
8a0867d6
LP
1499 .kill = swap_kill,
1500
68db7a3b
ZJS
1501 .get_timeout = swap_get_timeout,
1502
07b0b134
ML
1503 .serialize = swap_serialize,
1504 .deserialize_item = swap_deserialize_item,
1505
1506 .active_state = swap_active_state,
1507 .sub_state_to_string = swap_sub_state_to_string,
1508
1509 .check_gc = swap_check_gc,
1510
e04aad61 1511 .sigchld_event = swap_sigchld_event,
e04aad61
LP
1512
1513 .reset_failed = swap_reset_failed,
1514
291d565a
LP
1515 .control_pid = swap_control_pid,
1516
718db961 1517 .bus_vtable = bus_swap_vtable,
74c964d3
LP
1518 .bus_set_property = bus_swap_set_property,
1519 .bus_commit_properties = bus_swap_commit_properties,
07b0b134 1520
e04aad61 1521 .following = swap_following,
6210e7fc 1522 .following_set = swap_following_set,
5632e374 1523
6e620bec 1524 .enumerate = swap_enumerate,
c6918296 1525 .shutdown = swap_shutdown,
0faacd47 1526 .supported = swap_supported,
c6918296
MS
1527
1528 .status_message_formats = {
1529 .starting_stopping = {
1530 [0] = "Activating swap %s...",
1531 [1] = "Deactivating swap %s...",
1532 },
1533 .finished_start_job = {
1534 [JOB_DONE] = "Activated swap %s.",
1535 [JOB_FAILED] = "Failed to activate swap %s.",
c6918296
MS
1536 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1537 },
1538 .finished_stop_job = {
1539 [JOB_DONE] = "Deactivated swap %s.",
1540 [JOB_FAILED] = "Failed deactivating swap %s.",
1541 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1542 },
1543 },
07b0b134 1544};