summaryrefslogtreecommitdiff
path: root/src/core/swap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/swap.c')
-rw-r--r--src/core/swap.c269
1 files changed, 147 insertions, 122 deletions
diff --git a/src/core/swap.c b/src/core/swap.c
index b78b1aa266..2d8463b8b1 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -5,10 +5,13 @@
#include <sys/stat.h>
#include <unistd.h>
-#include "libudev.h"
+#include "sd-device.h"
#include "alloc-util.h"
#include "dbus-swap.h"
+#include "dbus-unit.h"
+#include "device-private.h"
+#include "device-util.h"
#include "device.h"
#include "escape.h"
#include "exit-status.h"
@@ -18,11 +21,11 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "serialize.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
#include "swap.h"
-#include "udev-util.h"
#include "unit-name.h"
#include "unit.h"
#include "virt.h"
@@ -196,7 +199,7 @@ static int swap_add_device_dependencies(Swap *s) {
/* 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, UNIT_DEPENDENCY_FILE);
+ return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, UNIT_DEPENDENCY_FILE);
}
static int swap_add_default_dependencies(Swap *s) {
@@ -215,11 +218,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, UNIT_DEPENDENCY_DEFAULT);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, 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, UNIT_DEPENDENCY_DEFAULT);
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static int swap_verify(Swap *s) {
@@ -247,7 +250,7 @@ static int swap_verify(Swap *s) {
}
static int swap_load_devnode(Swap *s) {
- _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *d = NULL;
struct stat st;
const char *p;
int r;
@@ -257,91 +260,105 @@ static int swap_load_devnode(Swap *s) {
if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
return 0;
- r = udev_device_new_from_stat_rdev(UNIT(s)->manager->udev, &st, &d);
+ r = device_new_from_stat_rdev(&d, &st);
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);
+ "Failed to allocate device for swap %s: %m", s->what);
return 0;
}
- p = udev_device_get_devnode(d);
- if (!p)
+ if (sd_device_get_devname(d, &p) < 0)
return 0;
return swap_set_devnode(s, p);
}
-static int swap_load(Unit *u) {
+static int swap_add_extras(Swap *s) {
int r;
- Swap *s = SWAP(u);
assert(s);
- assert(u->load_state == UNIT_STUB);
- /* Load a .swap file */
- if (SWAP(u)->from_proc_swaps)
- r = unit_load_fragment_and_dropin_optional(u);
- else
- r = unit_load_fragment_and_dropin(u);
+ if (UNIT(s)->fragment_path)
+ s->from_fragment = true;
+
+ if (!s->what) {
+ if (s->parameters_fragment.what)
+ s->what = strdup(s->parameters_fragment.what);
+ else if (s->parameters_proc_swaps.what)
+ s->what = strdup(s->parameters_proc_swaps.what);
+ else {
+ r = unit_name_to_path(UNIT(s)->id, &s->what);
+ if (r < 0)
+ return r;
+ }
+
+ if (!s->what)
+ return -ENOMEM;
+ }
+
+ path_simplify(s->what, false);
+
+ if (!UNIT(s)->description) {
+ r = unit_set_description(UNIT(s), s->what);
+ if (r < 0)
+ return r;
+ }
+
+ r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
if (r < 0)
return r;
- if (u->load_state == UNIT_LOADED) {
-
- if (UNIT(s)->fragment_path)
- s->from_fragment = true;
+ r = swap_add_device_dependencies(s);
+ if (r < 0)
+ return r;
- if (!s->what) {
- if (s->parameters_fragment.what)
- s->what = strdup(s->parameters_fragment.what);
- else if (s->parameters_proc_swaps.what)
- s->what = strdup(s->parameters_proc_swaps.what);
- else {
- r = unit_name_to_path(u->id, &s->what);
- if (r < 0)
- return r;
- }
+ r = swap_load_devnode(s);
+ if (r < 0)
+ return r;
- if (!s->what)
- return -ENOMEM;
- }
+ r = unit_patch_contexts(UNIT(s));
+ if (r < 0)
+ return r;
- path_simplify(s->what, false);
+ r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
+ if (r < 0)
+ return r;
- if (!UNIT(s)->description) {
- r = unit_set_description(u, s->what);
- if (r < 0)
- return r;
- }
+ r = unit_set_default_slice(UNIT(s));
+ if (r < 0)
+ return r;
- r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
- if (r < 0)
- return r;
+ r = swap_add_default_dependencies(s);
+ if (r < 0)
+ return r;
- r = swap_add_device_dependencies(s);
- if (r < 0)
- return r;
+ return 0;
+}
- r = swap_load_devnode(s);
- if (r < 0)
- return r;
+static int swap_load(Unit *u) {
+ Swap *s = SWAP(u);
+ int r, q;
- r = unit_patch_contexts(u);
- if (r < 0)
- return r;
+ assert(s);
+ assert(u->load_state == UNIT_STUB);
- r = unit_add_exec_dependencies(u, &s->exec_context);
- if (r < 0)
- return r;
+ /* Load a .swap file */
+ if (SWAP(u)->from_proc_swaps)
+ r = unit_load_fragment_and_dropin_optional(u);
+ else
+ r = unit_load_fragment_and_dropin(u);
- r = unit_set_default_slice(u);
- if (r < 0)
- return r;
+ /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is already
+ * active. */
+ if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
+ q = swap_add_extras(s);
+ else
+ q = 0;
- r = swap_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ if (r < 0)
+ return r;
+ if (q < 0)
+ return q;
return swap_verify(s);
}
@@ -368,13 +385,12 @@ static int swap_setup_unit(
return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
u = manager_get_unit(m, e);
-
if (u &&
SWAP(u)->from_proc_swaps &&
- !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) {
- log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
- return -EEXIST;
- }
+ !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
+ "Swap %s appeared twice with different device paths %s and %s",
+ e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
if (!u) {
delete = true;
@@ -403,6 +419,13 @@ static int swap_setup_unit(
}
}
+ /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
+ * loaded. After all we can load it now, from the data in /proc/swaps. */
+ if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
+ u->load_state = UNIT_LOADED;
+ u->load_error = 0;
+ }
+
if (set_flags) {
SWAP(u)->is_active = true;
SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
@@ -425,10 +448,9 @@ fail:
}
static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
- _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
- const char *dn;
- struct stat st;
+ _cleanup_(sd_device_unrefp) sd_device *d = NULL;
+ const char *dn, *devlink;
+ struct stat st, st_link;
int r;
assert(m);
@@ -442,41 +464,36 @@ 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;
- r = udev_device_new_from_stat_rdev(m->udev, &st, &d);
+ r = device_new_from_stat_rdev(&d, &st);
if (r < 0) {
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
- "Failed to allocate udev device for swap %s: %m", device);
+ "Failed to allocate device for swap %s: %m", device);
return 0;
}
/* Add the main device node */
- dn = udev_device_get_devnode(d);
- if (dn && !streq(dn, device))
+ if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device))
swap_setup_unit(m, dn, device, prio, set_flags);
/* Add additional units for all symlinks */
- first = udev_device_get_devlinks_list_entry(d);
- udev_list_entry_foreach(item, first) {
- const char *p;
+ FOREACH_DEVICE_DEVLINK(d, devlink) {
/* Don't bother with the /dev/block links */
- p = udev_list_entry_get_name(item);
-
- if (streq(p, device))
+ if (streq(devlink, device))
continue;
- if (path_startswith(p, "/dev/block/"))
+ if (path_startswith(devlink, "/dev/block/"))
continue;
- if (stat(p, &st) >= 0)
- if (!S_ISBLK(st.st_mode) ||
- st.st_rdev != udev_device_get_devnum(d))
- continue;
+ if (stat(devlink, &st_link) >= 0 &&
+ (!S_ISBLK(st_link.st_mode) ||
+ st_link.st_rdev != st.st_rdev))
+ continue;
- swap_setup_unit(m, p, device, prio, set_flags);
+ swap_setup_unit(m, devlink, device, prio, set_flags);
}
- return r;
+ return 0;
}
static void swap_set_state(Swap *s, SwapState state) {
@@ -485,6 +502,9 @@ static void swap_set_state(Swap *s, SwapState state) {
assert(s);
+ if (s->state != state)
+ bus_unit_send_pending_change_signal(UNIT(s), false);
+
old_state = s->state;
s->state = state;
@@ -601,11 +621,12 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
- ExecParameters exec_params = {
+ _cleanup_(exec_params_clear) ExecParameters exec_params = {
.flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
.stdin_fd = -1,
.stdout_fd = -1,
.stderr_fd = -1,
+ .exec_fd = -1,
};
pid_t pid;
int r;
@@ -622,7 +643,9 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
if (r < 0)
goto fail;
- unit_set_exec_params(UNIT(s), &exec_params);
+ r = unit_set_exec_params(UNIT(s), &exec_params);
+ if (r < 0)
+ goto fail;
r = exec_spawn(UNIT(s),
c,
@@ -655,9 +678,7 @@ 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));
-
+ unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result));
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
@@ -813,6 +834,14 @@ fail:
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
+static void swap_cycle_clear(Swap *s) {
+ assert(s);
+
+ s->result = SWAP_SUCCESS;
+ exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
+ UNIT(s)->reset_accounting = true;
+}
+
static int swap_start(Unit *u) {
Swap *s = SWAP(u), *other;
int r;
@@ -852,10 +881,7 @@ static int swap_start(Unit *u) {
if (r < 0)
return r;
- s->result = SWAP_SUCCESS;
-
- u->reset_accounting = true;
-
+ swap_cycle_clear(s);
swap_enter_activating(s);
return 1;
}
@@ -898,14 +924,14 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
- unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
- unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
+ (void) serialize_item(f, "state", swap_state_to_string(s->state));
+ (void) serialize_item(f, "result", swap_result_to_string(s->result));
if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
+ (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
if (s->control_command_id >= 0)
- unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
+ (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id));
return 0;
}
@@ -1012,8 +1038,11 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
}
- log_unit_full(u, f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
- "Swap process exited, code=%s status=%i", sigchld_code_to_string(code), status);
+ unit_log_process_exit(
+ u, f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ "Swap process",
+ swap_exec_command_to_string(s->control_command_id),
+ code, status);
switch (s->state) {
@@ -1084,7 +1113,6 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
unsigned i;
- int r = 0;
assert(m);
@@ -1116,12 +1144,10 @@ static int swap_load_proc_swaps(Manager *m, bool 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)
- r = k;
+ (void) swap_process_new(m, d, prio, set_flags);
}
- return r;
+ return 0;
}
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
@@ -1152,13 +1178,13 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
Swap *swap = SWAP(u);
if (!swap->is_active) {
- /* This has just been deactivated */
swap_unset_proc_swaps(swap);
switch (swap->state) {
case SWAP_ACTIVE:
+ /* This has just been deactivated */
swap_enter_dead(swap, SWAP_SUCCESS);
break;
@@ -1179,7 +1205,8 @@ 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));
+ (void) unit_acquire_invocation_id(u);
+ swap_cycle_clear(swap);
swap_enter_active(swap, SWAP_SUCCESS);
break;
@@ -1320,18 +1347,17 @@ fail:
swap_shutdown(m);
}
-int swap_process_device_new(Manager *m, struct udev_device *dev) {
- struct udev_list_entry *item = NULL, *first = NULL;
+int swap_process_device_new(Manager *m, sd_device *dev) {
_cleanup_free_ char *e = NULL;
- const char *dn;
+ const char *dn, *devlink;
Unit *u;
int r = 0;
assert(m);
assert(dev);
- dn = udev_device_get_devnode(dev);
- if (!dn)
+ r = sd_device_get_devname(dev, &dn);
+ if (r < 0)
return 0;
r = unit_name_from_path(dn, ".swap", &e);
@@ -1342,12 +1368,11 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
if (u)
r = swap_set_devnode(SWAP(u), dn);
- first = udev_device_get_devlinks_list_entry(dev);
- udev_list_entry_foreach(item, first) {
+ FOREACH_DEVICE_DEVLINK(dev, devlink) {
_cleanup_free_ char *n = NULL;
int q;
- q = unit_name_from_path(udev_list_entry_get_name(item), ".swap", &n);
+ q = unit_name_from_path(devlink, ".swap", &n);
if (q < 0)
return q;
@@ -1362,13 +1387,13 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
return r;
}
-int swap_process_device_remove(Manager *m, struct udev_device *dev) {
+int swap_process_device_remove(Manager *m, sd_device *dev) {
const char *dn;
int r = 0;
Swap *s;
- dn = udev_device_get_devnode(dev);
- if (!dn)
+ r = sd_device_get_devname(dev, &dn);
+ if (r < 0)
return 0;
while ((s = hashmap_get(m->swaps_by_devnode, dn))) {