diff options
author | Frantisek Sumsal <frantisek@sumsal.cz> | 2022-08-25 21:57:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-25 21:57:19 +0200 |
commit | 81d7682af7b398cf7992f4a44848f3df99a63dab (patch) | |
tree | 9fd61b58de84ecc29da693c677cdf437d0cfc26e /src | |
parent | virt: fix alignment (diff) | |
parent | udev: drop unnecessary calls of event_queue_start() (diff) | |
download | systemd-81d7682af7b398cf7992f4a44848f3df99a63dab.tar.xz systemd-81d7682af7b398cf7992f4a44848f3df99a63dab.zip |
Merge pull request #24442 from yuwata/udev-retry-event
udev: make requeued event actually restarted
Diffstat (limited to 'src')
-rw-r--r-- | src/udev/udevd.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 01162bc7b6..028492721e 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -135,8 +135,11 @@ typedef struct Event { const char *devpath; const char *devpath_old; const char *devnode; + + /* 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; @@ -186,6 +189,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); @@ -843,6 +847,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) @@ -999,6 +1005,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; @@ -1029,6 +1040,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; @@ -1155,9 +1175,6 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) (void) event_queue_assume_block_device_unlocked(manager, dev); - /* we have fresh events, try to schedule them */ - event_queue_start(manager); - return 1; } @@ -1224,9 +1241,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat event_free(worker->event); } - /* we have free workers, try to schedule events */ - event_queue_start(manager); - return 1; } @@ -1452,10 +1466,6 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda assert(manager); - r = event_source_disable(manager->kill_workers_event); - if (r < 0) - log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m"); - l = read(fd, &buffer, sizeof(buffer)); if (l < 0) { if (ERRNO_IS_TRANSIENT(errno)) @@ -1515,7 +1525,6 @@ static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { Manager *manager = ASSERT_PTR(worker->manager); sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL; EventResult result; - int r; assert(si); @@ -1551,16 +1560,6 @@ static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { worker_free(worker); - /* we can start new workers, try to schedule events */ - event_queue_start(manager); - - /* Disable unnecessary cleanup event */ - if (hashmap_isempty(manager->workers)) { - r = event_source_disable(manager->kill_workers_event); - if (r < 0) - log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m"); - } - return 1; } |