+/* 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;
old_state = s->state;
s->state = state;
- if (!IN_SET(state,
- SWAP_ACTIVATING,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL,
- SWAP_ACTIVATING_DONE,
- SWAP_DEACTIVATING,
- SWAP_DEACTIVATING_SIGTERM,
- 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) {
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;
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);
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;
if (s->result == SWAP_SUCCESS)
s->result = f;
- if (IN_SET(state, SWAP_ACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGTERM))
+ if (state == SWAP_DEACTIVATING_SIGTERM)
kop = KILL_TERMINATE;
else
kop = KILL_KILL;
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! */
-
+ /* We cannot fulfill this request right now, try again later please! */
if (IN_SET(s->state,
SWAP_DEACTIVATING,
SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL))
+ SWAP_DEACTIVATING_SIGKILL))
return -EAGAIN;
+ /* Already on it! */
if (s->state == SWAP_ACTIVATING)
return 0;
return r;
s->result = SWAP_SUCCESS;
- s->reset_cpu_usage = true;
+ s->reset_accounting = true;
swap_enter_activating(s);
return 1;
assert(s);
- if (IN_SET(s->state,
- SWAP_DEACTIVATING,
- SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL))
+ switch (s->state) {
+
+ case SWAP_DEACTIVATING:
+ case SWAP_DEACTIVATING_SIGTERM:
+ case SWAP_DEACTIVATING_SIGKILL:
+ /* Already on it */
+ return 0;
+
+ 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;
- assert(IN_SET(s->state, SWAP_ACTIVATING, SWAP_ACTIVATING_DONE, SWAP_ACTIVE));
+ case SWAP_ACTIVE:
+ if (detect_container() > 0)
+ return -EPERM;
- 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: