diff options
Diffstat (limited to 'src/core/swap.c')
-rw-r--r-- | src/core/swap.c | 269 |
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))) { |