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