mirror of
https://github.com/systemd/systemd.git
synced 2026-08-04 15:10:33 +00:00
udev: check earlier if there is a free room for processing an event
This commit is contained in:
@@ -538,19 +538,14 @@ static int worker_spawn(Manager *manager, Event *event) {
|
||||
}
|
||||
|
||||
static int event_run(Event *event) {
|
||||
static bool log_children_max_reached = true;
|
||||
Manager *manager;
|
||||
Worker *worker;
|
||||
Manager *manager = ASSERT_PTR(ASSERT_PTR(event)->manager);
|
||||
int r;
|
||||
|
||||
assert(event);
|
||||
assert(event->manager);
|
||||
|
||||
log_device_uevent(event->dev, "Device ready for processing");
|
||||
|
||||
(void) event_source_disable(event->retry_event_source);
|
||||
|
||||
manager = event->manager;
|
||||
Worker *worker;
|
||||
HASHMAP_FOREACH(worker, manager->workers) {
|
||||
if (worker->state != WORKER_IDLE)
|
||||
continue;
|
||||
@@ -564,28 +559,16 @@ static int event_run(Event *event) {
|
||||
continue;
|
||||
}
|
||||
worker_attach_event(worker, event);
|
||||
return 1; /* event is now processing. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hashmap_size(manager->workers) >= manager->config.children_max) {
|
||||
/* Avoid spamming the debug logs if the limit is already reached and
|
||||
* many events still need to be processed */
|
||||
if (log_children_max_reached && manager->config.children_max > 1) {
|
||||
log_debug("Maximum number (%u) of children reached.", hashmap_size(manager->workers));
|
||||
log_children_max_reached = false;
|
||||
}
|
||||
return 0; /* no free worker */
|
||||
}
|
||||
|
||||
/* Re-enable the debug message for the next batch of events */
|
||||
log_children_max_reached = true;
|
||||
|
||||
/* start new worker and pass initial device */
|
||||
assert(hashmap_size(manager->workers) < manager->config.children_max);
|
||||
r = worker_spawn(manager, event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1; /* event is now processing. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool devpath_conflict(const char *a, const char *b) {
|
||||
@@ -682,6 +665,36 @@ no_blocker:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool manager_can_process_event(Manager *manager) {
|
||||
static bool children_max_reached_logged = false;
|
||||
|
||||
assert(manager);
|
||||
|
||||
/* Check if there is a free room for processing an event. */
|
||||
|
||||
if (hashmap_size(manager->workers) < manager->config.children_max)
|
||||
goto yes_we_can; /* new worker can be spawned */
|
||||
|
||||
Worker *worker;
|
||||
HASHMAP_FOREACH(worker, manager->workers)
|
||||
if (worker->state == WORKER_IDLE)
|
||||
goto yes_we_can; /* found an idle worker */
|
||||
|
||||
/* Avoid spamming the debug logs if the limit is already reached and
|
||||
* many events still need to be processed */
|
||||
if (!children_max_reached_logged) {
|
||||
log_debug("Maximum number (%u) of children reached.", hashmap_size(manager->workers));
|
||||
children_max_reached_logged = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
yes_we_can:
|
||||
/* Re-enable the debug message for the next batch of events */
|
||||
children_max_reached_logged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int event_queue_start(Manager *manager) {
|
||||
int r;
|
||||
|
||||
@@ -697,6 +710,11 @@ static int event_queue_start(Manager *manager) {
|
||||
|
||||
manager_reload(manager, /* force = */ false);
|
||||
|
||||
/* manager_reload() may kill idle workers, hence we may not be possible to start processing an event.
|
||||
* Let's check that and return earlier if we cannot. */
|
||||
if (!manager_can_process_event(manager))
|
||||
return 0;
|
||||
|
||||
LIST_FOREACH(event, event, manager->events) {
|
||||
if (event->state != EVENT_QUEUED)
|
||||
continue;
|
||||
@@ -713,8 +731,12 @@ static int event_queue_start(Manager *manager) {
|
||||
strna(device_action_to_string(event->action)));
|
||||
|
||||
r = event_run(event);
|
||||
if (r <= 0) /* 0 means there are no idle workers. Let's escape from the loop. */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* A worker is activated now. Let's check if we can process more events. */
|
||||
if (!manager_can_process_event(manager))
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user