]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/swap.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / swap.c
index e839c26141158baa25075479428019ae2da5108f..cfe9d91cedb9d4e7725e6d0228491eb9ab2a0d23 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -49,8 +50,6 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
         [SWAP_ACTIVE] = UNIT_ACTIVE,
         [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
-        [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
-        [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
         [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
         [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
         [SWAP_FAILED] = UNIT_FAILED
@@ -59,6 +58,15 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
 static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 
+static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
+        return IN_SET(state,
+                      SWAP_ACTIVATING,
+                      SWAP_ACTIVATING_DONE,
+                      SWAP_DEACTIVATING,
+                      SWAP_DEACTIVATING_SIGTERM,
+                      SWAP_DEACTIVATING_SIGKILL);
+}
+
 static void swap_unset_proc_swaps(Swap *s) {
         assert(s);
 
@@ -190,7 +198,7 @@ static int swap_arm_timer(Swap *s, usec_t usec) {
         return 0;
 }
 
-static int swap_add_device_links(Swap *s) {
+static int swap_add_device_dependencies(Swap *s) {
         assert(s);
 
         if (!s->what)
@@ -200,12 +208,12 @@ static int swap_add_device_links(Swap *s) {
                 return 0;
 
         if (is_device_path(s->what))
-                return unit_add_node_link(UNIT(s), s->what, MANAGER_IS_SYSTEM(UNIT(s)->manager), UNIT_BINDS_TO);
+                return unit_add_node_dependency(UNIT(s), s->what, MANAGER_IS_SYSTEM(UNIT(s)->manager), UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE);
         else
                 /* File based swap devices need to be ordered after
                  * systemd-remount-fs.service, since they might need a
                  * writable file system. */
-                return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true);
+                return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true, UNIT_DEPENDENCY_FILE);
 }
 
 static int swap_add_default_dependencies(Swap *s) {
@@ -224,11 +232,11 @@ static int swap_add_default_dependencies(Swap *s) {
 
         /* swap units generated for the swap dev links are missing the
          * ordering dep against the swap target. */
-        r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, true);
+        r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
         if (r < 0)
                 return r;
 
-        return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
+        return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
 }
 
 static int swap_verify(Swap *s) {
@@ -316,11 +324,11 @@ static int swap_load(Unit *u) {
                                 return r;
                 }
 
-                r = unit_require_mounts_for(UNIT(s), s->what);
+                r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
                 if (r < 0)
                         return r;
 
-                r = swap_add_device_links(s);
+                r = swap_add_device_dependencies(s);
                 if (r < 0)
                         return r;
 
@@ -487,14 +495,7 @@ static void swap_set_state(Swap *s, SwapState state) {
         old_state = s->state;
         s->state = state;
 
-        if (!IN_SET(state,
-                    SWAP_ACTIVATING,
-                    SWAP_ACTIVATING_SIGTERM,
-                    SWAP_ACTIVATING_SIGKILL,
-                    SWAP_ACTIVATING_DONE,
-                    SWAP_DEACTIVATING,
-                    SWAP_DEACTIVATING_SIGTERM,
-                    SWAP_DEACTIVATING_SIGKILL)) {
+        if (!SWAP_STATE_WITH_PROCESS(state)) {
                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 swap_unwatch_control_pid(s);
                 s->control_command = NULL;
@@ -534,14 +535,7 @@ static int swap_coldplug(Unit *u) {
 
         if (s->control_pid > 0 &&
             pid_is_unwaited(s->control_pid) &&
-            IN_SET(new_state,
-                   SWAP_ACTIVATING,
-                   SWAP_ACTIVATING_SIGTERM,
-                   SWAP_ACTIVATING_SIGKILL,
-                   SWAP_ACTIVATING_DONE,
-                   SWAP_DEACTIVATING,
-                   SWAP_DEACTIVATING_SIGTERM,
-                   SWAP_DEACTIVATING_SIGKILL)) {
+            SWAP_STATE_WITH_PROCESS(new_state)) {
 
                 r = unit_watch_pid(UNIT(s), s->control_pid);
                 if (r < 0)
@@ -602,13 +596,14 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
 
         exec_context_dump(&s->exec_context, f, prefix);
         kill_context_dump(&s->kill_context, f, prefix);
+        cgroup_context_dump(&s->cgroup_context, f, prefix);
 }
 
 static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         pid_t pid;
         int r;
         ExecParameters exec_params = {
-                .flags     = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
+                .flags     = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
                 .stdin_fd  = -1,
                 .stdout_fd = -1,
                 .stderr_fd = -1,
@@ -619,11 +614,14 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         assert(_pid);
 
         (void) unit_realize_cgroup(UNIT(s));
-        if (s->reset_cpu_usage) {
-                (void) unit_reset_cpu_usage(UNIT(s));
-                s->reset_cpu_usage = false;
+        if (s->reset_accounting) {
+                (void) unit_reset_cpu_accounting(UNIT(s));
+                (void) unit_reset_ip_accounting(UNIT(s));
+                s->reset_accounting = false;
         }
 
+        unit_export_state_files(UNIT(s));
+
         r = unit_setup_exec_runtime(UNIT(s));
         if (r < 0)
                 goto fail;
@@ -636,12 +634,8 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        r = manager_set_exec_params(UNIT(s)->manager, &exec_params);
-        if (r < 0)
-                goto fail;
-
-        exec_params.cgroup_path = UNIT(s)->cgroup_path;
-        exec_params.cgroup_delegate = s->cgroup_context.delegate;
+        manager_set_exec_params(UNIT(s)->manager, &exec_params);
+        unit_set_exec_params(UNIT(s), &exec_params);
 
         r = exec_spawn(UNIT(s),
                        c,
@@ -674,6 +668,9 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
         if (s->result == SWAP_SUCCESS)
                 s->result = f;
 
+        if (s->result != SWAP_SUCCESS)
+                log_unit_warning(UNIT(s), "Failed with result '%s'.", swap_result_to_string(s->result));
+
         swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
 
         exec_runtime_destroy(s->exec_runtime);
@@ -695,6 +692,15 @@ static void swap_enter_active(Swap *s, SwapResult f) {
         swap_set_state(s, SWAP_ACTIVE);
 }
 
+static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
+        assert(s);
+
+        if (s->from_proc_swaps)
+                swap_enter_active(s, f);
+        else
+                swap_enter_dead(s, f);
+}
+
 static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
         int r;
         KillOperation kop;
@@ -704,7 +710,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
         if (s->result == SWAP_SUCCESS)
                 s->result = f;
 
-        if (IN_SET(state, SWAP_ACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGTERM))
+        if (state == SWAP_DEACTIVATING_SIGTERM)
                 kop = KILL_TERMINATE;
         else
                 kop = KILL_KILL;
@@ -719,18 +725,16 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
                         goto fail;
 
                 swap_set_state(s, state);
-        } else if (state == SWAP_ACTIVATING_SIGTERM)
-                swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS);
-        else if (state == SWAP_DEACTIVATING_SIGTERM)
+        } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
                 swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
         else
-                swap_enter_dead(s, SWAP_SUCCESS);
+                swap_enter_dead_or_active(s, SWAP_SUCCESS);
 
         return;
 
 fail:
         log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
-        swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
+        swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
 }
 
 static void swap_enter_activating(Swap *s) {
@@ -788,7 +792,7 @@ static void swap_enter_activating(Swap *s) {
 
 fail:
         log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
-        swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
+        swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
 }
 
 static void swap_enter_deactivating(Swap *s) {
@@ -818,7 +822,7 @@ static void swap_enter_deactivating(Swap *s) {
 
 fail:
         log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
-        swap_enter_active(s, SWAP_FAILURE_RESOURCES);
+        swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
 }
 
 static int swap_start(Unit *u) {
@@ -827,17 +831,14 @@ static int swap_start(Unit *u) {
 
         assert(s);
 
-        /* We cannot fulfill this request right now, try again later
-         * please! */
-
+        /* We cannot fulfill this request right now, try again later please! */
         if (IN_SET(s->state,
                    SWAP_DEACTIVATING,
                    SWAP_DEACTIVATING_SIGTERM,
-                   SWAP_DEACTIVATING_SIGKILL,
-                   SWAP_ACTIVATING_SIGTERM,
-                   SWAP_ACTIVATING_SIGKILL))
+                   SWAP_DEACTIVATING_SIGKILL))
                 return -EAGAIN;
 
+        /* Already on it! */
         if (s->state == SWAP_ACTIVATING)
                 return 0;
 
@@ -864,7 +865,7 @@ static int swap_start(Unit *u) {
                 return r;
 
         s->result = SWAP_SUCCESS;
-        s->reset_cpu_usage = true;
+        s->reset_accounting = true;
 
         swap_enter_activating(s);
         return 1;
@@ -875,21 +876,30 @@ static int swap_stop(Unit *u) {
 
         assert(s);
 
-        if (IN_SET(s->state,
-                   SWAP_DEACTIVATING,
-                   SWAP_DEACTIVATING_SIGTERM,
-                   SWAP_DEACTIVATING_SIGKILL,
-                   SWAP_ACTIVATING_SIGTERM,
-                   SWAP_ACTIVATING_SIGKILL))
+        switch (s->state) {
+
+        case SWAP_DEACTIVATING:
+        case SWAP_DEACTIVATING_SIGTERM:
+        case SWAP_DEACTIVATING_SIGKILL:
+                /* Already on it */
                 return 0;
 
-        assert(IN_SET(s->state, SWAP_ACTIVATING, SWAP_ACTIVATING_DONE, SWAP_ACTIVE));
+        case SWAP_ACTIVATING:
+        case SWAP_ACTIVATING_DONE:
+                /* There's a control process pending, directly enter kill mode */
+                swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
+                return 0;
 
-        if (detect_container() > 0)
-                return -EPERM;
+        case SWAP_ACTIVE:
+                if (detect_container() > 0)
+                        return -EPERM;
 
-        swap_enter_deactivating(s);
-        return 1;
+                swap_enter_deactivating(s);
+                return 1;
+
+        default:
+                assert_not_reached("Unexpected state.");
+        }
 }
 
 static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
@@ -1017,10 +1027,8 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
         case SWAP_ACTIVATING:
         case SWAP_ACTIVATING_DONE:
-        case SWAP_ACTIVATING_SIGTERM:
-        case SWAP_ACTIVATING_SIGKILL:
 
-                if (f == SWAP_SUCCESS)
+                if (f == SWAP_SUCCESS || s->from_proc_swaps)
                         swap_enter_active(s, f);
                 else
                         swap_enter_dead(s, f);
@@ -1030,7 +1038,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         case SWAP_DEACTIVATING_SIGKILL:
         case SWAP_DEACTIVATING_SIGTERM:
 
-                swap_enter_dead(s, f);
+                swap_enter_dead_or_active(s, f);
                 break;
 
         default:
@@ -1052,7 +1060,7 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
         case SWAP_ACTIVATING:
         case SWAP_ACTIVATING_DONE:
                 log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
-                swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
+                swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
         case SWAP_DEACTIVATING:
@@ -1060,30 +1068,19 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
                 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
-        case SWAP_ACTIVATING_SIGTERM:
-                if (s->kill_context.send_sigkill) {
-                        log_unit_warning(UNIT(s), "Activation timed out. Killing.");
-                        swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
-                } else {
-                        log_unit_warning(UNIT(s), "Activation timed out. Skipping SIGKILL. Ignoring.");
-                        swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
-                }
-                break;
-
         case SWAP_DEACTIVATING_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_unit_warning(UNIT(s), "Deactivation timed out. Killing.");
+                        log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
                         swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
                 } else {
-                        log_unit_warning(UNIT(s), "Deactivation timed out. Skipping SIGKILL. Ignoring.");
-                        swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
+                        log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
+                        swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
                 }
                 break;
 
-        case SWAP_ACTIVATING_SIGKILL:
         case SWAP_DEACTIVATING_SIGKILL:
                 log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
-                swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
+                swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
                 break;
 
         default: