]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add a separate unit directory for transient units
authorLennart Poettering <lennart@poettering.net>
Thu, 25 Feb 2016 00:13:57 +0000 (01:13 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 12 Apr 2016 11:43:30 +0000 (13:43 +0200)
Previously, transient units were created below the normal runtime directory
/run/systemd/system. With this change they are created in a special transient
directory /run/systemd/transient, which only contains data for transient units.

This clarifies the life-cycle of transient units, and makes clear they are
distinct from user-provided runtime units. In particular, users may now
extend transient units via /run/systemd/system, without systemd interfering
with the life-cycle of these files.

This change also adds code so that when a transient unit exits only the
drop-ins in this new directory are removed, but nothing else.

Fixes: #2139
src/core/manager.c
src/core/unit.c
src/shared/path-lookup.c
src/shared/path-lookup.h

index c72b46be30e64167f0ab16af4b0fa7684b875060..1bc7921abe8f58cd3d9a9abb92d03c730318ef5f 100644 (file)
@@ -63,6 +63,7 @@
 #include "manager.h"
 #include "missing.h"
 #include "mkdir.h"
+#include "mkdir.h"
 #include "parse-util.h"
 #include "path-lookup.h"
 #include "path-util.h"
@@ -1108,6 +1109,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         if (r < 0)
                 return r;
 
+        /* Make sure the transient directory always exists, so that it remains in the search path */
+        r = mkdir_p_label(m->lookup_paths.transient, 0755);
+        if (r < 0)
+                return r;
+
         dual_timestamp_get(&m->generators_start_timestamp);
         r = manager_run_generators(m);
         dual_timestamp_get(&m->generators_finish_timestamp);
index 565704851bbf956c96d1bed66db6359e78adf283..f6c9891aad6b3ee2e8c028ab9521685d83a734fe 100644 (file)
@@ -418,13 +418,22 @@ static void unit_remove_transient(Unit *u) {
                 (void) unlink(u->fragment_path);
 
         STRV_FOREACH(i, u->dropin_paths) {
-                _cleanup_free_ char *p = NULL;
+                _cleanup_free_ char *p = NULL, *pp = NULL;
 
-                (void) unlink(*i);
+                p = dirname_malloc(*i); /* Get the drop-in directory from the drop-in file */
+                if (!p)
+                        continue;
+
+                pp = dirname_malloc(p); /* Get the config directory from the drop-in directory */
+                if (!pp)
+                        continue;
+
+                /* Only drop transient drop-ins */
+                if (!path_equal(u->manager->lookup_paths.transient, pp))
+                        continue;
 
-                p = dirname_malloc(*i);
-                if (p)
-                        (void) rmdir(p);
+                (void) unlink(*i);
+                (void) rmdir(p);
         }
 }
 
@@ -3315,35 +3324,24 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) {
         return *(ExecRuntime**) ((uint8_t*) u + offset);
 }
 
-static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) {
+static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) {
         assert(u);
 
-        if (MANAGER_IS_USER(u->manager)) {
-                int r;
+        if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */
+                return u->manager->lookup_paths.transient;
 
-                if (mode == UNIT_PERSISTENT && !transient)
-                        r = user_config_home(dir);
-                else
-                        r = user_runtime_dir(dir);
-                if (r == 0)
-                        return -ENOENT;
+        if (mode == UNIT_RUNTIME)
+                return u->manager->lookup_paths.runtime_config;
 
-                return r;
-        }
+        if (mode == UNIT_PERSISTENT)
+                return u->manager->lookup_paths.persistent_config;
 
-        if (mode == UNIT_PERSISTENT && !transient)
-                *dir = strdup("/etc/systemd/system");
-        else
-                *dir = strdup("/run/systemd/system");
-        if (!*dir)
-                return -ENOMEM;
-
-        return 0;
+        return NULL;
 }
 
 int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
-
-        _cleanup_free_ char *dir = NULL, *p = NULL, *q = NULL;
+        _cleanup_free_ char *p = NULL, *q = NULL;
+        const char *dir;
         int r;
 
         assert(u);
@@ -3351,9 +3349,9 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co
         if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
                 return 0;
 
-        r = unit_drop_in_dir(u, mode, u->transient, &dir);
-        if (r < 0)
-                return r;
+        dir = unit_drop_in_dir(u, mode);
+        if (!dir)
+                return -EINVAL;
 
         r = write_drop_in(dir, u->id, 50, name, data);
         if (r < 0)
@@ -3398,7 +3396,7 @@ int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *n
 }
 
 int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
-        _cleanup_free_ char *ndata = NULL;
+        const char *ndata;
 
         assert(u);
         assert(name);
@@ -3410,9 +3408,7 @@ int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *
         if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
                 return 0;
 
-        ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
-        if (!ndata)
-                return -ENOMEM;
+        ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
 
         return unit_write_drop_in(u, mode, name, ndata);
 }
