]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-manager: broadcast event in event_requeue() on failure
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 20 Mar 2025 09:14:29 +0000 (18:14 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 2 Apr 2025 14:24:35 +0000 (23:24 +0900)
Also, send the actual error code rather than ETIMEDOUT.

src/udev/udev-manager.c

index dd6a2494736961925c93a8e00636549af8fa69a5..77853298f99f88dd2831a50623e2979b680277fe 100644 (file)
@@ -628,7 +628,7 @@ static int on_event_retry(sd_event_source *s, uint64_t usec, void *userdata) {
         return 1;
 }
 
-static int event_requeue(Event *event) {
+static void event_requeue(Event *event) {
         usec_t now_usec;
         int r;
 
@@ -636,23 +636,29 @@ static int event_requeue(Event *event) {
         assert(event->manager);
         assert(event->manager->event);
 
+        sd_device *dev = ASSERT_PTR(event->dev);
+
         event->timeout_warning_event = sd_event_source_disable_unref(event->timeout_warning_event);
         event->timeout_event = sd_event_source_disable_unref(event->timeout_event);
 
         /* add a short delay to suppress busy loop */
         r = sd_event_now(event->manager->event, CLOCK_BOOTTIME, &now_usec);
-        if (r < 0)
-                return log_device_warning_errno(event->dev, r,
-                                                "Failed to get current time, "
-                                                "skipping event (SEQNUM=%"PRIu64", ACTION=%s): %m",
-                                                event->seqnum, strna(device_action_to_string(event->action)));
-
-        if (event->retry_again_timeout_usec > 0 && event->retry_again_timeout_usec <= now_usec)
-                return log_device_warning_errno(event->dev, SYNTHETIC_ERRNO(ETIMEDOUT),
-                                                "The underlying block device is locked by a process more than %s, "
-                                                "skipping event (SEQNUM=%"PRIu64", ACTION=%s).",
-                                                FORMAT_TIMESPAN(EVENT_RETRY_TIMEOUT_USEC, USEC_PER_MINUTE),
-                                                event->seqnum, strna(device_action_to_string(event->action)));
+        if (r < 0) {
+                log_device_warning_errno(
+                                dev, r,
+                                "Failed to get current time, skipping event (SEQNUM=%"PRIu64", ACTION=%s): %m",
+                                event->seqnum, strna(device_action_to_string(event->action)));
+                goto fail;
+        }
+
+        if (event->retry_again_timeout_usec > 0 && event->retry_again_timeout_usec <= now_usec) {
+                r = log_device_warning_errno(
+                                dev, SYNTHETIC_ERRNO(ETIMEDOUT),
+                                "The underlying block device is locked by a process more than %s, skipping event (SEQNUM=%"PRIu64", ACTION=%s).",
+                                FORMAT_TIMESPAN(EVENT_RETRY_TIMEOUT_USEC, USEC_PER_MINUTE),
+                                event->seqnum, strna(device_action_to_string(event->action)));
+                goto fail;
+        }
 
         event->retry_again_next_usec = usec_add(now_usec, EVENT_RETRY_INTERVAL_USEC);
         if (event->retry_again_timeout_usec == 0)
@@ -662,17 +668,24 @@ static int event_requeue(Event *event) {
                                       CLOCK_MONOTONIC, EVENT_RETRY_INTERVAL_USEC, 0,
                                       on_event_retry, NULL,
                                       0, "retry-event", true);
-        if (r < 0)
-                return log_device_warning_errno(event->dev, r, "Failed to reset timer event source for retrying event, "
-                                                "skipping event (SEQNUM=%"PRIu64", ACTION=%s): %m",
-                                                event->seqnum, strna(device_action_to_string(event->action)));
+        if (r < 0) {
+                log_device_warning_errno(
+                                dev, r,
+                                "Failed to reset timer event source for retrying event, skipping event (SEQNUM=%"PRIu64", ACTION=%s): %m",
+                                event->seqnum, strna(device_action_to_string(event->action)));
+                goto fail;
+        }
 
-        if (event->worker && event->worker->event == event)
+        if (event->worker)
                 event->worker->event = NULL;
         event->worker = NULL;
 
         event->state = EVENT_QUEUED;
-        return 0;
+        return;
+
+fail:
+        udev_broadcast_result(event->manager->monitor, dev, r);
+        event_free(event);
 }
 
 static int event_queue_assume_block_device_unlocked(Manager *manager, sd_device *dev) {
@@ -843,13 +856,10 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
                 } else if (worker->state != WORKER_KILLED)
                         worker->state = WORKER_IDLE;
 
-                /* worker returned */
-                if (result == EVENT_RESULT_TRY_AGAIN &&
-                    event_requeue(worker->event) < 0)
-                        udev_broadcast_result(manager->monitor, worker->event->dev, -ETIMEDOUT);
-
-                /* When event_requeue() succeeds, worker->event is NULL, and event_free() handles NULL gracefully. */
-                event_free(worker->event);
+                if (result == EVENT_RESULT_TRY_AGAIN)
+                        event_requeue(worker->event);
+                else
+                        event_free(worker->event);
         }
 
         return 1;