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