summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/load-dropin.c12
-rw-r--r--src/load-fragment.c8
-rw-r--r--src/manager.c65
-rw-r--r--src/manager.h1
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;