Commit ae7a7182 authored by Oleksii Shevchuk's avatar Oleksii Shevchuk Committed by Zbigniew Jędrzejewski-Szmek

Introspect and monitor dropin configuration

parent 050fbdb8
......@@ -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) },
......
......@@ -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" \
......
......@@ -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;
}
......@@ -25,4 +25,5 @@
/* Read service data supplementary drop-in directories */
char **unit_find_dropin_paths(Unit *u);
int unit_load_dropin(Unit *u);
......@@ -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) {
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment