]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/swap.c
Merge pull request #9624 from poettering/service-state-flush
[thirdparty/systemd.git] / src / core / swap.c
index fffd8d4627b1bb372c18bf184c0f1f6fc1f96d08..000c028e77361ac8b7241f3f2df70c734b36cf54 100644 (file)
@@ -1,22 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
 
 #include <errno.h>
 #include <sys/epoll.h>
@@ -27,6 +9,7 @@
 
 #include "alloc-util.h"
 #include "dbus-swap.h"
+#include "device.h"
 #include "escape.h"
 #include "exit-status.h"
 #include "fd-util.h"
@@ -85,7 +68,7 @@ static int swap_set_devnode(Swap *s, const char *devnode) {
 
         assert(s);
 
-        r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &string_hash_ops);
+        r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &path_hash_ops);
         if (r < 0)
                 return r;
 
@@ -252,30 +235,34 @@ static int swap_verify(Swap *s) {
 
         if (!unit_has_name(UNIT(s), e)) {
                 log_unit_error(UNIT(s), "Value of What= and unit name do not match, not loading.");
-                return -EINVAL;
+                return -ENOEXEC;
         }
 
         if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
                 log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.");
-                return -EINVAL;
+                return -ENOEXEC;
         }
 
         return 0;
 }
 
 static int swap_load_devnode(Swap *s) {
-        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
         struct stat st;
         const char *p;
+        int r;
 
         assert(s);
 
         if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
                 return 0;
 
-        d = udev_device_new_from_devnum(UNIT(s)->manager->udev, 'b', st.st_rdev);
-        if (!d)
+        r = udev_device_new_from_stat_rdev(UNIT(s)->manager->udev, &st, &d);
+        if (r < 0) {
+                log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                              "Failed to allocate udev device for swap %s: %m", s->what);
                 return 0;
+        }
 
         p = udev_device_get_devnode(d);
         if (!p)
@@ -319,7 +306,7 @@ static int swap_load(Unit *u) {
                                 return -ENOMEM;
                 }
 
-                path_kill_slashes(s->what);
+                path_simplify(s->what, false);
 
                 if (!UNIT(s)->description) {
                         r = unit_set_description(u, s->what);
@@ -438,7 +425,7 @@ fail:
 }
 
 static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
-        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
         struct udev_list_entry *item = NULL, *first = NULL;
         const char *dn;
         struct stat st;
@@ -455,9 +442,12 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
         if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
                 return 0;
 
-        d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
-        if (!d)
+        r = udev_device_new_from_stat_rdev(m->udev, &st, &d);
+        if (r < 0) {
+                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                               "Failed to allocate udev device for swap %s: %m", device);
                 return 0;
+        }
 
         /* Add the main device node */
         dn = udev_device_get_devnode(d);
@@ -508,7 +498,7 @@ static void swap_set_state(Swap *s, SwapState state) {
         if (state != old_state)
                 log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
 
-        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
+        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
 
         /* If there other units for the same device node have a job
            queued it might be worth checking again if it is runnable
@@ -616,6 +606,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
                 .stdin_fd  = -1,
                 .stdout_fd = -1,
                 .stderr_fd = -1,
+                .exec_fd   = -1,
         };
         pid_t pid;
         int r;
@@ -632,7 +623,6 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        manager_set_exec_params(UNIT(s)->manager, &exec_params);
         unit_set_exec_params(UNIT(s), &exec_params);
 
         r = exec_spawn(UNIT(s),
@@ -864,6 +854,7 @@ static int swap_start(Unit *u) {
                 return r;
 
         s->result = SWAP_SUCCESS;
+        exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
 
         u->reset_accounting = true;
 
@@ -979,12 +970,15 @@ _pure_ static const char *swap_sub_state_to_string(Unit *u) {
         return swap_state_to_string(SWAP(u)->state);
 }
 
-_pure_ static bool swap_check_gc(Unit *u) {
+_pure_ static bool swap_may_gc(Unit *u) {
         Swap *s = SWAP(u);
 
         assert(s);
 
-        return s->from_proc_swaps;
+        if (s->from_proc_swaps)
+                return false;
+
+        return true;
 }
 
 static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -1122,7 +1116,7 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
                 if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
                         return log_oom();
 
-                device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
+                device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
 
                 k = swap_process_new(m, d, prio, set_flags);
                 if (k < 0)
@@ -1177,7 +1171,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
                         }
 
                         if (swap->what)
-                                device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
+                                device_found_node(m, swap->what, 0, DEVICE_FOUND_SWAP);
 
                 } else if (swap->just_activated) {
 
@@ -1251,7 +1245,7 @@ static Unit *swap_following(Unit *u) {
 
 static int swap_following_set(Unit *u, Set **_set) {
         Swap *s = SWAP(u), *other;
-        Set *set;
+        _cleanup_set_free_ Set *set = NULL;
         int r;
 
         assert(s);
@@ -1269,24 +1263,18 @@ static int swap_following_set(Unit *u, Set **_set) {
         LIST_FOREACH_OTHERS(same_devnode, other, s) {
                 r = set_put(set, other);
                 if (r < 0)
-                        goto fail;
+                        return r;
         }
 
-        *_set = set;
+        *_set = TAKE_PTR(set);
         return 1;
-
-fail:
-        set_free(set);
-        return r;
 }
 
 static void swap_shutdown(Manager *m) {
         assert(m);
 
         m->swap_event_source = sd_event_source_unref(m->swap_event_source);
-
         m->proc_swaps = safe_fclose(m->proc_swaps);
-
         m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
 }
 
@@ -1299,9 +1287,9 @@ static void swap_enumerate(Manager *m) {
                 m->proc_swaps = fopen("/proc/swaps", "re");
                 if (!m->proc_swaps) {
                         if (errno == ENOENT)
-                                log_debug("Not swap enabled, skipping enumeration");
+                                log_debug_errno(errno, "Not swap enabled, skipping enumeration.");
                         else
-                                log_error_errno(errno, "Failed to open /proc/swaps: %m");
+                                log_warning_errno(errno, "Failed to open /proc/swaps, ignoring: %m");
 
                         return;
                 }
@@ -1506,7 +1494,7 @@ const UnitVTable swap_vtable = {
         .active_state = swap_active_state,
         .sub_state_to_string = swap_sub_state_to_string,
 
-        .check_gc = swap_check_gc,
+        .may_gc = swap_may_gc,
 
         .sigchld_event = swap_sigchld_event,