From fe51822e7120e89566cf76278d0b78ec7db4b43a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Jul 2010 00:52:00 +0200 Subject: [PATCH] manager: introduce unit path cache to minimize disk accesses --- src/load-dropin.c | 12 +++++++-- src/load-fragment.c | 8 +++++- src/manager.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ src/manager.h | 1 + 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/load-dropin.c b/src/load-dropin.c index bdf3dd2c2..9ba1201db 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 6a71d422f..394aa023f 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 a7e24eb81..5125db2e9 100644 --- a/src/manager.c +++ b/src/manager.c @@ -36,6 +36,7 @@ #include #include #include +#include #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 f3bf96ee1..0eceab99e 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; -- 2.30.2