]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: split out legacy control socket handling to udev-manager-ctrl.c
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 15 Jan 2025 20:07:41 +0000 (05:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 19 Jan 2025 14:53:45 +0000 (23:53 +0900)
Mostly no functional change, except for that now the socket for device
monitor is determined by its name.

src/udev/meson.build
src/udev/udev-manager-ctrl.c [new file with mode: 0644]
src/udev/udev-manager-ctrl.h [new file with mode: 0644]
src/udev/udev-manager.c

index f008ea1f6653772c8ca8dcd88cf13c55c8ec17b7..fdd042aefa3f90b2f7e4b0e4b3792df9ab6037f7 100644 (file)
@@ -34,6 +34,7 @@ libudevd_core_sources = files(
         'udev-event.c',
         'udev-format.c',
         'udev-manager.c',
+        'udev-manager-ctrl.c',
         'udev-node.c',
         'udev-rules.c',
         'udev-spawn.c',
diff --git a/src/udev/udev-manager-ctrl.c b/src/udev/udev-manager-ctrl.c
new file mode 100644 (file)
index 0000000..b39af06
--- /dev/null
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "sd-daemon.h"
+#include "sd-event.h"
+
+#include "syslog-util.h"
+#include "udev-ctrl.h"
+#include "udev-manager.h"
+#include "udev-manager-ctrl.h"
+
+/* receive the udevd message from userspace */
+static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) {
+        Manager *manager = ASSERT_PTR(userdata);
+
+        assert(value);
+
+        switch (type) {
+        case UDEV_CTRL_SET_LOG_LEVEL:
+                if (!log_level_is_valid(value->intval)) {
+                        log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval);
+                        break;
+                }
+
+                log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
+
+                manager_set_log_level(manager, value->intval);
+                break;
+        case UDEV_CTRL_STOP_EXEC_QUEUE:
+                log_debug("Received udev control message (STOP_EXEC_QUEUE)");
+                manager->stop_exec_queue = true;
+                break;
+        case UDEV_CTRL_START_EXEC_QUEUE:
+                log_debug("Received udev control message (START_EXEC_QUEUE)");
+                manager->stop_exec_queue = false;
+                /* It is not necessary to call event_queue_start() here, as it will be called in on_post() if necessary. */
+                break;
+        case UDEV_CTRL_RELOAD:
+                log_debug("Received udev control message (RELOAD)");
+                manager_reload(manager, /* force = */ true);
+                break;
+        case UDEV_CTRL_SET_ENV:
+                if (!udev_property_assignment_is_valid(value->buf)) {
+                        log_debug("Received invalid udev control message(SET_ENV, %s), ignoring.", value->buf);
+                        break;
+                }
+
+                log_debug("Received udev control message(SET_ENV, %s)", value->buf);
+                manager_set_environment(manager, STRV_MAKE(value->buf));
+                break;
+        case UDEV_CTRL_SET_CHILDREN_MAX:
+                if (value->intval < 0) {
+                        log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval);
+                        return 0;
+                }
+
+                log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval);
+
+                manager_set_children_max(manager, value->intval);
+                break;
+        case UDEV_CTRL_PING:
+                log_debug("Received udev control message (PING)");
+                break;
+        case UDEV_CTRL_EXIT:
+                log_debug("Received udev control message (EXIT)");
+                manager_exit(manager);
+                break;
+        default:
+                log_debug("Received unknown udev control message, ignoring");
+        }
+
+        return 1;
+}
+
+int manager_init_ctrl(Manager *manager, int fd) {
+        int r;
+
+        assert(manager);
+
+        /* This takes passed file descriptor on success. */
+
+        if (fd >= 0) {
+                if (manager->ctrl)
+                        return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple control socket (%i), ignoring.", fd);
+
+                r = sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd);
+                if (r == 0)
+                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid control socket (%i), ignoring.", fd);
+        } else {
+                if (manager->ctrl)
+                        return 0;
+        }
+
+        r = udev_ctrl_new_from_fd(&manager->ctrl, fd);
+        if (r < 0)
+                return log_error_errno(r, "Failed to initialize udev control socket: %m");
+
+        return 0;
+}
+
+int manager_start_ctrl(Manager *manager) {
+        int r;
+
+        assert(manager);
+        assert(manager->event);
+
+        r = manager_init_ctrl(manager, -EBADF);
+        if (r < 0)
+                return r;
+
+        r = udev_ctrl_enable_receiving(manager->ctrl);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind udev control socket: %m");
+
+        r = udev_ctrl_attach_event(manager->ctrl, manager->event);
+        if (r < 0)
+                return log_error_errno(r, "Failed to attach event to udev control: %m");
+
+        r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
+        if (r < 0)
+                return log_error_errno(r, "Failed to start udev control: %m");
+
+        /* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
+         * after fully processing the pending uevents (including the synthetic ones we may create due to
+         * inotify events). */
+        r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
+
+        return 0;
+}
diff --git a/src/udev/udev-manager-ctrl.h b/src/udev/udev-manager-ctrl.h
new file mode 100644 (file)
index 0000000..507072c
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#pragma once
+
+typedef struct Manager Manager;
+
+int manager_init_ctrl(Manager *manager, int fd);
+int manager_start_ctrl(Manager *manager);
index caa43797597ece0fb591429c6bc7c4e7a1decf95..59a04c6f4413279387d57f3dab2128e404d45a98 100644 (file)
@@ -27,6 +27,7 @@
 #include "udev-ctrl.h"
 #include "udev-event.h"
 #include "udev-manager.h"
