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