]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: ignore IN_IGNORED inotify event earlier
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 15 Apr 2022 00:42:15 +0000 (09:42 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 11 Sep 2022 16:23:08 +0000 (01:23 +0900)
src/udev/udevd.c

index 2574844ed763a538077c150c6b70654fc06f4262..25496975d50bc1caa813dabdb5444b25e19fc13b 100644 (file)
@@ -1447,23 +1447,33 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
                 _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;
                 }
 
-                if (sd_device_get_devname(dev, &devnode) < 0)
+                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, "Inotify event: %x for %s", e->mask, devnode);
-                if (e->mask & IN_CLOSE_WRITE) {
-                        (void) event_queue_assume_block_device_unlocked(manager, dev);
-                        (void) synthesize_change(dev);
                 }
 
-                /* Do not handle IN_IGNORED here. It should be handled by worker in 'remove' uevent;
-                 * udev_event_execute_rules() -> event_execute_rules_on_remove() -> udev_watch_end(). */
+                log_device_debug(dev, "Received inotify event for %s.", devnode);
+
+                (void) event_queue_assume_block_device_unlocked(manager, dev);
+                (void) synthesize_change(dev);
         }
 
         return 0;