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