core: add generic "clean" operation to units
This adds basic infrastructure to implement a "clean" operation for unit types. This "clean" operation is supposed to remove on-disk resources of units, and is supposed to be used in a later commit to clean our RuntimeDirectory=, StateDirectory= and so on of service units. Later commits will open this up to the bus, and hook up service units with this. This also adds a new generic ActiveState called UNIT_MAINTENANCE. It's supposed to cover all kinds of "maintainance" state of units. Specifically, this is supposed to cover the "cleaning" operations later added for service units which might take a bit of time. This high-level, generic, abstract state is called UNIT_MAINTENANCE instead of the more specific "UNIT_CLEANING", since I think this should be kept open for different operations possibly later on that could be nicely subsumed under this (for example, maybe a recursive chown()ing operation could be covered by this, and similar).
This commit is contained in:
parent
c0228b4fa3
commit
380dc8b0a2
|
@ -102,7 +102,8 @@ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
|
|||
[UNIT_INACTIVE] = "inactive",
|
||||
[UNIT_FAILED] = "failed",
|
||||
[UNIT_ACTIVATING] = "activating",
|
||||
[UNIT_DEACTIVATING] = "deactivating"
|
||||
[UNIT_DEACTIVATING] = "deactivating",
|
||||
[UNIT_MAINTENANCE] = "maintenance",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
|
||||
|
|
|
@ -40,6 +40,7 @@ typedef enum UnitActiveState {
|
|||
UNIT_FAILED,
|
||||
UNIT_ACTIVATING,
|
||||
UNIT_DEACTIVATING,
|
||||
UNIT_MAINTENANCE,
|
||||
_UNIT_ACTIVE_STATE_MAX,
|
||||
_UNIT_ACTIVE_STATE_INVALID = -1
|
||||
} UnitActiveState;
|
||||
|
|
|
@ -132,6 +132,19 @@ typedef struct ExecDirectory {
|
|||
mode_t mode;
|
||||
} ExecDirectory;
|
||||
|
||||
typedef enum ExecCleanMask {
|
||||
/* In case you wonder why the bitmask below doesn't use "directory" in its name: we want to keep this
|
||||
* generic so that .timer timestamp files can nicely be covered by this too, and similar. */
|
||||
EXEC_CLEAN_RUNTIME = 1U << EXEC_DIRECTORY_RUNTIME,
|
||||
EXEC_CLEAN_STATE = 1U << EXEC_DIRECTORY_STATE,
|
||||
EXEC_CLEAN_CACHE = 1U << EXEC_DIRECTORY_CACHE,
|
||||
EXEC_CLEAN_LOGS = 1U << EXEC_DIRECTORY_LOGS,
|
||||
EXEC_CLEAN_CONFIGURATION = 1U << EXEC_DIRECTORY_CONFIGURATION,
|
||||
EXEC_CLEAN_NONE = 0,
|
||||
EXEC_CLEAN_ALL = (1U << _EXEC_DIRECTORY_TYPE_MAX) - 1,
|
||||
_EXEC_CLEAN_MASK_INVALID = -1,
|
||||
} ExecCleanMask;
|
||||
|
||||
/* Encodes configuration parameters applied to invoked commands. Does not carry runtime data, but only configuration
|
||||
* changes sourced from unit files and suchlike. ExecContext objects are usually embedded into Unit objects, and do not
|
||||
* change after being loaded. */
|
||||
|
|
|
@ -1750,6 +1750,8 @@ int unit_start(Unit *u) {
|
|||
state = unit_active_state(u);
|
||||
if (UNIT_IS_ACTIVE_OR_RELOADING(state))
|
||||
return -EALREADY;
|
||||
if (state == UNIT_MAINTENANCE)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Units that aren't loaded cannot be started */
|
||||
if (u->load_state != UNIT_LOADED)
|
||||
|
@ -5750,6 +5752,53 @@ int unit_test_trigger_loaded(Unit *u) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int unit_clean(Unit *u, ExecCleanMask mask) {
|
||||
UnitActiveState state;
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Special return values:
|
||||
*
|
||||
* -EOPNOTSUPP → cleaning not supported for this unit type
|
||||
* -EUNATCH → cleaning not defined for this resource type
|
||||
* -EBUSY → unit currently can't be cleaned since it's running or not properly loaded, or has
|
||||
* a job queued or similar
|
||||
*/
|
||||
|
||||
if (!UNIT_VTABLE(u)->clean)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (mask == 0)
|
||||
return -EUNATCH;
|
||||
|
||||
if (u->load_state != UNIT_LOADED)
|
||||
return -EBUSY;
|
||||
|
||||
if (u->job)
|
||||
return -EBUSY;
|
||||
|
||||
state = unit_active_state(u);
|
||||
if (!IN_SET(state, UNIT_INACTIVE))
|
||||
return -EBUSY;
|
||||
|
||||
return UNIT_VTABLE(u)->clean(u, mask);
|
||||
}
|
||||
|
||||
int unit_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
assert(u);
|
||||
|
||||
if (!UNIT_VTABLE(u)->clean ||
|
||||
u->load_state != UNIT_LOADED) {
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When the clean() method is set, can_clean() really should be set too */
|
||||
assert(UNIT_VTABLE(u)->can_clean);
|
||||
|
||||
return UNIT_VTABLE(u)->can_clean(u, ret);
|
||||
}
|
||||
|
||||
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||
[COLLECT_INACTIVE] = "inactive",
|
||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||
|
|
|
@ -475,6 +475,12 @@ typedef struct UnitVTable {
|
|||
|
||||
int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
|
||||
|
||||
/* Clear out the various runtime/state/cache/logs/configuration data */
|
||||
int (*clean)(Unit *u, ExecCleanMask m);
|
||||
|
||||
/* Return which kind of data can be cleaned */
|
||||
int (*can_clean)(Unit *u, ExecCleanMask *ret);
|
||||
|
||||
bool (*can_reload)(Unit *u);
|
||||
|
||||
/* Write all data that cannot be restored from other sources
|
||||
|
@ -854,6 +860,9 @@ int unit_failure_action_exit_status(Unit *u);
|
|||
|
||||
int unit_test_trigger_loaded(Unit *u);
|
||||
|
||||
int unit_clean(Unit *u, ExecCleanMask mask);
|
||||
int unit_can_clean(Unit *u, ExecCleanMask *ret_mask);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full(unit, level, error, ...) \
|
||||
|
|
Loading…
Reference in a new issue