]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: move inotify watch related functions to udev-watch.c
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 2 Apr 2025 17:55:36 +0000 (02:55 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 4 Apr 2025 22:10:17 +0000 (07:10 +0900)
src/udev/udev-manager.c
src/udev/udev-manager.h
src/udev/udev-watch.c
src/udev/udev-watch.h

index e319277c2bd30341180490c2206aa65b251276f7..5303c4d2536519f884555b5f88f77d939036197e 100644 (file)
@@ -1,6 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 
-#include "blockdev-util.h"
 #include "cgroup-util.h"
 #include "common-signal.h"
 #include "daemon-util.h"
@@ -12,7 +11,6 @@
 #include "fd-util.h"
 #include "fs-util.h"
 #include "hashmap.h"
-#include "inotify-util.h"
 #include "iovec-util.h"
 #include "list.h"
 #include "mkdir.h"
@@ -705,7 +703,7 @@ fail:
         event_free(event);
 }
 
-static int event_queue_assume_block_device_unlocked(Manager *manager, sd_device *dev) {
+int event_queue_assume_block_device_unlocked(Manager *manager, sd_device *dev) {
         const char *devname;
         int r;
 
@@ -858,162 +856,6 @@ static int on_worker_notify(sd_event_source *s, int fd, uint32_t revents, void *
         return 0;
 }
 
-static int synthesize_change_one(sd_device *dev, sd_device *target) {
-        int r;
-
-        assert(dev);
-        assert(target);
-
-        if (DEBUG_LOGGING) {
-                const char *syspath = NULL;
-                (void) sd_device_get_syspath(target, &syspath);
-                log_device_debug(dev, "device is closed, synthesising 'change' on %s", strna(syspath));
-        }
-
-        r = sd_device_trigger(target, SD_DEVICE_CHANGE);
-        if (r < 0)
-                return log_device_debug_errno(target, r, "Failed to trigger 'change' uevent: %m");
-
-        DEVICE_TRACE_POINT(synthetic_change_event, dev);
-
-        return 0;
-}
-
-static int synthesize_change_all(sd_device *dev) {
-        int r;
-
-        assert(dev);
-
-        r = blockdev_reread_partition_table(dev);
-        if (r < 0)
-                log_device_debug_errno(dev, r, "Failed to re-read partition table, ignoring: %m");
-        bool part_table_read = r >= 0;
-
-        /* search for partitions */
-        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
-        r = partition_enumerator_new(dev, &e);
-        if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to initialize partition enumerator, ignoring: %m");
-
-        /* We have partitions and re-read the table, the kernel already sent out a "change"
-         * event for the disk, and "remove/add" for all partitions. */
-        if (part_table_read && sd_device_enumerator_get_device_first(e))
-                return 0;
-
-        /* We have partitions but re-reading the partition table did not work, synthesize
-         * "change" for the disk and all partitions. */
-        r = synthesize_change_one(dev, dev);
-        FOREACH_DEVICE(e, d)
-                RET_GATHER(r, synthesize_change_one(dev, d));
-
-        return r;
-}
-
-static int synthesize_change_child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
-        Manager *manager = ASSERT_PTR(userdata);
-        assert(s);
-
-        sd_event_source_unref(set_remove(manager->synthesize_change_child_event_sources, s));
-        return 0;
-}
-
-static int synthesize_change(Manager *manager, sd_device *dev) {
-        int r;
-
-        assert(manager);
-        assert(dev);
-
-        const char *sysname;
-        r = sd_device_get_sysname(dev, &sysname);
-        if (r < 0)
-                return r;
-
-        if (startswith(sysname, "dm-") || block_device_is_whole_disk(dev) <= 0)
-                return synthesize_change_one(dev, dev);
-
-        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
-        r = pidref_safe_fork(
-                        "(udev-synth)",
-                        FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
-                        &pidref);
-        if (r < 0)
-                return r;
-        if (r == 0) {
-                /* child */
-                (void) synthesize_change_all(dev);
-                _exit(EXIT_SUCCESS);
-        }
-
-        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
-        r = event_add_child_pidref(manager->event, &s, &pidref, WEXITED, synthesize_change_child_handler, manager);
-        if (r < 0) {
-                log_debug_errno(r, "Failed to add child event source for "PID_FMT", ignoring: %m", pidref.pid);
-                return 0;
-        }
-
-        r = sd_event_source_set_child_pidfd_own(s, true);
-        if (r < 0)
-                return r;
-        TAKE_PIDREF(pidref);
-
-        r = set_ensure_put(&manager->synthesize_change_child_event_sources, &event_source_hash_ops, s);
-        if (r < 0)
-                return r;
-        TAKE_PTR(s);
-
-        return 0;
-}
-
-static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        Manager *manager = ASSERT_PTR(userdata);
-        union inotify_event_buffer buffer;
-        ssize_t l;
-        int r;
-
-        l = read(fd, &buffer, sizeof(buffer));
-        if (l < 0) {
-                if (ERRNO_IS_TRANSIENT(errno))
-                        return 0;
-
-                return log_error_errno(errno, "Failed to read inotify fd: %m");
-        }
-
-        FOREACH_INOTIFY_EVENT_WARN(e, buffer, l) {
-                _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
-                const char *devnode;
-
-                /* Do not handle IN_IGNORED here. Especially, do not try to call udev_watch_end() from the
-                 * main process. Otherwise, the pair of the symlinks may become inconsistent, and several
-                 * garbage may remain. The old symlinks are removed by a worker that processes the
-                 * corresponding 'remove' uevent;
-                 * udev_event_execute_rules() -> event_execute_rules_on_remove() -> udev_watch_end(). */
-
-                if (!FLAGS_SET(e->mask, IN_CLOSE_WRITE))
-                        continue;
-
-                r = device_new_from_watch_handle(&dev, e->wd);
-                if (r < 0) {
-                        /* Device may be removed just after closed. */
-                        log_debug_errno(r, "Failed to create sd_device object from watch handle, ignoring: %m");
-                        continue;
-                }
-
-                r = sd_device_get_devname(dev, &devnode);
-                if (r < 0) {
-                        /* Also here, device may be already removed. */
-                        log_device_debug_errno(dev, r, "Failed to get device node, ignoring: %m");
-                        continue;
-                }
-
-                log_device_debug(dev, "Received inotify event for %s.", devnode);
-
-                (void) event_queue_assume_block_device_unlocked(manager, dev);
-                (void) synthesize_change(manager, dev);
-        }
-
-        return 0;
-}
-
 static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
         Manager *manager = ASSERT_PTR(userdata);
 
