From e1ae931064be9483aa98249294f6e195537f43d1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 6 May 2025 02:25:32 +0900 Subject: [PATCH] udev: list up all dependencies of an event when the first time it is examined No functional change, just refactoring. --- src/udev/udev-manager.c | 120 ++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index b18d52181ff..504fdf2abfc 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -57,7 +57,6 @@ typedef struct Event { sd_device_action_t action; uint64_t seqnum; - uint64_t blocker_seqnum; const char *id; const char *devpath; const char *devpath_old; @@ -71,6 +70,10 @@ typedef struct Event { sd_event_source *timeout_warning_event; sd_event_source *timeout_event; + bool dependencies_built; + Set *blocker_events; + Set *blocking_events; + LIST_FIELDS(Event, event); } Event; @@ -90,6 +93,21 @@ typedef struct Worker { Event *event; } Worker; +static void event_clear_dependencies(Event *event) { + assert(event); + + Event *e; + while ((e = set_steal_first(event->blocker_events))) + assert_se(set_remove(e->blocking_events, event) == event); + event->blocker_events = set_free(event->blocker_events); + + while ((e = set_steal_first(event->blocking_events))) + assert_se(set_remove(e->blocker_events, event) == event); + event->blocking_events = set_free(event->blocking_events); + + event->dependencies_built = false; +} + static Event* event_free(Event *event) { if (!event) return NULL; @@ -103,6 +121,8 @@ static Event* event_free(Event *event) { if (event->worker) event->worker->event = NULL; + event_clear_dependencies(event); + sd_device_unref(event->dev); sd_event_source_unref(event->retry_event_source); @@ -584,85 +604,65 @@ bool devpath_conflict(const char *a, const char *b) { return *a == '/' || *b == '/' || *a == *b; } -static int event_is_blocked(Event *event) { - Event *loop_event = NULL; +static int event_build_dependencies(Event *event) { int r; - /* lookup event for identical, parent, child device */ - assert(event); - assert(event->manager); - assert(event->blocker_seqnum <= event->seqnum); - - if (event->retry_again_next_usec > 0) { - usec_t now_usec; - - r = sd_event_now(event->manager->event, CLOCK_BOOTTIME, &now_usec); - if (r < 0) - return r; - - if (event->retry_again_next_usec > now_usec) - return true; - } - if (event->blocker_seqnum == event->seqnum) - /* we have checked previously and no blocker found */ - return false; + /* lookup event for identical, parent, child device */ - LIST_FOREACH(event, e, event->manager->events) { - loop_event = e; + if (event->dependencies_built) + return 0; - /* we already found a later event, earlier cannot block us, no need to check again */ - if (loop_event->seqnum < event->blocker_seqnum) + LIST_FOREACH_BACKWARDS(event, e, event->event_prev) { + if (!streq_ptr(event->id, e->id) && + !devpath_conflict(event->devpath, e->devpath) && + !devpath_conflict(event->devpath, e->devpath_old) && + !devpath_conflict(event->devpath_old, e->devpath) && + !(event->devnode && streq_ptr(event->devnode, e->devnode))) continue; - /* event we checked earlier still exists, no need to check again */ - if (loop_event->seqnum == event->blocker_seqnum) - return true; + r = set_ensure_put(&event->blocker_events, NULL, e); + if (r < 0) + return r; - /* found ourself, no later event can block us */ - if (loop_event->seqnum >= event->seqnum) - goto no_blocker; + r = set_ensure_put(&e->blocking_events, NULL, event); + if (r < 0) { + assert_se(set_remove(event->blocker_events, e) == e); + return r; + } - /* found event we have not checked */ - break; + log_device_debug(event->dev, "SEQNUM=%" PRIu64 " blocked by SEQNUM=%" PRIu64, + event->seqnum, e->seqnum); } - assert(loop_event); - assert(loop_event->seqnum > event->blocker_seqnum && - loop_event->seqnum < event->seqnum); + event->dependencies_built = true; + return 0; +} - /* check if queue contains events we depend on */ - LIST_FOREACH(event, e, loop_event) { - loop_event = e; +static int event_is_blocked(Event *event) { + int r; - /* found ourself, no later event can block us */ - if (loop_event->seqnum >= event->seqnum) - goto no_blocker; + assert(event); + assert(event->manager); - if (streq_ptr(loop_event->id, event->id)) - break; + if (event->retry_again_next_usec > 0) { + assert(event->dependencies_built); - if (devpath_conflict(event->devpath, loop_event->devpath) || - devpath_conflict(event->devpath, loop_event->devpath_old) || - devpath_conflict(event->devpath_old, loop_event->devpath)) - break; + usec_t now_usec; + r = sd_event_now(event->manager->event, CLOCK_BOOTTIME, &now_usec); + if (r < 0) + return r; - if (event->devnode && streq_ptr(event->devnode, loop_event->devnode)) - break; + if (event->retry_again_next_usec > now_usec) + return true; } - assert(loop_event); - - log_device_debug(event->dev, "SEQNUM=%" PRIu64 " blocked by SEQNUM=%" PRIu64, - event->seqnum, loop_event->seqnum); - - event->blocker_seqnum = loop_event->seqnum; - return true; + r = event_build_dependencies(event); + if (r < 0) + return r; -no_blocker: - event->blocker_seqnum = event->seqnum; - return false; + return !set_isempty(event->blocker_events); } static bool manager_can_process_event(Manager *manager) { -- 2.47.3