a4b143
From f0af1f20acc04b744f4ce1ed4b028e84576541d7 Mon Sep 17 00:00:00 2001
a4b143
From: Lennart Poettering <lennart@poettering.net>
a4b143
Date: Thu, 26 Sep 2013 20:14:24 +0200
a4b143
Subject: [PATCH] core: rework how we match mount units against each other
a4b143
a4b143
Previously to automatically create dependencies between mount units we
a4b143
matched every mount unit agains all others resulting in O(n^2)
a4b143
complexity. On setups with large amounts of mount units this might make
a4b143
things slow.
a4b143
a4b143
This change replaces the matching code to use a hashtable that is keyed
a4b143
by a path prefix, and points to a set of units that require that path to
a4b143
be around. When a new mount unit is installed it is hence sufficient to
a4b143
simply look up this set of units via its own file system paths to know
a4b143
which units to order after itself.
a4b143
a4b143
This patch also changes all unit types to only create automatic mount
a4b143
dependencies via the RequiresMountsFor= logic, and this is exposed to
a4b143
the outside to make things more transparent.
a4b143
a4b143
With this change we still have some O(n) complexities in place when
a4b143
handling mounts, but that's currently unavoidable due to kernel APIs,
a4b143
and still substantially better than O(n^2) as before.
a4b143
a4b143
https://bugs.freedesktop.org/show_bug.cgi?id=69740
a4b143
---
a4b143
 src/core/automount.c                  |  33 +----
a4b143
 src/core/automount.h                  |   2 -
a4b143
 src/core/load-fragment-gperf.gperf.m4 |   2 +-
a4b143
 src/core/load-fragment.c              |  47 ++++---
a4b143
 src/core/manager.c                    |  44 +++++-
a4b143
 src/core/manager.h                    |  12 +-
a4b143
 src/core/mount.c                      | 255 +++++++++-------------------------
a4b143
 src/core/path.c                       |  32 +----
a4b143
 src/core/path.h                       |   4 -
a4b143
 src/core/socket.c                     |  49 ++-----
a4b143
 src/core/socket.h                     |   4 -
a4b143
 src/core/swap.c                       |  40 +-----
a4b143
 src/core/swap.h                       |   2 -
a4b143
 src/core/unit.c                       | 162 +++++++++++++++++----
a4b143
 src/core/unit.h                       |   6 +-
a4b143
 src/shared/socket-util.c              |   8 +-
a4b143
 src/shared/socket-util.h              |   2 +-
a4b143
 17 files changed, 309 insertions(+), 395 deletions(-)
a4b143
a4b143
diff --git a/src/core/automount.c b/src/core/automount.c
a4b143
index 6762392..d1379e0 100644
a4b143
--- a/src/core/automount.c
a4b143
+++ b/src/core/automount.c
a4b143
@@ -117,42 +117,17 @@ static void automount_done(Unit *u) {
a4b143
         a->tokens = NULL;
a4b143
 }
a4b143
 
a4b143
-int automount_add_one_mount_link(Automount *a, Mount *m) {
a4b143
+static int automount_add_mount_links(Automount *a) {
a4b143
+        _cleanup_free_ char *parent = NULL;
a4b143
         int r;
a4b143
 
a4b143
         assert(a);
a4b143
-        assert(m);
a4b143
-
a4b143
-        if (UNIT(a)->load_state != UNIT_LOADED ||
a4b143
-            UNIT(m)->load_state != UNIT_LOADED)
a4b143
-                return 0;
a4b143
-
a4b143
-        if (!path_startswith(a->where, m->where))
a4b143
-                return 0;
a4b143
 
a4b143
-        if (path_equal(a->where, m->where))
a4b143
-                return 0;
a4b143
-
a4b143
-        r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
a4b143
+        r = path_get_parent(a->where, &parent);
a4b143
         if (r < 0)
a4b143
                 return r;
a4b143
 
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int automount_add_mount_links(Automount *a) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(a);
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT]) {
a4b143
-                r = automount_add_one_mount_link(a, MOUNT(other));
a4b143
-                if (r < 0)
a4b143
-                        return r;
a4b143
-        }
a4b143
-
a4b143
-        return 0;
a4b143
+        return unit_require_mounts_for(UNIT(a), parent);
a4b143
 }
a4b143
 
a4b143
 static int automount_add_default_dependencies(Automount *a) {
a4b143
diff --git a/src/core/automount.h b/src/core/automount.h
a4b143
index 0c6b8a7..a7a25d3 100644
a4b143
--- a/src/core/automount.h
a4b143
+++ b/src/core/automount.h
a4b143
@@ -62,8 +62,6 @@ extern const UnitVTable automount_vtable;
a4b143
 
a4b143
 int automount_send_ready(Automount *a, int status);
a4b143
 
a4b143
-int automount_add_one_mount_link(Automount *a, Mount *m);
a4b143
-
a4b143
 const char* automount_state_to_string(AutomountState i) _const_;
a4b143
 AutomountState automount_state_from_string(const char *s) _pure_;
a4b143
 
a4b143
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
a4b143
index 33c6880..3f064a9 100644
a4b143
--- a/src/core/load-fragment-gperf.gperf.m4
a4b143
+++ b/src/core/load-fragment-gperf.gperf.m4
a4b143
@@ -117,7 +117,7 @@ Unit.PropagateReloadTo,          config_parse_unit_deps,             UNIT_PROPAG
a4b143
 Unit.ReloadPropagatedFrom,       config_parse_unit_deps,             UNIT_RELOAD_PROPAGATED_FROM,   0
a4b143
 Unit.PropagateReloadFrom,        config_parse_unit_deps,             UNIT_RELOAD_PROPAGATED_FROM,   0
a4b143
 Unit.PartOf,                     config_parse_unit_deps,             UNIT_PART_OF,                  0
a4b143
-Unit.RequiresMountsFor,          config_parse_unit_requires_mounts_for, 0,                          offsetof(Unit, requires_mounts_for)
a4b143
+Unit.RequiresMountsFor,          config_parse_unit_requires_mounts_for, 0,                          0
a4b143
 Unit.StopWhenUnneeded,           config_parse_bool,                  0,                             offsetof(Unit, stop_when_unneeded)
a4b143
 Unit.RefuseManualStart,          config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_start)