index 11b9bb6107ab0a303dae31b3e0540c5752376a3f..f437de370ca3919547dc373d4676aeff677ee38c 100644 (file)
@@ -111,7 +111,8 @@ static char** user_dirs(
                 const char *runtime_config,
                 const char *generator,
                 const char *generator_early,
-                const char *generator_late) {
+                const char *generator_late,
+                const char *transient) {
 
         const char * const config_unit_paths[] = {
                 USER_CONFIG_UNIT_PATH,
@@ -172,6 +173,10 @@ static char** user_dirs(
                 return NULL;
 
         /* Now merge everything we found. */
+        if (transient)
+                if (strv_extend(&res, transient) < 0)
+                        return NULL;
+
         if (generator_early)
                 if (strv_extend(&res, generator_early) < 0)
                         return NULL;
@@ -305,6 +310,42 @@ static int acquire_generator_dirs(
         return 0;
 }
 
+static int acquire_transient_dir(UnitFileScope scope, char **ret) {
+        char *transient;
+
+        assert(ret);
+
+        switch (scope) {
+
+        case UNIT_FILE_SYSTEM:
+                transient = strdup("/run/systemd/transient");
+                break;
+
+        case UNIT_FILE_USER: {
+                const char *e;
+
+                e = getenv("XDG_RUNTIME_DIR");
+                if (!e)
+                        return -ENXIO;
+
+                transient = strjoin(e, "/systemd/transient", NULL);
+                break;
+        }
+
+        case UNIT_FILE_GLOBAL:
+                return -EOPNOTSUPP;
+
+        default:
+                assert_not_reached("Hmm, unexpected scope value.");
+        }
+
+        if (!transient)
+                return -ENOMEM;
+
+        *ret = transient;
+        return 0;
+}
+
 static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
         _cleanup_free_ char *a = NULL, *b = NULL;
         int r;
@@ -377,8 +418,9 @@ int lookup_paths_init(
 
         _cleanup_free_ char
                 *root = NULL,
+                *persistent_config = NULL, *runtime_config = NULL,
                 *generator = NULL, *generator_early = NULL, *generator_late = NULL,
-                *persistent_config = NULL, *runtime_config = NULL;
+                *transient = NULL;
         bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
         char **l = NULL;
         const char *e;
@@ -411,6 +453,10 @@ int lookup_paths_init(
         if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
                 return r;
 
+        r = acquire_transient_dir(scope, &transient);
+        if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
+                return r;
+
         /* First priority is whatever has been passed to us via env
          * vars */
         e = getenv("SYSTEMD_UNIT_PATH");
@@ -449,6 +495,7 @@ int lookup_paths_init(
                         add = strv_new(
                                         /* If you modify this you also want to modify
                                          * systemdsystemunitpath= in systemd.pc.in! */
+                                        STRV_IFNOTNULL(transient),
                                         STRV_IFNOTNULL(generator_early),
                                         persistent_config,
                                         SYSTEM_CONFIG_UNIT_PATH,
@@ -471,6 +518,7 @@ int lookup_paths_init(
                                         /* If you modify this you also want to modify
                                          * systemduserunitpath= in systemd.pc.in, and
                                          * the arrays in user_dirs() above! */
+                                        STRV_IFNOTNULL(transient),
                                         STRV_IFNOTNULL(generator_early),
                                         persistent_config,
                                         USER_CONFIG_UNIT_PATH,
@@ -489,7 +537,8 @@ int lookup_paths_init(
 
                 case UNIT_FILE_USER:
                         add = user_dirs(persistent_config, runtime_config,
-                                        generator, generator_early, generator_late);
+                                        generator, generator_early, generator_late,
+                                        transient);
                         break;
 
                 default:
@@ -526,6 +575,10 @@ int lookup_paths_init(
         if (r < 0)
                 return r;
 
+        r = patch_root_prefix(&transient, root);
+        if (r < 0)
+                return r;
+
         if (!path_strv_resolve_uniq(l, root))
                 return -ENOMEM;
 
@@ -554,6 +607,9 @@ int lookup_paths_init(
         p->generator_late = generator_late;
         generator = generator_early = generator_late = NULL;
 
+        p->transient = transient;
+        transient = NULL;
+
         p->root_dir = root;
         root = NULL;
 
@@ -573,5 +629,7 @@ void lookup_paths_free(LookupPaths *p) {
         p->generator_early = mfree(p->generator_early);
         p->generator_late = mfree(p->generator_late);
 
+        p->transient = mfree(p->transient);
+
         p->root_dir = mfree(p->root_dir);
 }
index 078c3484f5092c7bfb55b6f6729bf041d57ec0b2..b0603c0c99bc52c2408bc4f63615076118558420 100644 (file)
@@ -38,6 +38,9 @@ struct LookupPaths {
         char *generator_early;
         char *generator_late;
 
+        /* Where to place transient unit files */
+        char *transient;
+
         /* The root directory prepended to all items above, or NULL */
         char *root_dir;
 };