core: add a separate unit directory for transient units
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
This commit is contained in:
parent
5f0a41dade
commit
3959135139
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
(void) unlink(*i);
|
||||
|
||||
p = dirname_malloc(*i);
|
||||
if (p)
|
||||
(void) rmdir(p);
|
||||
(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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue