[systemd-devel] [PATCH] core: add default extra dependency option

WaLyong Cho walyong.cho at samsung.com
Fri Feb 28 01:02:47 PST 2014


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



More information about the systemd-devel mailing list