a4b143
 Unit.RefuseManualStop,           config_parse_bool,                  0,                             offsetof(Unit, refuse_manual_stop)
a4b143
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
a4b143
index f4a268c..ed8602f 100644
a4b143
--- a/src/core/load-fragment.c
a4b143
+++ b/src/core/load-fragment.c
a4b143
@@ -1742,33 +1742,48 @@ int config_parse_unit_condition_null(const char *unit,
a4b143
 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
a4b143
 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
a4b143
 
a4b143
-int config_parse_unit_requires_mounts_for(const char *unit,
a4b143
-                                          const char *filename,
a4b143
-                                          unsigned line,
a4b143
-                                          const char *section,
a4b143
-                                          const char *lvalue,
a4b143
-                                          int ltype,
a4b143
-                                          const char *rvalue,
a4b143
-                                          void *data,
a4b143
-                                          void *userdata) {
a4b143
+int config_parse_unit_requires_mounts_for(
a4b143
+                const char *unit,
a4b143
+                const char *filename,
a4b143
+                unsigned line,
a4b143
+                const char *section,
a4b143
+                const char *lvalue,
a4b143
+                int ltype,
a4b143
+                const char *rvalue,
a4b143
+                void *data,
a4b143
+                void *userdata) {
a4b143
 
a4b143
         Unit *u = userdata;
a4b143
+        char *state;
a4b143
+        size_t l;
a4b143
+        char *w;
a4b143
         int r;
a4b143
-        bool empty_before;
a4b143
 
a4b143
         assert(filename);
a4b143
         assert(lvalue);
a4b143
         assert(rvalue);
a4b143
         assert(data);
a4b143
 
a4b143
-        empty_before = !u->requires_mounts_for;
a4b143
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
a4b143
+                _cleanup_free_ char *n;
a4b143
+
a4b143
+                n = strndup(w, l);
a4b143
+                if (!n)
a4b143
+                        return log_oom();
a4b143
 
a4b143
-        r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype,
a4b143
-                                   rvalue, data, userdata);
a4b143
+                if (!utf8_is_valid(n)) {
a4b143
+                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
a4b143
+                                   "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
a4b143
+                        continue;
a4b143
+                }
a4b143
 
a4b143
-        /* Make it easy to find units with requires_mounts set */
a4b143
-        if (empty_before && u->requires_mounts_for)
a4b143
-                LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
a4b143
+                r = unit_require_mounts_for(u, n);
a4b143
+                if (r < 0) {
a4b143
+                        log_syntax(unit, LOG_ERR, filename, line, r,
a4b143
+                                   "Failed to add required mount for, ignoring: %s", rvalue);
a4b143
+                        continue;
a4b143
+                }
a4b143
+        }
a4b143
 
a4b143
         return r;
a4b143
 }
a4b143
diff --git a/src/core/manager.c b/src/core/manager.c
a4b143
index 669af15..dadbedd 100644
a4b143
--- a/src/core/manager.c
a4b143
+++ b/src/core/manager.c
a4b143
@@ -771,6 +771,9 @@ void manager_free(Manager *m) {
a4b143
         for (i = 0; i < RLIMIT_NLIMITS; i++)
a4b143
                 free(m->rlimit[i]);
a4b143
 
a4b143
+        assert(hashmap_isempty(m->units_requiring_mounts_for));
a4b143
+        hashmap_free(m->units_requiring_mounts_for);
a4b143
+
a4b143
         free(m);
a4b143
 }
a4b143
 
a4b143
@@ -783,9 +786,11 @@ int manager_enumerate(Manager *m) {
a4b143
         /* Let's ask every type to load all units from disk/kernel
a4b143
          * that it might know */
a4b143
         for (c = 0; c < _UNIT_TYPE_MAX; c++)
a4b143
-                if (unit_vtable[c]->enumerate)
a4b143
-                        if ((q = unit_vtable[c]->enumerate(m)) < 0)
a4b143
+                if (unit_vtable[c]->enumerate) {
a4b143
+                        q = unit_vtable[c]->enumerate(m);
a4b143
+                        if (q < 0)
a4b143
                                 r = q;
a4b143
+                }
a4b143
 
a4b143
         manager_dispatch_load_queue(m);
a4b143
         return r;
a4b143
@@ -2765,6 +2770,41 @@ void manager_status_printf(Manager *m, bool ephemeral, const char *status, const
a4b143
         va_end(ap);
a4b143
 }
a4b143
 
a4b143
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
a4b143
+        _cleanup_free_ char *p = NULL;
a4b143
+        Unit *found;
a4b143
+
a4b143
+        assert(m);
a4b143
+        assert(path);
a4b143
+        assert(suffix);
a4b143
+        assert(_found);
a4b143
+
a4b143
+        p = unit_name_from_path(path, suffix);
a4b143
+        if (!p)
a4b143
+                return -ENOMEM;
a4b143
+
a4b143
+        found = manager_get_unit(m, p);
a4b143
+        if (!found) {
a4b143
+                *_found = NULL;
a4b143
+                return 0;
a4b143
+        }
a4b143
+
a4b143
+        *_found = found;
a4b143
+        return 1;
a4b143
+}
a4b143
+
a4b143
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
a4b143
+        char p[strlen(path)+1];
a4b143
+
a4b143
+        assert(m);
a4b143
+        assert(path);
a4b143
+
a4b143
+        strcpy(p, path);
a4b143
+        path_kill_slashes(p);
a4b143
+
a4b143
+        return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
a4b143
+}
a4b143
+
a4b143
 void watch_init(Watch *w) {
a4b143
         assert(w);
a4b143
 
a4b143
diff --git a/src/core/manager.h b/src/core/manager.h
a4b143
index 3969553..a3049b5 100644
a4b143
--- a/src/core/manager.h
a4b143
+++ b/src/core/manager.h
a4b143
@@ -103,9 +103,6 @@ struct Manager {
a4b143
          * type we maintain a per type linked list */
a4b143
         LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]);
