]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
relicense to LGPLv2.1 (with exceptions)
[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"
07b0b134
ML
41
42static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
43 [SWAP_DEAD] = UNIT_INACTIVE,
e04aad61 44 [SWAP_ACTIVATING] = UNIT_ACTIVATING,
07b0b134 45 [SWAP_ACTIVE] = UNIT_ACTIVE,
e04aad61
LP
46 [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
47 [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
48 [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
49 [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
50 [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
fdf20a31 51 [SWAP_FAILED] = UNIT_FAILED
07b0b134
ML
52};
53
e04aad61
LP
54static void swap_unset_proc_swaps(Swap *s) {
55 Swap *first;
56
57 assert(s);
58
59 if (!s->parameters_proc_swaps.what)
60 return;
61
62 /* Remove this unit from the chain of swaps which share the
63 * same kernel swap device. */
64
1124fe6f 65 first = hashmap_get(UNIT(s)->manager->swaps_by_proc_swaps, s->parameters_proc_swaps.what);
e04aad61
LP
66 LIST_REMOVE(Swap, same_proc_swaps, first, s);
67
68 if (first)
1124fe6f 69 hashmap_remove_and_replace(UNIT(s)->manager->swaps_by_proc_swaps, s->parameters_proc_swaps.what, first->parameters_proc_swaps.what, first);
e04aad61 70 else
1124fe6f 71 hashmap_remove(UNIT(s)->manager->swaps_by_proc_swaps, s->parameters_proc_swaps.what);
e04aad61
LP
72
73 free(s->parameters_proc_swaps.what);
74 s->parameters_proc_swaps.what = NULL;
75}
76
f6cebb3b 77static void swap_init(Unit *u) {
6e620bec
LP
78 Swap *s = SWAP(u);
79
80 assert(s);
1124fe6f 81 assert(UNIT(s)->load_state == UNIT_STUB);
6e620bec 82
e04aad61
LP
83 s->timeout_usec = DEFAULT_TIMEOUT_USEC;
84
85 exec_context_init(&s->exec_context);
ac155bb8
MS
86 s->exec_context.std_output = u->manager->default_std_output;
87 s->exec_context.std_error = u->manager->default_std_error;
e04aad61 88
4e85aff4 89 s->parameters_etc_fstab.priority = s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
e04aad61
LP
90
91 s->timer_watch.type = WATCH_INVALID;
92
e1770af8 93 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
c8f4d764 94
1124fe6f 95 UNIT(s)->ignore_on_isolate = true;
e04aad61
LP
96}
97
98static void swap_unwatch_control_pid(Swap *s) {
99 assert(s);
100
101 if (s->control_pid <= 0)
102 return;
103
104 unit_unwatch_pid(UNIT(s), s->control_pid);
105 s->control_pid = 0;
6e620bec
LP
106}
107
4e85aff4
LP
108static void swap_done(Unit *u) {
109 Swap *s = SWAP(u);
07b0b134 110
4e85aff4 111 assert(s);
07b0b134 112
e04aad61
LP
113 swap_unset_proc_swaps(s);
114
4e85aff4 115 free(s->what);
e04aad61
LP
116 s->what = NULL;
117
4e85aff4 118 free(s->parameters_etc_fstab.what);
4e85aff4 119 free(s->parameters_fragment.what);
e04aad61
LP
120 s->parameters_etc_fstab.what = s->parameters_fragment.what = NULL;
121
122 exec_context_done(&s->exec_context);
123 exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
124 s->control_command = NULL;
125
126 swap_unwatch_control_pid(s);
127
128 unit_unwatch_timer(u, &s->timer_watch);
07b0b134
ML
129}
130
6e2ef85b
LP
131int swap_add_one_mount_link(Swap *s, Mount *m) {
132 int r;
133
134 assert(s);
135 assert(m);
136
1124fe6f
MS
137 if (UNIT(s)->load_state != UNIT_LOADED ||
138 UNIT(m)->load_state != UNIT_LOADED)
6e2ef85b
LP
139 return 0;
140
8407a5d0
LP
141 if (is_device_path(s->what))
142 return 0;
143
6e2ef85b
LP
144 if (!path_startswith(s->what, m->where))
145 return 0;
146
2c966c03 147 if ((r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0)
6e2ef85b
LP
148 return r;
149
150 return 0;
151}
152
153static int swap_add_mount_links(Swap *s) {
ac155bb8 154 Unit *other;
6e2ef85b
LP
155 int r;
156
157 assert(s);
158
1124fe6f 159 LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT])
595ed347 160 if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0)
6e2ef85b
LP
161 return r;
162
163 return 0;
164}
165
07b0b134 166static int swap_add_target_links(Swap *s) {
07b0b134 167 Unit *tu;
4e85aff4 168 SwapParameters *p;
07b0b134
ML
169 int r;
170
4e85aff4
LP
171 assert(s);
172
173 if (s->from_fragment)
174 p = &s->parameters_fragment;
175 else if (s->from_etc_fstab)
176 p = &s->parameters_etc_fstab;
177 else
178 return 0;
179
1124fe6f 180 if ((r = manager_load_unit(UNIT(s)->manager, SPECIAL_SWAP_TARGET, NULL, NULL, &tu)) < 0)
07b0b134
ML
181 return r;
182
81bf310e 183 if (!p->noauto &&
85385610 184 !p->nofail &&
1124fe6f 185 (p->handle || UNIT(s)->manager->swap_auto) &&
510051fc 186 s->from_etc_fstab &&
1124fe6f 187 UNIT(s)->manager->running_as == MANAGER_SYSTEM)
6e2ef85b
LP
188 if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(s), true)) < 0)
189 return r;
07b0b134
ML
190
191 return unit_add_dependency(UNIT(s), UNIT_BEFORE, tu, true);
192}
193
173a8d04
LP
194static int swap_add_device_links(Swap *s) {
195 SwapParameters *p;
196
197 assert(s);
198
199 if (!s->what)
200 return 0;
201
202 if (s->from_fragment)
203 p = &s->parameters_fragment;
204 else if (s->from_etc_fstab)
205 p = &s->parameters_etc_fstab;
206 else
207 return 0;
208
cfcfd4ae
LP
209 if (is_device_path(s->what))
210 return unit_add_node_link(UNIT(s), s->what,
211 !p->noauto && p->nofail &&
1124fe6f 212 UNIT(s)->manager->running_as == MANAGER_SYSTEM);
cfcfd4ae
LP
213 else
214 /* File based swap devices need to be ordered after
215 * remount-rootfs.service, since they might need a
216 * writable file system. */
217 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_ROOTFS_SERVICE, NULL, true);
173a8d04
LP
218}
219
2edd4434
LP
220static int swap_add_default_dependencies(Swap *s) {
221 int r;
222
223 assert(s);
224
1124fe6f 225 if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) {
2edd4434 226
ead8e478 227 if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
e04aad61 228 return r;
2edd4434
LP
229 }
230
231 return 0;
232}
233
4e85aff4
LP
234static int swap_verify(Swap *s) {
235 bool b;
236 char *e;
237
1124fe6f 238 if (UNIT(s)->load_state != UNIT_LOADED)
4e85aff4
LP
239 return 0;
240
241 if (!(e = unit_name_from_path(s->what, ".swap")))
242 return -ENOMEM;
243
244 b = unit_has_name(UNIT(s), e);
245 free(e);
246
247 if (!b) {
1124fe6f 248 log_error("%s: Value of \"What\" and unit name do not match, not loading.\n", UNIT(s)->id);
4e85aff4
LP
249 return -EINVAL;
250 }
251
e04aad61 252 if (s->exec_context.pam_name && s->exec_context.kill_mode != KILL_CONTROL_GROUP) {
1124fe6f 253 log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(s)->id);
e04aad61
LP
254 return -EINVAL;
255 }
256
4e85aff4
LP
257 return 0;
258}
259
07b0b134
ML
260static int swap_load(Unit *u) {
261 int r;
262 Swap *s = SWAP(u);
263
264 assert(s);
ac155bb8 265 assert(u->load_state == UNIT_STUB);
07b0b134
ML
266
267 /* Load a .swap file */
268 if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
269 return r;
270
ac155bb8 271 if (u->load_state == UNIT_LOADED) {
27abbe82
LP
272 if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
273 return r;
4e85aff4 274
1124fe6f 275 if (UNIT(s)->fragment_path)
4e85aff4
LP
276 s->from_fragment = true;
277
278 if (!s->what) {
279 if (s->parameters_fragment.what)
280 s->what = strdup(s->parameters_fragment.what);
281 else if (s->parameters_etc_fstab.what)
282 s->what = strdup(s->parameters_etc_fstab.what);
283 else if (s->parameters_proc_swaps.what)
284 s->what = strdup(s->parameters_proc_swaps.what);
285 else
ac155bb8 286 s->what = unit_name_to_path(u->id);
4e85aff4
LP
287
288 if (!s->what)
07b0b134 289 return -ENOMEM;
4e85aff4 290 }
07b0b134
ML
291
292 path_kill_slashes(s->what);
293
1124fe6f 294 if (!UNIT(s)->description)
4e85aff4
LP
295 if ((r = unit_set_description(u, s->what)) < 0)
296 return r;
297
173a8d04 298 if ((r = swap_add_device_links(s)) < 0)
07b0b134
ML
299 return r;
300
6e2ef85b
LP
301 if ((r = swap_add_mount_links(s)) < 0)
302 return r;
07b0b134
ML
303
304 if ((r = swap_add_target_links(s)) < 0)
305 return r;
2edd4434 306
d686d8a9 307 if ((r = unit_add_default_cgroups(u)) < 0)
f1a1cd64
LP
308 return r;
309
1124fe6f 310 if (UNIT(s)->default_dependencies)
2edd4434
LP
311 if ((r = swap_add_default_dependencies(s)) < 0)
312 return r;
07b0b134
ML
313 }
314
315 return swap_verify(s);
316}
317
4e85aff4
LP
318int swap_add_one(
319 Manager *m,
320 const char *what,
e04aad61 321 const char *what_proc_swaps,
4e85aff4
LP
322 int priority,
323 bool noauto,
173a8d04 324 bool nofail,
4e85aff4 325 bool handle,
e04aad61
LP
326 bool set_flags) {
327
4e85aff4 328 Unit *u = NULL;
e04aad61 329 char *e = NULL, *wp = NULL;
2c7c6144 330 bool delete = false;
07b0b134 331 int r;
4e85aff4
LP
332 SwapParameters *p;
333
334 assert(m);
335 assert(what);
07b0b134 336
7d17cfbc
MS
337 e = unit_name_from_path(what, ".swap");
338 if (!e)
07b0b134
ML
339 return -ENOMEM;
340
e04aad61
LP
341 u = manager_get_unit(m, e);
342
343 if (what_proc_swaps &&
344 u &&
345 SWAP(u)->from_proc_swaps &&
346 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
347 return -EEXIST;
4e85aff4
LP
348
349 if (!u) {
07b0b134
ML
350 delete = true;
351
7d17cfbc
MS
352 u = unit_new(m, sizeof(Swap));
353 if (!u) {
07b0b134
ML
354 free(e);
355 return -ENOMEM;
356 }
e04aad61 357
7d17cfbc
MS
358 r = unit_add_name(u, e);
359 if (r < 0)
e04aad61
LP
360 goto fail;
361
7d17cfbc
MS
362 SWAP(u)->what = strdup(what);
363 if (!SWAP(u)->what) {
e04aad61
LP
364 r = -ENOMEM;
365 goto fail;
366 }
367
368 unit_add_to_load_queue(u);
4e85aff4
LP
369 } else
370 delete = false;
07b0b134 371
e04aad61
LP
372 if (what_proc_swaps) {
373 Swap *first;
07b0b134 374
4e85aff4 375 p = &SWAP(u)->parameters_proc_swaps;
e04aad61
LP
376
377 if (!p->what) {
378 if (!(wp = strdup(what_proc_swaps))) {
379 r = -ENOMEM;
380 goto fail;
381 }
382
383 if (!m->swaps_by_proc_swaps)
384 if (!(m->swaps_by_proc_swaps = hashmap_new(string_hash_func, string_compare_func))) {
385 r = -ENOMEM;
386 goto fail;
387 }
388
389 free(p->what);
390 p->what = wp;
391
392 first = hashmap_get(m->swaps_by_proc_swaps, wp);
393 LIST_PREPEND(Swap, same_proc_swaps, first, SWAP(u));
394
395 if ((r = hashmap_replace(m->swaps_by_proc_swaps, wp, first)) < 0)
396 goto fail;
397 }
398
399 if (set_flags) {
400 SWAP(u)->is_active = true;
401 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
402 }
403
4e85aff4 404 SWAP(u)->from_proc_swaps = true;
e04aad61 405
4e85aff4
LP
406 } else {
407 p = &SWAP(u)->parameters_etc_fstab;
e04aad61
LP
408
409 if (!(wp = strdup(what))) {
410 r = -ENOMEM;
411 goto fail;
412 }
413
414 free(p->what);
415 p->what = wp;
416
4e85aff4
LP
417 SWAP(u)->from_etc_fstab = true;
418 }
07b0b134 419
4e85aff4
LP
420 p->priority = priority;
421 p->noauto = noauto;
173a8d04 422 p->nofail = nofail;
4e85aff4 423 p->handle = handle;
07b0b134 424
4e85aff4 425 unit_add_to_dbus_queue(u);
07b0b134 426
4e85aff4 427 free(e);
07b0b134
ML
428
429 return 0;
430
431fail:
e04aad61
LP
432 log_warning("Failed to load swap unit: %s", strerror(-r));
433
434 free(wp);
4e85aff4
LP
435 free(e);
436
437 if (delete && u)
07b0b134
ML
438 unit_free(u);
439
4e85aff4 440 return r;
07b0b134
ML
441}
442
e04aad61
LP
443static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
444 struct stat st;
445 int r = 0, k;
446
447 assert(m);
448
449 if (stat(device, &st) >= 0 && S_ISBLK(st.st_mode)) {
450 struct udev_device *d;
451 const char *dn;
452 struct udev_list_entry *item = NULL, *first = NULL;
453
454 /* So this is a proper swap device. Create swap units
455 * for all names this swap device is known under */
456
457 if (!(d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev)))
458 return -ENOMEM;
459
460 if ((dn = udev_device_get_devnode(d)))
461 r = swap_add_one(m, dn, device, prio, false, false, false, set_flags);
462
463 /* Add additional units for all symlinks */
464 first = udev_device_get_devlinks_list_entry(d);
465 udev_list_entry_foreach(item, first) {
466 const char *p;
467
468 /* Don't bother with the /dev/block links */
469 p = udev_list_entry_get_name(item);
470
471 if (path_startswith(p, "/dev/block/"))
472 continue;
473
474 if (stat(p, &st) >= 0)
475 if ((!S_ISBLK(st.st_mode)) || st.st_rdev != udev_device_get_devnum(d))
476 continue;
477
478 if ((k = swap_add_one(m, p, device, prio, false, false, false, set_flags)) < 0)
479 r = k;
480 }
481
482 udev_device_unref(d);
483 }
484
485 if ((k = swap_add_one(m, device, device, prio, false, false, false, set_flags)) < 0)
486 r = k;
487
488 return r;
489}
490
07b0b134
ML
491static void swap_set_state(Swap *s, SwapState state) {
492 SwapState old_state;
e04aad61 493
07b0b134
ML
494 assert(s);
495
496 old_state = s->state;
497 s->state = state;
498
e04aad61
LP
499 if (state != SWAP_ACTIVATING &&
500 state != SWAP_ACTIVATING_SIGTERM &&
501 state != SWAP_ACTIVATING_SIGKILL &&
502 state != SWAP_DEACTIVATING &&
503 state != SWAP_DEACTIVATING_SIGTERM &&
504 state != SWAP_DEACTIVATING_SIGKILL) {
505 unit_unwatch_timer(UNIT(s), &s->timer_watch);
506 swap_unwatch_control_pid(s);
507 s->control_command = NULL;
508 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
509 }
510
07b0b134
ML
511 if (state != old_state)
512 log_debug("%s changed %s -> %s",
1124fe6f 513 UNIT(s)->id,
07b0b134
ML
514 swap_state_to_string(old_state),
515 swap_state_to_string(state));
516
e2f3b44c 517 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
07b0b134
ML
518}
519
520static int swap_coldplug(Unit *u) {
521 Swap *s = SWAP(u);
522 SwapState new_state = SWAP_DEAD;
e04aad61 523 int r;
07b0b134
ML
524
525 assert(s);
526 assert(s->state == SWAP_DEAD);
527
528 if (s->deserialized_state != s->state)
529 new_state = s->deserialized_state;
4e85aff4 530 else if (s->from_proc_swaps)
07b0b134
ML
531 new_state = SWAP_ACTIVE;
532
e04aad61
LP
533 if (new_state != s->state) {
534
535 if (new_state == SWAP_ACTIVATING ||
536 new_state == SWAP_ACTIVATING_SIGTERM ||
537 new_state == SWAP_ACTIVATING_SIGKILL ||
538 new_state == SWAP_DEACTIVATING ||
539 new_state == SWAP_DEACTIVATING_SIGTERM ||
540 new_state == SWAP_DEACTIVATING_SIGKILL) {
541
542 if (s->control_pid <= 0)
543 return -EBADMSG;
544
545 if ((r = unit_watch_pid(UNIT(s), s->control_pid)) < 0)
546 return r;
547
548 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
549 return r;
550 }
551
4e85aff4 552 swap_set_state(s, new_state);
e04aad61 553 }
07b0b134
ML
554
555 return 0;
556}
557
558static void swap_dump(Unit *u, FILE *f, const char *prefix) {
559 Swap *s = SWAP(u);
4e85aff4 560 SwapParameters *p;
07b0b134
ML
561
562 assert(s);
4e85aff4
LP
563 assert(f);
564
565 if (s->from_proc_swaps)
566 p = &s->parameters_proc_swaps;
567 else if (s->from_fragment)
568 p = &s->parameters_fragment;
569 else
570 p = &s->parameters_etc_fstab;
07b0b134
ML
571
572 fprintf(f,
4e85aff4 573 "%sSwap State: %s\n"
e1770af8 574 "%sResult: %s\n"
07b0b134
ML
575 "%sWhat: %s\n"
576 "%sPriority: %i\n"
4e85aff4 577 "%sNoAuto: %s\n"
173a8d04 578 "%sNoFail: %s\n"
4e85aff4
LP
579 "%sHandle: %s\n"
580 "%sFrom /etc/fstab: %s\n"
581 "%sFrom /proc/swaps: %s\n"
582 "%sFrom fragment: %s\n",
07b0b134 583 prefix, swap_state_to_string(s->state),
e1770af8 584 prefix, swap_result_to_string(s->result),
07b0b134 585 prefix, s->what,
4e85aff4
LP
586 prefix, p->priority,
587 prefix, yes_no(p->noauto),
173a8d04 588 prefix, yes_no(p->nofail),
4e85aff4
LP
589 prefix, yes_no(p->handle),
590 prefix, yes_no(s->from_etc_fstab),
591 prefix, yes_no(s->from_proc_swaps),
592 prefix, yes_no(s->from_fragment));
e04aad61
LP
593
594 if (s->control_pid > 0)
595 fprintf(f,
596 "%sControl PID: %lu\n",
597 prefix, (unsigned long) s->control_pid);
598
599 exec_context_dump(&s->exec_context, f, prefix);
600}
601
602static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
603 pid_t pid;
604 int r;
605
606 assert(s);
607 assert(c);
608 assert(_pid);
609
610 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
611 goto fail;
612
613 if ((r = exec_spawn(c,
614 NULL,
615 &s->exec_context,
616 NULL, 0,
1124fe6f 617 UNIT(s)->manager->environment,
e04aad61
LP
618 true,
619 true,
620 true,
1124fe6f
MS
621 UNIT(s)->manager->confirm_spawn,
622 UNIT(s)->cgroup_bondings,
623 UNIT(s)->cgroup_attributes,
e04aad61
LP
624 &pid)) < 0)
625 goto fail;
626
627 if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
628 /* FIXME: we need to do something here */
629 goto fail;
630
631 *_pid = pid;
632
633 return 0;
634
635fail:
636 unit_unwatch_timer(UNIT(s), &s->timer_watch);
637
638 return r;
07b0b134
ML
639}
640
e1770af8 641static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
642 assert(s);
643
e1770af8
LP
644 if (f != SWAP_SUCCESS)
645 s->result = f;
e04aad61 646
e1770af8 647 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
07b0b134
ML
648}
649
e1770af8 650static void swap_enter_active(Swap *s, SwapResult f) {
e04aad61
LP
651 assert(s);
652
e1770af8
LP
653 if (f != SWAP_SUCCESS)
654 s->result = f;
e04aad61
LP
655
656 swap_set_state(s, SWAP_ACTIVE);
657}
658
e1770af8 659static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
07b0b134 660 int r;
e04aad61
LP
661 Set *pid_set = NULL;
662 bool wait_for_exit = false;
07b0b134
ML
663
664 assert(s);
e04aad61 665
e1770af8
LP
666 if (f != SWAP_SUCCESS)
667 s->result = f;
e04aad61
LP
668
669 if (s->exec_context.kill_mode != KILL_NONE) {
670 int sig = (state == SWAP_ACTIVATING_SIGTERM ||
671 state == SWAP_DEACTIVATING_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
672
673 if (s->control_pid > 0) {
cd25cce9 674 if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
e04aad61
LP
675
676 log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
677 else
678 wait_for_exit = true;
679 }
680
681 if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) {
682
683 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
684 r = -ENOMEM;
685 goto fail;
686 }
687
688 /* Exclude the control pid from being killed via the cgroup */
689 if (s->control_pid > 0)
690 if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
691 goto fail;
692
1124fe6f 693 if ((r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, pid_set)) < 0) {
e04aad61
LP
694 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
695 log_warning("Failed to kill control group: %s", strerror(-r));
696 } else if (r > 0)
697 wait_for_exit = true;
698
699 set_free(pid_set);
da19d5c1 700 pid_set = NULL;
e04aad61
LP
701 }
702 }
703
704 if (wait_for_exit) {
705 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
706 goto fail;
707
708 swap_set_state(s, state);
709 } else
e1770af8 710 swap_enter_dead(s, SWAP_SUCCESS);
e04aad61
LP
711
712 return;
713
714fail:
1124fe6f 715 log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
e04aad61 716
e1770af8 717 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
718
719 if (pid_set)
720 set_free(pid_set);
721}
722
723static void swap_enter_activating(Swap *s) {
724 int r, priority;
725
726 assert(s);
727
728 s->control_command_id = SWAP_EXEC_ACTIVATE;
729 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 730
4e85aff4
LP
731 if (s->from_fragment)
732 priority = s->parameters_fragment.priority;
733 else if (s->from_etc_fstab)
734 priority = s->parameters_etc_fstab.priority;
e04aad61
LP
735 else
736 priority = -1;
4e85aff4 737
e04aad61
LP
738 if (priority >= 0) {
739 char p[LINE_MAX];
07b0b134 740
e04aad61
LP
741 snprintf(p, sizeof(p), "%i", priority);
742 char_array_0(p);
07b0b134 743
e04aad61
LP
744 r = exec_command_set(
745 s->control_command,
746 "/sbin/swapon",
747 "-p",
748 p,
749 s->what,
750 NULL);
751 } else
752 r = exec_command_set(
753 s->control_command,
754 "/sbin/swapon",
755 s->what,
756 NULL);
757
758 if (r < 0)
759 goto fail;
760
761 swap_unwatch_control_pid(s);
762
763 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
764 goto fail;
765
766 swap_set_state(s, SWAP_ACTIVATING);
767
768 return;
769
770fail:
1124fe6f 771 log_warning("%s failed to run 'swapon' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 772 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
773}
774
e1770af8 775static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
776 int r;
777
778 assert(s);
779
e04aad61
LP
780 s->control_command_id = SWAP_EXEC_DEACTIVATE;
781 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
782
783 if ((r = exec_command_set(
784 s->control_command,
785 "/sbin/swapoff",
786 s->what,
787 NULL)) < 0)
788 goto fail;
789
790 swap_unwatch_control_pid(s);
791
792 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
793 goto fail;
794
795 swap_set_state(s, SWAP_DEACTIVATING);
796
797 return;
798
799fail:
1124fe6f 800 log_warning("%s failed to run 'swapoff' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 801 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
802}
803
804static int swap_start(Unit *u) {
805 Swap *s = SWAP(u);
806
807 assert(s);
808
809 /* We cannot fulfill this request right now, try again later
810 * please! */
811
812 if (s->state == SWAP_DEACTIVATING ||
813 s->state == SWAP_DEACTIVATING_SIGTERM ||
814 s->state == SWAP_DEACTIVATING_SIGKILL ||
815 s->state == SWAP_ACTIVATING_SIGTERM ||
816 s->state == SWAP_ACTIVATING_SIGKILL)
817 return -EAGAIN;
818
819 if (s->state == SWAP_ACTIVATING)
820 return 0;
821
822 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
823
e1770af8 824 s->result = SWAP_SUCCESS;
e04aad61 825 swap_enter_activating(s);
07b0b134
ML
826 return 0;
827}
828
829static int swap_stop(Unit *u) {
830 Swap *s = SWAP(u);
07b0b134
ML
831
832 assert(s);
833
e04aad61
LP
834 if (s->state == SWAP_DEACTIVATING ||
835 s->state == SWAP_DEACTIVATING_SIGTERM ||
836 s->state == SWAP_DEACTIVATING_SIGKILL ||
837 s->state == SWAP_ACTIVATING_SIGTERM ||
838 s->state == SWAP_ACTIVATING_SIGKILL)
839 return 0;
07b0b134 840
e04aad61
LP
841 assert(s->state == SWAP_ACTIVATING ||
842 s->state == SWAP_ACTIVE);
07b0b134 843
e1770af8 844 swap_enter_deactivating(s);
07b0b134
ML
845 return 0;
846}
847
848static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
849 Swap *s = SWAP(u);
850
851 assert(s);
852 assert(f);
853 assert(fds);
854
855 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
e1770af8 856 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
e04aad61
LP
857
858 if (s->control_pid > 0)
859 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
860
861 if (s->control_command_id >= 0)
862 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
863
864 return 0;
865}
866
867static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
868 Swap *s = SWAP(u);
869
870 assert(s);
871 assert(fds);
872
873 if (streq(key, "state")) {
874 SwapState state;
875
876 if ((state = swap_state_from_string(value)) < 0)
877 log_debug("Failed to parse state value %s", value);
878 else
879 s->deserialized_state = state;
e1770af8
LP
880 } else if (streq(key, "result")) {
881 SwapResult f;
882
883 f = swap_result_from_string(value);
884 if (f < 0)
885 log_debug("Failed to parse result value %s", value);
886 else if (f != SWAP_SUCCESS)
887 s->result = f;
e04aad61
LP
888 } else if (streq(key, "control-pid")) {
889 pid_t pid;
890
891 if (parse_pid(value, &pid) < 0)
892 log_debug("Failed to parse control-pid value %s", value);
893 else
894 s->control_pid = pid;
895
896 } else if (streq(key, "control-command")) {
897 SwapExecCommand id;
898
899 if ((id = swap_exec_command_from_string(value)) < 0)
900 log_debug("Failed to parse exec-command value %s", value);
901 else {
902 s->control_command_id = id;
903 s->control_command = s->exec_command + id;
904 }
905
07b0b134
ML
906 } else
907 log_debug("Unknown serialization key '%s'", key);
908
909 return 0;
910}
911
912static UnitActiveState swap_active_state(Unit *u) {
913 assert(u);
914
915 return state_translation_table[SWAP(u)->state];
916}
917
918static const char *swap_sub_state_to_string(Unit *u) {
919 assert(u);
920
921 return swap_state_to_string(SWAP(u)->state);
922}
923
924static bool swap_check_gc(Unit *u) {
925 Swap *s = SWAP(u);
926
927 assert(s);
928
4e85aff4 929 return s->from_etc_fstab || s->from_proc_swaps;
07b0b134
ML
930}
931
e04aad61
LP
932static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
933 Swap *s = SWAP(u);
e1770af8 934 SwapResult f;
e04aad61
LP
935
936 assert(s);
937 assert(pid >= 0);
938
939 if (pid != s->control_pid)
940 return;
941
942 s->control_pid = 0;
943
e1770af8
LP
944 if (is_clean_exit(code, status))
945 f = SWAP_SUCCESS;
946 else if (code == CLD_EXITED)
947 f = SWAP_FAILURE_EXIT_CODE;
948 else if (code == CLD_KILLED)
949 f = SWAP_FAILURE_SIGNAL;
950 else if (code == CLD_DUMPED)
951 f = SWAP_FAILURE_CORE_DUMP;
952 else
953 assert_not_reached("Unknown code");
954
955 if (f != SWAP_SUCCESS)
956 s->result = f;
e04aad61
LP
957
958 if (s->control_command) {
6ea832a2 959 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 960
e04aad61
LP
961 s->control_command = NULL;
962 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
963 }
964
e1770af8 965 log_full(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
ac155bb8 966 "%s swap process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
e04aad61
LP
967
968 switch (s->state) {
969
970 case SWAP_ACTIVATING:
971 case SWAP_ACTIVATING_SIGTERM:
972 case SWAP_ACTIVATING_SIGKILL:
973
e1770af8
LP
974 if (f == SWAP_SUCCESS)
975 swap_enter_active(s, f);
e04aad61 976 else
e1770af8 977 swap_enter_dead(s, f);
e04aad61
LP
978 break;
979
980 case SWAP_DEACTIVATING:
981 case SWAP_DEACTIVATING_SIGKILL:
982 case SWAP_DEACTIVATING_SIGTERM:
983
e1770af8
LP
984 if (f == SWAP_SUCCESS)
985 swap_enter_dead(s, f);
e04aad61 986 else
e1770af8 987 swap_enter_dead(s, f);
e04aad61
LP
988 break;
989
990 default:
991 assert_not_reached("Uh, control process died at wrong time.");
992 }
993
994 /* Notify clients about changed exit status */
995 unit_add_to_dbus_queue(u);
996
997 /* Request a reload of /proc/swaps, so that following units
998 * can follow our state change */
ac155bb8 999 u->manager->request_reload = true;
e04aad61
LP
1000}
1001
1002static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
1003 Swap *s = SWAP(u);
1004
1005 assert(s);
1006 assert(elapsed == 1);
1007 assert(w == &s->timer_watch);
1008
1009 switch (s->state) {
1010
1011 case SWAP_ACTIVATING:
ac155bb8 1012 log_warning("%s activation timed out. Stopping.", u->id);
e1770af8 1013 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1014 break;
1015
1016 case SWAP_DEACTIVATING:
ac155bb8 1017 log_warning("%s deactivation timed out. Stopping.", u->id);
e1770af8 1018 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1019 break;
1020
1021 case SWAP_ACTIVATING_SIGTERM:
ba035df2 1022 if (s->exec_context.send_sigkill) {
ac155bb8 1023 log_warning("%s activation timed out. Killing.", u->id);
e1770af8 1024 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1025 } else {
ac155bb8 1026 log_warning("%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
e1770af8 1027 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1028 }
e04aad61
LP
1029 break;
1030
1031 case SWAP_DEACTIVATING_SIGTERM:
ba035df2 1032 if (s->exec_context.send_sigkill) {
ac155bb8 1033 log_warning("%s deactivation timed out. Killing.", u->id);
e1770af8 1034 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1035 } else {
ac155bb8 1036 log_warning("%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
e1770af8 1037 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1038 }
e04aad61
LP
1039 break;
1040
1041 case SWAP_ACTIVATING_SIGKILL:
1042 case SWAP_DEACTIVATING_SIGKILL:
ac155bb8 1043 log_warning("%s swap process still around after SIGKILL. Ignoring.", u->id);
e1770af8 1044 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1045 break;
1046
1047 default:
1048 assert_not_reached("Timeout at wrong time.");
1049 }
1050}
1051
1052static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1053 unsigned i;
1054 int r = 0;
1055
1056 assert(m);
1057
07b0b134 1058 rewind(m->proc_swaps);
bab45044 1059
4e85aff4 1060 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1061
e04aad61 1062 for (i = 1;; i++) {
07b0b134
ML
1063 char *dev = NULL, *d;
1064 int prio = 0, k;
1065
4e85aff4 1066 if ((k = fscanf(m->proc_swaps,
e04aad61
LP
1067 "%ms " /* device/file */
1068 "%*s " /* type of swap */
1069 "%*s " /* swap size */
1070 "%*s " /* used */
4e85aff4
LP
1071 "%i\n", /* priority */
1072 &dev, &prio)) != 2) {
07b0b134 1073
07b0b134 1074 if (k == EOF)
4e85aff4 1075 break;
07b0b134 1076
e04aad61 1077 log_warning("Failed to parse /proc/swaps:%u.", i);
07b0b134 1078 free(dev);
e04aad61 1079 continue;
07b0b134 1080 }
07b0b134 1081
4e85aff4 1082 d = cunescape(dev);
07b0b134 1083 free(dev);
4e85aff4
LP
1084
1085 if (!d)
1086 return -ENOMEM;
1087
e04aad61 1088 k = swap_process_new_swap(m, d, prio, set_flags);
07b0b134
ML
1089 free(d);
1090
1091 if (k < 0)
e04aad61 1092 r = k;
07b0b134
ML
1093 }
1094
e04aad61
LP
1095 return r;
1096}
1097
1098int swap_dispatch_reload(Manager *m) {
4e434314 1099 /* This function should go as soon as the kernel properly notifies us */
e04aad61
LP
1100
1101 if (_likely_(!m->request_reload))
1102 return 0;
1103
1104 m->request_reload = false;
1105
4e434314
LP
1106 return swap_fd_event(m, EPOLLPRI);
1107}
1108
1109int swap_fd_event(Manager *m, int events) {
595ed347 1110 Unit *u;
4e434314
LP
1111 int r;
1112
1113 assert(m);
1114 assert(events & EPOLLPRI);
1115
bd40a2d8 1116 if ((r = swap_load_proc_swaps(m, true)) < 0) {
e04aad61
LP
1117 log_error("Failed to reread /proc/swaps: %s", strerror(-r));
1118
1119 /* Reset flags, just in case, for late calls */
595ed347
MS
1120 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1121 Swap *swap = SWAP(u);
e04aad61
LP
1122
1123 swap->is_active = swap->just_activated = false;
1124 }
1125
1126 return 0;
1127 }
1128
1129 manager_dispatch_load_queue(m);
1130
595ed347
MS
1131 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1132 Swap *swap = SWAP(u);
e04aad61
LP
1133
1134 if (!swap->is_active) {
1135 /* This has just been deactivated */
1136
1137 swap->from_proc_swaps = false;
1138 swap_unset_proc_swaps(swap);
1139
1140 switch (swap->state) {
1141
1142 case SWAP_ACTIVE:
e1770af8 1143 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1144 break;
1145
1146 default:
1147 swap_set_state(swap, swap->state);
1148 break;
1149 }
1150
1151 } else if (swap->just_activated) {
1152
1153 /* New swap entry */
1154
1155 switch (swap->state) {
1156
1157 case SWAP_DEAD:
1158 case SWAP_FAILED:
e1770af8 1159 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1160 break;
1161
1162 default:
1163 /* Nothing really changed, but let's
1164 * issue an notification call
1165 * nonetheless, in case somebody is
1166 * waiting for this. */
1167 swap_set_state(swap, swap->state);
1168 break;
1169 }
1170 }
1171
1172 /* Reset the flags for later calls */
1173 swap->is_active = swap->just_activated = false;
1174 }
1175
1176 return 1;
1177}
1178
1179static Unit *swap_following(Unit *u) {
1180 Swap *s = SWAP(u);
1181 Swap *other, *first = NULL;
1182
1183 assert(s);
1184
1185 if (streq_ptr(s->what, s->parameters_proc_swaps.what))
1186 return NULL;
1187
1188 /* Make everybody follow the unit that's named after the swap
1189 * device in the kernel */
1190
1191 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1192 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1193 return UNIT(other);
1194
1195 LIST_FOREACH_BEFORE(same_proc_swaps, other, s) {
1196 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1197 return UNIT(other);
1198
1199 first = other;
1200 }
1201
1202 return UNIT(first);
07b0b134
ML
1203}
1204
6210e7fc
LP
1205static int swap_following_set(Unit *u, Set **_set) {
1206 Swap *s = SWAP(u);
1207 Swap *other;
1208 Set *set;
1209 int r;
1210
1211 assert(s);
1212 assert(_set);
1213
1214 if (LIST_JUST_US(same_proc_swaps, s)) {
1215 *_set = NULL;
1216 return 0;
1217 }
1218
1219 if (!(set = set_new(NULL, NULL)))
1220 return -ENOMEM;
1221
1222 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1223 if ((r = set_put(set, other)) < 0)
1224 goto fail;
1225
1226 LIST_FOREACH_BEFORE(same_proc_swaps, other, s)
1227 if ((r = set_put(set, other)) < 0)
1228 goto fail;
1229
1230 *_set = set;
1231 return 1;
1232
1233fail:
1234 set_free(set);
1235 return r;
1236}
1237
07b0b134
ML
1238static void swap_shutdown(Manager *m) {
1239 assert(m);
1240
1241 if (m->proc_swaps) {
1242 fclose(m->proc_swaps);
1243 m->proc_swaps = NULL;
1244 }
e04aad61
LP
1245
1246 hashmap_free(m->swaps_by_proc_swaps);
1247 m->swaps_by_proc_swaps = NULL;
07b0b134
ML
1248}
1249
07b0b134
ML
1250static int swap_enumerate(Manager *m) {
1251 int r;
4e434314 1252 struct epoll_event ev;
07b0b134
ML
1253 assert(m);
1254
4e434314 1255 if (!m->proc_swaps) {
4e85aff4 1256 if (!(m->proc_swaps = fopen("/proc/swaps", "re")))
3f858732 1257 return (errno == ENOENT) ? 0 : -errno;
07b0b134 1258
4e434314
LP
1259 m->swap_watch.type = WATCH_SWAP;
1260 m->swap_watch.fd = fileno(m->proc_swaps);
1261
1262 zero(ev);
1263 ev.events = EPOLLPRI;
1264 ev.data.ptr = &m->swap_watch;
1265
1266 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
1267 return -errno;
1268 }
1269
e04aad61
LP
1270 /* We rely on mount.c to load /etc/fstab for us */
1271
1272 if ((r = swap_load_proc_swaps(m, false)) < 0)
07b0b134
ML
1273 swap_shutdown(m);
1274
1275 return r;
1276}
1277
fdf20a31 1278static void swap_reset_failed(Unit *u) {
5632e374
LP
1279 Swap *s = SWAP(u);
1280
1281 assert(s);
1282
fdf20a31 1283 if (s->state == SWAP_FAILED)
5632e374 1284 swap_set_state(s, SWAP_DEAD);
e04aad61 1285
e1770af8 1286 s->result = SWAP_SUCCESS;
5632e374
LP
1287}
1288
8a0867d6
LP
1289static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
1290 Swap *s = SWAP(u);
1291 int r = 0;
1292 Set *pid_set = NULL;
1293
1294 assert(s);
1295
1296 if (who == KILL_MAIN) {
1297 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Swap units have no main processes");
a17204af 1298 return -ESRCH;
8a0867d6
LP
1299 }
1300
1301 if (s->control_pid <= 0 && who == KILL_CONTROL) {
1302 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
a17204af 1303 return -ESRCH;
8a0867d6
LP
1304 }
1305
3611581e
LP
1306 if (who == KILL_CONTROL || who == KILL_ALL)
1307 if (s->control_pid > 0)
1308 if (kill(s->control_pid, signo) < 0)
1309 r = -errno;
8a0867d6 1310
3611581e 1311 if (who == KILL_ALL && mode == KILL_CONTROL_GROUP) {
8a0867d6
LP
1312 int q;
1313
1314 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
1315 return -ENOMEM;
1316
1317 /* Exclude the control pid from being killed via the cgroup */
1318 if (s->control_pid > 0)
1319 if ((q = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0) {
1320 r = q;
1321 goto finish;
1322 }
1323
1124fe6f 1324 if ((q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, pid_set)) < 0)
3611581e 1325 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
8a0867d6
LP
1326 r = q;
1327 }
1328
1329finish:
1330 if (pid_set)
1331 set_free(pid_set);
1332
1333 return r;
1334}
1335
5632e374
LP
1336static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1337 [SWAP_DEAD] = "dead",
e04aad61 1338 [SWAP_ACTIVATING] = "activating",
5632e374 1339 [SWAP_ACTIVE] = "active",
e04aad61
LP
1340 [SWAP_DEACTIVATING] = "deactivating",
1341 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1342 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1343 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1344 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
fdf20a31 1345 [SWAP_FAILED] = "failed"
5632e374
LP
1346};
1347
1348DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1349
e04aad61
LP
1350static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1351 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1352 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1353};
1354
1355DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1356
e1770af8
LP
1357static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1358 [SWAP_SUCCESS] = "success",
1359 [SWAP_FAILURE_RESOURCES] = "resources",
1360 [SWAP_FAILURE_TIMEOUT] = "timeout",
1361 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1362 [SWAP_FAILURE_SIGNAL] = "signal",
1363 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1364};
1365
1366DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1367
07b0b134
ML
1368const UnitVTable swap_vtable = {
1369 .suffix = ".swap",
7d17cfbc 1370 .object_size = sizeof(Swap),
f975e971
LP
1371 .sections =
1372 "Unit\0"
1373 "Swap\0"
1374 "Install\0",
07b0b134 1375
e04aad61 1376 .no_alias = true,
07b0b134 1377 .no_instances = true,
9e58ff9c 1378 .show_status = true,
07b0b134 1379
4e85aff4 1380 .init = swap_init,
07b0b134 1381 .load = swap_load,
6e620bec 1382 .done = swap_done,
07b0b134
ML
1383
1384 .coldplug = swap_coldplug,
1385
1386 .dump = swap_dump,
1387
1388 .start = swap_start,
1389 .stop = swap_stop,
1390
8a0867d6
LP
1391 .kill = swap_kill,
1392
07b0b134
ML
1393 .serialize = swap_serialize,
1394 .deserialize_item = swap_deserialize_item,
1395
1396 .active_state = swap_active_state,
1397 .sub_state_to_string = swap_sub_state_to_string,
1398
1399 .check_gc = swap_check_gc,
1400
e04aad61
LP
1401 .sigchld_event = swap_sigchld_event,
1402 .timer_event = swap_timer_event,
1403
1404 .reset_failed = swap_reset_failed,
1405
c4e2ceae 1406 .bus_interface = "org.freedesktop.systemd1.Swap",
07b0b134 1407 .bus_message_handler = bus_swap_message_handler,
c4e2ceae 1408 .bus_invalidating_properties = bus_swap_invalidating_properties,
07b0b134 1409
e04aad61 1410 .following = swap_following,
6210e7fc 1411 .following_set = swap_following_set,
5632e374 1412
6e620bec
LP
1413 .enumerate = swap_enumerate,
1414 .shutdown = swap_shutdown
07b0b134 1415};