units: rework automatic dependency logic between automounts, mounts, sockets, swaps
authorLennart Poettering <lennart@poettering.net>
Thu, 13 May 2010 01:07:16 +0000 (03:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 13 May 2010 01:07:16 +0000 (03:07 +0200)
16 files changed:
automount.c
automount.h
dbus-manager.c
hashmap.h
main.c
manager.c
mount.c
mount.h
socket-util.c
socket-util.h
socket.c
socket.h
swap.c
swap.h
unit.c
unit.h

index cab7164..465354f 100644 (file)
@@ -105,6 +105,41 @@ static void automount_done(Unit *u) {
         a->tokens = NULL;
 }
 
+int automount_add_one_mount_link(Automount *a, Mount *m) {
+        int r;
+
+        assert(a);
+        assert(m);
+
+        if (a->meta.load_state != UNIT_LOADED ||
+            m->meta.load_state != UNIT_LOADED)
+                return 0;
+
+        if (!path_startswith(a->where, m->where))
+                return 0;
+
+        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(a), true)) < 0)
+                return r;
+
+        if ((r = unit_add_dependency(UNIT(a), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                return r;
+
+        return 0;
+}
+
+static int automount_add_mount_links(Automount *a) {
+        Meta *other;
+        int r;
+
+        assert(a);
+
+        LIST_FOREACH(units_per_type, other, a->meta.manager->units_per_type[UNIT_MOUNT])
+                if ((r = automount_add_one_mount_link(a, (Mount*) other)) < 0)
+                        return r;
+
+        return 0;
+}
+
 static int automount_verify(Automount *a) {
         bool b;
         char *e;
@@ -146,6 +181,9 @@ static int automount_load(Unit *u) {
 
                 path_kill_slashes(a->where);
 
+                if ((r = automount_add_mount_links(a)) < 0)
+                        return r;
+
                 if ((r = unit_load_related_unit(u, ".mount", (Unit**) &a->mount)) < 0)
                         return r;
 
index 5b62369..014482c 100644 (file)
@@ -57,6 +57,8 @@ extern const UnitVTable automount_vtable;
 
 int automount_send_ready(Automount *a, int status);
 
+int automount_add_one_mount_link(Automount *a, Mount *m);
+
 const char* automount_state_to_string(AutomountState i);
 AutomountState automount_state_from_string(const char *s);
 
index 4b3b45e..90ab8d1 100644 (file)
@@ -64,7 +64,7 @@
         "   <arg name=\"names\" type=\"as\" direction=\"in\"/>"         \
         "  </method>"                                                   \
         "  <method name=\"UnsetEnvironment\">"                          \
-        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>"        \
+        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>"         \
         "  </method>"                                                   \
         "  <signal name=\"UnitNew\">"                                   \
         "   <arg name=\"id\" type=\"s\"/>"                              \
index 9cdd701..3ff3efe 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -80,6 +80,6 @@ void* hashmap_last(Hashmap *h);
         for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); (e); (e) = hashmap_iterate((h), &(i), (const void**) &(k)))
 
 #define HASHMAP_FOREACH_BACKWARDS(e, h, i) \
-        for ((i) = ITERATE_LAST, (e) = hashmap_iterate_backwards((h), &(i), NULL); (e); (e) = hashmap_iterate_backwards((h), &(i), NULL))
+        for ((i) = ITERATOR_LAST, (e) = hashmap_iterate_backwards((h), &(i), NULL); (e); (e) = hashmap_iterate_backwards((h), &(i), NULL))
 
 #endif
diff --git a/main.c b/main.c
index aa58040..b0b3cfb 100644 (file)
--- a/main.c
+++ b/main.c
@@ -653,7 +653,7 @@ int main(int argc, char *argv[]) {
         }
 
         if ((r = manager_startup(m, serialization, fds)) < 0)
-                log_error("Failed to fully startup daemon: %s", strerror(-r));
+                log_error("Failed to fully start up daemon: %s", strerror(-r));
 
         if (fds) {
                 /* This will close all file descriptors that were opened, but
index a4696d6..6913ff4 100644 (file)
--- a/manager.c
+++ b/manager.c
@@ -254,7 +254,7 @@ static int manager_find_paths(Manager *m) {
         }
 
         if (m->running_as == MANAGER_INIT) {
-                /* /etc/init.d/ compativility does not matter to users */
+                /* /etc/init.d/ compatibility does not matter to users */
 
                 if ((e = getenv("SYSTEMD_SYSVINIT_PATH")))
                         if (!(m->sysvinit_path = split_path_and_make_absolute(e)))
diff --git a/mount.c b/mount.c
index ce99af0..adb3a08 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -113,85 +113,82 @@ static void mount_done(Unit *u) {
         unit_unwatch_timer(u, &m->timer_watch);
 }
 
-int mount_add_node_links(Unit *u, const char *what) {
-        Unit *device;
-        char *e;
+static int mount_add_mount_links(Mount *m) {
+        Meta *other;
         int r;
 
-        assert(u);
+        assert(m);
 
-        if (!what)
-                /* We observe kernel mounts only while they are live,
-                 * hence don't create any links for them */
-                return 0;
+        /* Adds in links to other mount points that might lie below or
+         * above us in the hierarchy */
 
-        /* Adds in links to the device that this node is based on */
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_MOUNT]) {
+                Mount *n = (Mount*) other;
 
-        if (!path_startswith(what, "/dev/"))
-                return 0;
+                if (n == m)
+                        continue;
 
-        if (!(e = unit_name_build_escape(what+1, NULL, ".device")))
-                return -ENOMEM;
+                if (n->meta.load_state != UNIT_LOADED)
+                        continue;
 
-        r = manager_load_unit(u->meta.manager, e, NULL, &device);
-        free(e);
+                if (path_startswith(m->where, n->where)) {
 
-        if (r < 0)
-                return r;
+                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
+                                return r;
 
-        if ((r = unit_add_dependency(u, UNIT_AFTER, device, true)) < 0)
-                return r;
+                        if (n->from_etc_fstab || n->from_fragment)
+                                if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
+                                        return r;
 
-        if ((r = unit_add_dependency(u, UNIT_REQUIRES, device, true)) < 0)
-                return r;
+                } else if (path_startswith(n->where, m->where)) {
 
-        if (u->meta.manager->running_as == MANAGER_INIT ||
-            u->meta.manager->running_as == MANAGER_SYSTEM)
-                if ((r = unit_add_dependency(device, UNIT_WANTS, u, false)) < 0)
-                        return r;
+                        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(n), true)) < 0)
+                                return r;
+
+                        if (m->from_etc_fstab || m->from_fragment)
+                                if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                                        return r;
+                }
+        }
 
         return 0;
 }
 
