mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-08-25 13:50:12 +03:00
udev: certainly restart event for previously locked device
If udevd receives a uevent for a locked block device, then the event is requeued. However, the queued event will be processed only when at least one sd_event_source is processed. Hence, if udevd has no event under processing, or receives no new uevent, etc., then the requeued event will be never processed. Follow-up for400e3d21f8
. Fixes #24439. (cherry picked from commit4f294ffdf1
)
This commit is contained in:
committed by
Zbigniew Jędrzejewski-Szmek
parent
7dacfb3fb4
commit
1b1ad8c79f
@ -131,8 +131,11 @@ typedef struct Event {
|
||||
sd_device_action_t action;
|
||||
uint64_t seqnum;
|
||||
uint64_t blocker_seqnum;
|
||||
|
||||
/* Used when the device is locked by another program. */
|
||||
usec_t retry_again_next_usec;
|
||||
usec_t retry_again_timeout_usec;
|
||||
sd_event_source *retry_event_source;
|
||||
|
||||
sd_event_source *timeout_warning_event;
|
||||
sd_event_source *timeout_event;
|
||||
@ -182,6 +185,7 @@ static Event *event_free(Event *event) {
|
||||
|
||||
/* Do not use sd_event_source_disable_unref() here, as this is called by both workers and the
|
||||
* main process. */
|
||||
sd_event_source_unref(event->retry_event_source);
|
||||
sd_event_source_unref(event->timeout_warning_event);
|
||||
sd_event_source_unref(event->timeout_event);
|
||||
|
||||
@ -813,6 +817,8 @@ static int event_run(Event *event) {
|
||||
|
||||
log_device_uevent(event->dev, "Device ready for processing");
|
||||
|
||||
(void) event_source_disable(event->retry_event_source);
|
||||
|
||||
manager = event->manager;
|
||||
HASHMAP_FOREACH(worker, manager->workers) {
|
||||
if (worker->state != WORKER_IDLE)
|
||||
@ -1062,6 +1068,11 @@ static int event_queue_start(Manager *manager) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_event_retry(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
/* This does nothing. The on_post() callback will start the event if there exists an idle worker. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int event_requeue(Event *event) {
|
||||
usec_t now_usec;
|
||||
int r;
|
||||
@ -1092,6 +1103,15 @@ static int event_requeue(Event *event) {
|
||||
if (event->retry_again_timeout_usec == 0)
|
||||
event->retry_again_timeout_usec = usec_add(now_usec, EVENT_RETRY_TIMEOUT_USEC);
|
||||
|
||||
r = event_reset_time_relative(event->manager->event, &event->retry_event_source,
|
||||
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 (event->worker && event->worker->event == event)
|
||||
event->worker->event = NULL;
|
||||
event->worker = NULL;
|
||||
|
Reference in New Issue
Block a user