1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
26 #include <sys/epoll.h>
33 #include "load-fragment.h"
34 #include "load-dropin.h"
35 #include "unit-name.h"
36 #include "dbus-swap.h"
38 #include "bus-errors.h"
39 #include "exit-status.h"
41 #include "path-util.h"
44 static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
45 [SWAP_DEAD] = UNIT_INACTIVE,
46 [SWAP_ACTIVATING] = UNIT_ACTIVATING,
47 [SWAP_ACTIVE] = UNIT_ACTIVE,
48 [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
49 [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
50 [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
51 [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
52 [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
53 [SWAP_FAILED] = UNIT_FAILED
56 static void swap_unset_proc_swaps(Swap *s) {
62 if (!s->parameters_proc_swaps.what)
65 /* Remove this unit from the chain of swaps which share the
66 * same kernel swap device. */
67 swaps = UNIT(s)->manager->swaps_by_proc_swaps;
68 first = hashmap_get(swaps, s->parameters_proc_swaps.what);
69 LIST_REMOVE(Swap, same_proc_swaps, first, s);
72 hashmap_remove_and_replace(swaps,
73 s->parameters_proc_swaps.what,
74 first->parameters_proc_swaps.what,
77 hashmap_remove(swaps, s->parameters_proc_swaps.what);
79 free(s->parameters_proc_swaps.what);
80 s->parameters_proc_swaps.what = NULL;
83 static void swap_init(Unit *u) {
87 assert(UNIT(s)->load_state == UNIT_STUB);
89 s->timeout_usec = DEFAULT_TIMEOUT_USEC;
91 exec_context_init(&s->exec_context);
92 s->exec_context.std_output = u->manager->default_std_output;
93 s->exec_context.std_error = u->manager->default_std_error;
94 kill_context_init(&s->kill_context);
96 s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
98 s->timer_watch.type = WATCH_INVALID;
100 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
102 UNIT(s)->ignore_on_isolate = true;
105 static void swap_unwatch_control_pid(Swap *s) {
108 if (s->control_pid <= 0)
111 unit_unwatch_pid(UNIT(s), s->control_pid);
115 static void swap_done(Unit *u) {
120 swap_unset_proc_swaps(s);
125 free(s->parameters_fragment.what);
126 s->parameters_fragment.what = NULL;
128 exec_context_done(&s->exec_context, manager_is_reloading_or_reexecuting(u->manager));
129 exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
130 s->control_command = NULL;
132 swap_unwatch_control_pid(s);
134 unit_unwatch_timer(u, &s->timer_watch);
137 int swap_add_one_mount_link(Swap *s, Mount *m) {
143 if (UNIT(s)->load_state != UNIT_LOADED ||
144 UNIT(m)->load_state != UNIT_LOADED)
147 if (is_device_path(s->what))
150 if (!path_startswith(s->what, m->where))
153 r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
160 static int swap_add_mount_links(Swap *s) {
166 LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT])
167 if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0)
173 static int swap_add_device_links(Swap *s) {
181 if (s->from_fragment)
182 p = &s->parameters_fragment;
186 if (is_device_path(s->what))
187 return unit_add_node_link(UNIT(s), s->what,
188 !p->noauto && p->nofail &&
189 UNIT(s)->manager->running_as == SYSTEMD_SYSTEM);
191 /* File based swap devices need to be ordered after
192 * systemd-remount-fs.service, since they might need a
193 * writable file system. */
194 return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true);
197 static int swap_add_default_dependencies(Swap *s) {
202 if (UNIT(s)->manager->running_as != SYSTEMD_SYSTEM)
205 if (detect_container(NULL) > 0)
208 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
215 static int swap_verify(Swap *s) {
217 _cleanup_free_ char *e = NULL;
219 if (UNIT(s)->load_state != UNIT_LOADED)
222 e = unit_name_from_path(s->what, ".swap");
226 b = unit_has_name(UNIT(s), e);
228 log_error_unit(UNIT(s)->id,
229 "%s: Value of \"What\" and unit name do not match, not loading.",
234 if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
235 log_error_unit(UNIT(s)->id,
236 "%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.",
244 static int swap_load(Unit *u) {
249 assert(u->load_state == UNIT_STUB);
251 /* Load a .swap file */
252 r = unit_load_fragment_and_dropin_optional(u);
256 if (u->load_state == UNIT_LOADED) {
257 r = unit_add_exec_dependencies(u, &s->exec_context);
261 if (UNIT(s)->fragment_path)
262 s->from_fragment = true;
265 if (s->parameters_fragment.what)
266 s->what = strdup(s->parameters_fragment.what);
267 else if (s->parameters_proc_swaps.what)
268 s->what = strdup(s->parameters_proc_swaps.what);
270 s->what = unit_name_to_path(u->id);
276 path_kill_slashes(s->what);
278 if (!UNIT(s)->description)
279 if ((r = unit_set_description(u, s->what)) < 0)
282 r = swap_add_device_links(s);
286 r = swap_add_mount_links(s);
290 r = unit_add_default_cgroups(u);
294 if (UNIT(s)->default_dependencies) {
295 r = swap_add_default_dependencies(s);
300 r = unit_exec_context_defaults(u, &s->exec_context);
305 return swap_verify(s);
308 static int swap_add_one(
311 const char *what_proc_swaps,
318 _cleanup_free_ char *e = NULL;
327 assert(what_proc_swaps);
329 e = unit_name_from_path(what, ".swap");
333 u = manager_get_unit(m, e);
336 SWAP(u)->from_proc_swaps &&
337 !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
343 u = unit_new(m, sizeof(Swap));
347 r = unit_add_name(u, e);
351 SWAP(u)->what = strdup(what);
352 if (!SWAP(u)->what) {
357 unit_add_to_load_queue(u);
361 p = &SWAP(u)->parameters_proc_swaps;
364 wp = strdup(what_proc_swaps);
370 if (!m->swaps_by_proc_swaps) {
371 m->swaps_by_proc_swaps = hashmap_new(string_hash_func, string_compare_func);
372 if (!m->swaps_by_proc_swaps) {
381 first = hashmap_get(m->swaps_by_proc_swaps, wp);
382 LIST_PREPEND(Swap, same_proc_swaps, first, SWAP(u));
384 r = hashmap_replace(m->swaps_by_proc_swaps, wp, first);
390 SWAP(u)->is_active = true;
391 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
394 SWAP(u)->from_proc_swaps = true;
396 p->priority = priority;
400 unit_add_to_dbus_queue(u);
405 log_warning_unit(e, "Failed to load swap unit: %s", strerror(-r));
415 static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
421 if (stat(device, &st) >= 0 && S_ISBLK(st.st_mode)) {
422 struct udev_device *d;
424 struct udev_list_entry *item = NULL, *first = NULL;
426 /* So this is a proper swap device. Create swap units
427 * for all names this swap device is known under */
429 d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
433 dn = udev_device_get_devnode(d);
434 /* Skip dn==device, since that case will be handled below */
435 if (dn && !streq(dn, device))
436 r = swap_add_one(m, dn, device, prio, false, false, set_flags);
438 /* Add additional units for all symlinks */
439 first = udev_device_get_devlinks_list_entry(d);
440 udev_list_entry_foreach(item, first) {
443 /* Don't bother with the /dev/block links */
444 p = udev_list_entry_get_name(item);
446 if (path_startswith(p, "/dev/block/"))
449 if (stat(p, &st) >= 0)
450 if ((!S_ISBLK(st.st_mode)) ||
451 st.st_rdev != udev_device_get_devnum(d))
454 k = swap_add_one(m, p, device, prio, false, false, set_flags);
459 udev_device_unref(d);
462 k = swap_add_one(m, device, device, prio, false, false, set_flags);
469 static void swap_set_state(Swap *s, SwapState state) {
474 old_state = s->state;
477 if (state != SWAP_ACTIVATING &&
478 state != SWAP_ACTIVATING_SIGTERM &&
479 state != SWAP_ACTIVATING_SIGKILL &&
480 state != SWAP_DEACTIVATING &&
481 state != SWAP_DEACTIVATING_SIGTERM &&
482 state != SWAP_DEACTIVATING_SIGKILL) {
483 unit_unwatch_timer(UNIT(s), &s->timer_watch);
484 swap_unwatch_control_pid(s);
485 s->control_command = NULL;
486 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
489 if (state != old_state)
490 log_debug_unit(UNIT(s)->id,
491 "%s changed %s -> %s",
493 swap_state_to_string(old_state),
494 swap_state_to_string(state));
496 unit_notify(UNIT(s), state_translation_table[old_state],
497 state_translation_table[state], true);
500 static int swap_coldplug(Unit *u) {
502 SwapState new_state = SWAP_DEAD;
506 assert(s->state == SWAP_DEAD);
508 if (s->deserialized_state != s->state)
509 new_state = s->deserialized_state;
510 else if (s->from_proc_swaps)
511 new_state = SWAP_ACTIVE;
513 if (new_state != s->state) {
515 if (new_state == SWAP_ACTIVATING ||
516 new_state == SWAP_ACTIVATING_SIGTERM ||
517 new_state == SWAP_ACTIVATING_SIGKILL ||
518 new_state == SWAP_DEACTIVATING ||
519 new_state == SWAP_DEACTIVATING_SIGTERM ||
520 new_state == SWAP_DEACTIVATING_SIGKILL) {
522 if (s->control_pid <= 0)
525 r = unit_watch_pid(UNIT(s), s->control_pid);
529 r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
534 swap_set_state(s, new_state);
540 static void swap_dump(Unit *u, FILE *f, const char *prefix) {
547 if (s->from_proc_swaps)
548 p = &s->parameters_proc_swaps;
549 else if (s->from_fragment)
550 p = &s->parameters_fragment;
558 "%sFrom /proc/swaps: %s\n"
559 "%sFrom fragment: %s\n",
560 prefix, swap_state_to_string(s->state),
561 prefix, swap_result_to_string(s->result),
563 prefix, yes_no(s->from_proc_swaps),
564 prefix, yes_no(s->from_fragment));
572 prefix, yes_no(p->noauto),
573 prefix, yes_no(p->nofail));
575 if (s->control_pid > 0)
577 "%sControl PID: %lu\n",
578 prefix, (unsigned long) s->control_pid);
580 exec_context_dump(&s->exec_context, f, prefix);
581 kill_context_dump(&s->kill_context, f, prefix);
584 static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
592 r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
600 UNIT(s)->manager->environment,
604 UNIT(s)->manager->confirm_spawn,
605 UNIT(s)->cgroup_bondings,
606 UNIT(s)->cgroup_attributes,
614 r = unit_watch_pid(UNIT(s), pid);
616 /* FIXME: we need to do something here */
624 unit_unwatch_timer(UNIT(s), &s->timer_watch);
629 static void swap_enter_dead(Swap *s, SwapResult f) {
632 if (f != SWAP_SUCCESS)
635 exec_context_tmp_dirs_done(&s->exec_context);
636 swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
639 static void swap_enter_active(Swap *s, SwapResult f) {
642 if (f != SWAP_SUCCESS)
645 swap_set_state(s, SWAP_ACTIVE);
648 static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
653 if (f != SWAP_SUCCESS)
656 r = unit_kill_context(
659 state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM,
667 r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
671 swap_set_state(s, state);
673 swap_enter_dead(s, SWAP_SUCCESS);
678 log_warning_unit(UNIT(s)->id,
679 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
681 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
684 static void swap_enter_activating(Swap *s) {
689 s->control_command_id = SWAP_EXEC_ACTIVATE;
690 s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
692 if (s->from_fragment)
693 priority = s->parameters_fragment.priority;
700 snprintf(p, sizeof(p), "%i", priority);
703 r = exec_command_set(
711 r = exec_command_set(
720 swap_unwatch_control_pid(s);
722 r = swap_spawn(s, s->control_command, &s->control_pid);
726 swap_set_state(s, SWAP_ACTIVATING);
731 log_warning_unit(UNIT(s)->id,
732 "%s failed to run 'swapon' task: %s",
733 UNIT(s)->id, strerror(-r));
734 swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
737 static void swap_enter_deactivating(Swap *s) {
742 s->control_command_id = SWAP_EXEC_DEACTIVATE;
743 s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
745 r = exec_command_set(s->control_command,
752 swap_unwatch_control_pid(s);
754 r = swap_spawn(s, s->control_command, &s->control_pid);
758 swap_set_state(s, SWAP_DEACTIVATING);
763 log_warning_unit(UNIT(s)->id,
764 "%s failed to run 'swapoff' task: %s",
765 UNIT(s)->id, strerror(-r));
766 swap_enter_active(s, SWAP_FAILURE_RESOURCES);
769 static int swap_start(Unit *u) {
774 /* We cannot fulfill this request right now, try again later
777 if (s->state == SWAP_DEACTIVATING ||
778 s->state == SWAP_DEACTIVATING_SIGTERM ||
779 s->state == SWAP_DEACTIVATING_SIGKILL ||
780 s->state == SWAP_ACTIVATING_SIGTERM ||
781 s->state == SWAP_ACTIVATING_SIGKILL)
784 if (s->state == SWAP_ACTIVATING)
787 assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
789 if (detect_container(NULL) > 0)
792 s->result = SWAP_SUCCESS;
793 swap_enter_activating(s);
797 static int swap_stop(Unit *u) {
802 if (s->state == SWAP_DEACTIVATING ||
803 s->state == SWAP_DEACTIVATING_SIGTERM ||
804 s->state == SWAP_DEACTIVATING_SIGKILL ||
805 s->state == SWAP_ACTIVATING_SIGTERM ||
806 s->state == SWAP_ACTIVATING_SIGKILL)
809 assert(s->state == SWAP_ACTIVATING ||
810 s->state == SWAP_ACTIVE);
812 if (detect_container(NULL) > 0)
815 swap_enter_deactivating(s);
819 static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
826 unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
827 unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
829 if (s->control_pid > 0)
830 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
832 if (s->control_command_id >= 0)
833 unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
835 exec_context_serialize(&s->exec_context, UNIT(s), f);
840 static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
846 if (streq(key, "state")) {
849 state = swap_state_from_string(value);
851 log_debug_unit(u->id, "Failed to parse state value %s", value);
853 s->deserialized_state = state;
854 } else if (streq(key, "result")) {
857 f = swap_result_from_string(value);
859 log_debug_unit(u->id, "Failed to parse result value %s", value);
860 else if (f != SWAP_SUCCESS)
862 } else if (streq(key, "control-pid")) {
865 if (parse_pid(value, &pid) < 0)
866 log_debug_unit(u->id, "Failed to parse control-pid value %s", value);
868 s->control_pid = pid;
870 } else if (streq(key, "control-command")) {
873 id = swap_exec_command_from_string(value);
875 log_debug_unit(u->id, "Failed to parse exec-command value %s", value);
877 s->control_command_id = id;
878 s->control_command = s->exec_command + id;
880 } else if (streq(key, "tmp-dir")) {
887 s->exec_context.tmp_dir = t;
888 } else if (streq(key, "var-tmp-dir")) {
895 s->exec_context.var_tmp_dir = t;
897 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
902 static UnitActiveState swap_active_state(Unit *u) {
905 return state_translation_table[SWAP(u)->state];
908 static const char *swap_sub_state_to_string(Unit *u) {
911 return swap_state_to_string(SWAP(u)->state);
914 static bool swap_check_gc(Unit *u) {
919 return s->from_proc_swaps;
922 static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
929 if (pid != s->control_pid)
934 if (is_clean_exit(code, status, NULL))
936 else if (code == CLD_EXITED)
937 f = SWAP_FAILURE_EXIT_CODE;
938 else if (code == CLD_KILLED)
939 f = SWAP_FAILURE_SIGNAL;
940 else if (code == CLD_DUMPED)
941 f = SWAP_FAILURE_CORE_DUMP;
943 assert_not_reached("Unknown code");
945 if (f != SWAP_SUCCESS)
948 if (s->control_command) {
949 exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
951 s->control_command = NULL;
952 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
955 log_full_unit(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
957 "%s swap process exited, code=%s status=%i",
958 u->id, sigchld_code_to_string(code), status);
962 case SWAP_ACTIVATING:
963 case SWAP_ACTIVATING_SIGTERM:
964 case SWAP_ACTIVATING_SIGKILL:
966 if (f == SWAP_SUCCESS)
967 swap_enter_active(s, f);
969 swap_enter_dead(s, f);
972 case SWAP_DEACTIVATING:
973 case SWAP_DEACTIVATING_SIGKILL:
974 case SWAP_DEACTIVATING_SIGTERM:
976 if (f == SWAP_SUCCESS)
977 swap_enter_dead(s, f);
979 swap_enter_dead(s, f);
983 assert_not_reached("Uh, control process died at wrong time.");
986 /* Notify clients about changed exit status */
987 unit_add_to_dbus_queue(u);
989 /* Request a reload of /proc/swaps, so that following units
990 * can follow our state change */
991 u->manager->request_reload = true;
994 static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
998 assert(elapsed == 1);
999 assert(w == &s->timer_watch);
1003 case SWAP_ACTIVATING:
1004 log_warning_unit(u->id, "%s activation timed out. Stopping.", u->id);
1005 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
1008 case SWAP_DEACTIVATING:
1009 log_warning_unit(u->id, "%s deactivation timed out. Stopping.", u->id);
1010 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
1013 case SWAP_ACTIVATING_SIGTERM:
1014 if (s->kill_context.send_sigkill) {
1015 log_warning_unit(u->id, "%s activation timed out. Killing.", u->id);
1016 swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
1018 log_warning_unit(u->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
1019 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
1023 case SWAP_DEACTIVATING_SIGTERM:
1024 if (s->kill_context.send_sigkill) {
1025 log_warning_unit(u->id, "%s deactivation timed out. Killing.", u->id);
1026 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
1028 log_warning_unit(u->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
1029 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
1033 case SWAP_ACTIVATING_SIGKILL:
1034 case SWAP_DEACTIVATING_SIGKILL:
1035 log_warning_unit(u->id, "%s swap process still around after SIGKILL. Ignoring.", u->id);
1036 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
1040 assert_not_reached("Timeout at wrong time.");
1044 static int swap_load_proc_swaps(Manager *m, bool set_flags) {
1050 rewind(m->proc_swaps);
1052 (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
1055 char *dev = NULL, *d;
1058 k = fscanf(m->proc_swaps,
1059 "%ms " /* device/file */
1060 "%*s " /* type of swap */
1061 "%*s " /* swap size */
1063 "%i\n", /* priority */
1069 log_warning("Failed to parse /proc/swaps:%u", i);
1080 k = swap_process_new_swap(m, d, prio, set_flags);
1090 int swap_dispatch_reload(Manager *m) {
1091 /* This function should go as soon as the kernel properly notifies us */
1093 if (_likely_(!m->request_reload))
1096 m->request_reload = false;
1098 return swap_fd_event(m, EPOLLPRI);
1101 int swap_fd_event(Manager *m, int events) {
1106 assert(events & EPOLLPRI);
1108 r = swap_load_proc_swaps(m, true);
1110 log_error("Failed to reread /proc/swaps: %s", strerror(-r));
1112 /* Reset flags, just in case, for late calls */
1113 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1114 Swap *swap = SWAP(u);
1116 swap->is_active = swap->just_activated = false;
1122 manager_dispatch_load_queue(m);
1124 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
1125 Swap *swap = SWAP(u);
1127 if (!swap->is_active) {
1128 /* This has just been deactivated */
1130 swap->from_proc_swaps = false;
1131 swap_unset_proc_swaps(swap);
1133 switch (swap->state) {
1136 swap_enter_dead(swap, SWAP_SUCCESS);
1140 swap_set_state(swap, swap->state);
1144 } else if (swap->just_activated) {
1146 /* New swap entry */
1148 switch (swap->state) {
1152 swap_enter_active(swap, SWAP_SUCCESS);
1156 /* Nothing really changed, but let's
1157 * issue an notification call
1158 * nonetheless, in case somebody is
1159 * waiting for this. */
1160 swap_set_state(swap, swap->state);
1165 /* Reset the flags for later calls */
1166 swap->is_active = swap->just_activated = false;
1172 static Unit *swap_following(Unit *u) {
1174 Swap *other, *first = NULL;
1178 if (streq_ptr(s->what, s->parameters_proc_swaps.what))
1181 /* Make everybody follow the unit that's named after the swap
1182 * device in the kernel */
1184 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1185 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1188 LIST_FOREACH_BEFORE(same_proc_swaps, other, s) {
1189 if (streq_ptr(other->what, other->parameters_proc_swaps.what))
1198 static int swap_following_set(Unit *u, Set **_set) {
1207 if (LIST_JUST_US(same_proc_swaps, s)) {
1212 if (!(set = set_new(NULL, NULL)))
1215 LIST_FOREACH_AFTER(same_proc_swaps, other, s)
1216 if ((r = set_put(set, other)) < 0)
1219 LIST_FOREACH_BEFORE(same_proc_swaps, other, s)
1220 if ((r = set_put(set, other)) < 0)
1231 static void swap_shutdown(Manager *m) {
1234 if (m->proc_swaps) {
1235 fclose(m->proc_swaps);
1236 m->proc_swaps = NULL;
1239 hashmap_free(m->swaps_by_proc_swaps);
1240 m->swaps_by_proc_swaps = NULL;
1243 static int swap_enumerate(Manager *m) {
1247 if (!m->proc_swaps) {
1248 struct epoll_event ev = {
1250 .data.ptr = &m->swap_watch,
1253 m->proc_swaps = fopen("/proc/swaps", "re");
1255 return (errno == ENOENT) ? 0 : -errno;
1257 m->swap_watch.type = WATCH_SWAP;
1258 m->swap_watch.fd = fileno(m->proc_swaps);
1260 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
1264 r = swap_load_proc_swaps(m, false);
1271 static void swap_reset_failed(Unit *u) {
1276 if (s->state == SWAP_FAILED)
1277 swap_set_state(s, SWAP_DEAD);
1279 s->result = SWAP_SUCCESS;
1282 static int swap_kill(Unit *u, KillWho who, int signo, DBusError *error) {
1283 return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
1286 static const char* const swap_state_table[_SWAP_STATE_MAX] = {
1287 [SWAP_DEAD] = "dead",
1288 [SWAP_ACTIVATING] = "activating",
1289 [SWAP_ACTIVE] = "active",
1290 [SWAP_DEACTIVATING] = "deactivating",
1291 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
1292 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
1293 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
1294 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
1295 [SWAP_FAILED] = "failed"
1298 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
1300 static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
1301 [SWAP_EXEC_ACTIVATE] = "ExecActivate",
1302 [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
1305 DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
1307 static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
1308 [SWAP_SUCCESS] = "success",
1309 [SWAP_FAILURE_RESOURCES] = "resources",
1310 [SWAP_FAILURE_TIMEOUT] = "timeout",
1311 [SWAP_FAILURE_EXIT_CODE] = "exit-code",
1312 [SWAP_FAILURE_SIGNAL] = "signal",
1313 [SWAP_FAILURE_CORE_DUMP] = "core-dump"
1316 DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
1318 const UnitVTable swap_vtable = {
1319 .object_size = sizeof(Swap),
1326 .exec_context_offset = offsetof(Swap, exec_context),
1327 .exec_section = "Swap",
1330 .no_instances = true,
1336 .coldplug = swap_coldplug,
1340 .start = swap_start,
1345 .serialize = swap_serialize,
1346 .deserialize_item = swap_deserialize_item,
1348 .active_state = swap_active_state,
1349 .sub_state_to_string = swap_sub_state_to_string,
1351 .check_gc = swap_check_gc,
1353 .sigchld_event = swap_sigchld_event,
1354 .timer_event = swap_timer_event,
1356 .reset_failed = swap_reset_failed,
1358 .bus_interface = "org.freedesktop.systemd1.Swap",
1359 .bus_message_handler = bus_swap_message_handler,
1360 .bus_invalidating_properties = bus_swap_invalidating_properties,
1362 .following = swap_following,
1363 .following_set = swap_following_set,
1365 .enumerate = swap_enumerate,
1366 .shutdown = swap_shutdown,
1368 .status_message_formats = {
1369 .starting_stopping = {
1370 [0] = "Activating swap %s...",
1371 [1] = "Deactivating swap %s...",
1373 .finished_start_job = {
1374 [JOB_DONE] = "Activated swap %s.",
1375 [JOB_FAILED] = "Failed to activate swap %s.",
1376 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1377 [JOB_TIMEOUT] = "Timed out activating swap %s.",
1379 .finished_stop_job = {
1380 [JOB_DONE] = "Deactivated swap %s.",
1381 [JOB_FAILED] = "Failed deactivating swap %s.",
1382 [JOB_TIMEOUT] = "Timed out deactivating swap %s.",