[systemd-devel] [PATCH] [RFCv3] Introspect and monitor dropin configuration

Oleksii Shevchuk alxchk at gmail.com
Mon Apr 1 03:32:35 PDT 2013


---
 src/core/dbus-unit.c   |  1 +
 src/core/dbus-unit.h   |  1 +
 src/core/load-dropin.c | 60 ++++++++++++++++++++++++++++++++++----------------
 src/core/load-dropin.h |  1 +
 src/core/unit.c        | 32 ++++++++++++++++++++++++++-
 src/core/unit.h        |  2 ++
 6 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index dc7d1f1..f413386 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1284,6 +1284,7 @@ const BusProperty bus_unit_properties[] = {
         { "SubState",             bus_unit_append_sub_state,          "s", 0 },
         { "FragmentPath",         bus_property_append_string,         "s", offsetof(Unit, fragment_path),                              true },
         { "SourcePath",           bus_property_append_string,         "s", offsetof(Unit, source_path),                                true },
+        { "DropinPaths",          bus_property_append_strv,          "as", offsetof(Unit, dropin_paths),                               true },
         { "UnitFileState",        bus_unit_append_file_state,         "s", 0 },
         { "InactiveExitTimestamp",bus_property_append_usec,           "t", offsetof(Unit, inactive_exit_timestamp.realtime)   },
         { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic)  },
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index 34980b0..e4c5666 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -88,6 +88,7 @@
         "  <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"SourcePath\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"DropinPaths\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 95c9a38..6a57532 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -137,12 +137,44 @@ static int process_dir(Unit *u, const char *unit_path, const char *name, const c
         return 0;
 }
 
-int unit_load_dropin(Unit *u) {
+char ** unit_find_dropin_paths(Unit *u) {
         Iterator i;
         char *t;
         _cleanup_strv_free_ char **strv = NULL;
+        char **configs = NULL;
         int r;
 
+        assert(u);
+
+        SET_FOREACH(t, u->names, i) {
+                char **p;
+
+                STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
+                        /* This loads the drop-in config snippets */
+                        r = process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
+                        if (r < 0)
+                                return NULL;
+                }
+        }
+
+        if (!strv_isempty(strv)) {
+                r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
+                if (r < 0) {
+                        log_error("Failed to get list of configuration files: %s", strerror(-r));
+                        strv_free(configs);
+                        return NULL;
+                }
+
+        }
+
+        return configs;
+}
+
+int unit_load_dropin(Unit *u) {
+        Iterator i;
+        char *t, **f;
+        _cleanup_strv_free_ char **strv = NULL;
+        int r;
 
         assert(u);
 
@@ -159,30 +191,20 @@ int unit_load_dropin(Unit *u) {
                         r = process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL);
                         if (r < 0)
                                 return r;
-
-                        /* This loads the drop-in config snippets */
-                        r = process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
-                        if (r < 0)
-                                return r;
                 }
         }
 
-        if (!strv_isempty(strv)) {
-                _cleanup_strv_free_ char **files = NULL;
-                char **f;
+        u->dropin_paths = unit_find_dropin_paths(u);
+        if (! u->dropin_paths)
+                return 0;
 
-                r = conf_files_list_strv(&files, ".conf", NULL, (const char**) strv);
-                if (r < 0) {
-                        log_error("Failed to get list of configuration files: %s", strerror(-r));
+        STRV_FOREACH(f, u->dropin_paths) {
+                r = config_parse(*f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
+                if (r < 0)
                         return r;
-                }
-
-                STRV_FOREACH(f, files) {
-                        r = config_parse(*f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
-                        if (r < 0)
-                                return r;
-                }
         }
 
+        u->dropin_mtime = now(CLOCK_REALTIME);
+
         return 0;
 }
diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h
index 1d2fafe..277bff3 100644
--- a/src/core/load-dropin.h
+++ b/src/core/load-dropin.h
@@ -25,4 +25,5 @@
 
 /* Read service data supplementary drop-in directories */
 
+char ** unit_find_dropin_paths(Unit *u);
 int unit_load_dropin(Unit *u);
diff --git a/src/core/unit.c b/src/core/unit.c
index 7111679..75a49d5 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -408,6 +408,7 @@ void unit_free(Unit *u) {
         strv_free(u->documentation);
         free(u->fragment_path);
         free(u->source_path);
+        strv_free(u->dropin_paths);
         free(u->instance);
 
         set_free_free(u->names);
@@ -696,6 +697,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
         if (u->source_path)
                 fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
 
+        STRV_FOREACH(j, u->dropin_paths)
+                fprintf(f, "%s\tDropin Path: %s\n", prefix, *j);
+
         if (u->job_timeout > 0)
                 fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout));
 
@@ -2553,7 +2557,10 @@ void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg
 }
 
 bool unit_need_daemon_reload(Unit *u) {
+        _cleanup_strv_free_ char **t = NULL;
+        char **path;
         struct stat st;
+        unsigned loaded_cnt, current_cnt;
 
         assert(u);
 
@@ -2578,7 +2585,30 @@ bool unit_need_daemon_reload(Unit *u) {
                         return true;
         }
 
-        return false;
+        t = unit_find_dropin_paths(u);
+        loaded_cnt = strv_length(t);
+        current_cnt = strv_length(u->dropin_paths);
+
+        if (loaded_cnt == current_cnt) {
+                if (loaded_cnt == 0)
+                        return false;
+
+                if (strv_overlap(u->dropin_paths, t)) {
+                        STRV_FOREACH(path, u->dropin_paths) {
+                                zero(st);
+                                if (stat(*path, &st) < 0)
+                                        return true;
+
+                                if (u->dropin_mtime > 0 &&
+                                    timespec_load(&st.st_mtim) > u->dropin_mtime)
+                                        return true;
+                        }
+
+                        return false;
+                } else
+                        return true;
+        } else
+                return true;
 }
 
 void unit_reset_failed(Unit *u) {
diff --git a/src/core/unit.h b/src/core/unit.h
index 3da6a50..80a96e8 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -138,8 +138,10 @@ struct Unit {
 
         char *fragment_path; /* if loaded from a config file this is the primary path to it */
         char *source_path; /* if converted, the source file */
+        char **dropin_paths;
         usec_t fragment_mtime;
         usec_t source_mtime;
+        usec_t dropin_mtime;
 
         /* If there is something to do with this unit, then this is the installed job for it */
         Job *job;
-- 
1.8.1.2



More information about the systemd-devel mailing list