X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fswap.c;h=b2ca048bcbc0c23c3d476243b1e89e39dc3fb4b7;hb=718880ba0d557a045e2f969e141cbd59e78c76f4;hp=9f353af430be489b9624b52d998760125259be4b;hpb=de0671ee7fe465e108f62dcbbbe9366f81dd9e9a;p=elogind.git diff --git a/src/core/swap.c b/src/core/swap.c index 9f353af43..b2ca048bc 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -77,7 +77,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_func, string_compare_func); + r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &string_hash_ops); if (r < 0) return r; @@ -152,6 +152,9 @@ static void swap_done(Unit *u) { free(s->parameters_fragment.what); s->parameters_fragment.what = NULL; + free(s->parameters_fragment.discard); + s->parameters_fragment.discard = NULL; + s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -210,7 +213,7 @@ static int swap_add_device_links(Swap *s) { } static int swap_add_default_dependencies(Swap *s) { - bool nofail = false, noauto = false; + bool nofail, noauto; int r; assert(s); @@ -225,23 +228,25 @@ static int swap_add_default_dependencies(Swap *s) { if (r < 0) return r; - if (s->from_fragment) { - SwapParameters *p = &s->parameters_fragment; + if (!s->from_fragment) + /* The swap unit can either be for an alternative device name, in which + * case we don't need to add the dependency on swap.target because this unit + * is following a different unit which will have this dependency added, + * or it can be derived from /proc/swaps, in which case it was started + * manually, and should not become a dependency of swap.target. */ + return 0; - nofail = p->nofail; - noauto = p->noauto; - } + nofail = s->parameters_fragment.nofail; + noauto = s->parameters_fragment.noauto; if (!noauto) { if (nofail) r = unit_add_dependency_by_name_inverse(UNIT(s), UNIT_WANTS, SPECIAL_SWAP_TARGET, NULL, true); else r = unit_add_two_dependencies_by_name_inverse(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SWAP_TARGET, NULL, true); - if (r < 0) - return r; } - return 0; + return r < 0 ? r : 0; } static int swap_verify(Swap *s) { @@ -602,10 +607,12 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sPriority: %i\n" "%sNoAuto: %s\n" - "%sNoFail: %s\n", + "%sNoFail: %s\n" + "%sDiscard: %s\n", prefix, p->priority, prefix, yes_no(p->noauto), - prefix, yes_no(p->nofail)); + prefix, yes_no(p->nofail), + prefix, p->discard ?: "none"); if (s->control_pid > 0) fprintf(f, @@ -619,6 +626,11 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) { static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; + ExecParameters exec_params = { + .apply_permissions = true, + .apply_chroot = true, + .apply_tty_stdin = true, + }; assert(s); assert(c); @@ -634,21 +646,16 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { if (r < 0) goto fail; + exec_params.environment = UNIT(s)->manager->environment; + exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; + exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; + exec_params.cgroup_path = UNIT(s)->cgroup_path; + exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager); + exec_params.unit_id = UNIT(s)->id; + r = exec_spawn(c, - NULL, &s->exec_context, - NULL, 0, - UNIT(s)->manager->environment, - true, - true, - true, - UNIT(s)->manager->confirm_spawn, - UNIT(s)->manager->cgroup_supported, - UNIT(s)->cgroup_path, - manager_get_runtime_prefix(UNIT(s)->manager), - UNIT(s)->id, - 0, - NULL, + &exec_params, s->exec_runtime, &pid); if (r < 0) @@ -734,36 +741,46 @@ fail: static void swap_enter_activating(Swap *s) { int r, priority; + char *discard; assert(s); s->control_command_id = SWAP_EXEC_ACTIVATE; s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; - if (s->from_fragment) + if (s->from_fragment) { priority = s->parameters_fragment.priority; - else + discard = s->parameters_fragment.discard; + } else { priority = -1; + discard = NULL; + } + + r = exec_command_set(s->control_command, "/sbin/swapon", NULL); + if (r < 0) + goto fail; if (priority >= 0) { char p[DECIMAL_STR_MAX(int)]; sprintf(p, "%i", priority); + r = exec_command_append(s->control_command, "-p", p, NULL); + if (r < 0) + goto fail; + } - r = exec_command_set( - s->control_command, - "/sbin/swapon", - "-p", - p, - s->what, - NULL); - } else - r = exec_command_set( - s->control_command, - "/sbin/swapon", - s->what, - NULL); + if (discard && !streq(discard, "none")) { + const char *discard_arg = "--discard"; + + if (!streq(discard, "all")) + discard_arg = strappenda("--discard=", discard); + r = exec_command_append(s->control_command, discard_arg, NULL); + if (r < 0) + goto fail; + } + + r = exec_command_append(s->control_command, s->what, NULL); if (r < 0) goto fail; @@ -1193,11 +1210,25 @@ static Unit *swap_following(Unit *u) { assert(s); - if (streq_ptr(s->what, s->devnode)) + /* If the user configured the swap through /etc/fstab or + * a device unit, follow that. */ + + if (s->from_fragment) return NULL; - /* Make everybody follow the unit that's named after the swap - * device in the kernel */ + LIST_FOREACH_AFTER(same_devnode, other, s) + if (other->from_fragment) + return UNIT(other); + + LIST_FOREACH_BEFORE(same_devnode, other, s) + if (other->from_fragment) + return UNIT(other); + + /* Otherwise make everybody follow the unit that's named after + * the swap device in the kernel */ + + if (streq_ptr(s->what, s->devnode)) + return NULL; LIST_FOREACH_AFTER(same_devnode, other, s) if (streq_ptr(other->what, other->devnode)) @@ -1210,6 +1241,7 @@ static Unit *swap_following(Unit *u) { first = other; } + /* Fall back to the first on the list */ return UNIT(first); } @@ -1226,7 +1258,7 @@ static int swap_following_set(Unit *u, Set **_set) { return 0; } - set = set_new(NULL, NULL); + set = set_new(NULL); if (!set) return -ENOMEM;