-int mount_add_path_links(Unit *u, const char *where, bool requires) {
+static int mount_add_swap_links(Mount *m) {
         Meta *other;
         int r;
 
-        assert(u);
-
-        /* Adds in link to other mount points, that might lie below or
-         * above us in the hierarchy */
-
-        LIST_FOREACH(units_per_type, other, u->meta.manager->units_per_type[UNIT_MOUNT]) {
-                Mount *n;
+        assert(m);
 
-                n = (Mount*) other;
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_SWAP])
+                if ((r = swap_add_one_mount_link((Swap*) other, m)) < 0)
+                        return r;
 
-                if (UNIT(n) == u)
-                        continue;
+        return 0;
+}
 
-                if (u->meta.load_state != UNIT_LOADED)
-                        continue;
+static int mount_add_automount_links(Mount *m) {
+        Meta *other;
+        int r;
 
-                if (path_startswith(where, n->where)) {
+        assert(m);
 
-                        if ((r = unit_add_dependency(u, UNIT_AFTER, UNIT(other), true)) < 0)
-                                return r;
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_AUTOMOUNT])
+                if ((r = automount_add_one_mount_link((Automount*) other, m)) < 0)
+                        return r;
 
-                        if (requires)
-                                if ((r = unit_add_dependency(u, UNIT_REQUIRES, UNIT(other), true)) < 0)
-                                        return r;
+        return 0;
+}
 
