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