core/swap: support "systemctl clean" for swap units
This commit is contained in:
parent
17e9d53d87
commit
a8b689b7d0
|
@ -219,7 +219,8 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
|
|||
[SWAP_DEACTIVATING] = "deactivating",
|
||||
[SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
|
||||
[SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
|
||||
[SWAP_FAILED] = "failed"
|
||||
[SWAP_FAILED] = "failed",
|
||||
[SWAP_CLEANING] = "cleaning",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
|
||||
|
|
|
@ -162,6 +162,7 @@ typedef enum SwapState {
|
|||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL,
|
||||
SWAP_FAILED,
|
||||
SWAP_CLEANING,
|
||||
_SWAP_STATE_MAX,
|
||||
_SWAP_STATE_INVALID = -1
|
||||
} SwapState;
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ struct Swap {
|
|||
bool just_activated:1;
|
||||
|
||||
SwapResult result;
|
||||
SwapResult clean_result;
|
||||
|
||||
usec_t timeout_usec;
|
||||
|
||||
|
|
Loading…
Reference in a new issue