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