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