|
|
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_;
|