a4b143
 
a4b143
-        /* To optimize iteration of units that have requires_mounts_for set */
a4b143
-        LIST_HEAD(Unit, has_requires_mounts_for);
a4b143
-
a4b143
         /* Units that need to be loaded */
a4b143
         LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */
a4b143
 
a4b143
@@ -251,6 +248,11 @@ struct Manager {
a4b143
 
a4b143
         char *switch_root;
a4b143
         char *switch_root_init;
a4b143
+
a4b143
+        /* This maps all possible path prefixes to the units needing
a4b143
+         * them. It's a hashmap with a path string as key and a Set as
a4b143
+         * value where Unit objects are contained. */
a4b143
+        Hashmap *units_requiring_mounts_for;
a4b143
 };
a4b143
 
a4b143
 int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m);
a4b143
@@ -263,6 +265,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
a4b143
 Job *manager_get_job(Manager *m, uint32_t id);
a4b143
 Unit *manager_get_unit(Manager *m, const char *name);
a4b143
 
a4b143
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found);
a4b143
+
a4b143
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
a4b143
 
a4b143
 int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
a4b143
@@ -316,4 +320,6 @@ void manager_recheck_journal(Manager *m);
a4b143
 void manager_set_show_status(Manager *m, bool b);
a4b143
 void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_attr_(4,5);
a4b143
 
a4b143
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
a4b143
+
a4b143
 void watch_init(Watch *w);
a4b143
diff --git a/src/core/mount.c b/src/core/mount.c
a4b143
index 78c5c1e..3d46557 100644
a4b143
--- a/src/core/mount.c
a4b143
+++ b/src/core/mount.c
a4b143
@@ -157,138 +157,58 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
a4b143
 }
a4b143
 
a4b143
 static int mount_add_mount_links(Mount *m) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
+        _cleanup_free_ char *parent = NULL;
a4b143
         MountParameters *pm;
a4b143
-
a4b143
-        assert(m);
a4b143
-
a4b143
-        pm = get_mount_parameters_fragment(m);
a4b143
-
a4b143
-        /* Adds in links to other mount points that might lie below or
a4b143
-         * above us in the hierarchy */
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) {
a4b143
-                Mount *n = MOUNT(other);
a4b143
-                MountParameters *pn;
a4b143
-
a4b143
-                if (n == m)
a4b143
-                        continue;
a4b143
-
a4b143
-                if (UNIT(n)->load_state != UNIT_LOADED)
a4b143
-                        continue;
a4b143
-
a4b143
-                pn = get_mount_parameters_fragment(n);
a4b143
-
a4b143
-                if (path_startswith(m->where, n->where)) {
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
a4b143
-                                return r;
a4b143
-
a4b143
-                        if (pn)
a4b143
-                                if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
a4b143
-                                        return r;
a4b143
-
a4b143
-                } else if (path_startswith(n->where, m->where)) {
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
a4b143
-                                return r;
a4b143
-
a4b143
-                        if (pm)
a4b143
-                                if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
a4b143
-                                        return r;
a4b143
-
a4b143
-                } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
a4b143
-                                return r;
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
a4b143
-                                return r;
a4b143
-
a4b143
-                } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
a4b143
-                                return r;
a4b143
-
a4b143
-                        if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
a4b143
-                                return r;
a4b143
-                }
a4b143
-        }
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int mount_add_swap_links(Mount *m) {
a4b143
         Unit *other;
a4b143
+        Iterator i;
a4b143
+        Set *s;
a4b143
         int r;
a4b143
 
a4b143
         assert(m);
a4b143
 
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) {
a4b143
-                r = swap_add_one_mount_link(SWAP(other), m);
a4b143
+        if (!path_equal(m->where, "/")) {
a4b143
+                /* Adds in links to other mount points that might lie further
a4b143
+                 * up in the hierarchy */
a4b143
+                r = path_get_parent(m->where, &parent);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
-        }
a4b143
 
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int mount_add_path_links(Mount *m) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(m);
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) {
a4b143
-                r = path_add_one_mount_link(PATH(other), m);
a4b143
+                r = unit_require_mounts_for(UNIT(m), parent);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
         }
