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