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