a4b143
 
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int mount_add_automount_links(Mount *m) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(m);
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) {
a4b143
-                r = automount_add_one_mount_link(AUTOMOUNT(other), m);
a4b143
+        /* Adds in links to other mount points that might be needed
a4b143
+         * for the source path (if this is a bind mount) to be
a4b143
+         * available. */
a4b143
+        pm = get_mount_parameters_fragment(m);
a4b143
+        if (pm && path_is_absolute(pm->what)) {
a4b143
+                r = unit_require_mounts_for(UNIT(m), pm->what);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
         }
a4b143
 
a4b143
-        return 0;
a4b143
-}
a4b143
+        /* Adds in links to other units that use this path or paths
a4b143
+         * further down in the hierarchy */
a4b143
+        s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
a4b143
+        SET_FOREACH(other, s, i) {
a4b143
 
a4b143
-static int mount_add_socket_links(Mount *m) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
+                if (other->load_state != UNIT_LOADED)
a4b143
+                        continue;
a4b143
 
a4b143
-        assert(m);
a4b143
+                if (other == UNIT(m))
a4b143
+                        continue;
a4b143
 
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET]) {
a4b143
-                r = socket_add_one_mount_link(SOCKET(other), m);
a4b143
+                r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
-        }
a4b143
 
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int mount_add_requires_mounts_links(Mount *m) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(m);
a4b143
-
a4b143
-        LIST_FOREACH(has_requires_mounts_for, other, UNIT(m)->manager->has_requires_mounts_for) {
a4b143
-                r = unit_add_one_mount_link(other, m);
a4b143
-                if (r < 0)
a4b143
-                        return r;
a4b143
+                if (UNIT(m)->fragment_path) {
a4b143
+                        /* If we have fragment configuration, then make this dependency required */
a4b143
+                        r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
a4b143
+                        if (r < 0)
a4b143
+                                return r;
a4b143
+                }
a4b143
         }
a4b143
 
a4b143
         return 0;
a4b143
@@ -567,8 +487,9 @@ static int mount_fix_timeouts(Mount *m) {
a4b143
 }
a4b143
 
