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