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