a4b143
 static int mount_verify(Mount *m) {
a4b143
+        _cleanup_free_ char *e = NULL;
a4b143
         bool b;
a4b143
-        char *e;
a4b143
+
a4b143
         assert(m);
a4b143
 
a4b143
         if (UNIT(m)->load_state != UNIT_LOADED)
a4b143
@@ -577,12 +498,11 @@ static int mount_verify(Mount *m) {
a4b143
         if (!m->from_fragment && !m->from_proc_self_mountinfo)
a4b143
                 return -ENOENT;
a4b143
 
a4b143
-        if (!(e = unit_name_from_path(m->where, ".mount")))
a4b143
+        e = unit_name_from_path(m->where, ".mount");
a4b143
+        if (!e)
a4b143
                 return -ENOMEM;
a4b143
 
a4b143
         b = unit_has_name(UNIT(m), e);
a4b143
-        free(e);
a4b143
-
a4b143
         if (!b) {
a4b143
                 log_error_unit(UNIT(m)->id,
a4b143
                                "%s's Where setting doesn't match unit name. Refusing.",
a4b143
@@ -646,26 +566,6 @@ static int mount_add_extras(Mount *m) {
a4b143
         if (r < 0)
a4b143
                 return r;
a4b143
 
a4b143
-        r = mount_add_socket_links(m);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        r = mount_add_swap_links(m);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        r = mount_add_path_links(m);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        r = mount_add_requires_mounts_links(m);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        r = mount_add_automount_links(m);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
         r = mount_add_quota_links(m);
a4b143
         if (r < 0)
a4b143
                 return r;
a4b143
@@ -1650,79 +1550,56 @@ fail:
a4b143
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
a4b143
         int r = 0;
a4b143
         unsigned i;
a4b143
-        char *device, *path, *options, *options2, *fstype, *d, *p, *o;
a4b143
 
a4b143
         assert(m);
a4b143
 
a4b143
         rewind(m->proc_self_mountinfo);
a4b143
 
a4b143
         for (i = 1;; i++) {
a4b143
+                _cleanup_free_ char *device = NULL, *path = NULL, *options = NULL, *options2 = NULL, *fstype = NULL, *d = NULL, *p = NULL, *o = NULL;
a4b143
                 int k;
a4b143
 
a4b143
-                device = path = options = options2 = fstype = d = p = o = NULL;
a4b143
-
a4b143
-                if ((k = fscanf(m->proc_self_mountinfo,
a4b143
-                                "%*s "       /* (1) mount id */
a4b143
-                                "%*s "       /* (2) parent id */
a4b143
-                                "%*s "       /* (3) major:minor */
a4b143
-                                "%*s "       /* (4) root */
a4b143
-                                "%ms "       /* (5) mount point */
a4b143
-                                "%ms"        /* (6) mount options */
a4b143
-                                "%*[^-]"     /* (7) optional fields */
a4b143
-                                "- "         /* (8) separator */
a4b143
-                                "%ms "       /* (9) file system type */
a4b143
-                                "%ms"        /* (10) mount source */
a4b143
-                                "%ms"        /* (11) mount options 2 */
a4b143
-                                "%*[^\n]",   /* some rubbish at the end */
a4b143
-                                &path,
a4b143
-                                &options,
a4b143
-                                &fstype,
a4b143
-                                &device,
a4b143
-                                &options2)) != 5) {
a4b143
-
a4b143
-                        if (k == EOF)
a4b143
-                                break;
a4b143
-
a4b143
+                k = fscanf(m->proc_self_mountinfo,
a4b143
+                           "%*s "       /* (1) mount id */
a4b143
+                           "%*s "       /* (2) parent id */
a4b143
+                           "%*s "       /* (3) major:minor */
a4b143
+                           "%*s "       /* (4) root */
a4b143
+                           "%ms "       /* (5) mount point */
a4b143
+                           "%ms"        /* (6) mount options */
a4b143
+                           "%*[^-]"     /* (7) optional fields */
a4b143
+                           "- "         /* (8) separator */
a4b143
+                           "%ms "       /* (9) file system type */
a4b143
+                           "%ms"        /* (10) mount source */
a4b143
+                           "%ms"        /* (11) mount options 2 */
a4b143
+                           "%*[^\n]",   /* some rubbish at the end */
a4b143
+                           &path,
a4b143
+                           &options,
a4b143
+                           &fstype,
a4b143
+                           &device,
a4b143
+                           &options2);
a4b143
+
a4b143
+                if (k == EOF)
a4b143
+                        break;
a4b143
+
a4b143
+                if (k != 5) {
a4b143
                         log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
a4b143
-                        goto clean_up;
a4b143
+                        continue;
a4b143
                 }
a4b143
 
a4b143
                 o = strjoin(options, ",", options2, NULL);
a4b143
-                if (!o) {
a4b143
-                        r = -ENOMEM;
a4b143
-                        goto finish;
a4b143
-                }
a4b143
+                if (!o)
a4b143
+                        return log_oom();
a4b143
 
a4b143
-                if (!(d = cunescape(device)) ||
a4b143
-                    !(p = cunescape(path))) {
a4b143
-                        r = -ENOMEM;
a4b143
-                        goto finish;
a4b143
-                }
a4b143
+                d = cunescape(device);
a4b143
+                p = cunescape(path);
a4b143
+                if (!d || !p)
a4b143
+                        return log_oom();
a4b143
 
a4b143
-                if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0)
a4b143
+                k = mount_add_one(m, d, p, o, fstype, 0, set_flags);
a4b143
+                if (k < 0)
a4b143
                         r = k;
a4b143
-
a4b143
-clean_up:
a4b143
-                free(device);
a4b143
-                free(path);
a4b143
-                free(options);
a4b143
-                free(options2);
a4b143
-                free(fstype);
a4b143
-                free(d);
a4b143
-                free(p);
a4b143
-                free(o);
a4b143
         }
a4b143
 
a4b143
-finish:
a4b143
-        free(device);
a4b143
-        free(path);
a4b143
-        free(options);
a4b143
-        free(options2);
a4b143
-        free(fstype);
a4b143
-        free(d);
a4b143
-        free(p);
a4b143
-        free(o);
a4b143
-
a4b143
         return r;
a4b143
 }
a4b143
 
a4b143
diff --git a/src/core/path.c b/src/core/path.c
a4b143
index 8a09deb..99e2fed 100644
a4b143
--- a/src/core/path.c
a4b143
+++ b/src/core/path.c
a4b143
@@ -241,10 +241,6 @@ static bool path_spec_check_good(PathSpec *s, bool initial) {
a4b143
         return good;
a4b143
 }
a4b143
 
a4b143
-static bool path_spec_startswith(PathSpec *s, const char *what) {
a4b143
-        return path_startswith(s->path, what);
a4b143
-}
a4b143
-
a4b143
 static void path_spec_mkdir(PathSpec *s, mode_t mode) {
a4b143
         int r;
a4b143
 
a4b143
@@ -301,38 +297,14 @@ static void path_done(Unit *u) {
a4b143
         path_free_specs(p);
a4b143
 }
a4b143
 
a4b143
-int path_add_one_mount_link(Path *p, Mount *m) {
a4b143
+static int path_add_mount_links(Path *p) {
a4b143
         PathSpec *s;
a4b143
         int r;
a4b143
 
a4b143
         assert(p);
a4b143
-        assert(m);
a4b143
-
a4b143
-        if (UNIT(p)->load_state != UNIT_LOADED ||
a4b143
-            UNIT(m)->load_state != UNIT_LOADED)
a4b143
-                return 0;
a4b143
 
a4b143
         LIST_FOREACH(spec, s, p->specs) {
a4b143
-                if (!path_spec_startswith(s, m->where))
a4b143
-                        continue;
a4b143
-
a4b143
-                r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES,
a4b143
-                                              UNIT(m), true);
a4b143
-                if (r < 0)
a4b143
-                        return r;
a4b143
-        }
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int path_add_mount_links(Path *p) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(p);
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(p)->manager->units_by_type[UNIT_MOUNT]) {
a4b143
-                r = path_add_one_mount_link(p, MOUNT(other));
a4b143
+                r = unit_require_mounts_for(UNIT(p), s->path);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
         }
a4b143
diff --git a/src/core/path.h b/src/core/path.h
a4b143
index 6adab58..dec3df7 100644
a4b143
--- a/src/core/path.h
a4b143
+++ b/src/core/path.h
a4b143
@@ -90,10 +90,6 @@ struct Path {
a4b143
         PathResult result;
a4b143
 };
a4b143
 
a4b143
-/* Called from the mount code figure out if a mount is a dependency of
a4b143
- * any of the paths of this path object */
a4b143
-int path_add_one_mount_link(Path *p, Mount *m);
a4b143
-
a4b143
 void path_free_specs(Path *p);
a4b143
 
a4b143
 extern const UnitVTable path_vtable;
a4b143
diff --git a/src/core/socket.c b/src/core/socket.c
a4b143
index 25c2a51..778f8c8 100644
a4b143
--- a/src/core/socket.c
a4b143
+++ b/src/core/socket.c
a4b143
@@ -258,53 +258,24 @@ static int socket_verify(Socket *s) {
a4b143
         return 0;
a4b143
 }
a4b143
 
a4b143
-static bool socket_needs_mount(Socket *s, const char *prefix) {
a4b143
+static int socket_add_mount_links(Socket *s) {
a4b143
         SocketPort *p;
a4b143
-
a4b143
-        assert(s);
a4b143
-
a4b143
-        LIST_FOREACH(port, p, s->ports) {
a4b143
-
a4b143
-                if (p->type == SOCKET_SOCKET) {
a4b143
-                        if (socket_address_needs_mount(&p->address, prefix))
a4b143
-                                return true;
a4b143
-                } else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL) {
a4b143
-                        if (path_startswith(p->path, prefix))
a4b143
-                                return true;
a4b143
-                }
a4b143
-        }
a4b143
-
a4b143
-        return false;
a4b143
-}
a4b143
-
a4b143
-int socket_add_one_mount_link(Socket *s, Mount *m) {
a4b143
         int r;
a4b143
 
a4b143
         assert(s);
a4b143
-        assert(m);
a4b143
 
a4b143
-        if (UNIT(s)->load_state != UNIT_LOADED ||
a4b143
-            UNIT(m)->load_state != UNIT_LOADED)
a4b143
-                return 0;
a4b143
-
a4b143
-        if (!socket_needs_mount(s, m->where))
a4b143
-                return 0;
a4b143
-
a4b143
-        r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
+        LIST_FOREACH(port, p, s->ports) {
a4b143
+                const char *path = NULL;
a4b143
 
a4b143
-static int socket_add_mount_links(Socket *s) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
+                if (p->type == SOCKET_SOCKET)
a4b143
+                        path = socket_address_get_path(&p->address);
a4b143
+                else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL)
a4b143
+                        path = p->path;
a4b143
 
a4b143
-        assert(s);
a4b143
+                if (!path)
a4b143
+                        continue;
a4b143
 
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT]) {
a4b143
-                r = socket_add_one_mount_link(s, MOUNT(other));
a4b143
+                r = unit_require_mounts_for(UNIT(s), path);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
         }
a4b143
diff --git a/src/core/socket.h b/src/core/socket.h
a4b143
index 5733322..3d7eadc 100644
a4b143
--- a/src/core/socket.h
a4b143
+++ b/src/core/socket.h
a4b143
@@ -156,10 +156,6 @@ struct Socket {
a4b143
 /* Called from the service code when collecting fds */
a4b143
 int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
a4b143
 
a4b143
-/* Called from the mount code figure out if a mount is a dependency of
a4b143
- * any of the sockets of this socket */
a4b143
-int socket_add_one_mount_link(Socket *s, Mount *m);
a4b143
-
a4b143
 /* Called from the service code when a per-connection service ended */
a4b143
 void socket_connection_unref(Socket *s);
a4b143
 
a4b143
diff --git a/src/core/swap.c b/src/core/swap.c
a4b143
index d225485..6f86a86 100644
a4b143
--- a/src/core/swap.c
a4b143
+++ b/src/core/swap.c
a4b143
@@ -137,42 +137,6 @@ static void swap_done(Unit *u) {
a4b143
         unit_unwatch_timer(u, &s->timer_watch);
a4b143
 }
a4b143
 
a4b143
-int swap_add_one_mount_link(Swap *s, Mount *m) {
a4b143
-         int r;
a4b143
-
a4b143
-        assert(s);
a4b143
-        assert(m);
a4b143
-
a4b143
-        if (UNIT(s)->load_state != UNIT_LOADED ||
a4b143
-            UNIT(m)->load_state != UNIT_LOADED)
a4b143
-                return 0;
a4b143
-
a4b143
-        if (is_device_path(s->what))
a4b143
-                return 0;
a4b143
-
a4b143
-        if (!path_startswith(s->what, m->where))
a4b143
-                return 0;
a4b143
-
a4b143
-        r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
a4b143
-        if (r < 0)
a4b143
-                return r;
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
-static int swap_add_mount_links(Swap *s) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
-
a4b143
-        assert(s);
a4b143
-
a4b143
-        LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT])
a4b143
-                if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0)
a4b143
-                        return r;
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
-
a4b143
 static int swap_add_device_links(Swap *s) {
a4b143
         SwapParameters *p;
a4b143
 
a4b143
@@ -300,11 +264,11 @@ static int swap_load(Unit *u) {
a4b143
                         if ((r = unit_set_description(u, s->what)) < 0)
a4b143
                                 return r;
a4b143
 
a4b143
-                r = swap_add_device_links(s);
a4b143
+                r = unit_require_mounts_for(UNIT(s), s->what);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
 
a4b143
-                r = swap_add_mount_links(s);
a4b143
+                r = swap_add_device_links(s);
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
 
a4b143
diff --git a/src/core/swap.h b/src/core/swap.h
a4b143
index 7e48c0e..dd89535 100644
a4b143
--- a/src/core/swap.h
a4b143
+++ b/src/core/swap.h
a4b143
@@ -107,8 +107,6 @@ struct Swap {
a4b143
 
a4b143
 extern const UnitVTable swap_vtable;
a4b143
 
a4b143
-int swap_add_one_mount_link(Swap *s, Mount *m);
a4b143
-
a4b143
 int swap_dispatch_reload(Manager *m);
a4b143
 int swap_fd_event(Manager *m, int events);
a4b143
 
a4b143
diff --git a/src/core/unit.c b/src/core/unit.c
a4b143
index ab313b9..4b97710 100644
a4b143
--- a/src/core/unit.c
a4b143
+++ b/src/core/unit.c
a4b143
@@ -374,6 +374,34 @@ static void unit_remove_transient(Unit *u) {
a4b143
         }
a4b143
 }
a4b143
 
a4b143
+static void unit_free_requires_mounts_for(Unit *u) {
a4b143
+        char **j;
a4b143
+
a4b143
+        STRV_FOREACH(j, u->requires_mounts_for) {
a4b143
+                char s[strlen(*j) + 1];
a4b143
+
a4b143
+                PATH_FOREACH_PREFIX_MORE(s, *j) {
a4b143
+                        char *y;
a4b143
+                        Set *x;
a4b143
+
a4b143
+                        x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
a4b143
+                        if (!x)
a4b143
+                                continue;
a4b143
+
a4b143
+                        set_remove(x, u);
a4b143
+
a4b143
+                        if (set_isempty(x)) {
a4b143
+                                hashmap_remove(u->manager->units_requiring_mounts_for, y);
a4b143
+                                free(y);
a4b143
+                                set_free(x);
a4b143
+                        }
a4b143
+                }
a4b143
+        }
a4b143
+
a4b143
+        strv_free(u->requires_mounts_for);
a4b143
+        u->requires_mounts_for = NULL;
a4b143
+}
a4b143
+
a4b143
 void unit_free(Unit *u) {
a4b143
         UnitDependency d;
a4b143
         Iterator i;
a4b143
@@ -390,6 +418,8 @@ void unit_free(Unit *u) {
a4b143
                 if (UNIT_VTABLE(u)->done)
a4b143
                         UNIT_VTABLE(u)->done(u);
a4b143
 
a4b143
+        unit_free_requires_mounts_for(u);
a4b143
+
a4b143
         SET_FOREACH(t, u->names, i)
a4b143
                 hashmap_remove_value(u->manager->units, t, u);
a4b143
 
a4b143
@@ -408,11 +438,6 @@ void unit_free(Unit *u) {
a4b143
         for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
a4b143
                 bidi_set_free(u, u->dependencies[d]);
a4b143
 
a4b143
-        if (u->requires_mounts_for) {
a4b143
-                LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
a4b143
-                strv_free(u->requires_mounts_for);
a4b143
-        }
a4b143
-
a4b143
         if (u->type != _UNIT_TYPE_INVALID)
a4b143
                 LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
a4b143
 
a4b143
@@ -2659,40 +2684,39 @@ void unit_ref_unset(UnitRef *ref) {
a4b143
         ref->unit = NULL;
a4b143
 }
a4b143
 
a4b143
-int unit_add_one_mount_link(Unit *u, Mount *m) {
a4b143
+int unit_add_mount_links(Unit *u) {
a4b143
         char **i;
a4b143
+        int r;
a4b143
 
a4b143
         assert(u);
a4b143
-        assert(m);
a4b143
-
a4b143
-        if (u->load_state != UNIT_LOADED ||
a4b143
-            UNIT(m)->load_state != UNIT_LOADED)
a4b143
-                return 0;
a4b143
 
a4b143
         STRV_FOREACH(i, u->requires_mounts_for) {
a4b143
+                char prefix[strlen(*i) + 1];
a4b143
 
a4b143
-                if (UNIT(m) == u)
a4b143
-                        continue;
a4b143
+                PATH_FOREACH_PREFIX_MORE(prefix, *i) {
a4b143
+                        Unit *m;
a4b143
 
a4b143
-                if (!path_startswith(*i, m->where))
a4b143
-                        continue;
a4b143
-
a4b143
-                return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
a4b143
-        }
a4b143
-
a4b143
-        return 0;
a4b143
-}
a4b143
+                        r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m);
a4b143
+                        if (r < 0)
a4b143
+                                return r;
a4b143
+                        if (r == 0)
a4b143
+                                continue;
a4b143
+                        if (m == u)
a4b143
+                                continue;
a4b143
 
a4b143
-int unit_add_mount_links(Unit *u) {
a4b143
-        Unit *other;
a4b143
-        int r;
a4b143
+                        if (m->load_state != UNIT_LOADED)
a4b143
+                                continue;
a4b143
 
a4b143
-        assert(u);
a4b143
+                        r = unit_add_dependency(u, UNIT_AFTER, m, true);
a4b143
+                        if (r < 0)
a4b143
+                                return r;
a4b143
 
a4b143
-        LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) {
a4b143
-                r = unit_add_one_mount_link(u, MOUNT(other));
a4b143
-                if (r < 0)
a4b143
-                        return r;
a4b143
+                        if (m->fragment_path) {
a4b143
+                                r = unit_add_dependency(u, UNIT_REQUIRES, m, true);
a4b143
+                                if (r < 0)
a4b143
+                                        return r;
a4b143
+                        }
a4b143
+                }
a4b143
         }
a4b143
 
a4b143
         return 0;
a4b143
@@ -3012,6 +3036,86 @@ int unit_kill_context(
a4b143
         return wait_for_exit;
a4b143
 }
a4b143
 
a4b143
+int unit_require_mounts_for(Unit *u, const char *path) {
a4b143
+        char prefix[strlen(path) + 1], *p;
a4b143
+        int r;
a4b143
+
a4b143
+        assert(u);
a4b143
+        assert(path);
a4b143
+
a4b143
+        /* Registers a unit for requiring a certain path and all its
a4b143
+         * prefixes. We keep a simple array of these paths in the
a4b143
+         * unit, since its usually short. However, we build a prefix
a4b143
+         * table for all possible prefixes so that new appearing mount
a4b143
+         * units can easily determine which units to make themselves a
a4b143
+         * dependency of. */
a4b143
+
a4b143
+        p = strdup(path);
a4b143
+        if (!p)
a4b143
+                return -ENOMEM;
a4b143
+
a4b143
+        path_kill_slashes(p);
a4b143
+
a4b143
+        if (!path_is_absolute(p)) {
a4b143
+                free(p);
a4b143
+                return -EINVAL;
a4b143
+        }
a4b143
+
a4b143
+        if (!path_is_safe(p)) {
a4b143
+                free(p);
a4b143
+                return -EPERM;
a4b143
+        }
a4b143
+
a4b143
+        if (strv_contains(u->requires_mounts_for, p)) {
a4b143
+                free(p);
a4b143
+                return 0;
a4b143
+        }
a4b143
+
a4b143
+        r = strv_push(&u->requires_mounts_for, p);
a4b143
+        if (r < 0) {
a4b143
+                free(p);
a4b143
+                return r;
a4b143
+        }
a4b143
+
a4b143
+        PATH_FOREACH_PREFIX_MORE(prefix, p) {
a4b143
+                Set *x;
a4b143
+
a4b143
+                x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
a4b143
+                if (!x) {
a4b143
+                        char *q;
a4b143
+
a4b143
+                        if (!u->manager->units_requiring_mounts_for) {
a4b143
+                                u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func);
a4b143
+                                if (!u->manager->units_requiring_mounts_for)
a4b143
+                                        return -ENOMEM;
a4b143
+                        }
a4b143
+
a4b143
+                        q = strdup(prefix);
a4b143
+                        if (!q)
a4b143
+                                return -ENOMEM;
a4b143
+
a4b143
+                        x = set_new(NULL, NULL);
a4b143
+                        if (!x) {
a4b143
+                                free(q);
a4b143
+                                return -ENOMEM;
a4b143
+                        }
a4b143
+
a4b143
+                        r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
a4b143
+                        if (r < 0) {
a4b143
+                                free(q);
a4b143
+                                set_free(x);
a4b143
+                                return r;
a4b143
+                        }
a4b143
+                }
a4b143
+
a4b143
+                r = set_put(x, u);
a4b143
+                if (r < 0)
a4b143
+                        return r;
a4b143
+        }
a4b143
+
a4b143
+        return 0;
a4b143
+}
a4b143
+
a4b143
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
a4b143
         [UNIT_ACTIVE] = "active",
a4b143
         [UNIT_RELOADING] = "reloading",
a4b143
diff --git a/src/core/unit.h b/src/core/unit.h
a4b143
index 0caea18..6dd750f 100644
a4b143
--- a/src/core/unit.h
a4b143
+++ b/src/core/unit.h
a4b143
@@ -173,7 +173,6 @@ struct Unit {
a4b143
 
a4b143
         /* Counterparts in the cgroup filesystem */
a4b143
         char *cgroup_path;
a4b143
-        bool cgroup_realized;
a4b143
         CGroupControllerMask cgroup_mask;
a4b143
 
a4b143
         UnitRef slice;
a4b143
@@ -255,6 +254,8 @@ struct Unit {
a4b143
         bool no_gc:1;
a4b143
 
a4b143
         bool in_audit:1;
a4b143
+
a4b143
+        bool cgroup_realized:1;
a4b143
 };
a4b143
 
a4b143
 struct UnitStatusMessageFormats {
a4b143
@@ -589,7 +590,6 @@ void unit_ref_unset(UnitRef *ref);
a4b143
 #define UNIT_DEREF(ref) ((ref).unit)
a4b143
 #define UNIT_ISSET(ref) (!!(ref).unit)
a4b143
 
a4b143
-int unit_add_one_mount_link(Unit *u, Mount *m);
a4b143
 int unit_add_mount_links(Unit *u);
a4b143
 
a4b143
 int unit_exec_context_defaults(Unit *u, ExecContext *c);
a4b143
@@ -609,6 +609,8 @@ int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid
a4b143
 
a4b143
 int unit_make_transient(Unit *u);
a4b143
 
a4b143
+int unit_require_mounts_for(Unit *u, const char *path);
a4b143
+
a4b143
 const char *unit_active_state_to_string(UnitActiveState i) _const_;
a4b143
 UnitActiveState unit_active_state_from_string(const char *s) _pure_;
a4b143
 
a4b143
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
a4b143
index c583d3d..9224208 100644
a4b143
--- a/src/shared/socket-util.c
a4b143
+++ b/src/shared/socket-util.c
a4b143
@@ -486,16 +486,16 @@ bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
a4b143
         return socket_address_equal(a, &b);
a4b143
 }
a4b143
 
a4b143
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
a4b143
+const char* socket_address_get_path(const SocketAddress *a) {
a4b143
         assert(a);
a4b143
 
a4b143
         if (socket_address_family(a) != AF_UNIX)
a4b143
-                return false;
a4b143
+                return NULL;
a4b143
 
a4b143
         if (a->sockaddr.un.sun_path[0] == 0)
a4b143
-                return false;
a4b143
+                return NULL;
a4b143
 
a4b143
-        return path_startswith(a->sockaddr.un.sun_path, prefix);
a4b143
+        return a->sockaddr.un.sun_path;
a4b143
 }
a4b143
 
a4b143
 bool socket_ipv6_is_supported(void) {
a4b143
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
a4b143
index 7829a33..e0b85ad 100644
a4b143
--- a/src/shared/socket-util.h
a4b143
+++ b/src/shared/socket-util.h
a4b143
@@ -92,7 +92,7 @@ int make_socket_fd(const char* address, int flags);
a4b143
 
a4b143
 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
a4b143
 
a4b143
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
a4b143
+const char* socket_address_get_path(const SocketAddress *a);
a4b143
 
a4b143
 const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
a4b143
 SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;