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