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