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