]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/swap.c
NEWS: fix even more typos
[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;
07b0b134
ML
538
539 fprintf(f,
4e85aff4 540 "%sSwap State: %s\n"
e1770af8 541 "%sResult: %s\n"
07b0b134
ML
542 "%sWhat: %s\n"
543 "%sPriority: %i\n"
4e85aff4 544 "%sNoAuto: %s\n"
173a8d04 545 "%sNoFail: %s\n"
4e85aff4
LP
546 "%sFrom /proc/swaps: %s\n"
547 "%sFrom fragment: %s\n",
07b0b134 548 prefix, swap_state_to_string(s->state),
e1770af8 549 prefix, swap_result_to_string(s->result),
07b0b134 550 prefix, s->what,
4e85aff4
LP
551 prefix, p->priority,
552 prefix, yes_no(p->noauto),
173a8d04 553 prefix, yes_no(p->nofail),
4e85aff4
LP
554 prefix, yes_no(s->from_proc_swaps),
555 prefix, yes_no(s->from_fragment));
e04aad61
LP
556
557 if (s->control_pid > 0)
558 fprintf(f,
559 "%sControl PID: %lu\n",
560 prefix, (unsigned long) s->control_pid);
561
562 exec_context_dump(&s->exec_context, f, prefix);
563}
564
565static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
566 pid_t pid;
567 int r;
568
569 assert(s);
570 assert(c);
571 assert(_pid);
572
573 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
574 goto fail;
575
576 if ((r = exec_spawn(c,
577 NULL,
578 &s->exec_context,
579 NULL, 0,
1124fe6f 580 UNIT(s)->manager->environment,
e04aad61
LP
581 true,
582 true,
583 true,
1124fe6f
MS
584 UNIT(s)->manager->confirm_spawn,
585 UNIT(s)->cgroup_bondings,
586 UNIT(s)->cgroup_attributes,
ecedd90f 587 NULL,
f2b68789 588 NULL,
e04aad61
LP
589 &pid)) < 0)
590 goto fail;
591
592 if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
593 /* FIXME: we need to do something here */
594 goto fail;
595
596 *_pid = pid;
597
598 return 0;
599
600fail:
601 unit_unwatch_timer(UNIT(s), &s->timer_watch);
602
603 return r;
07b0b134
ML
604}
605
e1770af8 606static void swap_enter_dead(Swap *s, SwapResult f) {
07b0b134
ML
607 assert(s);
608
e1770af8
LP
609 if (f != SWAP_SUCCESS)
610 s->result = f;
e04aad61 611
e1770af8 612 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
07b0b134
ML
613}
614
e1770af8 615static void swap_enter_active(Swap *s, SwapResult f) {
e04aad61
LP
616 assert(s);
617
e1770af8
LP
618 if (f != SWAP_SUCCESS)
619 s->result = f;
e04aad61
LP
620
621 swap_set_state(s, SWAP_ACTIVE);
622}
623
e1770af8 624static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
07b0b134 625 int r;
e04aad61
LP
626 Set *pid_set = NULL;
627 bool wait_for_exit = false;
07b0b134
ML
628
629 assert(s);
e04aad61 630
e1770af8
LP
631 if (f != SWAP_SUCCESS)
632 s->result = f;
e04aad61
LP
633
634 if (s->exec_context.kill_mode != KILL_NONE) {
635 int sig = (state == SWAP_ACTIVATING_SIGTERM ||
636 state == SWAP_DEACTIVATING_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
637
638 if (s->control_pid > 0) {
cd25cce9 639 if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
e04aad61
LP
640
641 log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
642 else
643 wait_for_exit = true;
644 }
645
646 if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) {
647
648 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
649 r = -ENOMEM;
650 goto fail;
651 }
652
653 /* Exclude the control pid from being killed via the cgroup */
654 if (s->control_pid > 0)
655 if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
656 goto fail;
657
88f3e0c9 658 r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
ecedd90f 659 if (r < 0) {
e04aad61
LP
660 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
661 log_warning("Failed to kill control group: %s", strerror(-r));
662 } else if (r > 0)
663 wait_for_exit = true;
664
665 set_free(pid_set);
da19d5c1 666 pid_set = NULL;
e04aad61
LP
667 }
668 }
669
670 if (wait_for_exit) {
671 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
672 goto fail;
673
674 swap_set_state(s, state);
675 } else
e1770af8 676 swap_enter_dead(s, SWAP_SUCCESS);
e04aad61
LP
677
678 return;
679
680fail:
1124fe6f 681 log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
e04aad61 682
e1770af8 683 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
684
685 if (pid_set)
686 set_free(pid_set);
687}
688
689static void swap_enter_activating(Swap *s) {
690 int r, priority;
691
692 assert(s);
693
694 s->control_command_id = SWAP_EXEC_ACTIVATE;
695 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
07b0b134 696
4e85aff4
LP
697 if (s->from_fragment)
698 priority = s->parameters_fragment.priority;
e04aad61
LP
699 else
700 priority = -1;
4e85aff4 701
e04aad61
LP
702 if (priority >= 0) {
703 char p[LINE_MAX];
07b0b134 704
e04aad61
LP
705 snprintf(p, sizeof(p), "%i", priority);
706 char_array_0(p);
07b0b134 707
e04aad61
LP
708 r = exec_command_set(
709 s->control_command,
710 "/sbin/swapon",
711 "-p",
712 p,
713 s->what,
714 NULL);
715 } else
716 r = exec_command_set(
717 s->control_command,
718 "/sbin/swapon",
719 s->what,
720 NULL);
721
722 if (r < 0)
723 goto fail;
724
725 swap_unwatch_control_pid(s);
726
727 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
728 goto fail;
729
730 swap_set_state(s, SWAP_ACTIVATING);
731
732 return;
733
734fail:
1124fe6f 735 log_warning("%s failed to run 'swapon' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 736 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
737}
738
e1770af8 739static void swap_enter_deactivating(Swap *s) {
e04aad61
LP
740 int r;
741
742 assert(s);
743
e04aad61
LP
744 s->control_command_id = SWAP_EXEC_DEACTIVATE;
745 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
746
747 if ((r = exec_command_set(
748 s->control_command,
749 "/sbin/swapoff",
750 s->what,
751 NULL)) < 0)
752 goto fail;
753
754 swap_unwatch_control_pid(s);
755
756 if ((r = swap_spawn(s, s->control_command, &s->control_pid)) < 0)
757 goto fail;
758
759 swap_set_state(s, SWAP_DEACTIVATING);
760
761 return;
762
763fail:
1124fe6f 764 log_warning("%s failed to run 'swapoff' task: %s", UNIT(s)->id, strerror(-r));
e1770af8 765 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
e04aad61
LP
766}
767
768static int swap_start(Unit *u) {
769 Swap *s = SWAP(u);
770
771 assert(s);
772
773 /* We cannot fulfill this request right now, try again later
774 * please! */
775
776 if (s->state == SWAP_DEACTIVATING ||
777 s->state == SWAP_DEACTIVATING_SIGTERM ||
778 s->state == SWAP_DEACTIVATING_SIGKILL ||
779 s->state == SWAP_ACTIVATING_SIGTERM ||
780 s->state == SWAP_ACTIVATING_SIGKILL)
781 return -EAGAIN;
782
783 if (s->state == SWAP_ACTIVATING)
784 return 0;
785
786 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
787
e1770af8 788 s->result = SWAP_SUCCESS;
e04aad61 789 swap_enter_activating(s);
07b0b134
ML
790 return 0;
791}
792
793static int swap_stop(Unit *u) {
794 Swap *s = SWAP(u);
07b0b134
ML
795
796 assert(s);
797
e04aad61
LP
798 if (s->state == SWAP_DEACTIVATING ||
799 s->state == SWAP_DEACTIVATING_SIGTERM ||
800 s->state == SWAP_DEACTIVATING_SIGKILL ||
801 s->state == SWAP_ACTIVATING_SIGTERM ||
802 s->state == SWAP_ACTIVATING_SIGKILL)
803 return 0;
07b0b134 804
e04aad61
LP
805 assert(s->state == SWAP_ACTIVATING ||
806 s->state == SWAP_ACTIVE);
07b0b134 807
e1770af8 808 swap_enter_deactivating(s);
07b0b134
ML
809 return 0;
810}
811
812static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
813 Swap *s = SWAP(u);
814
815 assert(s);
816 assert(f);
817 assert(fds);
818
819 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
e1770af8 820 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
e04aad61
LP
821
822 if (s->control_pid > 0)
823 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
824
825 if (s->control_command_id >= 0)
826 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
07b0b134
ML
827
828 return 0;
829}
830
831static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
832 Swap *s = SWAP(u);
833
834 assert(s);
835 assert(fds);
836
837 if (streq(key, "state")) {
838 SwapState state;
839
840 if ((state = swap_state_from_string(value)) < 0)
841 log_debug("Failed to parse state value %s", value);
842 else
843 s->deserialized_state = state;
e1770af8
LP
844 } else if (streq(key, "result")) {
845 SwapResult f;
846
847 f = swap_result_from_string(value);
848 if (f < 0)
849 log_debug("Failed to parse result value %s", value);
850 else if (f != SWAP_SUCCESS)
851 s->result = f;
e04aad61
LP
852 } else if (streq(key, "control-pid")) {
853 pid_t pid;
854
855 if (parse_pid(value, &pid) < 0)
856 log_debug("Failed to parse control-pid value %s", value);
857 else
858 s->control_pid = pid;
859
860 } else if (streq(key, "control-command")) {
861 SwapExecCommand id;
862
863 if ((id = swap_exec_command_from_string(value)) < 0)
864 log_debug("Failed to parse exec-command value %s", value);
865 else {
866 s->control_command_id = id;
867 s->control_command = s->exec_command + id;
868 }
869
07b0b134
ML
870 } else
871 log_debug("Unknown serialization key '%s'", key);
872
873 return 0;
874}
875
876static UnitActiveState swap_active_state(Unit *u) {
877 assert(u);
878
879 return state_translation_table[SWAP(u)->state];
880}
881
882static const char *swap_sub_state_to_string(Unit *u) {
883 assert(u);
884
885 return swap_state_to_string(SWAP(u)->state);
886}
887
888static bool swap_check_gc(Unit *u) {
889 Swap *s = SWAP(u);
890
891 assert(s);
892
6b1dc2bd 893 return s->from_proc_swaps;
07b0b134
ML
894}
895
e04aad61
LP
896static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
897 Swap *s = SWAP(u);
e1770af8 898 SwapResult f;
e04aad61
LP
899
900 assert(s);
901 assert(pid >= 0);
902
903 if (pid != s->control_pid)
904 return;
905
906 s->control_pid = 0;
907
e1770af8
LP
908 if (is_clean_exit(code, status))
909 f = SWAP_SUCCESS;
910 else if (code == CLD_EXITED)
911 f = SWAP_FAILURE_EXIT_CODE;
912 else if (code == CLD_KILLED)
913 f = SWAP_FAILURE_SIGNAL;
914 else if (code == CLD_DUMPED)
915 f = SWAP_FAILURE_CORE_DUMP;
916 else
917 assert_not_reached("Unknown code");
918
919 if (f != SWAP_SUCCESS)
920 s->result = f;
e04aad61
LP
921
922 if (s->control_command) {
6ea832a2 923 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
e1770af8 924
e04aad61
LP
925 s->control_command = NULL;
926 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
927 }
928
e1770af8 929 log_full(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
ac155bb8 930 "%s swap process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
e04aad61
LP
931
932 switch (s->state) {
933
934 case SWAP_ACTIVATING:
935 case SWAP_ACTIVATING_SIGTERM:
936 case SWAP_ACTIVATING_SIGKILL:
937
e1770af8
LP
938 if (f == SWAP_SUCCESS)
939 swap_enter_active(s, f);
e04aad61 940 else
e1770af8 941 swap_enter_dead(s, f);
e04aad61
LP
942 break;
943
944 case SWAP_DEACTIVATING:
945 case SWAP_DEACTIVATING_SIGKILL:
946 case SWAP_DEACTIVATING_SIGTERM:
947
e1770af8
LP
948 if (f == SWAP_SUCCESS)
949 swap_enter_dead(s, f);
e04aad61 950 else
e1770af8 951 swap_enter_dead(s, f);
e04aad61
LP
952 break;
953
954 default:
955 assert_not_reached("Uh, control process died at wrong time.");
956 }
957
958 /* Notify clients about changed exit status */
959 unit_add_to_dbus_queue(u);
960
961 /* Request a reload of /proc/swaps, so that following units
962 * can follow our state change */
ac155bb8 963 u->manager->request_reload = true;
e04aad61
LP
964}
965
966static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
967 Swap *s = SWAP(u);
968
969 assert(s);
970 assert(elapsed == 1);
971 assert(w == &s->timer_watch);
972
973 switch (s->state) {
974
975 case SWAP_ACTIVATING:
ac155bb8 976 log_warning("%s activation timed out. Stopping.", u->id);
e1770af8 977 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
978 break;
979
980 case SWAP_DEACTIVATING:
ac155bb8 981 log_warning("%s deactivation timed out. Stopping.", u->id);
e1770af8 982 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
983 break;
984
985 case SWAP_ACTIVATING_SIGTERM:
ba035df2 986 if (s->exec_context.send_sigkill) {
ac155bb8 987 log_warning("%s activation timed out. Killing.", u->id);
e1770af8 988 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 989 } else {
ac155bb8 990 log_warning("%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
e1770af8 991 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
ba035df2 992 }
e04aad61
LP
993 break;
994
995 case SWAP_DEACTIVATING_SIGTERM:
ba035df2 996 if (s->exec_context.send_sigkill) {
ac155bb8 997 log_warning("%s deactivation timed out. Killing.", u->id);
e1770af8 998 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
ba035df2 999 } else {
ac155bb8 1000 log_warning("%s deactivation 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_ACTIVATING_SIGKILL:
1006 case SWAP_DEACTIVATING_SIGKILL:
ac155bb8 1007 log_warning("%s swap process still around after SIGKILL. Ignoring.", u->id);
e1770af8 1008 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
e04aad61
LP
1009 break;
1010
1011 default:
1012 assert_not_reached("Timeout at wrong time.");
1013 }
1014}
1015
1016static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1017 unsigned i;
1018 int r = 0;
1019
1020 assert(m);
1021
07b0b134 1022 rewind(m->proc_swaps);
bab45044 1023
4e85aff4 1024 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
07b0b134 1025
e04aad61 1026 for (i = 1;; i++) {
07b0b134
ML
1027 char *dev = NULL, *d;
1028 int prio = 0, k;
1029
4e85aff4 1030 if ((k = fscanf(m->proc_swaps,
e04aad61
LP
1031 "%ms " /* device/file */
1032 "%*s " /* type of swap */
1033 "%*s " /* swap size */
1034 "%*s " /* used */
4e85aff4
LP
1035 "%i\n", /* priority */
1036 &dev, &prio)) != 2) {
07b0b134 1037
07b0b134 1038 if (k == EOF)
4e85aff4 1039 break;
07b0b134 1040
e04aad61 1041 log_warning("Failed to parse /proc/swaps:%u.", i);
07b0b134 1042 free(dev);
e04aad61 1043 continue;
07b0b134 1044 }
07b0b134 1045
4e85aff4 1046 d = cunescape(dev);
07b0b134 1047 free(dev);
4e85aff4
LP
1048
1049 if (!d)
1050 return -ENOMEM;
1051
e04aad61 1052 k = swap_process_new_swap(m, d, prio, set_flags);
07b0b134
ML
1053 free(d);
1054
1055 if (k < 0)
e04aad61 1056 r = k;
07b0b134
ML
1057 }
1058
e04aad61
LP
1059 return r;
1060}
1061
1062int swap_dispatch_reload(Manager *m) {
4e434314 1063 /* This function should go as soon as the kernel properly notifies us */
e04aad61
LP
1064
1065 if (_likely_(!m->request_reload))
1066 return 0;
1067
1068 m->request_reload = false;
1069
4e434314
LP
1070 return swap_fd_event(m, EPOLLPRI);
1071}
1072
1073int swap_fd_event(Manager *m, int events) {
595ed347 1074 Unit *u;
4e434314
LP
1075 int r;
1076
1077 assert(m);
1078 assert(events & EPOLLPRI);
1079
bd40a2d8 1080 if ((r = swap_load_proc_swaps(m, true)) < 0) {
e04aad61
LP
1081 log_error("Failed to reread /proc/swaps: %s", strerror(-r));
1082
1083 /* Reset flags, just in case, for late calls */
595ed347
MS
1084 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1085 Swap *swap = SWAP(u);
e04aad61
LP
1086
1087 swap->is_active = swap->just_activated = false;
1088 }
1089
1090 return 0;
1091 }
1092
1093 manager_dispatch_load_queue(m);
1094
595ed347
MS
1095 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1096 Swap *swap = SWAP(u);
e04aad61
LP
1097
1098 if (!swap->is_active) {
1099 /* This has just been deactivated */
1100
1101 swap->from_proc_swaps = false;
1102 swap_unset_proc_swaps(swap);
1103
1104 switch (swap->state) {
1105
1106 case SWAP_ACTIVE:
e1770af8 1107 swap_enter_dead(swap, SWAP_SUCCESS);
e04aad61
LP
1108 break;
1109
1110 default:
1111 swap_set_state(swap, swap->state);
1112 break;
1113 }
1114
1115 } else if (swap->just_activated) {
1116
1117 /* New swap entry */
1118
1119 switch (swap->state) {
1120
1121 case SWAP_DEAD:
1122 case SWAP_FAILED:
e1770af8 1123 swap_enter_active(swap, SWAP_SUCCESS);
e04aad61
LP
1124 break;
1125
1126 default:
1127 /* Nothing really changed, but let's
1128 * issue an notification call
1129 * nonetheless, in case somebody is
1130 * waiting for this. */
1131 swap_set_state(swap, swap->state);
1132 break;
1133 }
1134 }
1135
1136 /* Reset the flags for later calls */
1137 swap->is_active = swap->just_activated = false;
1138 }
1139
1140 return 1;
1141}
1142
1143static Unit *swap_following(Unit *u) {
1144 Swap *s = SWAP(u);
1145 Swap *other, *first = NULL;
1146
1147 assert(s);
1148
1149 if (streq_ptr(s->what, s->parameters_proc_swaps.what))
1150 return NULL;
1151
1152 /* Make everybody follow the unit that's named after the swap
1153 * device in the kernel */
1154
1155 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1156 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1157 return UNIT(other);
1158
1159 LIST_FOREACH_BEFORE(same_proc_swaps, other, s) {
1160 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1161 return UNIT(other);
1162
1163 first = other;
1164 }
1165
1166 return UNIT(first);
07b0b134
ML
1167}
1168
6210e7fc
LP
1169static int swap_following_set(Unit *u, Set **_set) {
1170 Swap *s = SWAP(u);
1171 Swap *other;
1172 Set *set;
1173 int r;
1174
1175 assert(s);
1176 assert(_set);
1177
1178 if (LIST_JUST_US(same_proc_swaps, s)) {
1179 *_set = NULL;
1180 return 0;
1181 }
1182
1183 if (!(set = set_new(NULL, NULL)))
1184 return -ENOMEM;
1185
1186 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1187 if ((r = set_put(set, other)) < 0)
1188 goto fail;
1189
1190 LIST_FOREACH_BEFORE(same_proc_swaps, other, s)
1191 if ((r = set_put(set, other)) < 0)
1192 goto fail;
1193
1194 *_set = set;
1195 return 1;
1196
1197fail:
1198 set_free(set);
1199 return r;
1200}
1201
07b0b134
ML
1202static void swap_shutdown(Manager *m) {
1203 assert(m);
1204
1205 if (m->proc_swaps) {
1206 fclose(m->proc_swaps);
1207 m->proc_swaps = NULL;
1208 }
e04aad61
LP
1209
1210 hashmap_free(m->swaps_by_proc_swaps);
1211 m->swaps_by_proc_swaps = NULL;
07b0b134
ML
1212}
1213
07b0b134
ML
1214static int swap_enumerate(Manager *m) {
1215 int r;
4e434314 1216 struct epoll_event ev;
07b0b134
ML
1217 assert(m);
1218
4e434314 1219 if (!m->proc_swaps) {
4e85aff4 1220 if (!(m->proc_swaps = fopen("/proc/swaps", "re")))
3f858732 1221 return (errno == ENOENT) ? 0 : -errno;
07b0b134 1222
4e434314
LP
1223 m->swap_watch.type = WATCH_SWAP;
1224 m->swap_watch.fd = fileno(m->proc_swaps);
1225
1226 zero(ev);
1227 ev.events = EPOLLPRI;
1228 ev.data.ptr = &m->swap_watch;
1229
1230 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
1231 return -errno;
1232 }
1233
e04aad61 1234 if ((r = swap_load_proc_swaps(m, false)) < 0)
07b0b134
ML
1235 swap_shutdown(m);
1236
1237 return r;
1238}
1239
fdf20a31 1240static void swap_reset_failed(Unit *u) {
5632e374
LP
1241 Swap *s = SWAP(u);
1242
1243 assert(s);
1244
fdf20a31 1245 if (s->state == SWAP_FAILED)
5632e374 1246 swap_set_state(s, SWAP_DEAD);
e04aad61 1247
e1770af8 1248 s->result = SWAP_SUCCESS;
5632e374
LP
1249}
1250
8a0867d6
LP
1251static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
1252 Swap *s = SWAP(u);
1253 int r = 0;
1254 Set *pid_set = NULL;
1255
1256 assert(s);
1257
1258 if (who == KILL_MAIN) {
1259 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Swap units have no main processes");
a17204af 1260 return -ESRCH;
8a0867d6
LP
1261 }
1262
1263 if (s->control_pid <= 0 && who == KILL_CONTROL) {
1264 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
a17204af 1265 return -ESRCH;
8a0867d6
LP
1266 }
1267
3611581e
LP
1268 if (who == KILL_CONTROL || who == KILL_ALL)
1269 if (s->control_pid > 0)
1270 if (kill(s->control_pid, signo) < 0)
1271 r = -errno;
8a0867d6 1272
3611581e 1273 if (who == KILL_ALL && mode == KILL_CONTROL_GROUP) {
8a0867d6
LP
1274 int q;
1275
1276 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
1277 return -ENOMEM;
1278
1279 /* Exclude the control pid from being killed via the cgroup */
1280 if (s->control_pid > 0)
1281 if ((q = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0) {
1282 r = q;
1283 goto finish;
1284 }
1285
88f3e0c9 1286 q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
ecedd90f 1287 if (q < 0)
3611581e 1288 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
8a0867d6
LP
1289 r = q;
1290 }
1291
1292finish:
1293 if (pid_set)
1294 set_free(pid_set);
1295
1296 return r;
1297}
1298
5632e374
LP
1299static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1300 [SWAP_DEAD] = "dead",
e04aad61 1301 [SWAP_ACTIVATING] = "activating",
5632e374 1302 [SWAP_ACTIVE] = "active",
e04aad61
LP
1303 [SWAP_DEACTIVATING] = "deactivating",
1304 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1305 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1306 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1307 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
fdf20a31 1308 [SWAP_FAILED] = "failed"
5632e374
LP
1309};
1310
1311DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1312
e04aad61
LP
1313static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1314 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1315 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1316};
1317
1318DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1319
e1770af8
LP
1320static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1321 [SWAP_SUCCESS] = "success",
1322 [SWAP_FAILURE_RESOURCES] = "resources",
1323 [SWAP_FAILURE_TIMEOUT] = "timeout",
1324 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1325 [SWAP_FAILURE_SIGNAL] = "signal",
1326 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1327};
1328
1329DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1330
07b0b134
ML
1331const UnitVTable swap_vtable = {
1332 .suffix = ".swap",
7d17cfbc 1333 .object_size = sizeof(Swap),
f975e971
LP
1334 .sections =
1335 "Unit\0"
1336 "Swap\0"
1337 "Install\0",
07b0b134 1338
e04aad61 1339 .no_alias = true,
07b0b134
ML
1340 .no_instances = true,
1341
4e85aff4 1342 .init = swap_init,
07b0b134 1343 .load = swap_load,
6e620bec 1344 .done = swap_done,
07b0b134
ML
1345
1346 .coldplug = swap_coldplug,
1347
1348 .dump = swap_dump,
1349
1350 .start = swap_start,
1351 .stop = swap_stop,
1352
8a0867d6
LP
1353 .kill = swap_kill,
1354
07b0b134
ML
1355 .serialize = swap_serialize,
1356 .deserialize_item = swap_deserialize_item,
1357
1358 .active_state = swap_active_state,
1359 .sub_state_to_string = swap_sub_state_to_string,
1360
1361 .check_gc = swap_check_gc,
1362
e04aad61
LP
1363 .sigchld_event = swap_sigchld_event,
1364 .timer_event = swap_timer_event,
1365
1366 .reset_failed = swap_reset_failed,
1367
c4e2ceae 1368 .bus_interface = "org.freedesktop.systemd1.Swap",
07b0b134 1369 .bus_message_handler = bus_swap_message_handler,
c4e2ceae 1370 .bus_invalidating_properties = bus_swap_invalidating_properties,
07b0b134 1371
e04aad61 1372 .following = swap_following,
6210e7fc 1373 .following_set = swap_following_set,
5632e374 1374
6e620bec 1375 .enumerate = swap_enumerate,
c6918296
MS
1376 .shutdown = swap_shutdown,
1377
1378 .status_message_formats = {
1379 .starting_stopping = {
1380 [0] = "Activating swap %s...",
1381 [1] = "Deactivating swap %s...",
1382 },
1383 .finished_start_job = {
1384 [JOB_DONE] = "Activated swap %s.",
1385 [JOB_FAILED] = "Failed to activate swap %s.",
1386 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1387 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1388 },
1389 .finished_stop_job = {
1390 [JOB_DONE] = "Deactivated swap %s.",
1391 [JOB_FAILED] = "Failed deactivating swap %s.",
1392 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
1393 },
1394 },
07b0b134 1395};