-                } else if (path_startswith(n->where, where)) {
+static int mount_add_socket_links(Mount *m) {
+        Meta *other;
+        int r;
 
-                        if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(other), true)) < 0)
-                                return r;
+        assert(m);
 
-                        if (requires)
-                                if ((r = unit_add_dependency(UNIT(other), UNIT_REQUIRES, u, true)) < 0)
-                                        return r;
-                }
-        }
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_SOCKET])
+                if ((r = socket_add_one_mount_link((Socket*) other, m)) < 0)
+                        return r;
 
         return 0;
 }
@@ -301,6 +298,7 @@ static int mount_load(Unit *u) {
         /* This is a new unit? Then let's add in some extras */
         if (u->meta.load_state == UNIT_LOADED) {
                 const char *what = m->parameters_fragment.what;
+
                 if (!what)
                         what = m->parameters_etc_fstab.what;
 
@@ -317,13 +315,24 @@ static int mount_load(Unit *u) {
                 if (m->parameters_fragment.what)
                         m->from_fragment = true;
 
-                if ((r = mount_add_node_links(u, what)) < 0)
+                if ((r = unit_add_node_link(u, what,
+                                            (u->meta.manager->running_as == MANAGER_INIT ||
+                                             u->meta.manager->running_as == MANAGER_SYSTEM))) < 0)
+                        return r;
+
+                if ((r = mount_add_mount_links(m)) < 0)
+                        return r;
+
+                if ((r = mount_add_socket_links(m)) < 0)
+                        return r;
+
+                if ((r = mount_add_swap_links(m)) < 0)
                         return r;
 
-                if ((r = mount_add_path_links(u, m->where, m->from_etc_fstab || m->from_fragment)) < 0)
+                if ((r = mount_add_automount_links(m)) < 0)
                         return r;
 
-                if ((r = mount_add_target_links(MOUNT(u))) < 0)
+                if ((r = mount_add_target_links(m)) < 0)
                         return r;
 
                 if ((r = unit_add_default_cgroup(u)) < 0)
diff --git a/mount.h b/mount.h
index dec1b64..3b28e89 100644 (file)
--- a/mount.h
+++ b/mount.h
@@ -100,8 +100,6 @@ extern const UnitVTable mount_vtable;
 void mount_fd_event(Manager *m, int events);
 
 int mount_path_is_mounted(Manager *m, const char* path);
-int mount_add_node_links(Unit *m, const char *what);
-int mount_add_path_links(Unit *m, const char *where, bool requires);
 
 const char* mount_state_to_string(MountState i);
 MountState mount_state_from_string(const char *s);
index 8141ab0..32f6bcb 100644 (file)
@@ -453,5 +453,16 @@ bool socket_address_is(const SocketAddress *a, const char *s) {
                 return false;
 
         return socket_address_equal(a, &b);
+}
+
+bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
+        assert(a);
+
+        if (socket_address_family(a) != AF_UNIX)
+                return false;
+
+        if (a->sockaddr.un.sun_path[0] == 0)
+                return false;
 
+        return path_startswith(a->sockaddr.un.sun_path, prefix);
 }
index af452ef..1419216 100644 (file)
@@ -74,4 +74,6 @@ bool socket_address_is(const SocketAddress *a, const char *s);
 
 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b);
 
+bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
+
 #endif
index 402eeaf..aafe439 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -145,6 +145,79 @@ static int socket_verify(Socket *s) {
         return 0;
 }
 
+static bool socket_needs_mount(Socket *s, const char *prefix) {
+        SocketPort *p;
+
+        assert(s);
+
+        LIST_FOREACH(port, p, s->ports) {
+
+                if (p->type == SOCKET_SOCKET) {
+                        if (socket_address_needs_mount(&p->address, prefix))
+                                return true;
+                } else {
+                        assert(p->type == SOCKET_FIFO);
+                        if (path_startswith(p->path, prefix))
+                                return true;
+                }
+        }
+
+        return false;
+}
+
+int socket_add_one_mount_link(Socket *s, Mount *m) {
+        int r;
+
+        assert(s);
+        assert(m);
+
+        if (s->meta.load_state != UNIT_LOADED ||
+            m->meta.load_state != UNIT_LOADED)
+                return 0;
+
+        if (!socket_needs_mount(s, m->where))
+                return 0;
+
+        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(s), true)) < 0)
+                return r;
+
+        if ((r = unit_add_dependency(UNIT(s), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                return r;
+
+        return 0;
+}
+
+static int socket_add_mount_links(Socket *s) {
+        Meta *other;
+        int r;
+
+        assert(s);
+
+        LIST_FOREACH(units_per_type, other, s->meta.manager->units_per_type[UNIT_MOUNT])
+                if ((r = socket_add_one_mount_link(s, (Mount*) other)) < 0)
+                        return r;
+
+        return 0;
+}
+
+static int socket_add_device_link(Socket *s) {
+        char *t;
+        int r;
+
+        assert(s);
+
+        if (!s->bind_to_device)
+                return 0;
+
+        if (asprintf(&t, "/sys/subsystem/net/devices/%s", s->bind_to_device) < 0)
+                return -ENOMEM;
+
+        r = unit_add_node_link(UNIT(s), t, false);
+        free(t);
+
+        return r;
+}
+
 static int socket_load(Unit *u) {
         Socket *s = SOCKET(u);
         int r;
@@ -166,6 +239,12 @@ static int socket_load(Unit *u) {
                                 return r;
                 }
 
+                if ((r = socket_add_mount_links(s)) < 0)
+                        return r;
+
+                if ((r = socket_add_device_link(s)) < 0)
+                        return r;
+
                 if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
                         return r;
 
index 7076be7..43d28d7 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -27,6 +27,7 @@ typedef struct Socket Socket;
 #include "manager.h"
 #include "unit.h"
 #include "socket-util.h"
+#include "mount.h"
 
 typedef enum SocketState {
         SOCKET_DEAD,
@@ -116,6 +117,10 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
 /* Called from the service when it shut down */
 void socket_notify_service_dead(Socket *s);
 
+/* Called from the mount code figure out if a mount is a dependency of
+ * any of the sockets of this socket */
+int socket_add_one_mount_link(Socket *s, Mount *m);
+
 extern const UnitVTable socket_vtable;
 
 const char* socket_state_to_string(SocketState i);
diff --git a/swap.c b/swap.c
index fffd0b9..275f1d4 100644 (file)
--- a/swap.c
+++ b/swap.c
@@ -68,17 +68,52 @@ static int swap_verify(Swap *s) {
         return 0;
 }
 
+int swap_add_one_mount_link(Swap *s, Mount *m) {
+         int r;
+
+        assert(s);
+        assert(m);
+
+        if (s->meta.load_state != UNIT_LOADED ||
+            m->meta.load_state != UNIT_LOADED)
+                return 0;
+
+        if (!path_startswith(s->what, m->where))
+                return 0;
+
+        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(s), true)) < 0)
+                return r;
+
+        if ((r = unit_add_dependency(UNIT(s), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                return r;
+
+        return 0;
+}
+
+static int swap_add_mount_links(Swap *s) {
+        Meta *other;
+        int r;
+
+        assert(s);
+
+        LIST_FOREACH(units_per_type, other, s->meta.manager->units_per_type[UNIT_MOUNT])
+                if ((r = swap_add_one_mount_link(s, (Mount*) other)) < 0)
+                        return r;
+
+        return 0;
+}
+
 static int swap_add_target_links(Swap *s) {
         Manager *m = s->meta.manager;
         Unit *tu;
         int r;
 
-        r = manager_load_unit(m, SPECIAL_SWAP_TARGET, NULL, &tu);
-        if (r < 0)
+        if ((r = manager_load_unit(m, SPECIAL_SWAP_TARGET, NULL, &tu)) < 0)
                 return r;
 
-        if (!s->no_auto && (r = unit_add_dependency(tu, UNIT_WANTS, UNIT(s), true)) < 0)
-                return r;
+        if (!s->no_auto)
+                if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(s), true)) < 0)
+                        return r;
 
         return unit_add_dependency(UNIT(s), UNIT_BEFORE, tu, true);
 }
@@ -101,12 +136,13 @@ static int swap_load(Unit *u) {
 
                 path_kill_slashes(s->what);
 
-                if ((r = mount_add_node_links(u, s->what)) < 0)
+                if ((r = unit_add_node_link(u, s->what,
+                                            (u->meta.manager->running_as == MANAGER_INIT ||
+                                             u->meta.manager->running_as == MANAGER_SYSTEM))) < 0)
                         return r;
 
-                if (!path_startswith(s->what, "/dev/"))
-                        if ((r = mount_add_path_links(u, s->what, true)) < 0)
-                                return r;
+                if ((r = swap_add_mount_links(s)) < 0)
+                        return r;
 
                 if ((r = swap_add_target_links(s)) < 0)
                         return r;
diff --git a/swap.h b/swap.h
index d869250..758cdbd 100644 (file)
--- a/swap.h
+++ b/swap.h
@@ -47,14 +47,17 @@ struct Swap {
         bool from_proc_swaps_only:1;
         bool found_in_proc_swaps:1;
 
-        MountState state, deserialized_state;
+        SwapState state, deserialized_state;
 };
 
 extern const UnitVTable swap_vtable;
 
+int swap_add_one(Manager *m, const char *what, bool no_auto, int prio, bool from_proc_swap);
+
+int swap_add_one_mount_link(Swap *s, Mount *m);
+
 const char* swap_state_to_string(SwapState i);
 SwapState swap_state_from_string(const char *s);
 
-extern int swap_add_one(Manager *m, const char *what, bool no_auto, int prio, bool from_proc_swap);
 
 #endif
diff --git a/unit.c b/unit.c
index dea6b8b..60d4bb7 100644 (file)
--- a/unit.c
+++ b/unit.c
@@ -1831,6 +1831,42 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
         }
 }
 
