diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-08-25 22:08:47 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-08-28 23:09:54 +0900 |
commit | 17e9d53d87245bff7191d6962fdc9eca42195ed2 (patch) | |
tree | e98dcc13d16fb39924e68fbbf7551b56a0dd6471 | |
parent | c968d76a382f905b419cacd23a6b20aa31aca580 (diff) | |
download | systemd-17e9d53d87245bff7191d6962fdc9eca42195ed2.tar.gz |
core/mount: support "systemctl clean" for mount units
-rw-r--r-- | src/basic/unit-def.c | 3 | ||||
-rw-r--r-- | src/basic/unit-def.h | 1 | ||||
-rw-r--r-- | src/core/mount.c | 85 | ||||
-rw-r--r-- | src/core/mount.h | 1 |
4 files changed, 86 insertions, 4 deletions
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c index e0928f9c02..b0b2d917fa 100644 --- a/src/basic/unit-def.c +++ b/src/basic/unit-def.c @@ -136,7 +136,8 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = { [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill", [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm", [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill", - [MOUNT_FAILED] = "failed" + [MOUNT_FAILED] = "failed", + [MOUNT_CLEANING] = "cleaning", }; DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState); diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h index 9155c500a3..4ddaf34b5f 100644 --- a/src/basic/unit-def.h +++ b/src/basic/unit-def.h @@ -79,6 +79,7 @@ typedef enum MountState { MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED, + MOUNT_CLEANING, _MOUNT_STATE_MAX, _MOUNT_STATE_INVALID = -1 } MountState; diff --git a/src/core/mount.c b/src/core/mount.c index 4f37d3e9a9..74da0f031b 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -45,7 +45,8 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING, [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING, [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING, - [MOUNT_FAILED] = UNIT_FAILED + [MOUNT_FAILED] = UNIT_FAILED, + [MOUNT_CLEANING] = UNIT_MAINTENANCE, }; static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); @@ -61,7 +62,8 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) { MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING, MOUNT_UNMOUNTING_SIGTERM, - MOUNT_UNMOUNTING_SIGKILL); + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_CLEANING); } static bool mount_is_network(const MountParameters *p) { @@ -731,6 +733,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sMount State: %s\n" "%sResult: %s\n" + "%sClean Result: %s\n" "%sWhere: %s\n" "%sWhat: %s\n" "%sFile System Type: %s\n" @@ -745,6 +748,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sTimeoutSec: %s\n", prefix, mount_state_to_string(m->state), prefix, mount_result_to_string(m->result), + prefix, mount_result_to_string(m->clean_result), prefix, m->where, prefix, p ? strna(p->what) : "n/a", prefix, p ? strna(p->fstype) : "n/a", @@ -1090,7 +1094,8 @@ static int mount_start(Unit *u) { if (IN_SET(m->state, MOUNT_UNMOUNTING, MOUNT_UNMOUNTING_SIGTERM, - MOUNT_UNMOUNTING_SIGKILL)) + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_CLEANING)) return -EAGAIN; /* Already on it! */ @@ -1149,6 +1154,11 @@ static int mount_stop(Unit *u) { mount_enter_unmounting(m); return 1; + case MOUNT_CLEANING: + /* If we are currently cleaning, then abort it, brutally. */ + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); + return 0; + default: assert_not_reached("Unexpected state."); } @@ -1382,6 +1392,13 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { mount_enter_dead_or_mounted(m, f); break; + case MOUNT_CLEANING: + if (m->clean_result == MOUNT_SUCCESS) + m->clean_result = f; + + mount_enter_dead(m, MOUNT_SUCCESS); + break; + default: assert_not_reached("Uh, control process died at wrong time."); } @@ -1449,6 +1466,15 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT); break; + case MOUNT_CLEANING: + log_unit_warning(UNIT(m), "Cleaning timed out. killing."); + + if (m->clean_result == MOUNT_SUCCESS) + m->clean_result = MOUNT_FAILURE_TIMEOUT; + + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, 0); + break; + default: assert_not_reached("Timeout at wrong time."); } @@ -1923,6 +1949,7 @@ static void mount_reset_failed(Unit *u) { m->result = MOUNT_SUCCESS; m->reload_result = MOUNT_SUCCESS; + m->clean_result = MOUNT_SUCCESS; } static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { @@ -1941,6 +1968,56 @@ static int mount_control_pid(Unit *u) { return m->control_pid; } +static int mount_clean(Unit *u, ExecCleanMask mask) { + _cleanup_strv_free_ char **l = NULL; + Mount *m = MOUNT(u); + int r; + + assert(m); + assert(mask != 0); + + if (m->state != MOUNT_DEAD) + return -EBUSY; + + r = exec_context_get_clean_directories(&m->exec_context, u->manager->prefix, mask, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return -EUNATCH; + + mount_unwatch_control_pid(m); + m->clean_result = MOUNT_SUCCESS; + m->control_command = NULL; + m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; + + r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->exec_context.timeout_clean_usec)); + if (r < 0) + goto fail; + + r = unit_fork_and_watch_rm_rf(u, l, &m->control_pid); + if (r < 0) + goto fail; + + mount_set_state(m, MOUNT_CLEANING); + + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m"); + m->clean_result = MOUNT_FAILURE_RESOURCES; + m->timer_event_source = sd_event_source_unref(m->timer_event_source); + return r; +} + +static int mount_can_clean(Unit *u, ExecCleanMask *ret) { + Mount *m = MOUNT(u); + + assert(m); + + return exec_context_get_clean_mask(&m->exec_context, ret); +} + static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { [MOUNT_EXEC_MOUNT] = "ExecMount", [MOUNT_EXEC_UNMOUNT] = "ExecUnmount", @@ -1989,6 +2066,8 @@ const UnitVTable mount_vtable = { .reload = mount_reload, .kill = mount_kill, + .clean = mount_clean, + .can_clean = mount_can_clean, .serialize = mount_serialize, .deserialize_item = mount_deserialize_item, diff --git a/src/core/mount.h b/src/core/mount.h index 2e59f1fe04..07fa05f3ca 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -61,6 +61,7 @@ struct Mount { MountResult result; MountResult reload_result; + MountResult clean_result; mode_t directory_mode; |