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