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