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