]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/udevd.c
udev: open control and netlink sockets before daemonization
[thirdparty/systemd.git] / src / udev / udevd.c
index db33de3c5f800f292f144616e1ae7d1ecc88f1f3..697506feaf55dd5a826a434e42215cf393ac3bb8 100644 (file)
@@ -31,6 +31,7 @@
 #include "sd-event.h"
 
 #include "alloc-util.h"
+#include "build.h"
 #include "cgroup-util.h"
 #include "cpu-set-util.h"
 #include "dev-setup.h"
@@ -57,6 +58,7 @@
 #include "signal-util.h"
 #include "socket-util.h"
 #include "string-util.h"
+#include "strv.h"
 #include "strxcpyx.h"
 #include "syslog-util.h"
 #include "udev-builtin.h"
@@ -80,7 +82,7 @@ typedef struct Manager {
         const char *cgroup;
         pid_t pid; /* the process that originally allocated the manager object */
 
-        struct udev_rules *rules;
+        UdevRules *rules;
         Hashmap *properties;
 
         sd_netlink *rtnl;
@@ -310,7 +312,7 @@ static void manager_free(Manager *manager) {
         sd_netlink_unref(manager->rtnl);
 
         hashmap_free_free_free(manager->properties);
-        udev_rules_unref(manager->rules);
+        udev_rules_free(manager->rules);
 
         safe_close(manager->fd_inotify);
         safe_close_pair(manager->worker_watch);
@@ -361,9 +363,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) {
         if (r < 0)
                 return log_device_debug_errno(dev, r, "Failed to get sysname: %m");
 
-        if (startswith(val, "dm-") ||
-            startswith(val, "md") ||
-            startswith(val, "drbd"))
+        if (STARTSWITH_SET(val, "dm-", "md", "drbd"))
                 return 0;
 
         r = sd_device_get_devtype(dev, &val);
@@ -395,7 +395,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) {
 }
 
 static int worker_process_device(Manager *manager, sd_device *dev) {
-        _cleanup_(udev_event_freep) struct udev_event *udev_event = NULL;
+        _cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
         _cleanup_close_ int fd_lock = -1;
         const char *seqnum;
         int r;
@@ -465,7 +465,7 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
 static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device *first_device) {
         _cleanup_(sd_device_unrefp) sd_device *dev = first_device;
         _cleanup_(manager_freep) Manager *manager = _manager;
-        int r, ret;
+        int r;
 
         assert(manager);
         assert(monitor);
@@ -508,11 +508,7 @@ static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device
         if (r < 0)
                 return log_error_errno(r, "Event loop failed: %m");
 
-        r = sd_event_get_exit_code(manager->event, &ret);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get exit code: %m");
-
-        return ret;
+        return 0;
 }
 
 static int worker_spawn(Manager *manager, struct event *event) {
@@ -843,7 +839,7 @@ static void manager_reload(Manager *manager) {
                   "STATUS=Flushing configuration...");
 
         manager_kill_workers(manager);
-        manager->rules = udev_rules_unref(manager->rules);
+        manager->rules = udev_rules_free(manager->rules);
         udev_builtin_exit();
 
         sd_notifyf(false,
@@ -891,9 +887,11 @@ static void event_queue_start(Manager *manager) {
         udev_builtin_init();
 
         if (!manager->rules) {
-                manager->rules = udev_rules_new(arg_resolve_name_timing);
-                if (!manager->rules)
+                r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to read udev rules: %m");
                         return;
+                }
         }
 
         LIST_FOREACH(event, event, manager->events) {
@@ -1578,7 +1576,7 @@ static int parse_argv(int argc, char *argv[]) {
                 case 'h':
                         return help();
                 case 'V':
-                        printf("%s\n", PACKAGE_VERSION);
+                        printf("%s\n", GIT_VERSION);
                         return 0;
                 case '?':
                         return -EINVAL;
@@ -1593,7 +1591,7 @@ static int parse_argv(int argc, char *argv[]) {
 
 static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) {
         _cleanup_(manager_freep) Manager *manager = NULL;
-        int r, fd_worker;
+        int r;
 
         assert(ret);
 
@@ -1607,12 +1605,6 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
                 .cgroup = cgroup,
         };
 
-        udev_builtin_init();
-
-        manager->rules = udev_rules_new(arg_resolve_name_timing);
-        if (!manager->rules)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to read udev rules");
-
         manager->ctrl = udev_ctrl_new_from_fd(fd_ctrl);
         if (!manager->ctrl)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize udev control socket");
@@ -1621,16 +1613,24 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
         if (r < 0)
                 return log_error_errno(r, "Failed to bind udev control socket: %m");
 
-        fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
-        if (fd_ctrl < 0)
-                return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
-
         r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize device monitor: %m");
 
         (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
 
+        r = device_monitor_enable_receiving(manager->monitor);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind netlink socket: %m");
+
+        *ret = TAKE_PTR(manager);
+
+        return 0;
+}
+
+static int main_loop(Manager *manager) {
+        int fd_worker, fd_ctrl, r;
+
         /* unnamed socket from workers to the main daemon */
         r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
         if (r < 0)
@@ -1676,6 +1676,10 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
         if (r < 0)
                 return log_error_errno(r, "Failed to create watchdog event source: %m");
 
+        fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
+        if (fd_ctrl < 0)
+                return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+
         r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager);
         if (r < 0)
                 return log_error_errno(r, "Failed to create udev control event source: %m");
@@ -1710,20 +1714,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
         if (r < 0)
                 return log_error_errno(r, "Failed to create post event source: %m");
 
-        *ret = TAKE_PTR(manager);
-
-        return 0;
-}
-
-static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
-        _cleanup_(manager_freep) Manager *manager = NULL;
-        int r;
+        udev_builtin_init();
 
-        r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
-        if (r < 0) {
-                r = log_error_errno(r, "Failed to allocate manager object: %m");
-                goto exit;
-        }
+        r = udev_rules_new(&manager->rules, arg_resolve_name_timing);
+        if (!manager->rules)
+                return log_error_errno(r, "Failed to read udev rules: %m");
 
         r = udev_rules_apply_static_dev_perms(manager->rules);
         if (r < 0)
@@ -1734,24 +1729,18 @@ static int main_loop(int fd_ctrl, int fd_uevent, const char *cgroup) {
                           "STATUS=Processing with %u children at max", arg_children_max);
 
         r = sd_event_loop(manager->event);
-        if (r < 0) {
+        if (r < 0)
                 log_error_errno(r, "Event loop failed: %m");
-                goto exit;
-        }
 
-        sd_event_get_exit_code(manager->event, &r);
-
-exit:
         sd_notify(false,
                   "STOPPING=1\n"
                   "STATUS=Shutting down...");
-        if (manager)
-                udev_ctrl_cleanup(manager->ctrl);
         return r;
 }
 
 static int run(int argc, char *argv[]) {
         _cleanup_free_ char *cgroup = NULL;
+        _cleanup_(manager_freep) Manager *manager = NULL;
         int fd_ctrl = -1, fd_uevent = -1;
         int r;
 
@@ -1828,10 +1817,14 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return log_error_errno(r, "Failed to listen on fds: %m");
 
+        r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
+        if (r < 0)
+                return log_error_errno(r, "Failed to create manager: %m");
+
         if (arg_daemonize) {
                 pid_t pid;
 
-                log_info("starting version " PACKAGE_VERSION);
+                log_info("Starting version " GIT_VERSION);
 
                 /* connect /dev/null to stdin, stdout, stderr */
                 if (log_get_max_level() < LOG_DEBUG) {
@@ -1848,14 +1841,17 @@ static int run(int argc, char *argv[]) {
                         return 0;
 
                 /* child */
-                setsid();
+                (void) setsid();
 
                 r = set_oom_score_adjust(-1000);
                 if (r < 0)
                         log_debug_errno(r, "Failed to adjust OOM score, ignoring: %m");
         }
 
-        return main_loop(fd_ctrl, fd_uevent, cgroup);
+        r = main_loop(manager);
+        /* FIXME: move this into manager_free() */
+        udev_ctrl_cleanup(manager->ctrl);
+        return r;
 }
 
 DEFINE_MAIN_FUNCTION(run);