From ac19bdd04b376c12787b75428bf3d6caf43805ff Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 23 Jun 2021 17:32:15 +0200 Subject: [PATCH] core: avoid calling path_simplify() unnecessarilly for u.requires_mounts_for keys MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We would always call path_simplify() before doing a lookup, which requires the path key to be duplicated first. But the hashmap lookup doesn't require this… So let's opportunistically skip the allocation if the key is already present. Inspired by https://github.com/systemd/systemd/pull/19973. --- src/core/manager.c | 10 ++++------ src/core/unit.c | 30 ++++++++++++++---------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 21358a0469b..f3275a4070e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -4511,16 +4511,14 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons va_end(ap); } -Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { - char p[strlen(path)+1]; - +Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) { assert(m); assert(path); - strcpy(p, path); - path_simplify(p); + if (path_equal(path, "/")) + path = ""; - return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); + return hashmap_get(m->units_requiring_mounts_for, path); } int manager_update_failed_units(Manager *m, Unit *u, bool failed) { diff --git a/src/core/unit.c b/src/core/unit.c index 0cfb2aa281f..3792cee7112 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4562,45 +4562,43 @@ int unit_kill_context( } int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) { - _cleanup_free_ char *p = NULL; - UnitDependencyInfo di; int r; assert(u); assert(path); - /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in - * the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to - * be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily - * determine which units to make themselves a dependency of. */ + /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these + * paths in the unit (from the path to the UnitDependencyInfo structure indicating how to the + * dependency came to be). However, we build a prefix table for all possible prefixes so that new + * appearing mount units can easily determine which units to make themselves a dependency of. */ if (!path_is_absolute(path)) return -EINVAL; - r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops); - if (r < 0) - return r; + if (hashmap_contains(u->requires_mounts_for, path)) /* Exit quickly if the path is already covered. */ + return 0; - p = strdup(path); + _cleanup_free_ char *p = strdup(path); if (!p) return -ENOMEM; + /* Use the canonical form of the path as the stored key. We call path_is_normalized() + * only after simplification, since path_is_normalized() rejects paths with '.'. + * path_is_normalized() also verifies that the path fits in PATH_MAX. */ path = path_simplify(p); if (!path_is_normalized(path)) return -EPERM; - if (hashmap_contains(u->requires_mounts_for, path)) - return 0; - - di = (UnitDependencyInfo) { + UnitDependencyInfo di = { .origin_mask = mask }; - r = hashmap_put(u->requires_mounts_for, path, di.data); + r = hashmap_ensure_put(&u->requires_mounts_for, &path_hash_ops, p, di.data); if (r < 0) return r; - p = NULL; + assert(r > 0); + TAKE_PTR(p); /* path remains a valid pointer to the string stored in the hashmap */ char prefix[strlen(path) + 1]; PATH_FOREACH_PREFIX_MORE(prefix, path) { -- 2.47.3