@@ -1252,31 +1094,6 @@ static int manager_start_device_monitor(Manager *manager) {
         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_notify(Manager *manager) {
         int r;
 
index dab271abaa825fe78b4655003c340c708650de32..3ed393c1f00c7052475a8862e37d6c548bb26b2f 100644 (file)
@@ -66,3 +66,5 @@ void notify_ready(Manager *manager);
 void manager_kill_workers(Manager *manager, bool force);
 
 bool devpath_conflict(const char *a, const char *b);
+
+int event_queue_assume_block_device_unlocked(Manager *manager, sd_device *dev);
index 0254cf6ed96d4fbb718f9d612689f0e572cb64d1..c4b63a4d2f89b03cc155c297bcf23182c10be792 100644 (file)
@@ -4,23 +4,25 @@
  * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
  */
 
-#include <sys/inotify.h>
-
 #include "alloc-util.h"
-#include "device-private.h"
+#include "blockdev-util.h"
 #include "device-util.h"
 #include "dirent-util.h"
+#include "event-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
+#include "inotify-util.h"
 #include "mkdir.h"
 #include "parse-util.h"
 #include "rm-rf.h"
 #include "stdio-util.h"
 #include "string-util.h"
+#include "udev-manager.h"
+#include "udev-trace.h"
 #include "udev-util.h"
 #include "udev-watch.h"
 
-int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
+static int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
         char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
         _cleanup_free_ char *id = NULL;
         int r;
@@ -43,7 +45,163 @@ int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
         return sd_device_new_from_device_id(ret, id);
 }
 
-int udev_watch_restore(int inotify_fd) {
+static int synthesize_change_one(sd_device *dev, sd_device *target) {
+        int r;
+
+        assert(dev);
+        assert(target);
+
+        if (DEBUG_LOGGING) {
+                const char *syspath = NULL;
+                (void) sd_device_get_syspath(target, &syspath);
+                log_device_debug(dev, "device is closed, synthesising 'change' on %s", strna(syspath));
+        }
+
+        r = sd_device_trigger(target, SD_DEVICE_CHANGE);
+        if (r < 0)
+                return log_device_debug_errno(target, r, "Failed to trigger 'change' uevent: %m");
+
+        DEVICE_TRACE_POINT(synthetic_change_event, dev);
+
+        return 0;
+}
+
+static int synthesize_change_all(sd_device *dev) {
+        int r;
+
+        assert(dev);
+
+        r = blockdev_reread_partition_table(dev);
+        if (r < 0)
+                log_device_debug_errno(dev, r, "Failed to re-read partition table, ignoring: %m");
+        bool part_table_read = r >= 0;
+
+        /* search for partitions */
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        r = partition_enumerator_new(dev, &e);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to initialize partition enumerator, ignoring: %m");
+
+        /* We have partitions and re-read the table, the kernel already sent out a "change"
+         * event for the disk, and "remove/add" for all partitions. */
+        if (part_table_read && sd_device_enumerator_get_device_first(e))
+                return 0;
+
+        /* We have partitions but re-reading the partition table did not work, synthesize
+         * "change" for the disk and all partitions. */
+        r = synthesize_change_one(dev, dev);
+        FOREACH_DEVICE(e, d)
+                RET_GATHER(r, synthesize_change_one(dev, d));
+
+        return r;
+}
+
+static int synthesize_change_child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
+        Manager *manager = ASSERT_PTR(userdata);
+        assert(s);
+
+        sd_event_source_unref(set_remove(manager->synthesize_change_child_event_sources, s));
+        return 0;
+}
+
+static int synthesize_change(Manager *manager, sd_device *dev) {
+        int r;
+
+        assert(manager);
+        assert(dev);
+
+        const char *sysname;
+        r = sd_device_get_sysname(dev, &sysname);
+        if (r < 0)
+                return r;
+
+        if (startswith(sysname, "dm-") || block_device_is_whole_disk(dev) <= 0)
+                return synthesize_change_one(dev, dev);
+
+        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+        r = pidref_safe_fork(
+                        "(udev-synth)",
+                        FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+                        &pidref);
+        if (r < 0)
+                return r;
+        if (r == 0) {
+                /* child */
+                (void) synthesize_change_all(dev);
+                _exit(EXIT_SUCCESS);
+        }
+
+        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+        r = event_add_child_pidref(manager->event, &s, &pidref, WEXITED, synthesize_change_child_handler, manager);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to add child event source for "PID_FMT", ignoring: %m", pidref.pid);
+                return 0;
+        }
+
+        r = sd_event_source_set_child_pidfd_own(s, true);
+        if (r < 0)
+                return r;
+        TAKE_PIDREF(pidref);
+
+        r = set_ensure_put(&manager->synthesize_change_child_event_sources, &event_source_hash_ops, s);
+        if (r < 0)
+                return r;
+        TAKE_PTR(s);
+
+        return 0;
+}
+
+static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Manager *manager = ASSERT_PTR(userdata);
+        union inotify_event_buffer buffer;
+        ssize_t l;
+        int r;
+
+        l = read(fd, &buffer, sizeof(buffer));
+        if (l < 0) {
+                if (ERRNO_IS_TRANSIENT(errno))
+                        return 0;
+
+                return log_error_errno(errno, "Failed to read inotify fd: %m");
+        }
+
+        FOREACH_INOTIFY_EVENT_WARN(e, buffer, l) {
+                _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+                const char *devnode;
+
+                /* Do not handle IN_IGNORED here. Especially, do not try to call udev_watch_end() from the
+                 * main process. Otherwise, the pair of the symlinks may become inconsistent, and several
+                 * garbage may remain. The old symlinks are removed by a worker that processes the
+                 * corresponding 'remove' uevent;
+                 * udev_event_execute_rules() -> event_execute_rules_on_remove() -> udev_watch_end(). */
+
+                if (!FLAGS_SET(e->mask, IN_CLOSE_WRITE))
+                        continue;
+
+                r = device_new_from_watch_handle_at(&dev, -EBADF, e->wd);
+                if (r < 0) {
+                        /* Device may be removed just after closed. */
+                        log_debug_errno(r, "Failed to create sd_device object from watch handle, ignoring: %m");
+                        continue;
+                }
+
+                r = sd_device_get_devname(dev, &devnode);
+                if (r < 0) {
+                        /* Also here, device may be already removed. */
+                        log_device_debug_errno(dev, r, "Failed to get device node, ignoring: %m");
+                        continue;
+                }
+
+                log_device_debug(dev, "Received inotify event for %s.", devnode);
+
+                (void) event_queue_assume_block_device_unlocked(manager, dev);
+                (void) synthesize_change(manager, dev);
+        }
+
+        return 0;
+}
+
+static int udev_watch_restore(int inotify_fd) {
         _cleanup_(rm_rf_safep) const char *old = "/run/udev/watch.old/";
         int r;
 
@@ -88,6 +246,31 @@ int udev_watch_restore(int inotify_fd) {
         return 0;
 }
 
+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 udev_watch_clear(sd_device *dev, int dirfd, int *ret_wd) {
         _cleanup_free_ char *wd_str = NULL, *buf = NULL;
         const char *id;
index c454deead3cff2b7ac8801575638ce675084fc42..3976a835a1de8777cb1c26a88068573f7103fa3d 100644 (file)
@@ -3,11 +3,9 @@
 
 #include "sd-device.h"
 
-int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd);
-static inline int device_new_from_watch_handle(sd_device **ret, int wd) {
-        return device_new_from_watch_handle_at(ret, -1, wd);
-}
+typedef struct Manager Manager;
+
+int manager_start_inotify(Manager *manager);
 
-int udev_watch_restore(int inotify_fd);
 int udev_watch_begin(int inotify_fd, sd_device *dev);
 int udev_watch_end(int inotify_fd, sd_device *dev);