From: Yu Watanabe Date: Thu, 20 Mar 2025 09:14:29 +0000 (+0900) Subject: udev-manager: broadcast event in event_requeue() on failure X-Git-Tag: v258-rc1~948^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4090767a22008ac9da571a964ca2938e21382a4d;p=thirdparty%2Fsystemd.git udev-manager: broadcast event in event_requeue() on failure Also, send the actual error code rather than ETIMEDOUT. --- diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index dd6a2494736..77853298f99 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -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;