From 6e2ef85b2572af82a0ce035516d65218bdc80fa4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 May 2010 03:07:16 +0200 Subject: [PATCH] units: rework automatic dependency logic between automounts, mounts, sockets, swaps --- automount.c | 38 +++++++++++++++ automount.h | 2 + dbus-manager.c | 2 +- hashmap.h | 2 +- main.c | 2 +- manager.c | 2 +- mount.c | 125 ++++++++++++++++++++++++++----------------------- mount.h | 2 - socket-util.c | 13 ++++- socket-util.h | 2 + socket.c | 79 +++++++++++++++++++++++++++++++ socket.h | 5 ++ swap.c | 52 ++++++++++++++++---- swap.h | 7 ++- unit.c | 36 ++++++++++++++ unit.h | 2 + 16 files changed, 296 insertions(+), 75 deletions(-) diff --git a/automount.c b/automount.c index cab7164a5..465354f55 100644 --- a/automount.c +++ b/automount.c @@ -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; diff --git a/automount.h b/automount.h index 5b623691d..014482cc5 100644 --- a/automount.h +++ b/automount.h @@ -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); diff --git a/dbus-manager.c b/dbus-manager.c index 4b3b45e60..90ab8d1a0 100644 --- a/dbus-manager.c +++ b/dbus-manager.c @@ -64,7 +64,7 @@ " " \ " " \ " " \ - " " \ + " " \ " " \ " " \ " " \ diff --git a/hashmap.h b/hashmap.h index 9cdd7016b..3ff3efe8d 100644 --- 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 aa58040ff..b0b3cfb58 100644 --- 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 diff --git a/manager.c b/manager.c index a4696d6e9..6913ff400 100644 --- 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 ce99af077..adb3a084a 100644 --- 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) + 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; +} + +static int mount_add_swap_links(Mount *m) { + Meta *other; + int r; + + assert(m); + + 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; return 0; } -int mount_add_path_links(Unit *u, const char *where, bool requires) { +static int mount_add_automount_links(Mount *m) { Meta *other; int r; - assert(u); + assert(m); - /* Adds in link to other mount points, that might lie below or - * above us in the hierarchy */ + 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; - LIST_FOREACH(units_per_type, other, u->meta.manager->units_per_type[UNIT_MOUNT]) { - Mount *n; + return 0; +} - n = (Mount*) other; +static int mount_add_socket_links(Mount *m) { + Meta *other; + int r; - if (UNIT(n) == u) - continue; + assert(m); - if (u->meta.load_state != UNIT_LOADED) - continue; - - if (path_startswith(where, n->where)) { - - if ((r = unit_add_dependency(u, UNIT_AFTER, UNIT(other), true)) < 0) - return r; - - if (requires) - if ((r = unit_add_dependency(u, UNIT_REQUIRES, UNIT(other), true)) < 0) - return r; - - } else if (path_startswith(n->where, where)) { - - if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(other), true)) < 0) - return r; - - 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_path_links(u, m->where, m->from_etc_fstab || m->from_fragment)) < 0) + if ((r = mount_add_mount_links(m)) < 0) return r; - if ((r = mount_add_target_links(MOUNT(u))) < 0) + if ((r = mount_add_socket_links(m)) < 0) + return r; + + if ((r = mount_add_swap_links(m)) < 0) + return r; + + if ((r = mount_add_automount_links(m)) < 0) + return r; + + 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 dec1b6478..3b28e89ed 100644 --- 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); diff --git a/socket-util.c b/socket-util.c index 8141ab09e..32f6bcb94 100644 --- a/socket-util.c +++ b/socket-util.c @@ -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); } diff --git a/socket-util.h b/socket-util.h index af452efdd..14192167a 100644 --- a/socket-util.h +++ b/socket-util.h @@ -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 diff --git a/socket.c b/socket.c index 402eeaf62..aafe43987 100644 --- 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; diff --git a/socket.h b/socket.h index 7076be7ef..43d28d7e0 100644 --- 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 fffd0b923..275f1d4a9 100644 --- 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 d8692509b..758cdbd31 100644 --- 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 dea6b8bf7..60d4bb7b2 100644 --- 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 72a742ca4..5b76a59b7 100644 --- 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);