summaryrefslogtreecommitdiffstats
path: root/src/core/swap.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-08-25 15:26:33 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-08-28 16:09:54 +0200
commita8b689b7d01a9b7c7a66a29b0ea79d883b38a279 (patch)
tree2d3cd87d434d1d13a558587e49c451b9a991ef1d /src/core/swap.c
parentcore/mount: support "systemctl clean" for mount units (diff)
downloadsystemd-a8b689b7d01a9b7c7a66a29b0ea79d883b38a279.tar.xz
systemd-a8b689b7d01a9b7c7a66a29b0ea79d883b38a279.zip
core/swap: support "systemctl clean" for swap units
Diffstat (limited to 'src/core/swap.c')
-rw-r--r--src/core/swap.c86
1 files changed, 83 insertions, 3 deletions
diff --git a/src/core/swap.c b/src/core/swap.c
index 74381c0c95..0719d3efcc 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -38,7 +38,8 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
[SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
- [SWAP_FAILED] = UNIT_FAILED
+ [SWAP_FAILED] = UNIT_FAILED,
+ [SWAP_CLEANING] = UNIT_MAINTENANCE,
};
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
@@ -51,7 +52,8 @@ static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
SWAP_ACTIVATING_DONE,
SWAP_DEACTIVATING,
SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL);
+ SWAP_DEACTIVATING_SIGKILL,
+ SWAP_CLEANING);
}
static void swap_unset_proc_swaps(Swap *s) {
@@ -587,11 +589,13 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sSwap State: %s\n"
"%sResult: %s\n"
+ "%sClean Result: %s\n"
"%sWhat: %s\n"
"%sFrom /proc/swaps: %s\n"
"%sFrom fragment: %s\n",
prefix, swap_state_to_string(s->state),
prefix, swap_result_to_string(s->result),
+ prefix, swap_result_to_string(s->clean_result),
prefix, s->what,
prefix, yes_no(s->from_proc_swaps),
prefix, yes_no(s->from_fragment));
@@ -852,7 +856,8 @@ static int swap_start(Unit *u) {
if (IN_SET(s->state,
SWAP_DEACTIVATING,
SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL))
+ SWAP_DEACTIVATING_SIGKILL,
+ SWAP_CLEANING))
return -EAGAIN;
/* Already on it! */
@@ -912,6 +917,12 @@ static int swap_stop(Unit *u) {
swap_enter_deactivating(s);
return 1;
+ case SWAP_CLEANING:
+ /* If we are currently cleaning, then abort it, brutally. */
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
+ return 0;
+
+
default:
assert_not_reached("Unexpected state.");
}
@@ -1067,6 +1078,13 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
swap_enter_dead_or_active(s, f);
break;
+ case SWAP_CLEANING:
+ if (s->clean_result == SWAP_SUCCESS)
+ s->clean_result = f;
+
+ swap_enter_dead(s, SWAP_SUCCESS);
+ break;
+
default:
assert_not_reached("Uh, control process died at wrong time.");
}
@@ -1109,6 +1127,15 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
break;
+ case SWAP_CLEANING:
+ log_unit_warning(UNIT(s), "Cleaning timed out. killing.");
+
+ if (s->clean_result == SWAP_SUCCESS)
+ s->clean_result = SWAP_FAILURE_TIMEOUT;
+
+ swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, 0);
+ break;
+
default:
assert_not_reached("Timeout at wrong time.");
}
@@ -1428,6 +1455,7 @@ static void swap_reset_failed(Unit *u) {
swap_set_state(s, SWAP_DEAD);
s->result = SWAP_SUCCESS;
+ s->clean_result = SWAP_SUCCESS;
}
static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
@@ -1475,6 +1503,56 @@ static int swap_control_pid(Unit *u) {
return s->control_pid;
}
+static int swap_clean(Unit *u, ExecCleanMask mask) {
+ _cleanup_strv_free_ char **l = NULL;
+ Swap *s = SWAP(u);
+ int r;
+
+ assert(s);
+ assert(mask != 0);
+
+ if (s->state != SWAP_DEAD)
+ return -EBUSY;
+
+ r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
+ if (r < 0)
+ return r;
+
+ if (strv_isempty(l))
+ return -EUNATCH;
+
+ swap_unwatch_control_pid(s);
+ s->clean_result = SWAP_SUCCESS;
+ s->control_command = NULL;
+ s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
+
+ r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
+ if (r < 0)
+ goto fail;
+
+ r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
+ if (r < 0)
+ goto fail;
+
+ swap_set_state(s, SWAP_CLEANING);
+
+ return 0;
+
+fail:
+ log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
+ s->clean_result = SWAP_FAILURE_RESOURCES;
+ s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+ return r;
+}
+
+static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
+ Swap *s = SWAP(u);
+
+ assert(s);
+
+ return exec_context_get_clean_mask(&s->exec_context, ret);
+}
+
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
@@ -1520,6 +1598,8 @@ const UnitVTable swap_vtable = {
.stop = swap_stop,
.kill = swap_kill,
+ .clean = swap_clean,
+ .can_clean = swap_can_clean,
.get_timeout = swap_get_timeout,