[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);
MOUNT_REMOUNTING_SIGKILL,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
- MOUNT_UNMOUNTING_SIGKILL);
+ MOUNT_UNMOUNTING_SIGKILL,
+ MOUNT_CLEANING);
}
static bool mount_is_network(const MountParameters *p) {
fprintf(f,
"%sMount State: %s\n"
"%sResult: %s\n"
+ "%sClean Result: %s\n"
"%sWhere: %s\n"
"%sWhat: %s\n"
"%sFile System Type: %s\n"
"%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",
if (IN_SET(m->state,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
- MOUNT_UNMOUNTING_SIGKILL))
+ MOUNT_UNMOUNTING_SIGKILL,
+ MOUNT_CLEANING))
return -EAGAIN;
/* Already on it! */
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.");
}
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.");
}
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.");
}
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) {
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",
.reload = mount_reload,
.kill = mount_kill,
+ .clean = mount_clean,
+ .can_clean = mount_can_clean,
.serialize = mount_serialize,
.deserialize_item = mount_deserialize_item,