systemd is already provide a special unit. If the type of unit is service then that is 'basic.target'. Additionally default extra dependency can be listed in system.conf and then other service unit will have "After=" dependency implicitly. In config directory /etc/systemd/default-extra-dependencies, if a service unit is listed ignore-units or exist symlink in ignore-units.d then the service units can be launched before extra dependencies. --- src/core/main.c | 4 +++ src/core/manager.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/manager.h | 2 ++ src/core/service.c | 50 +++++++++++++++++++++++++++++ src/core/system.conf | 1 + 5 files changed, 142 insertions(+)
diff --git a/src/core/main.c b/src/core/main.c index d3581fc..4352138 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -102,6 +102,7 @@ static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; static usec_t arg_runtime_watchdog = 0; static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; static char **arg_default_environment = NULL; +static char **arg_default_extra_dependencies = NULL; static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {}; static uint64_t arg_capability_bounding_set_drop = 0; static nsec_t arg_timer_slack_nsec = (nsec_t) -1; @@ -660,6 +661,7 @@ static int parse_config_file(void) { { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst }, { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment }, + { "Manager", "DefaultExtraDependencies", config_parse_strv, 0, &arg_default_extra_dependencies }, { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU] }, { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] }, { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA] }, @@ -1611,6 +1613,8 @@ int main(int argc, char *argv[]) { manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); manager_set_show_status(m, arg_show_status); + if (arg_running_as == SYSTEMD_SYSTEM && arg_default_extra_dependencies) + manager_set_default_extra_dependencies(m, arg_default_extra_dependencies); /* Remember whether we should queue the default job */ queue_default_job = !arg_serialization || arg_switched_root; diff --git a/src/core/manager.c b/src/core/manager.c index f5801b4..7605777 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -67,6 +67,7 @@ #include "audit-fd.h" #include "boot-timestamps.h" #include "env-util.h" +#include "fileio.c" #include "bus-errors.h" #include "bus-error.h" #include "bus-util.h" @@ -2720,6 +2721,90 @@ int manager_environment_add(Manager *m, char **minus, char **plus) { return 0; } +int manager_set_default_extra_dependencies(Manager *m, char **dependencies) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *de; + char *state, *word, **d = NULL; + size_t len; + int r = 0; + + assert(m); + + if (strv_extend_strv(&m->dependencies, dependencies) < 0) { + strv_free(m->dependencies); + return log_oom(); + } + + if (mkdir("/run/systemd/default-extra-dependencies", 0755) && errno != EEXIST) + return -errno; + + f = fopen("/run/systemd/default-extra-dependencies/ignore-units", "we"); + if (!f) + return -errno; + + STRV_FOREACH(d, m->dependencies) { + r = write_string_to_file(f, *d); + if (r < 0) + return r; + } + + r = read_full_file(PKGSYSCONFDIR "/default-extra-dependencies/ignore-units", + &buf, NULL); + if (r < 0) + goto dir; + + FOREACH_WORD_SEPARATOR(word, len, buf, NEWLINE, state) { + _cleanup_free_ char *copy; + + copy = strndup(word, len); + if (!copy) + return -ENOMEM; + + if (len <= 0) + continue; + + r = write_string_to_file(f, copy); + if (r < 0) + return r; + } + +dir: + dir = opendir(PKGSYSCONFDIR "/default-extra-dependencies/ignore-units.d"); + if (!dir) + return 0; + + FOREACH_DIRENT(de, dir, return -errno) { + _cleanup_free_ char *src = NULL, *dst = NULL; + + if (de->d_type != DT_LNK) + continue; + + src = strappend(PKGSYSCONFDIR "/default-extra-dependencies/ignore-units.d/", + de->d_name); + if (!src) { + r = -ENOMEM; + return r; + } + + r = readlink_and_canonicalize(src, &dst); + if (r < 0) + continue; + + if (access(dst, F_OK) < 0) { + log_debug("Failed to add extra dependency for unit %s, ignoring: %m", dst); + continue; + } + + r = write_string_to_file(f, basename(dst)); + if (r < 0) + return r; + } + + return 0; +} + int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { int i; diff --git a/src/core/manager.h b/src/core/manager.h index 9dee48d..f1a353f 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -125,6 +125,7 @@ struct Manager { Set *unit_path_cache; char **environment; + char **dependencies; usec_t runtime_watchdog; usec_t shutdown_watchdog; @@ -278,6 +279,7 @@ void manager_clear_jobs(Manager *m); unsigned manager_dispatch_load_queue(Manager *m); int manager_environment_add(Manager *m, char **minus, char **plus); +int manager_set_default_extra_dependencies(Manager *m, char **dependencies); int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit); int manager_loop(Manager *m); diff --git a/src/core/service.c b/src/core/service.c index 6de24ec..f38b5ad 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1123,6 +1123,53 @@ static int service_verify(Service *s) { return 0; } +static bool check_ignore_default_extra_dependencies(Service *s) { + _cleanup_free_ char *buf = NULL, *p = NULL; + _cleanup_closedir_ DIR *dir = NULL; + char *state, *word; + int r; + size_t len; + + r = read_full_file("/run/systemd/default-extra-dependencies/ignore-units", + &buf, NULL); + if (r < 0) + return false; + + FOREACH_WORD_SEPARATOR(word, len, buf, NEWLINE, state) { + _cleanup_free_ char *copy; + + copy = strndup(word, len); + if (streq(copy, UNIT(s)->id)) + return true; + } + + return false; +} + +static int add_default_extra_dependencies(Service *s) { + char **d; + int r; + bool ignore; + + if (!(UNIT(s)->manager->dependencies)) + return 0; + + /* Do NOT add dependencies for systemd unit files */ + if (startswith(UNIT(s)->id, "systemd-")) + return 0; + + ignore = check_ignore_default_extra_dependencies(s); + if (ignore) + return 0; + + STRV_FOREACH(d, UNIT(s)->manager->dependencies) { + r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, *d, NULL, true); + if (r < 0) + return r; + } + return 0; +} + static int service_add_default_dependencies(Service *s) { int r; @@ -1137,6 +1184,9 @@ static int service_add_default_dependencies(Service *s) { if (r < 0) return r; + r = add_default_extra_dependencies(s); + if (r < 0) + return r; /* Second, activate normal shutdown */ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); diff --git a/src/core/system.conf b/src/core/system.conf index 5be158d..aa7d80a 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -31,6 +31,7 @@ #DefaultStartLimitInterval=10s #DefaultStartLimitBurst=5 #DefaultEnvironment= +#DefaultExtraDependencies= #DefaultCPUAccounting=no #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no -- 1.7.9.5 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel