X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fswap.c;h=d53cabef2a5281a66c3ebabef9ecf6033e310b39;hp=fff613934ae009954331f722292621cb68cb2a32;hb=e10c9985bbc3cf79f12f9ec7317adfe697fa8214;hpb=5bcb0f2ba0615897662fcd4f6227d066781c6fc2 diff --git a/src/core/swap.c b/src/core/swap.c index fff613934..d53cabef2 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -59,29 +59,55 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static void swap_unset_proc_swaps(Swap *s) { + assert(s); + + if (!s->from_proc_swaps) + return; + + free(s->parameters_proc_swaps.what); + s->parameters_proc_swaps.what = NULL; + + s->from_proc_swaps = false; +} + +static int swap_set_devnode(Swap *s, const char *devnode) { Hashmap *swaps; Swap *first; + int r; assert(s); - if (!s->parameters_proc_swaps.what) - return; + r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, string_hash_func, string_compare_func); + if (r < 0) + return r; - /* Remove this unit from the chain of swaps which share the - * same kernel swap device. */ - swaps = UNIT(s)->manager->swaps_by_proc_swaps; - first = hashmap_get(swaps, s->parameters_proc_swaps.what); - LIST_REMOVE(same_proc_swaps, first, s); + swaps = UNIT(s)->manager->swaps_by_devnode; - if (first) - hashmap_remove_and_replace(swaps, s->parameters_proc_swaps.what, first->parameters_proc_swaps.what, first); - else - hashmap_remove(swaps, s->parameters_proc_swaps.what); + if (s->devnode) { + first = hashmap_get(swaps, s->devnode); - free(s->parameters_proc_swaps.what); - s->parameters_proc_swaps.what = NULL; + LIST_REMOVE(same_devnode, first, s); + if (first) + hashmap_replace(swaps, first->devnode, first); + else + hashmap_remove(swaps, s->devnode); - s->from_proc_swaps = false; + free(s->devnode); + s->devnode = NULL; + } + + if (devnode) { + s->devnode = strdup(devnode); + if (!s->devnode) + return -ENOMEM; + + first = hashmap_get(swaps, s->devnode); + LIST_PREPEND(same_devnode, first, s); + + return hashmap_replace(swaps, first->devnode, first); + } + + return 0; } static void swap_init(Unit *u) { @@ -121,6 +147,7 @@ static void swap_done(Unit *u) { assert(s); swap_unset_proc_swaps(s); + swap_set_devnode(s, NULL); free(s->what); s->what = NULL; @@ -128,12 +155,12 @@ static void swap_done(Unit *u) { free(s->parameters_fragment.what); s->parameters_fragment.what = NULL; - exec_context_done(&s->exec_context, manager_is_reloading_or_reexecuting(u->manager)); + cgroup_context_done(&s->cgroup_context); + exec_context_done(&s->exec_context); + s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; - cgroup_context_done(&s->cgroup_context); - swap_unwatch_control_pid(s); s->timer_event_source = sd_event_source_unref(s->timer_event_source); @@ -242,6 +269,27 @@ static int swap_verify(Swap *s) { return 0; } +static int swap_load_devnode(Swap *s) { + _cleanup_udev_device_unref_ struct udev_device *d = NULL; + struct stat st; + const char *p; + + 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) + return 0; + + p = udev_device_get_devnode(d); + if (!p) + return 0; + + return swap_set_devnode(s, p); +} + static int swap_load(Unit *u) { int r; Swap *s = SWAP(u); @@ -290,6 +338,10 @@ static int swap_load(Unit *u) { if (r < 0) return r; + r = swap_load_devnode(s); + if (r < 0) + return r; + r = unit_add_default_slice(u); if (r < 0) return r; @@ -322,7 +374,6 @@ static int swap_add_one( Unit *u = NULL; int r; SwapParameters *p; - Swap *first; assert(m); assert(what); @@ -368,17 +419,6 @@ static int swap_add_one( r = -ENOMEM; goto fail; } - - r = hashmap_ensure_allocated(&m->swaps_by_proc_swaps, string_hash_func, string_compare_func); - if (r < 0) - goto fail; - - first = hashmap_get(m->swaps_by_proc_swaps, p->what); - LIST_PREPEND(same_proc_swaps, first, SWAP(u)); - - r = hashmap_replace(m->swaps_by_proc_swaps, p->what, first); - if (r < 0) - goto fail; } if (set_flags) { @@ -554,6 +594,9 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->from_proc_swaps), prefix, yes_no(s->from_fragment)); + if (s->devnode) + fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode); + if (p) fprintf(f, "%sPriority: %i\n" @@ -582,6 +625,10 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { unit_realize_cgroup(UNIT(s)); + r = unit_setup_exec_runtime(UNIT(s)); + if (r < 0) + goto fail; + r = swap_arm_timer(s); if (r < 0) goto fail; @@ -598,7 +645,9 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { UNIT(s)->manager->cgroup_supported, UNIT(s)->cgroup_path, UNIT(s)->id, + 0, NULL, + s->exec_runtime, &pid); if (r < 0) goto fail; @@ -624,7 +673,9 @@ static void swap_enter_dead(Swap *s, SwapResult f) { if (f != SWAP_SUCCESS) s->result = f; - exec_context_tmp_dirs_done(&s->exec_context); + exec_runtime_destroy(s->exec_runtime); + s->exec_runtime = exec_runtime_unref(s->exec_runtime); + swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); } @@ -661,7 +712,11 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { goto fail; swap_set_state(s, state); - } else + } else if (state == SWAP_ACTIVATING_SIGTERM) + swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS); + else if (state == SWAP_DEACTIVATING_SIGTERM) + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); + else swap_enter_dead(s, SWAP_SUCCESS); return; @@ -824,8 +879,6 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { if (s->control_command_id >= 0) unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id)); - exec_context_serialize(&s->exec_context, UNIT(s), f); - return 0; } @@ -869,22 +922,6 @@ static int swap_deserialize_item(Unit *u, const char *key, const char *value, FD s->control_command_id = id; s->control_command = s->exec_command + id; } - } else if (streq(key, "tmp-dir")) { - char *t; - - t = strdup(value); - if (!t) - return log_oom(); - - s->exec_context.tmp_dir = t; - } else if (streq(key, "var-tmp-dir")) { - char *t; - - t = strdup(value); - if (!t) - return log_oom(); - - s->exec_context.var_tmp_dir = t; } else log_debug_unit(u->id, "Unknown serialization key '%s'", key); @@ -966,10 +1003,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { case SWAP_DEACTIVATING_SIGKILL: case SWAP_DEACTIVATING_SIGTERM: - if (f == SWAP_SUCCESS) - swap_enter_dead(s, f); - else - swap_enter_dead(s, f); + swap_enter_dead(s, f); break; default: @@ -1155,18 +1189,18 @@ static Unit *swap_following(Unit *u) { assert(s); - if (streq_ptr(s->what, s->parameters_proc_swaps.what)) + if (streq_ptr(s->what, s->devnode)) return NULL; /* Make everybody follow the unit that's named after the swap * device in the kernel */ - LIST_FOREACH_AFTER(same_proc_swaps, other, s) - if (streq_ptr(other->what, other->parameters_proc_swaps.what)) + LIST_FOREACH_AFTER(same_devnode, other, s) + if (streq_ptr(other->what, other->devnode)) return UNIT(other); - LIST_FOREACH_BEFORE(same_proc_swaps, other, s) { - if (streq_ptr(other->what, other->parameters_proc_swaps.what)) + LIST_FOREACH_BEFORE(same_devnode, other, s) { + if (streq_ptr(other->what, other->devnode)) return UNIT(other); first = other; @@ -1183,7 +1217,7 @@ static int swap_following_set(Unit *u, Set **_set) { assert(s); assert(_set); - if (LIST_JUST_US(same_proc_swaps, s)) { + if (LIST_JUST_US(same_devnode, s)) { *_set = NULL; return 0; } @@ -1192,13 +1226,13 @@ static int swap_following_set(Unit *u, Set **_set) { if (!set) return -ENOMEM; - LIST_FOREACH_AFTER(same_proc_swaps, other, s) { + LIST_FOREACH_AFTER(same_devnode, other, s) { r = set_put(set, other); if (r < 0) goto fail; } - LIST_FOREACH_BEFORE(same_proc_swaps, other, s) { + LIST_FOREACH_BEFORE(same_devnode, other, s) { r = set_put(set, other); if (r < 0) goto fail; @@ -1222,12 +1256,13 @@ static void swap_shutdown(Manager *m) { m->proc_swaps = NULL; } - hashmap_free(m->swaps_by_proc_swaps); - m->swaps_by_proc_swaps = NULL; + hashmap_free(m->swaps_by_devnode); + m->swaps_by_devnode = NULL; } static int swap_enumerate(Manager *m) { int r; + assert(m); if (!m->proc_swaps) { @@ -1238,6 +1273,13 @@ static int swap_enumerate(Manager *m) { r = sd_event_add_io(m->event, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m, &m->swap_event_source); if (r < 0) goto fail; + + /* Dispatch this before we dispatch SIGCHLD, so that + * we always get the events from /proc/swaps before + * the SIGCHLD of /sbin/swapon. */ + r = sd_event_source_set_priority(m->swap_event_source, -10); + if (r < 0) + goto fail; } r = swap_load_proc_swaps(m, false); @@ -1251,6 +1293,69 @@ fail: return r; } +int swap_process_new_device(Manager *m, struct udev_device *dev) { + struct udev_list_entry *item = NULL, *first = NULL; + _cleanup_free_ char *e = NULL; + const char *dn; + Swap *s; + int r = 0; + + assert(m); + assert(dev); + + dn = udev_device_get_devnode(dev); + if (!dn) + return 0; + + e = unit_name_from_path(dn, ".swap"); + if (!e) + return -ENOMEM; + + s = hashmap_get(m->units, e); + if (s) + r = swap_set_devnode(s, dn); + + first = udev_device_get_devlinks_list_entry(dev); + udev_list_entry_foreach(item, first) { + _cleanup_free_ char *n = NULL; + + n = unit_name_from_path(udev_list_entry_get_name(item), ".swap"); + if (!n) + return -ENOMEM; + + s = hashmap_get(m->units, n); + if (s) { + int q; + + q = swap_set_devnode(s, dn); + if (q < 0) + r = q; + } + } + + return r; +} + +int swap_process_removed_device(Manager *m, struct udev_device *dev) { + const char *dn; + int r = 0; + Swap *s; + + dn = udev_device_get_devnode(dev); + if (!dn) + return 0; + + while ((s = hashmap_get(m->swaps_by_devnode, dn))) { + int q; + + q = swap_set_devnode(s, NULL); + if (q < 0) + r = q; + } + + return r; +} + static void swap_reset_failed(Unit *u) { Swap *s = SWAP(u); @@ -1266,6 +1371,20 @@ static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error); } +static int swap_get_timeout(Unit *u, uint64_t *timeout) { + Swap *s = SWAP(u); + int r; + + if (!s->timer_event_source) + return 0; + + r = sd_event_source_get_time(s->timer_event_source, timeout); + if (r < 0) + return r; + + return 1; +} + static const char* const swap_state_table[_SWAP_STATE_MAX] = { [SWAP_DEAD] = "dead", [SWAP_ACTIVATING] = "activating", @@ -1304,6 +1423,7 @@ const UnitVTable swap_vtable = { .exec_context_offset = offsetof(Swap, exec_context), .cgroup_context_offset = offsetof(Swap, cgroup_context), .kill_context_offset = offsetof(Swap, kill_context), + .exec_runtime_offset = offsetof(Swap, exec_runtime), .sections = "Unit\0" @@ -1327,6 +1447,8 @@ const UnitVTable swap_vtable = { .kill = swap_kill, + .get_timeout = swap_get_timeout, + .serialize = swap_serialize, .deserialize_item = swap_deserialize_item, @@ -1341,7 +1463,6 @@ const UnitVTable swap_vtable = { .bus_interface = "org.freedesktop.systemd1.Swap", .bus_vtable = bus_swap_vtable, - .bus_changing_properties = bus_swap_changing_properties, .bus_set_property = bus_swap_set_property, .bus_commit_properties = bus_swap_commit_properties,