diff options
-rw-r--r-- | src/load-dropin.c | 12 | ||||
-rw-r--r-- | src/load-fragment.c | 8 | ||||
-rw-r--r-- | src/manager.c | 65 | ||||
-rw-r--r-- | src/manager.h | 1 |
4 files changed, 83 insertions, 3 deletions
diff --git a/src/load-dropin.c b/src/load-dropin.c index bdf3dd2c2e..9ba1201dbc 100644 --- a/src/load-dropin.c +++ b/src/load-dropin.c @@ -84,7 +84,11 @@ int unit_load_dropin(Unit *u) { if (asprintf(&path, "%s/%s.wants", *p, t) < 0) return -ENOMEM; - r = iterate_dir(u, path); + if (u->meta.manager->unit_path_cache && + !set_get(u->meta.manager->unit_path_cache, path)) + r = 0; + else + r = iterate_dir(u, path); free(path); if (r < 0) @@ -103,7 +107,11 @@ int unit_load_dropin(Unit *u) { if (r < 0) return -ENOMEM; - r = iterate_dir(u, path); + if (u->meta.manager->unit_path_cache && + !set_get(u->meta.manager->unit_path_cache, path)) + r = 0; + else + r = iterate_dir(u, path); free(path); if (r < 0) diff --git a/src/load-fragment.c b/src/load-fragment.c index 6a71d422f4..394aa023f3 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1690,7 +1690,13 @@ static int load_from_path(Unit *u, const char *path) { goto finish; } - if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) { + if (u->meta.manager->unit_path_cache && + !set_get(u->meta.manager->unit_path_cache, filename)) + r = -ENOENT; + else + r = open_follow(&filename, &f, symlink_names, &id); + + if (r < 0) { char *sn; free(filename); diff --git a/src/manager.c b/src/manager.c index a7e24eb812..5125db2e9a 100644 --- a/src/manager.c +++ b/src/manager.c @@ -36,6 +36,7 @@ #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> +#include <dirent.h> #include "manager.h" #include "hashmap.h" @@ -478,11 +479,71 @@ int manager_coldplug(Manager *m) { return r; } +static void manager_build_unit_path_cache(Manager *m) { + char **i; + DIR *d = NULL; + int r; + + assert(m); + + set_free_free(m->unit_path_cache); + + if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) { + log_error("Failed to allocate unit path cache."); + return; + } + + /* This simply builds a list of files we know exist, so that + * we don't always have to go to disk */ + + STRV_FOREACH(i, m->lookup_paths.unit_path) { + struct dirent *de; + + if (!(d = opendir(*i))) { + log_error("Failed to open directory: %m"); + continue; + } + + while ((de = readdir(d))) { + char *p; + + if (ignore_file(de->d_name)) + continue; + + if (asprintf(&p, "%s/%s", streq(*i, "/") ? "" : *i, de->d_name) < 0) { + r = -ENOMEM; + goto fail; + } + + if ((r = set_put(m->unit_path_cache, p)) < 0) { + free(p); + goto fail; + } + } + + closedir(d); + d = NULL; + } + + return; + +fail: + log_error("Failed to build unit path cache: %s", strerror(-r)); + + set_free_free(m->unit_path_cache); + m->unit_path_cache = NULL; + + if (d) + closedir(d); +} + int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { int r, q; assert(m); + manager_build_unit_path_cache(m); + /* First, enumerate what we can from all config files */ r = manager_enumerate(m); @@ -1993,6 +2054,10 @@ int manager_loop(Manager *m) { assert(m); m->exit_code = MANAGER_RUNNING; + /* Release the path cache */ + set_free_free(m->unit_path_cache); + m->unit_path_cache = NULL; + /* There might still be some zombies hanging around from * before we were exec()'ed. Leat's reap them */ if ((r = manager_dispatch_sigchld(m)) < 0) diff --git a/src/manager.h b/src/manager.h index f3bf96ee16..0eceab99ea 100644 --- a/src/manager.h +++ b/src/manager.h @@ -134,6 +134,7 @@ struct Manager { unsigned n_snapshots; LookupPaths lookup_paths; + Set *unit_path_cache; char **environment; |