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