From 044ac33c35ab1aeb35fc8b84462a9549cbbac294 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 17 Jun 2021 16:57:32 +0900
Subject: [PATCH] udev: do not try to find blocker again when no blocker found
 previously
 
Reference:https://github.com/systemd/systemd/commit/044ac33c35ab1aeb35fc8b84462a9549cbbac294
Conflict:NA
 
---
 src/udev/udevd.c | 45 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 10 deletions(-)
 
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 20bd556..be2c3ee 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -783,6 +783,35 @@ static int event_is_blocked(Event *event) {
 
         /* lookup event for identical, parent, child device */
 
+        assert(event);
+        assert(event->manager);
+        assert(event->blocker_seqnum <= event->seqnum);
+
+        if (event->blocker_seqnum == event->seqnum)
+                /* we have checked previously and no blocker found */
+                return false;
+
+        LIST_FOREACH(event, loop_event, event->manager->events) {
+                /* we already found a later event, earlier cannot block us, no need to check again */
+                if (loop_event->seqnum < event->blocker_seqnum)
+                        continue;
+
+                /* event we checked earlier still exists, no need to check again */
+                if (loop_event->seqnum == event->blocker_seqnum)
+                        return true;
+
+                /* found ourself, no later event can block us */
+                if (loop_event->seqnum >= event->seqnum)
+                        goto no_blocker;
+
+                /* found event we have not checked */
+                break;
+        }
+
+        assert(loop_event);
+        assert(loop_event->seqnum > event->blocker_seqnum &&
+               loop_event->seqnum < event->seqnum);
+
         r = sd_device_get_subsystem(event->dev, &subsystem);
         if (r < 0)
                 return r;
@@ -808,21 +837,13 @@ static int event_is_blocked(Event *event) {
                 return r;
 
         /* check if queue contains events we depend on */
-        LIST_FOREACH(event, loop_event, event->manager->events) {
+        LIST_FOREACH(event, loop_event, loop_event) {
                 size_t loop_devpath_len, common;
                 const char *loop_devpath;
 
-                /* we already found a later event, earlier cannot block us, no need to check again */
-                if (loop_event->seqnum < event->blocker_seqnum)
-                        continue;
-
-                /* event we checked earlier still exists, no need to check again */
-                if (loop_event->seqnum == event->blocker_seqnum)
-                        return true;
-
                 /* found ourself, no later event can block us */
                 if (loop_event->seqnum >= event->seqnum)
-                        return false;
+                        goto no_blocker;
 
                 /* check major/minor */
                 if (major(devnum) != 0) {
@@ -882,6 +903,10 @@ static int event_is_blocked(Event *event) {
 
         event->blocker_seqnum = loop_event->seqnum;
         return true;
+
+no_blocker:
+        event->blocker_seqnum = event->seqnum;
+        return false;
 }
 
 static int event_queue_start(Manager *manager) {
-- 
2.33.0
 