]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
systemctl: allow 'systemctl reboot -ff' to succeed even without D-Bus
[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 &&
510051fc 185 s->from_etc_fstab &&
1124fe6f 186 UNIT(s)->manager->running_as == MANAGER_SYSTEM)
6e2ef85b
LP
187 if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(s), true)) < 0)
188 return r;
07b0b134
ML
189
190 return unit_add_dependency(UNIT(s), UNIT_BEFORE, tu, true);
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;
203 else if (s->from_etc_fstab)
204 p = &s->parameters_etc_fstab;
205 else
206 return 0;
207
cfcfd4ae
LP
208 if (is_device_path(s->what))
209 return unit_add_node_link(UNIT(s), s->what,
210 !p->noauto && p->nofail &&
1124fe6f 211 UNIT(s)->manager->running_as == MANAGER_SYSTEM);
cfcfd4ae
LP
212 else
213 /* File based swap devices need to be ordered after
2b93b027 214 * systemd-remount-fs.service, since they might need a
cfcfd4ae 215 * writable file system. */
2b93b027 216 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true);
173a8d04
LP
217}
218
2edd4434
LP
219static int swap_add_default_dependencies(Swap *s) {
220 int r;
221
222 assert(s);
223
1124fe6f 224 if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) {
2edd4434 225
ead8e478 226 if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
e04aad61 227 return r;
2edd4434
LP
228 }
229
230 return 0;
231}
232
4e85aff4
LP
233static int swap_verify(Swap *s) {
234 bool b;
235 char *e;
236
1124fe6f 237 if (UNIT(s)->load_state != UNIT_LOADED)
4e85aff4
LP
238 return 0;
239
240 if (!(e = unit_name_from_path(s->what, ".swap")))
241 return -ENOMEM;
242
243 b = unit_has_name(UNIT(s), e);
244 free(e);
245
246 if (!b) {
1124fe6f 247 log_error("%s: Value of \"What\" and unit name do not match, not loading.\n", UNIT(s)->id);
4e85aff4
LP
248 return -EINVAL;
249 }
250
e04aad61 251 if (s->exec_context.pam_name && s->exec_context.kill_mode != KILL_CONTROL_GROUP) {
1124fe6f 252 log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(s)->id);
e04aad61
LP
253 return -EINVAL;
254 }
255
4e85aff4
LP
256 return 0;
257}
258
07b0b134
ML
259static int swap_load(Unit *u) {
260 int r;
261 Swap *s = SWAP(u);
262
263 assert(s);
ac155bb8 264 assert(u->load_state == UNIT_STUB);
07b0b134
ML
265
266 /* Load a .swap file */
267 if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
268 return r;
269
ac155bb8 270 if (u->load_state == UNIT_LOADED) {
27abbe82
LP
271 if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
272 return r;
4e85aff4 273
1124fe6f 274 if (UNIT(s)->fragment_path)
4e85aff4
LP
275 s->from_fragment = true;
276
277 if (!s->what) {
278 if (s->parameters_fragment.what)
279 s->what = strdup(s->parameters_fragment.what);
280 else if (s->parameters_etc_fstab.what)
281 s->what = strdup(s->parameters_etc_fstab.what);
282 else if (s->parameters_proc_swaps.what)
283 s->what = strdup(s->parameters_proc_swaps.what);
284 else
ac155bb8 285 s->what = unit_name_to_path(u->id);
4e85aff4
LP
286
287 if (!s->what)
07b0b134 288 return -ENOMEM;
4e85aff4 289 }
07b0b134
ML
290
291 path_kill_slashes(s->what);
292
1124fe6f 293 if (!UNIT(s)->description)
4e85aff4
LP
294 if ((r = unit_set_description(u, s->what)) < 0)
295 return r;
296
173a8d04 297 if ((r = swap_add_device_links(s)) < 0)
07b0b134
ML
298 return r;
299
6e2ef85b
LP
300 if ((r = swap_add_mount_links(s)) < 0)
301 return r;
07b0b134
ML
302
303 if ((r = swap_add_target_links(s)) < 0)
304 return r;
2edd4434 305
d686d8a9 306 if ((r = unit_add_default_cgroups(u)) < 0)
f1a1cd64
LP
307 return r;
308
1124fe6f 309 if (UNIT(s)->default_dependencies)
2edd4434
LP
310 if ((r = swap_add_default_dependencies(s)) < 0)
311 return r;
07b0b134
ML
312 }
313
314 return swap_verify(s);
315}
316
4e85aff4
LP
317int swap_add_one(
318 Manager *m,
319 const char *what,
e04aad61 320 const char *what_proc_swaps,
4e85aff4
LP
321 int priority,
322 bool noauto,
173a8d04 323 bool nofail,
e04aad61
LP
324 bool set_flags) {
325
4e85aff4 326 Unit *u = NULL;
e04aad61 327 char *e = NULL, *wp = NULL;
2c7c6144 328 bool delete = false;
07b0b134 329 int r;
4e85aff4
LP
330 SwapParameters *p;
331
332 assert(m);
333 assert(what);
07b0b134 334
7d17cfbc
MS
335 e = unit_name_from_path(what, ".swap");
336 if (!e)
07b0b134
ML
337 return -ENOMEM;
338
e04aad61
LP
339 u = manager_get_unit(m, e);
340
341 if (what_proc_swaps &&
342 u &&
343 SWAP(u)->from_proc_swaps &&
344 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
345 return -EEXIST;
4e85aff4
LP
346
347 if (!u) {
07b0b134
ML
348 delete = true;
349
7d17cfbc
MS
350 u = unit_new(m, sizeof(Swap));
351 if (!u) {
07b0b134
ML
352 free(e);
353 return -ENOMEM;
354 }
e04aad61 355
7d17cfbc
MS
356 r = unit_add_name(u, e);
357 if (r < 0)
e04aad61
LP
358 goto fail;
359
7d17cfbc
MS
360 SWAP(u)->what = strdup(what);
361 if (!SWAP(u)->what) {
e04aad61
LP
362 r = -ENOMEM;
363 goto fail;
364 }
365
366 unit_add_to_load_queue(u);
4e85aff4
LP
367 } else
368 delete = false;
07b0b134 369
e04aad61
LP
370 if (what_proc_swaps) {
371 Swap *first;
07b0b134 372
4e85aff4 373 p = &SWAP(u)->parameters_proc_swaps;
e04aad61
LP
374
375 if (!p->what) {
376 if (!(wp = strdup(what_proc_swaps))) {
377 r = -ENOMEM;
378 goto fail;
379 }
380
381 if (!m->swaps_by_proc_swaps)
382 if (!(m->swaps_by_proc_swaps = hashmap_new(string_hash_func, string_compare_func))) {
383 r = -ENOMEM;
384 goto fail;
385 }
386
387 free(p->what);
388 p->what = wp;
389
390 first = hashmap_get(m->swaps_by_proc_swaps, wp);
391 LIST_PREPEND(Swap, same_proc_swaps, first, SWAP(u));
392
393 if ((r = hashmap_replace(m->swaps_by_proc_swaps, wp, first)) < 0)
394 goto fail;
395 }
396
397 if (set_flags) {
398 SWAP(u)->is_active = true;
399 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
400 }
401
4e85aff4 402 SWAP(u)->from_proc_swaps = true;
e04aad61 403
4e85aff4
LP
404 } else {
405 p = &SWAP(u)->parameters_etc_fstab;
e04aad61
LP
406
407 if (!(wp = strdup(what))) {
408 r = -ENOMEM;
409 goto fail;
410 }
411
412 free(p->what);
413 p->what = wp;
414
4e85aff4
LP
415 SWAP(u)->from_etc_fstab = true;
416 }
07b0b134 417
4e85aff4
LP
418 p->priority = priority;
419 p->noauto = noauto;
173a8d04 420 p->nofail = nofail;
07b0b134 421
4e85aff4 422 unit_add_to_dbus_queue(u);
07b0b134 423
4e85aff4 424 free(e);
07b0b134
ML
425
426 return 0;
427
428fail:
e04aad61
LP
429 log_warning("Failed to load swap unit: %s", strerror(-r));
430
431 free(wp);
4e85aff4
LP
432 free(e);
433
434 if (delete && u)
07b0b134
ML
435 unit_free(u);
436
4e85aff4 437 return r;
07b0b134
ML
438}
439
e04aad61
LP
440static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
441 struct stat st;
442 int r = 0, k;
443
444 assert(m);
445
446 if (stat(device, &st) >= 0 && S_ISBLK(st.st_mode)) {
447 struct udev_device *d;
448 const char *dn;
449 struct udev_list_entry *item = NULL, *first = NULL;
450
451 /* So this is a proper swap device. Create swap units
452 * for all names this swap device is known under */
453
454 if (!(d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev)))
455 return -ENOMEM;
456
8d8e9456
LP
457 dn = udev_device_get_devnode(d);
458 if (dn)
459 r = swap_add_one(m, dn, device, prio, false, false, set_flags);
e04aad61
LP
460
461 /* Add additional units for all symlinks */
462 first = udev_device_get_devlinks_list_entry(d);
463 udev_list_entry_foreach(item, first) {
464 const char *p;
465
466 /* Don't bother with the /dev/block links */
467 p = udev_list_entry_get_name(item);
468
469 if (path_startswith(p, "/dev/block/"))
470 continue;
471
472 if (stat(p, &st) >= 0)
473 if ((!S_ISBLK(st.st_mode)) || st.st_rdev != udev_device_get_devnum(d))
474 continue;
475
8d8e9456
LP
476 k = swap_add_one(m, p, device, prio, false, false, set_flags);
477 if (k < 0)
e04aad61
LP
478 r = k;
479 }
480
481 udev_device_unref(d);
482 }
483
8d8e9456
LP
484 k = swap_add_one(m, device, device, prio, false, false, set_flags);
485 if (k < 0)
e04aad61
LP
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 "%sFrom /etc/fstab: %s\n"
580 "%sFrom /proc/swaps: %s\n"
581 "%sFrom fragment: %s\n",
07b0b134 582 prefix, swap_state_to_string(s->state),
e1770af8 583 prefix, swap_result_to_string(s->result),
07b0b134 584 prefix, s->what,
4e85aff4
LP
585 prefix, p->priority,
586 prefix, yes_no(p->noauto),
173a8d04 587 prefix, yes_no(p->nofail),
4e85aff4
LP
588 prefix, yes_no(s->from_etc_fstab),
589 prefix, yes_no(s->from_proc_swaps),
590 prefix, yes_no(s->from_fragment));
e04aad61
LP
591
592 if (s->control_pid > 0)
593 fprintf(f,
594 "%sControl PID: %lu\n",
595 prefix, (unsigned long) s->control_pid);
596
597 exec_context_dump(&s->exec_context, f, prefix);
598}
599
600static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
601 pid_t pid;
602 int r;
603
604 assert(s);
605 assert(c);
606 assert(_pid);
607
608 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
609 goto fail;
610
611 if ((r = exec_spawn(c,
612 NULL,
613 &s->exec_context,
614 NULL, 0,
1124fe6f 615 UNIT(s)->manager->environment,
e04aad61
LP
616 true,
617 true,
618 true,
1124fe6f
MS
619 UNIT(s)->manager->confirm_spawn,
620 UNIT(s)->cgroup_bondings,
621 UNIT(s)->cgroup_attributes,
ecedd90f 622 NULL,
f2b68789 623 NULL,
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
ecedd90f
LP
693 r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, pid_set, NULL);
694 if (r < 0) {
e04aad61
LP
695 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
696 log_warning("Failed to kill control group: %s", strerror(-r));
697 } else if (r > 0)
698 wait_for_exit = true;
699
700 set_free(pid_set);
da19d5c1 701 pid_set = NULL;
e04aad61
LP
702 }
703 }
704
705 if (wait_for_exit) {
706 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
707 goto fail;
708
709 swap_set_state(s, state);
710 } else
e1770af8 711 swap_enter_dead(s, SWAP_SUCCESS);
e04aad61
LP
712
713 return;
714
715fail:
1124fe6f 716 log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
e04aad61 717
e1770af8 718 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
719
720 if (pid_set)
721 set_free(pid_set);
722}
723
724static void swap_enter_activating(Swap *s) {
725 int r, priority;
726
727 assert(s);
728
729 s->control_command_id = SWAP_EXEC_ACTIVATE;
730 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 731
4e85aff4
LP
732 if (s->from_fragment)
733 priority = s->parameters_fragment.priority;
734 else if (s->from_etc_fstab)
735 priority = s->parameters_etc_fstab.priority;
e04aad61
LP
736 else
737 priority = -1;
4e85aff4 738
e04aad61
LP
739 if (priority >= 0) {
740 char p[LINE_MAX];
07b0b134 741
e04aad61
LP
742 snprintf(p, sizeof(p), "%i", priority);
743 char_array_0(p);
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
764 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
765 goto fail;
766
767 swap_set_state(s, SWAP_ACTIVATING);
768
769 return;
770
771fail:
1124fe6f 772 log_warning("%s failed to run 'swapon' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 773 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
774}
775
e1770af8 776static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
777 int r;
778
779 assert(s);
780
e04aad61
LP
781 s->control_command_id = SWAP_EXEC_DEACTIVATE;
782 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
783
784 if ((r = exec_command_set(
785 s->control_command,
786 "/sbin/swapoff",
787 s->what,
788 NULL)) < 0)
789 goto fail;
790
791 swap_unwatch_control_pid(s);
792
793 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
794 goto fail;
795
796 swap_set_state(s, SWAP_DEACTIVATING);
797
798 return;
799
800fail:
1124fe6f 801 log_warning("%s failed to run 'swapoff' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 802 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
803}
804
805static int swap_start(Unit *u) {
806 Swap *s = SWAP(u);
807
808 assert(s);
809
810 /* We cannot fulfill this request right now, try again later
811 * please! */
812
813 if (s->state == SWAP_DEACTIVATING ||
814 s->state == SWAP_DEACTIVATING_SIGTERM ||
815 s->state == SWAP_DEACTIVATING_SIGKILL ||
816 s->state == SWAP_ACTIVATING_SIGTERM ||
817 s->state == SWAP_ACTIVATING_SIGKILL)
818 return -EAGAIN;
819
820 if (s->state == SWAP_ACTIVATING)
821 return 0;
822
823 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
824
e1770af8 825 s->result = SWAP_SUCCESS;
e04aad61 826 swap_enter_activating(s);
07b0b134
ML
827 return 0;
828}
829
830static int swap_stop(Unit *u) {
831 Swap *s = SWAP(u);
07b0b134
ML
832
833 assert(s);
834
e04aad61
LP
835 if (s->state == SWAP_DEACTIVATING ||
836 s->state == SWAP_DEACTIVATING_SIGTERM ||
837 s->state == SWAP_DEACTIVATING_SIGKILL ||
838 s->state == SWAP_ACTIVATING_SIGTERM ||
839 s->state == SWAP_ACTIVATING_SIGKILL)
840 return 0;
07b0b134 841
e04aad61
LP
842 assert(s->state == SWAP_ACTIVATING ||
843 s->state == SWAP_ACTIVE);
07b0b134 844
e1770af8 845 swap_enter_deactivating(s);
07b0b134
ML
846 return 0;
847}
848
849static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
850 Swap *s = SWAP(u);
851
852 assert(s);
853 assert(f);
854 assert(fds);
855
856 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
e1770af8 857 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
e04aad61
LP
858
859 if (s->control_pid > 0)
860 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
861
862 if (s->control_command_id >= 0)
863 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
864
865 return 0;
866}
867
868static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
869 Swap *s = SWAP(u);
870
871 assert(s);
872 assert(fds);
873
874 if (streq(key, "state")) {
875 SwapState state;
876
877 if ((state = swap_state_from_string(value)) < 0)
878 log_debug("Failed to parse state value %s", value);
879 else
880 s->deserialized_state = state;
e1770af8
LP
881 } else if (streq(key, "result")) {
882 SwapResult f;
883
884 f = swap_result_from_string(value);
885 if (f < 0)
886 log_debug("Failed to parse result value %s", value);
887 else if (f != SWAP_SUCCESS)
888 s->result = f;
e04aad61
LP
889 } else if (streq(key, "control-pid")) {
890 pid_t pid;
891
892 if (parse_pid(value, &pid) < 0)
893 log_debug("Failed to parse control-pid value %s", value);
894 else
895 s->control_pid = pid;
896
897 } else if (streq(key, "control-command")) {
898 SwapExecCommand id;
899
900 if ((id = swap_exec_command_from_string(value)) < 0)
901 log_debug("Failed to parse exec-command value %s", value);
902 else {
903 s->control_command_id = id;
904 s->control_command = s->exec_command + id;
905 }
906
07b0b134
ML
907 } else
908 log_debug("Unknown serialization key '%s'", key);
909
910 return 0;
911}
912
913static UnitActiveState swap_active_state(Unit *u) {
914 assert(u);
915
916 return state_translation_table[SWAP(u)->state];
917}
918
919static const char *swap_sub_state_to_string(Unit *u) {
920 assert(u);
921
922 return swap_state_to_string(SWAP(u)->state);
923}
924
925static bool swap_check_gc(Unit *u) {
926 Swap *s = SWAP(u);
927
928 assert(s);
929
4e85aff4 930 return s->from_etc_fstab || s->from_proc_swaps;
07b0b134
ML
931}
932
e04aad61
LP
933static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
934 Swap *s = SWAP(u);
e1770af8 935 SwapResult f;
e04aad61
LP
936
937 assert(s);
938 assert(pid >= 0);
939
940 if (pid != s->control_pid)
941 return;
942
943 s->control_pid = 0;
944
e1770af8
LP
945 if (is_clean_exit(code, status))
946 f = SWAP_SUCCESS;
947 else if (code == CLD_EXITED)
948 f = SWAP_FAILURE_EXIT_CODE;
949 else if (code == CLD_KILLED)
950 f = SWAP_FAILURE_SIGNAL;
951 else if (code == CLD_DUMPED)
952 f = SWAP_FAILURE_CORE_DUMP;
953 else
954 assert_not_reached("Unknown code");
955
956 if (f != SWAP_SUCCESS)
957 s->result = f;
e04aad61
LP
958
959 if (s->control_command) {
6ea832a2 960 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 961
e04aad61
LP
962 s->control_command = NULL;
963 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
964 }
965
e1770af8 966 log_full(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
ac155bb8 967 "%s swap process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
e04aad61
LP
968
969 switch (s->state) {
970
971 case SWAP_ACTIVATING:
972 case SWAP_ACTIVATING_SIGTERM:
973 case SWAP_ACTIVATING_SIGKILL:
974
e1770af8
LP
975 if (f == SWAP_SUCCESS)
976 swap_enter_active(s, f);
e04aad61 977 else
e1770af8 978 swap_enter_dead(s, f);
e04aad61
LP
979 break;
980
981 case SWAP_DEACTIVATING:
982 case SWAP_DEACTIVATING_SIGKILL:
983 case SWAP_DEACTIVATING_SIGTERM:
984
e1770af8
LP
985 if (f == SWAP_SUCCESS)
986 swap_enter_dead(s, f);
e04aad61 987 else
e1770af8 988 swap_enter_dead(s, f);
e04aad61
LP
989 break;
990
991 default:
992 assert_not_reached("Uh, control process died at wrong time.");
993 }
994
995 /* Notify clients about changed exit status */
996 unit_add_to_dbus_queue(u);
997
998 /* Request a reload of /proc/swaps, so that following units
999 * can follow our state change */
ac155bb8 1000 u->manager->request_reload = true;
e04aad61
LP
1001}
1002
1003static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
1004 Swap *s = SWAP(u);
1005
1006 assert(s);
1007 assert(elapsed == 1);
1008 assert(w == &s->timer_watch);
1009
1010 switch (s->state) {
1011
1012 case SWAP_ACTIVATING:
ac155bb8 1013 log_warning("%s activation timed out. Stopping.", u->id);
e1770af8 1014 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1015 break;
1016
1017 case SWAP_DEACTIVATING:
ac155bb8 1018 log_warning("%s deactivation timed out. Stopping.", u->id);
e1770af8 1019 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1020 break;
1021
1022 case SWAP_ACTIVATING_SIGTERM:
ba035df2 1023 if (s->exec_context.send_sigkill) {
ac155bb8 1024 log_warning("%s activation timed out. Killing.", u->id);
e1770af8 1025 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1026 } else {
ac155bb8 1027 log_warning("%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
e1770af8 1028 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1029 }
e04aad61
LP
1030 break;
1031
1032 case SWAP_DEACTIVATING_SIGTERM:
ba035df2 1033 if (s->exec_context.send_sigkill) {
ac155bb8 1034 log_warning("%s deactivation timed out. Killing.", u->id);
e1770af8 1035 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 1036 } else {
ac155bb8 1037 log_warning("%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
e1770af8 1038 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 1039 }
e04aad61
LP
1040 break;
1041
1042 case SWAP_ACTIVATING_SIGKILL:
1043 case SWAP_DEACTIVATING_SIGKILL:
ac155bb8 1044 log_warning("%s swap process still around after SIGKILL. Ignoring.", u->id);
e1770af8 1045 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1046 break;
1047
1048 default:
1049 assert_not_reached("Timeout at wrong time.");
1050 }
1051}
1052
1053static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1054 unsigned i;
1055 int r = 0;
1056
1057 assert(m);
1058
07b0b134 1059 rewind(m->proc_swaps);
bab45044 1060
4e85aff4 1061 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1062
e04aad61 1063 for (i = 1;; i++) {
07b0b134
ML
1064 char *dev = NULL, *d;
1065 int prio = 0, k;
1066
4e85aff4 1067 if ((k = fscanf(m->proc_swaps,
e04aad61
LP
1068 "%ms " /* device/file */
1069 "%*s " /* type of swap */
1070 "%*s " /* swap size */
1071 "%*s " /* used */
4e85aff4
LP
1072 "%i\n", /* priority */
1073 &dev, &prio)) != 2) {
07b0b134 1074
07b0b134 1075 if (k == EOF)
4e85aff4 1076 break;
07b0b134 1077
e04aad61 1078 log_warning("Failed to parse /proc/swaps:%u.", i);
07b0b134 1079 free(dev);
e04aad61 1080 continue;
07b0b134 1081 }
07b0b134 1082
4e85aff4 1083 d = cunescape(dev);
07b0b134 1084 free(dev);
4e85aff4
LP
1085
1086 if (!d)
1087 return -ENOMEM;
1088
e04aad61 1089 k = swap_process_new_swap(m, d, prio, set_flags);
07b0b134
ML
1090 free(d);
1091
1092 if (k < 0)
e04aad61 1093 r = k;
07b0b134
ML
1094 }
1095
e04aad61
LP
1096 return r;
1097}
1098
1099int swap_dispatch_reload(Manager *m) {
4e434314 1100 /* This function should go as soon as the kernel properly notifies us */
e04aad61
LP
1101
1102 if (_likely_(!m->request_reload))
1103 return 0;
1104
1105 m->request_reload = false;
1106
4e434314
LP
1107 return swap_fd_event(m, EPOLLPRI);
1108}
1109
1110int swap_fd_event(Manager *m, int events) {
595ed347 1111 Unit *u;
4e434314
LP
1112 int r;
1113
1114 assert(m);
1115 assert(events & EPOLLPRI);
1116
bd40a2d8 1117 if ((r = swap_load_proc_swaps(m, true)) < 0) {
e04aad61
LP
1118 log_error("Failed to reread /proc/swaps: %s", strerror(-r));
1119
1120 /* Reset flags, just in case, for late calls */
595ed347
MS
1121 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1122 Swap *swap = SWAP(u);
e04aad61
LP
1123
1124 swap->is_active = swap->just_activated = false;
1125 }
1126
1127 return 0;
1128 }
1129
1130 manager_dispatch_load_queue(m);
1131
595ed347
MS
1132 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1133 Swap *swap = SWAP(u);
e04aad61
LP
1134
1135 if (!swap->is_active) {
1136 /* This has just been deactivated */
1137
1138 swap->from_proc_swaps = false;
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:
1148 swap_set_state(swap, swap->state);
1149 break;
1150 }
1151
1152 } else if (swap->just_activated) {
1153
1154 /* New swap entry */
1155
1156 switch (swap->state) {
1157
1158 case SWAP_DEAD:
1159 case SWAP_FAILED:
e1770af8 1160 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1161 break;
1162
1163 default:
1164 /* Nothing really changed, but let's
1165 * issue an notification call
1166 * nonetheless, in case somebody is
1167 * waiting for this. */
1168 swap_set_state(swap, swap->state);
1169 break;
1170 }
1171 }
1172
1173 /* Reset the flags for later calls */
1174 swap->is_active = swap->just_activated = false;
1175 }
1176
1177 return 1;
1178}
1179
1180static Unit *swap_following(Unit *u) {
1181 Swap *s = SWAP(u);
1182 Swap *other, *first = NULL;
1183
1184 assert(s);
1185
1186 if (streq_ptr(s->what, s->parameters_proc_swaps.what))
1187 return NULL;
1188
1189 /* Make everybody follow the unit that's named after the swap
1190 * device in the kernel */
1191
1192 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1193 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1194 return UNIT(other);
1195
1196 LIST_FOREACH_BEFORE(same_proc_swaps, other, s) {
1197 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1198 return UNIT(other);
1199
1200 first = other;
1201 }
1202
1203 return UNIT(first);
07b0b134
ML
1204}
1205
6210e7fc
LP
1206static int swap_following_set(Unit *u, Set **_set) {
1207 Swap *s = SWAP(u);
1208 Swap *other;
1209 Set *set;
1210 int r;
1211
1212 assert(s);
1213 assert(_set);
1214
1215 if (LIST_JUST_US(same_proc_swaps, s)) {
1216 *_set = NULL;
1217 return 0;
1218 }
1219
1220 if (!(set = set_new(NULL, NULL)))
1221 return -ENOMEM;
1222
1223 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1224 if ((r = set_put(set, other)) < 0)
1225 goto fail;
1226
1227 LIST_FOREACH_BEFORE(same_proc_swaps, other, s)
1228 if ((r = set_put(set, other)) < 0)
1229 goto fail;
1230
1231 *_set = set;
1232 return 1;
1233
1234fail:
1235 set_free(set);
1236 return r;
1237}
1238
07b0b134
ML
1239static void swap_shutdown(Manager *m) {
1240 assert(m);
1241
1242 if (m->proc_swaps) {
1243 fclose(m->proc_swaps);
1244 m->proc_swaps = NULL;
1245 }
e04aad61
LP
1246
1247 hashmap_free(m->swaps_by_proc_swaps);
1248 m->swaps_by_proc_swaps = NULL;
07b0b134
ML
1249}
1250
07b0b134
ML
1251static int swap_enumerate(Manager *m) {
1252 int r;
4e434314 1253 struct epoll_event ev;
07b0b134
ML
1254 assert(m);
1255
4e434314 1256 if (!m->proc_swaps) {
4e85aff4 1257 if (!(m->proc_swaps = fopen("/proc/swaps", "re")))
3f858732 1258 return (errno == ENOENT) ? 0 : -errno;
07b0b134 1259
4e434314
LP
1260 m->swap_watch.type = WATCH_SWAP;
1261 m->swap_watch.fd = fileno(m->proc_swaps);
1262
1263 zero(ev);
1264 ev.events = EPOLLPRI;
1265 ev.data.ptr = &m->swap_watch;
1266
1267 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
1268 return -errno;
1269 }
1270
e04aad61
LP
1271 /* We rely on mount.c to load /etc/fstab for us */
1272
1273 if ((r = swap_load_proc_swaps(m, false)) < 0)
07b0b134
ML
1274 swap_shutdown(m);
1275
1276 return r;
1277}
1278
fdf20a31 1279static void swap_reset_failed(Unit *u) {
5632e374
LP
1280 Swap *s = SWAP(u);
1281
1282 assert(s);
1283
fdf20a31 1284 if (s->state == SWAP_FAILED)
5632e374 1285 swap_set_state(s, SWAP_DEAD);
e04aad61 1286
e1770af8 1287 s->result = SWAP_SUCCESS;
5632e374
LP
1288}
1289
8a0867d6
LP
1290static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
1291 Swap *s = SWAP(u);
1292 int r = 0;
1293 Set *pid_set = NULL;
1294
1295 assert(s);
1296
1297 if (who == KILL_MAIN) {
1298 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Swap units have no main processes");
a17204af 1299 return -ESRCH;
8a0867d6
LP
1300 }
1301
1302 if (s->control_pid <= 0 && who == KILL_CONTROL) {
1303 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
a17204af 1304 return -ESRCH;
8a0867d6
LP
1305 }
1306
3611581e
LP
1307 if (who == KILL_CONTROL || who == KILL_ALL)
1308 if (s->control_pid > 0)
1309 if (kill(s->control_pid, signo) < 0)
1310 r = -errno;
8a0867d6 1311
3611581e 1312 if (who == KILL_ALL && mode == KILL_CONTROL_GROUP) {
8a0867d6
LP
1313 int q;
1314
1315 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
1316 return -ENOMEM;
1317
1318 /* Exclude the control pid from being killed via the cgroup */
1319 if (s->control_pid > 0)
1320 if ((q = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0) {
1321 r = q;
1322 goto finish;
1323 }
1324
ecedd90f
LP
1325 q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, pid_set, NULL);
1326 if (q < 0)
3611581e 1327 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
8a0867d6
LP
1328 r = q;
1329 }
1330
1331finish:
1332 if (pid_set)
1333 set_free(pid_set);
1334
1335 return r;
1336}
1337
5632e374
LP
1338static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1339 [SWAP_DEAD] = "dead",
e04aad61 1340 [SWAP_ACTIVATING] = "activating",
5632e374 1341 [SWAP_ACTIVE] = "active",
e04aad61
LP
1342 [SWAP_DEACTIVATING] = "deactivating",
1343 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1344 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1345 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1346 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
fdf20a31 1347 [SWAP_FAILED] = "failed"
5632e374
LP
1348};
1349
1350DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1351
e04aad61
LP
1352static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1353 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1354 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1355};
1356
1357DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1358
e1770af8
LP
1359static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1360 [SWAP_SUCCESS] = "success",
1361 [SWAP_FAILURE_RESOURCES] = "resources",
1362 [SWAP_FAILURE_TIMEOUT] = "timeout",
1363 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1364 [SWAP_FAILURE_SIGNAL] = "signal",
1365 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1366};
1367
1368DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1369
07b0b134
ML
1370const UnitVTable swap_vtable = {
1371 .suffix = ".swap",
7d17cfbc 1372 .object_size = sizeof(Swap),
f975e971
LP
1373 .sections =
1374 "Unit\0"
1375 "Swap\0"
1376 "Install\0",
07b0b134 1377
e04aad61 1378 .no_alias = true,
07b0b134 1379 .no_instances = true,
9e58ff9c 1380 .show_status = true,
07b0b134 1381
4e85aff4 1382 .init = swap_init,
07b0b134 1383 .load = swap_load,
6e620bec 1384 .done = swap_done,
07b0b134
ML
1385
1386 .coldplug = swap_coldplug,
1387
1388 .dump = swap_dump,
1389
1390 .start = swap_start,
1391 .stop = swap_stop,
1392
8a0867d6
LP
1393 .kill = swap_kill,
1394
07b0b134
ML
1395 .serialize = swap_serialize,
1396 .deserialize_item = swap_deserialize_item,
1397
1398 .active_state = swap_active_state,
1399 .sub_state_to_string = swap_sub_state_to_string,
1400
1401 .check_gc = swap_check_gc,
1402
e04aad61
LP
1403 .sigchld_event = swap_sigchld_event,
1404 .timer_event = swap_timer_event,
1405
1406 .reset_failed = swap_reset_failed,
1407
c4e2ceae 1408 .bus_interface = "org.freedesktop.systemd1.Swap",
07b0b134 1409 .bus_message_handler = bus_swap_message_handler,
c4e2ceae 1410 .bus_invalidating_properties = bus_swap_invalidating_properties,
07b0b134 1411
e04aad61 1412 .following = swap_following,
6210e7fc 1413 .following_set = swap_following_set,
5632e374 1414
6e620bec
LP
1415 .enumerate = swap_enumerate,
1416 .shutdown = swap_shutdown
07b0b134 1417};