summaryrefslogtreecommitdiffstats
path: root/src/shared/unit-file.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-07-10 18:01:13 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-07-30 14:01:46 +0200
commit91e0ee5f16321656ed6f827742ecbeb2b36027f2 (patch)
tree41f3b5b389f8e6353b5e8bfb34272add25b10385 /src/shared/unit-file.c
parentanalyze: add "unit-files" to dump the unit fragment map (diff)
downloadsystemd-91e0ee5f16321656ed6f827742ecbeb2b36027f2.tar.xz
systemd-91e0ee5f16321656ed6f827742ecbeb2b36027f2.zip
pid1: drop unit caches only based on mtime
v2: - do not watch mtime of transient and generated dirs We'd reload the map after every transient unit we created, which we don't need to do, since we create those units ourselves and know their fragment path.
Diffstat (limited to 'src/shared/unit-file.c')
-rw-r--r--src/shared/unit-file.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c
index 90fa949d24..8a09f3827f 100644
--- a/src/shared/unit-file.c
+++ b/src/shared/unit-file.c
@@ -152,8 +152,47 @@ static int unit_ids_map_get(
return -ELOOP;
}
+static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) {
+ /* Paths that are under our exclusive control. Users shall not alter those directly. */
+
+ return streq_ptr(path, lp->generator) ||
+ streq_ptr(path, lp->generator_early) ||
+ streq_ptr(path, lp->generator_late) ||
+ streq_ptr(path, lp->transient) ||
+ streq_ptr(path, lp->persistent_control) ||
+ streq_ptr(path, lp->runtime_control);
+}
+
+static bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) {
+ char **dir;
+
+ STRV_FOREACH(dir, (char**) lp->search_path) {
+ struct stat st;
+
+ if (lookup_paths_mtime_exclude(lp, *dir))
+ continue;
+
+ /* Determine the latest lookup path modification time */
+ if (stat(*dir, &st) < 0) {
+ if (errno == ENOENT)
+ continue;
+
+ log_debug_errno(errno, "Failed to stat %s, ignoring: %m", *dir);
+ continue;
+ }
+
+ if (timespec_load(&st.st_mtim) > mtime) {
+ log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir);
+ return false;
+ }
+ }
+
+ return true;
+}
+
int unit_file_build_name_map(
const LookupPaths *lp,
+ usec_t *cache_mtime,
Hashmap **ret_unit_ids_map,
Hashmap **ret_unit_names_map,
Set **ret_path_cache) {
@@ -171,6 +210,12 @@ int unit_file_build_name_map(
_cleanup_set_free_free_ Set *paths = NULL;
char **dir;
int r;
+ usec_t mtime = 0;
+
+ /* Before doing anything, check if the mtime that was passed is still valid. If
+ * yes, do nothing. If *cache_time == 0, always build the cache. */
+ if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime))
+ return 0;
if (ret_path_cache) {
paths = set_new(&path_hash_ops);
@@ -181,6 +226,7 @@ int unit_file_build_name_map(
STRV_FOREACH(dir, (char**) lp->search_path) {
struct dirent *de;
_cleanup_closedir_ DIR *d = NULL;
+ struct stat st;
d = opendir(*dir);
if (!d) {
@@ -189,6 +235,13 @@ int unit_file_build_name_map(
continue;
}
+ /* Determine the latest lookup path modification time */
+ if (fstat(dirfd(d), &st) < 0)
+ return log_error_errno(errno, "Failed to fstat %s: %m", *dir);
+
+ if (!lookup_paths_mtime_exclude(lp, *dir))
+ mtime = MAX(mtime, timespec_load(&st.st_mtim));
+
FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
char *filename;
_cleanup_free_ char *_filename_free = NULL, *simplified = NULL;
@@ -316,12 +369,14 @@ int unit_file_build_name_map(
basename(dst), src);
}
+ if (cache_mtime)
+ *cache_mtime = mtime;
*ret_unit_ids_map = TAKE_PTR(ids);
*ret_unit_names_map = TAKE_PTR(names);
if (ret_path_cache)
*ret_path_cache = TAKE_PTR(paths);
- return 0;
+ return 1;
}
int unit_file_find_fragment(