summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-06-25 11:31:28 +0200
committerLennart Poettering <lennart@poettering.net>2019-07-11 12:18:51 +0200
commit380dc8b0a25f544269fdff7d9fd0e488fb374031 (patch)
tree8272684786fb0df16e30f2ad07b57b972ddddfb1 /src/core
parentc0228b4fa3e4e633afa5eb8417e6cd3e311cd250 (diff)
downloadsystemd-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/core')
-rw-r--r--src/core/execute.h13
-rw-r--r--src/core/unit.c49
-rw-r--r--src/core/unit.h9
3 files changed, 71 insertions, 0 deletions
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, ...) \