+int unit_add_node_link(Unit *u, const char *what, bool wants) {
+        Unit *device;
+        char *e;
+        int r;
+
+        assert(u);
+
+        if (!what)
+                return 0;
+
+        /* Adds in links to the device node that this unit is based on */
+
+        if (!path_startswith(what, "/dev/") && !path_startswith(what, "/sys/"))
+                return 0;
+
+        if (!(e = unit_name_build_escape(what+1, NULL, ".device")))
+                return -ENOMEM;
+
+        r = manager_load_unit(u->meta.manager, e, NULL, &device);
+        free(e);
+
+        if (r < 0)
+                return r;
+
+        if ((r = unit_add_dependency(u, UNIT_AFTER, device, true)) < 0)
+                return r;
+
+        if ((r = unit_add_dependency(u, UNIT_REQUIRES, device, true)) < 0)
+                return r;
+
+        if (wants)
+                if ((r = unit_add_dependency(device, UNIT_WANTS, u, false)) < 0)
+                        return r;
+
+        return 0;
+}
 
 static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = "service",
diff --git a/unit.h b/unit.h
index 72a742c..5b76a59 100644 (file)
--- a/unit.h
+++ b/unit.h
@@ -426,6 +426,8 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *v
 void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
 int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
 
+int unit_add_node_link(Unit *u, const char *what, bool wants);
+
 const char *unit_type_to_string(UnitType i);
 UnitType unit_type_from_string(const char *s);