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