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