diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-06-25 11:31:28 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-07-11 12:18:51 +0200 |
commit | 380dc8b0a25f544269fdff7d9fd0e488fb374031 (patch) | |
tree | 8272684786fb0df16e30f2ad07b57b972ddddfb1 /src | |
parent | c0228b4fa3e4e633afa5eb8417e6cd3e311cd250 (diff) | |
download | systemd-380dc8b0a25f544269fdff7d9fd0e488fb374031.tar.gz systemd-380dc8b0a25f544269fdff7d9fd0e488fb374031.tar.bz2 systemd-380dc8b0a25f544269fdff7d9fd0e488fb374031.zip |
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).
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/unit-def.c | 3 | ||||
-rw-r--r-- | src/basic/unit-def.h | 1 | ||||
-rw-r--r-- | src/core/execute.h | 13 | ||||
-rw-r--r-- | src/core/unit.c | 49 | ||||
-rw-r--r-- | src/core/unit.h | 9 |
5 files changed, 74 insertions, 1 deletions
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c index 245daabcf8..3c0482366e 100644 --- a/src/basic/unit-def.c +++ b/src/basic/unit-def.c @@ -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); diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h index 85f3e42d30..b3e111da3f 100644 --- a/src/basic/unit-def.h +++ b/src/basic/unit-def.h @@ -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; diff --git a/src/core/execute.h b/src/core/execute.h index 609e15fc07..1b4998a759 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -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. */ diff --git a/src/core/unit.c b/src/core/unit.c index d880e709ae..5bf905c312 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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", diff --git a/src/core/unit.h b/src/core/unit.h index 02c7a56392..603c20a904 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -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, ...) \ |