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