311 lines
13 KiB
Diff
311 lines
13 KiB
Diff
From b6876d46a4695c0626db089170ea28cb263d3cdb Mon Sep 17 00:00:00 2001
|
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
|
Date: Sun, 22 Dec 2024 00:11:38 +0900
|
|
Subject: [PATCH] udev: split manager_init() and manager_main() into small
|
|
pieces
|
|
|
|
No functional change, just refactoring.
|
|
|
|
Co-authored-by: David Tardon <dtardon@redhat.com>
|
|
(cherry picked from commit 0079651876aa5df73fd787b272e91ae4a7898853)
|
|
|
|
Resolves: RHEL-75774
|
|
---
|
|
src/udev/udev-manager.c | 217 +++++++++++++++++++++++++++++-----------
|
|
1 file changed, 161 insertions(+), 56 deletions(-)
|
|
|
|
diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c
|
|
index 4fc316e106..d9bd9d6d7b 100644
|
|
--- a/src/udev/udev-manager.c
|
|
+++ b/src/udev/udev-manager.c
|
|
@@ -1232,32 +1232,66 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
|
|
return 0;
|
|
}
|
|
|
|
-int manager_init(Manager *manager) {
|
|
- _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
|
|
- _cleanup_free_ char *cgroup = NULL;
|
|
+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);
|
|
|
|
- r = listen_fds(&fd_ctrl, &fd_uevent);
|
|
- if (r < 0)
|
|
- return log_error_errno(r, "Failed to listen on fds: %m");
|
|
+ /* This consumes passed file descriptor. */
|
|
|
|
- r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl);
|
|
+ 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_ctrl);
|
|
+ TAKE_FD(fd);
|
|
|
|
- r = udev_ctrl_enable_receiving(manager->ctrl);
|
|
+ r = udev_ctrl_enable_receiving(ctrl);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to bind udev control socket: %m");
|
|
|
|
- r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent);
|
|
+ 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;
|
|
+ int r;
|
|
+
|
|
+ assert(manager);
|
|
+
|
|
+ /* This consumes passed file descriptor. */
|
|
+
|
|
+ r = device_monitor_new_full(&monitor, MONITOR_GROUP_KERNEL, fd);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to initialize device monitor: %m");
|
|
- TAKE_FD(fd_uevent);
|
|
+ TAKE_FD(fd);
|
|
+
|
|
+ (void) sd_device_monitor_set_description(monitor, "manager");
|
|
+
|
|
+ manager->monitor = TAKE_PTR(monitor);
|
|
+ return 0;
|
|
+}
|
|
|
|
- (void) sd_device_monitor_set_description(manager->monitor, "manager");
|
|
+int manager_init(Manager *manager) {
|
|
+ _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF;
|
|
+ _cleanup_free_ char *cgroup = NULL;
|
|
+ int r;
|
|
+
|
|
+ assert(manager);
|
|
+
|
|
+ r = listen_fds(&fd_ctrl, &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;
|
|
|
|
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
|
|
if (r < 0)
|
|
@@ -1270,95 +1304,166 @@ int manager_init(Manager *manager) {
|
|
return 0;
|
|
}
|
|
|
|
-int manager_main(Manager *manager) {
|
|
- int fd_worker, r;
|
|
+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;
|
|
+
|
|
+ assert(manager);
|
|
+ assert(manager->monitor);
|
|
+
|
|
+ r = sd_device_monitor_attach_event(manager->monitor, manager->event);
|
|
+ if (r < 0)
|
|
+ return log_error_errno(r, "Failed to attach event to device monitor: %m");
|
|
+
|
|
+ r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
|
|
+ if (r < 0)
|
|
+ return log_error_errno(r, "Failed to start device monitor: %m");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int manager_start_inotify(Manager *manager) {
|
|
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
|
|
+ _cleanup_close_ int fd = -EBADF;
|
|
+ int r;
|
|
+
|
|
+ assert(manager);
|
|
+ assert(manager->event);
|
|
+
|
|
+ fd = inotify_init1(IN_CLOEXEC);
|
|
+ if (fd < 0)
|
|
+ return log_error_errno(errno, "Failed to create inotify descriptor: %m");
|
|
+
|
|
+ udev_watch_restore(fd);
|
|
+
|
|
+ r = sd_event_add_io(manager->event, &s, fd, EPOLLIN, on_inotify, manager);
|
|
+ if (r < 0)
|
|
+ return log_error_errno(r, "Failed to create inotify event source: %m");
|
|
+
|
|
+ (void) sd_event_source_set_description(s, "manager-inotify");
|
|
+
|
|
+ manager->inotify_fd = TAKE_FD(fd);
|
|
+ manager->inotify_event = TAKE_PTR(s);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int manager_start_worker_event(Manager *manager) {
|
|
+ int r;
|
|
+
|
|
+ assert(manager);
|
|
+ assert(manager->event);
|
|
|
|
/* unnamed socket from workers to the main daemon */
|
|
r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
|
|
if (r < 0)
|
|
return log_error_errno(errno, "Failed to create socketpair for communicating with workers: %m");
|
|
|
|
- fd_worker = manager->worker_watch[READ_END];
|
|
-
|
|
- r = setsockopt_int(fd_worker, SOL_SOCKET, SO_PASSCRED, true);
|
|
+ r = setsockopt_int(manager->worker_watch[READ_END], SOL_SOCKET, SO_PASSCRED, true);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
|
|
|
|
- manager->inotify_fd = inotify_init1(IN_CLOEXEC);
|
|
- if (manager->inotify_fd < 0)
|
|
- return log_error_errno(errno, "Failed to create inotify descriptor: %m");
|
|
+ r = sd_event_add_io(manager->event, NULL, manager->worker_watch[READ_END], EPOLLIN, on_worker, manager);
|
|
+ if (r < 0)
|
|
+ return log_error_errno(r, "Failed to create worker event source: %m");
|
|
|
|
- udev_watch_restore(manager->inotify_fd);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int manager_setup_event(Manager *manager) {
|
|
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
|
+ int r;
|
|
+
|
|
+ assert(manager);
|
|
|
|
/* block SIGCHLD for listening child events. */
|
|
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
|
|
- r = sd_event_default(&manager->event);
|
|
+ r = sd_event_default(&e);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to allocate event loop: %m");
|
|
|
|
- r = sd_event_add_signal(manager->event, NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
|
|
+ r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to create SIGINT event source: %m");
|
|
|
|
- r = sd_event_add_signal(manager->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
|
|
+ r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to create SIGTERM event source: %m");
|
|
|
|
- r = sd_event_add_signal(manager->event, NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
|
|
+ r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to create SIGHUP event source: %m");
|
|
|
|
- r = sd_event_set_watchdog(manager->event, true);
|
|
+ r = sd_event_add_post(e, /* ret_event_source = */ NULL, on_post, manager);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to create watchdog event source: %m");
|
|
+ return log_error_errno(r, "Failed to create post event source: %m");
|
|
|
|
- r = udev_ctrl_attach_event(manager->ctrl, manager->event);
|
|
+ /* Eventually, we probably want to do more here on memory pressure, for example, kill idle workers immediately */
|
|
+ r = sd_event_add_memory_pressure(e, /* ret_event_source= */ NULL, /* callback= */ NULL, /* userdata= */ NULL);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to attach event to udev control: %m");
|
|
+ log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
|
|
+ "Failed to allocate memory pressure watch, ignoring: %m");
|
|
|
|
- r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
|
|
+ r = sd_event_add_signal(e, /* ret_event_source= */ NULL,
|
|
+ (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, /* userdata= */ NULL);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to start udev control: %m");
|
|
+ return log_error_errno(r, "Failed to allocate SIGRTMIN+18 event source, ignoring: %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);
|
|
+ r = sd_event_set_watchdog(e, true);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
|
|
+ return log_error_errno(r, "Failed to create watchdog event source: %m");
|
|
|
|
- r = sd_event_add_io(manager->event, &manager->inotify_event, manager->inotify_fd, EPOLLIN, on_inotify, manager);
|
|
- if (r < 0)
|
|
- return log_error_errno(r, "Failed to create inotify event source: %m");
|
|
+ manager->event = TAKE_PTR(e);
|
|
+ return 0;
|
|
+}
|
|
|
|
- r = sd_device_monitor_attach_event(manager->monitor, manager->event);
|
|
- if (r < 0)
|
|
- return log_error_errno(r, "Failed to attach event to device monitor: %m");
|
|
+int manager_main(Manager *manager) {
|
|
+ int r;
|
|
|
|
- r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
|
|
+ assert(manager);
|
|
+
|
|
+ r = manager_setup_event(manager);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to start device monitor: %m");
|
|
+ return r;
|
|
|
|
- r = sd_event_add_io(manager->event, NULL, fd_worker, EPOLLIN, on_worker, manager);
|
|
+ r = manager_start_ctrl(manager);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to create worker event source: %m");
|
|
+ return r;
|
|
|
|
- r = sd_event_add_post(manager->event, NULL, on_post, manager);
|
|
+ r = manager_start_device_monitor(manager);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to create post event source: %m");
|
|
+ return r;
|
|
|
|
- /* Eventually, we probably want to do more here on memory pressure, for example, kill idle workers immediately */
|
|
- r = sd_event_add_memory_pressure(manager->event, /* ret_event_source= */ NULL, /* callback= */ NULL, /* userdata= */ NULL);
|
|
+ r = manager_start_inotify(manager);
|
|
if (r < 0)
|
|
- log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
|
|
- "Failed to allocate memory pressure watch, ignoring: %m");
|
|
+ return r;
|
|
|
|
- r = sd_event_add_signal(manager->event, /* ret_event_source= */ NULL,
|
|
- (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, /* userdata= */ NULL);
|
|
+ r = manager_start_worker_event(manager);
|
|
if (r < 0)
|
|
- return log_error_errno(r, "Failed to allocate SIGRTMIN+18 event source, ignoring: %m");
|
|
+ return r;
|
|
|
|
manager->last_usec = now(CLOCK_MONOTONIC);
|
|
|