+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
[SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
[SWAP_ACTIVE] = UNIT_ACTIVE,
[SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
- [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
- [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
[SWAP_FAILED] = UNIT_FAILED
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
+ return IN_SET(state,
+ SWAP_ACTIVATING,
+ SWAP_ACTIVATING_DONE,
+ SWAP_DEACTIVATING,
+ SWAP_DEACTIVATING_SIGTERM,
+ SWAP_DEACTIVATING_SIGKILL);
+}
+
static void swap_unset_proc_swaps(Swap *s) {
assert(s);
return 0;
}
-static int swap_add_device_links(Swap *s) {
+static int swap_add_device_dependencies(Swap *s) {
assert(s);
if (!s->what)
return 0;
if (is_device_path(s->what))
- return unit_add_node_link(UNIT(s), s->what, MANAGER_IS_SYSTEM(UNIT(s)->manager), UNIT_BINDS_TO);
+ return unit_add_node_dependency(UNIT(s), s->what, MANAGER_IS_SYSTEM(UNIT(s)->manager), UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE);
else
/* 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);
+ return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true, UNIT_DEPENDENCY_FILE);
}
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);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, 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);
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
}
static int swap_verify(Swap *s) {
return r;
}
- r = unit_require_mounts_for(UNIT(s), s->what);
+ r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
if (r < 0)
return r;
- r = swap_add_device_links(s);
+ r = swap_add_device_dependencies(s);
if (r < 0)
return r;
fail:
log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
- if (delete && u)
+ if (delete)
unit_free(u);
return r;
old_state = s->state;
s->state = state;
- if (state != SWAP_ACTIVATING &&
- state != SWAP_ACTIVATING_SIGTERM &&
- state != SWAP_ACTIVATING_SIGKILL &&
- state != SWAP_ACTIVATING_DONE &&
- state != SWAP_DEACTIVATING &&
- state != SWAP_DEACTIVATING_SIGTERM &&
- state != SWAP_DEACTIVATING_SIGKILL) {
+ if (!SWAP_STATE_WITH_PROCESS(state)) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
swap_unwatch_control_pid(s);
s->control_command = NULL;
if (s->control_pid > 0 &&
pid_is_unwaited(s->control_pid) &&
- IN_SET(new_state,
- SWAP_ACTIVATING,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL,
- SWAP_ACTIVATING_DONE,
- SWAP_DEACTIVATING,
- SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL)) {
+ SWAP_STATE_WITH_PROCESS(new_state)) {
r = unit_watch_pid(UNIT(s), s->control_pid);
if (r < 0)
exec_context_dump(&s->exec_context, f, prefix);
kill_context_dump(&s->kill_context, f, prefix);
+ cgroup_context_dump(&s->cgroup_context, f, prefix);
}
static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
pid_t pid;
int r;
ExecParameters exec_params = {
- .flags = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
+ .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
.stdin_fd = -1,
.stdout_fd = -1,
.stderr_fd = -1,
assert(_pid);
(void) unit_realize_cgroup(UNIT(s));
- if (s->reset_cpu_usage) {
- (void) unit_reset_cpu_usage(UNIT(s));
- s->reset_cpu_usage = false;
+ if (s->reset_accounting) {
+ (void) unit_reset_cpu_accounting(UNIT(s));
+ (void) unit_reset_ip_accounting(UNIT(s));
+ s->reset_accounting = false;
}
+ unit_export_state_files(UNIT(s));
+
r = unit_setup_exec_runtime(UNIT(s));
if (r < 0)
goto fail;
r = unit_setup_dynamic_creds(UNIT(s));
if (r < 0)
- return r;
+ goto fail;
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
- exec_params.environment = UNIT(s)->manager->environment;
- exec_params.flags |= UNIT(s)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0;
- exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
- exec_params.cgroup_path = UNIT(s)->cgroup_path;
- exec_params.cgroup_delegate = s->cgroup_context.delegate;
- exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
+ manager_set_exec_params(UNIT(s)->manager, &exec_params);
+ unit_set_exec_params(UNIT(s), &exec_params);
r = exec_spawn(UNIT(s),
c,
fail:
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+
return r;
}
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));
+
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
exec_runtime_destroy(s->exec_runtime);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
- exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+ exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
unit_unref_uid_gid(UNIT(s), true);
swap_set_state(s, SWAP_ACTIVE);
}
+static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
+ assert(s);
+
+ if (s->from_proc_swaps)
+ swap_enter_active(s, f);
+ else
+ swap_enter_dead(s, f);
+}
+
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
int r;
+ KillOperation kop;
assert(s);
if (s->result == SWAP_SUCCESS)
s->result = f;
- r = unit_kill_context(
- UNIT(s),
- &s->kill_context,
- (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ?
- KILL_KILL : KILL_TERMINATE,
- -1,
- s->control_pid,
- false);
+ if (state == SWAP_DEACTIVATING_SIGTERM)
+ kop = KILL_TERMINATE;
+ else
+ kop = KILL_KILL;
+
+ r = unit_kill_context(UNIT(s), &s->kill_context, kop, -1, s->control_pid, false);
if (r < 0)
goto fail;
goto fail;
swap_set_state(s, state);
- } else if (state == SWAP_ACTIVATING_SIGTERM)
- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS);
- else if (state == SWAP_DEACTIVATING_SIGTERM)
+ } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
else
- swap_enter_dead(s, SWAP_SUCCESS);
+ swap_enter_dead_or_active(s, SWAP_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
static void swap_enter_activating(Swap *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
static void swap_enter_deactivating(Swap *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
- swap_enter_active(s, SWAP_FAILURE_RESOURCES);
+ swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
static int swap_start(Unit *u) {
assert(s);
- /* We cannot fulfill this request right now, try again later
- * please! */
-
- if (s->state == SWAP_DEACTIVATING ||
- s->state == SWAP_DEACTIVATING_SIGTERM ||
- s->state == SWAP_DEACTIVATING_SIGKILL ||
- s->state == SWAP_ACTIVATING_SIGTERM ||
- s->state == SWAP_ACTIVATING_SIGKILL)
+ /* We cannot fulfill this request right now, try again later please! */
+ if (IN_SET(s->state,
+ SWAP_DEACTIVATING,
+ SWAP_DEACTIVATING_SIGTERM,
+ SWAP_DEACTIVATING_SIGKILL))
return -EAGAIN;
+ /* Already on it! */
if (s->state == SWAP_ACTIVATING)
return 0;
- assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
+ assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
if (detect_container() > 0)
return -EPERM;
return r;
s->result = SWAP_SUCCESS;
- s->reset_cpu_usage = true;
+ s->reset_accounting = true;
swap_enter_activating(s);
return 1;
assert(s);
- if (s->state == SWAP_DEACTIVATING ||
- s->state == SWAP_DEACTIVATING_SIGTERM ||
- s->state == SWAP_DEACTIVATING_SIGKILL ||
- s->state == SWAP_ACTIVATING_SIGTERM ||
- s->state == SWAP_ACTIVATING_SIGKILL)
+ switch (s->state) {
+
+ case SWAP_DEACTIVATING:
+ case SWAP_DEACTIVATING_SIGTERM:
+ case SWAP_DEACTIVATING_SIGKILL:
+ /* Already on it */
return 0;
- assert(s->state == SWAP_ACTIVATING ||
- s->state == SWAP_ACTIVATING_DONE ||
- s->state == SWAP_ACTIVE);
+ case SWAP_ACTIVATING:
+ case SWAP_ACTIVATING_DONE:
+ /* There's a control process pending, directly enter kill mode */
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
+ return 0;
- if (detect_container() > 0)
- return -EPERM;
+ case SWAP_ACTIVE:
+ if (detect_container() > 0)
+ return -EPERM;
- swap_enter_deactivating(s);
- return 1;
+ swap_enter_deactivating(s);
+ return 1;
+
+ default:
+ assert_not_reached("Unexpected state.");
+ }
}
static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
case SWAP_ACTIVATING:
case SWAP_ACTIVATING_DONE:
- case SWAP_ACTIVATING_SIGTERM:
- case SWAP_ACTIVATING_SIGKILL:
- if (f == SWAP_SUCCESS)
+ if (f == SWAP_SUCCESS || s->from_proc_swaps)
swap_enter_active(s, f);
else
swap_enter_dead(s, f);
case SWAP_DEACTIVATING_SIGKILL:
case SWAP_DEACTIVATING_SIGTERM:
- swap_enter_dead(s, f);
+ swap_enter_dead_or_active(s, f);
break;
default:
case SWAP_ACTIVATING:
case SWAP_ACTIVATING_DONE:
log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
- swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
break;
case SWAP_DEACTIVATING:
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
break;
- case SWAP_ACTIVATING_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_unit_warning(UNIT(s), "Activation timed out. Killing.");
- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
- } else {
- log_unit_warning(UNIT(s), "Activation timed out. Skipping SIGKILL. Ignoring.");
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
- }
- break;
-
case SWAP_DEACTIVATING_SIGTERM:
if (s->kill_context.send_sigkill) {
- log_unit_warning(UNIT(s), "Deactivation timed out. Killing.");
+ log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
} else {
- log_unit_warning(UNIT(s), "Deactivation timed out. Skipping SIGKILL. Ignoring.");
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
+ log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
+ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
}
break;
- case SWAP_ACTIVATING_SIGKILL:
case SWAP_DEACTIVATING_SIGKILL:
log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
+ swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
break;
default:
struct udev_list_entry *item = NULL, *first = NULL;
_cleanup_free_ char *e = NULL;
const char *dn;
- Swap *s;
+ Unit *u;
int r = 0;
assert(m);
if (r < 0)
return r;
- s = hashmap_get(m->units, e);
- if (s)
- r = swap_set_devnode(s, dn);
+ u = manager_get_unit(m, e);
+ if (u)
+ r = swap_set_devnode(SWAP(u), dn);
first = udev_device_get_devlinks_list_entry(dev);
udev_list_entry_foreach(item, first) {
if (q < 0)
return q;
- s = hashmap_get(m->units, n);
- if (s) {
- q = swap_set_devnode(s, dn);
+ u = manager_get_unit(m, n);
+ if (u) {
+ q = swap_set_devnode(SWAP(u), dn);
if (q < 0)
r = q;
}