]> 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 fee9e7b0e6d7c1b257ebdf4ceb6339ffc1b8b851..cfe9d91cedb9d4e7725e6d0228491eb9ab2a0d23 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -29,7 +30,7 @@
 #include "escape.h"
 #include "exit-status.h"
 #include "fd-util.h"
-#include "formats-util.h"
+#include "format-util.h"
 #include "fstab-util.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -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;
 
@@ -381,11 +389,7 @@ static int swap_setup_unit(
         if (!u) {
                 delete = true;
 
-                u = unit_new(m, sizeof(Swap));
-                if (!u)
-                        return log_oom();
-
-                r = unit_add_name(u, e);
+                r = unit_new_for_name(m, sizeof(Swap), e, &u);
                 if (r < 0)
                         goto fail;
 
@@ -424,7 +428,7 @@ static int swap_setup_unit(
 fail:
         log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
 
-        if (delete && u)
+        if (delete)
                 unit_free(u);
 
         return r;
@@ -491,13 +495,7 @@ static void swap_set_state(Swap *s, SwapState state) {
         old_state = s->state;
         s->state = state;
 
-        if (state != SWAP_ACTIVATING &&
-            state != SWAP_ACTIVATING_SIGTERM &&
-            state != SWAP_ACTIVATING_SIGKILL &&
-            state != SWAP_ACTIVATING_DONE &&
-            state != SWAP_DEACTIVATING &&
-            state != SWAP_DEACTIVATING_SIGTERM &&
-            state != 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;
@@ -537,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)
@@ -605,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,
@@ -622,29 +614,28 @@ 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;
 
         r = unit_setup_dynamic_creds(UNIT(s));
         if (r < 0)
-                return r;
+                goto fail;
 
         r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
         if (r < 0)
                 goto fail;
 
-        exec_params.environment = UNIT(s)->manager->environment;
-        exec_params.flags |= UNIT(s)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0;
-        exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
-        exec_params.cgroup_path = UNIT(s)->cgroup_path;
-        exec_params.cgroup_delegate = s->cgroup_context.delegate;
-        exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
+        manager_set_exec_params(UNIT(s)->manager, &exec_params);
+        unit_set_exec_params(UNIT(s), &exec_params);
 
         r = exec_spawn(UNIT(s),
                        c,
@@ -667,6 +658,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
 
 fail:
         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+
         return r;
 }
 
@@ -676,12 +668,15 @@ 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);
         s->exec_runtime = exec_runtime_unref(s->exec_runtime);
 
-        exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+        exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
 
         unit_unref_uid_gid(UNIT(s), true);
 
@@ -697,22 +692,30 @@ 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;
 
         assert(s);
 
         if (s->result == SWAP_SUCCESS)
                 s->result = f;
 
-        r = unit_kill_context(
-                        UNIT(s),
-                        &s->kill_context,
-                        (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ?
-                        KILL_KILL : KILL_TERMINATE,
-                        -1,
-                        s->control_pid,
-                        false);
+        if (state == SWAP_DEACTIVATING_SIGTERM)
+                kop = KILL_TERMINATE;
+        else
+                kop = KILL_KILL;
+
+        r = unit_kill_context(UNIT(s), &s->kill_context, kop, -1, s->control_pid, false);
         if (r < 0)
                 goto fail;
 
@@ -722,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) {
@@ -791,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) {
@@ -821,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) {
@@ -830,20 +831,18 @@ static int swap_start(Unit *u) {
 
         assert(s);
 
-        /* We cannot fulfill this request right now, try again later
-         * please! */
-
-        if (s->state == SWAP_DEACTIVATING ||
-            s->state == SWAP_DEACTIVATING_SIGTERM ||
-            s->state == SWAP_DEACTIVATING_SIGKILL ||
-            s->state == SWAP_ACTIVATING_SIGTERM ||
-            s->state == SWAP_ACTIVATING_SIGKILL)
+        /* We cannot fulfill this request right now, try again later please! */
+        if (IN_SET(s->state,
+                   SWAP_DEACTIVATING,
+                   SWAP_DEACTIVATING_SIGTERM,
+                   SWAP_DEACTIVATING_SIGKILL))
                 return -EAGAIN;
 
+        /* Already on it! */
         if (s->state == SWAP_ACTIVATING)
                 return 0;
 
-        assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
+        assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
 
         if (detect_container() > 0)
                 return -EPERM;
@@ -861,8 +860,12 @@ static int swap_start(Unit *u) {
                 return r;
         }
 
+        r = unit_acquire_invocation_id(u);
+        if (r < 0)
+                return r;
+
         s->result = SWAP_SUCCESS;
-        s->reset_cpu_usage = true;
+        s->reset_accounting = true;
 
         swap_enter_activating(s);
         return 1;
@@ -873,22 +876,30 @@ static int swap_stop(Unit *u) {
 
         assert(s);
 
-        if (s->state == SWAP_DEACTIVATING ||
-            s->state == SWAP_DEACTIVATING_SIGTERM ||
-            s->state == SWAP_DEACTIVATING_SIGKILL ||
-            s->state == SWAP_ACTIVATING_SIGTERM ||
-            s->state == SWAP_ACTIVATING_SIGKILL)
+        switch (s->state) {
+
+        case SWAP_DEACTIVATING:
+        case SWAP_DEACTIVATING_SIGTERM:
+        case SWAP_DEACTIVATING_SIGKILL:
+                /* Already on it */
                 return 0;
 
-        assert(s->state == SWAP_ACTIVATING ||
-               s->state == SWAP_ACTIVATING_DONE ||
-               s->state == 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) {
@@ -1016,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);
@@ -1029,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:
@@ -1051,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:
@@ -1059,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:
@@ -1189,6 +1187,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
 
                         case SWAP_DEAD:
                         case SWAP_FAILED:
+                                (void) unit_acquire_invocation_id(UNIT(swap));
                                 swap_enter_active(swap, SWAP_SUCCESS);
                                 break;
 
@@ -1339,7 +1338,7 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
         struct udev_list_entry *item = NULL, *first = NULL;
         _cleanup_free_ char *e = NULL;
         const char *dn;
-        Swap *s;
+        Unit *u;
         int r = 0;
 
         assert(m);
@@ -1353,9 +1352,9 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
         if (r < 0)
                 return r;
 
-        s = hashmap_get(m->units, e);
-        if (s)
-                r = swap_set_devnode(s, dn);
+        u = manager_get_unit(m, e);
+        if (u)
+                r = swap_set_devnode(SWAP(u), dn);
 
         first = udev_device_get_devlinks_list_entry(dev);
         udev_list_entry_foreach(item, first) {
@@ -1366,9 +1365,9 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
                 if (q < 0)
                         return q;
 
-                s = hashmap_get(m->units, n);
-                if (s) {
-                        q = swap_set_devnode(s, dn);
+                u = manager_get_unit(m, n);
+                if (u) {
+                        q = swap_set_devnode(SWAP(u), dn);
                         if (q < 0)
                                 r = q;
                 }