+#include "udev-manager-ctrl.h"
 #include "udev-node.h"
 #include "udev-rules.h"
 #include "udev-spawn.h"
@@ -843,69 +844,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
         return 1;
 }
 
-/* receive the udevd message from userspace */
-static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) {
-        Manager *manager = ASSERT_PTR(userdata);
-
-        assert(value);
-
-        switch (type) {
-        case UDEV_CTRL_SET_LOG_LEVEL:
-                if (!log_level_is_valid(value->intval)) {
-                        log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval);
-                        break;
-                }
-
-                log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
-
-                manager_set_log_level(manager, value->intval);
-                break;
-        case UDEV_CTRL_STOP_EXEC_QUEUE:
-                log_debug("Received udev control message (STOP_EXEC_QUEUE)");
-                manager->stop_exec_queue = true;
-                break;
-        case UDEV_CTRL_START_EXEC_QUEUE:
-                log_debug("Received udev control message (START_EXEC_QUEUE)");
-                manager->stop_exec_queue = false;
-                /* It is not necessary to call event_queue_start() here, as it will be called in on_post() if necessary. */
-                break;
-        case UDEV_CTRL_RELOAD:
-                log_debug("Received udev control message (RELOAD)");
-                manager_reload(manager, /* force = */ true);
-                break;
-        case UDEV_CTRL_SET_ENV:
-                if (!udev_property_assignment_is_valid(value->buf)) {
-                        log_debug("Received invalid udev control message(SET_ENV, %s), ignoring.", value->buf);
-                        break;
-                }
-
-                log_debug("Received udev control message(SET_ENV, %s)", value->buf);
-                manager_set_environment(manager, STRV_MAKE(value->buf));
-                break;
-        case UDEV_CTRL_SET_CHILDREN_MAX:
-                if (value->intval < 0) {
-                        log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval);
-                        return 0;
-                }
-
-                log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval);
-
-                manager_set_children_max(manager, value->intval);
-                break;
-        case UDEV_CTRL_PING:
-                log_debug("Received udev control message (PING)");
-                break;
-        case UDEV_CTRL_EXIT:
-                log_debug("Received udev control message (EXIT)");
-                manager_exit(manager);
-                break;
-        default:
-                log_debug("Received unknown udev control message, ignoring");
-        }
-
-        return 1;
-}
-
 static int synthesize_change_one(sd_device *dev, sd_device *target) {
         int r;
 
@@ -1135,11 +1073,12 @@ Manager* manager_new(void) {
         return manager;
 }
 
-static int listen_fds(int *ret_ctrl, int *ret_netlink) {
+static int manager_listen_fds(Manager *manager, int *ret_netlink) {
         _cleanup_strv_free_ char **names = NULL;
-        _cleanup_close_ int ctrl_fd = -EBADF, netlink_fd = -EBADF;
+        _cleanup_close_ int netlink_fd = -EBADF;
+        int r;
 
-        assert(ret_ctrl);
+        assert(manager);
         assert(ret_netlink);
 
         int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
@@ -1152,19 +1091,6 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
         for (int i = 0; i < n; i++) {
                 int fd = SD_LISTEN_FDS_START + i;
 
-                if (streq(names[i], "varlink"))
-                        continue; /* The fd will be handled by sd_varlink_server_listen_auto(). */
-
-                if (sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1) > 0) {
-                        if (ctrl_fd >= 0) {
-                                log_debug("Received multiple seqpacket socket (%s), ignoring.", names[i]);
-                                goto unused;
-                        }
-
-                        ctrl_fd = fd;
-                        continue;
-                }
-
                 if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
                         if (netlink_fd >= 0) {
                                 log_debug("Received multiple netlink socket (%s), ignoring.", names[i]);
@@ -1175,39 +1101,24 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
                         continue;
                 }
 
-                log_debug("Received unexpected fd (%s), ignoring.", names[i]);
+                if (streq(names[i], "varlink"))
+                        r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
+                else if (streq(names[i], "systemd-udevd-control.socket"))
+                        r = manager_init_ctrl(manager, fd);
+                else
+                        r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                            "Received unexpected fd (%s), ignoring.", names[i]);
+                if (r < 0)
+                        goto unused;
 
         unused:
                 close_and_notify_warn(fd, names[i]);
         }
 
-        *ret_ctrl = TAKE_FD(ctrl_fd);
         *ret_netlink = TAKE_FD(netlink_fd);
         return 0;
 }
 
