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