-static int manager_init_ctrl(Manager *manager, int fd_ctrl) {
-        _cleanup_(udev_ctrl_unrefp) UdevCtrl *ctrl = NULL;
-        _cleanup_close_ int fd = fd_ctrl;
-        int r;
-
-        assert(manager);
-
-        /* This consumes passed file descriptor. */
-
-        r = udev_ctrl_new_from_fd(&ctrl, fd);
-        if (r < 0)
-                return log_error_errno(r, "Failed to initialize udev control socket: %m");
-        TAKE_FD(fd);
-
-        r = udev_ctrl_enable_receiving(ctrl);
-        if (r < 0)
-                return log_error_errno(r, "Failed to bind udev control socket: %m");
-
-        manager->ctrl = TAKE_PTR(ctrl);
-        return 0;
-}
-
 static int manager_init_device_monitor(Manager *manager, int fd_uevent) {
         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
         _cleanup_close_ int fd = fd_uevent;
@@ -1229,20 +1140,16 @@ static int manager_init_device_monitor(Manager *manager, int fd_uevent) {
 }
 
 int manager_init(Manager *manager) {
-        _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
+        _cleanup_close_ int fd_uevent = -EBADF;
         _cleanup_free_ char *cgroup = NULL;
         int r;
 
         assert(manager);
 
-        r = listen_fds(&fd_ctrl, &fd_uevent);
+        r = manager_listen_fds(manager, &fd_uevent);
         if (r < 0)
                 return log_error_errno(r, "Failed to listen on fds: %m");
 
-        r = manager_init_ctrl(manager, TAKE_FD(fd_ctrl));
-        if (r < 0)
-                return r;
-
         r = manager_init_device_monitor(manager, TAKE_FD(fd_uevent));
         if (r < 0)
                 return r;
@@ -1258,30 +1165,6 @@ int manager_init(Manager *manager) {
         return 0;
 }
 
-static int manager_start_ctrl(Manager *manager) {
-        int r;
-
-        assert(manager);
-        assert(manager->ctrl);
-
-        r = udev_ctrl_attach_event(manager->ctrl, manager->event);
-        if (r < 0)
-                return log_error_errno(r, "Failed to attach event to udev control: %m");
-
-        r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
-        if (r < 0)
-                return log_error_errno(r, "Failed to start udev control: %m");
-
-        /* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
-         * after fully processing the pending uevents (including the synthetic ones we may create due to
-         * inotify events). */
-        r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
-        if (r < 0)
-                return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
-
-        return 0;
-}
-
 static int manager_start_device_monitor(Manager *manager) {
         int r;