udev: sort queued events by their seqnum
Unfortunately, the kernel may send events in a random order: ``` [ 25.769624] systemd-udevd[194]: sdi7: Device is queued (SEQNUM=2843, ACTION=add) [ 25.769893] systemd-udevd[194]: sda5: Device is queued (SEQNUM=2842, ACTION=add) [ 25.770517] systemd-udevd[194]: sdi8: Device is queued (SEQNUM=2844, ACTION=add) ``` As you can see, udevd receives the event with SEQNUM=2843 earlier than one with SEQNUM=2842. Let's make queued events sorted, as our logic of determining which event is ready for being processed assumes that queued events are sorted. See event_build_dependencies(). Also, refuse to queue an event if another event with the same seqnum is already queued.
This commit is contained in:
+22
-2
@@ -930,8 +930,28 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
|
||||
.locked_event_prioq_index = PRIOQ_IDX_NULL,
|
||||
};
|
||||
|
||||
LIST_INSERT_AFTER(event, manager->events, manager->last_event, event);
|
||||
manager->last_event = event;
|
||||
Event *prev = NULL;
|
||||
LIST_FOREACH_BACKWARDS(event, e, manager->last_event) {
|
||||
if (e->seqnum < event->seqnum) {
|
||||
prev = e;
|
||||
break;
|
||||
}
|
||||
if (e->seqnum == event->seqnum)
|
||||
return log_device_warning_errno(dev, SYNTHETIC_ERRNO(EALREADY),
|
||||
"The event (SEQNUM=%"PRIu64") has been already queued.",
|
||||
event->seqnum);
|
||||
|
||||
/* Inserting an event in an earlier place may change dependency tree. Let's rebuild it later. */
|
||||
event_clear_dependencies(e);
|
||||
}
|
||||
|
||||
LIST_INSERT_AFTER(event, manager->events, prev, event);
|
||||
if (prev == manager->last_event)
|
||||
manager->last_event = event;
|
||||
else
|
||||
log_device_debug(dev, "Unordered event is received (last queued event seqnum=%"PRIu64", newly received event seqnum=%"PRIu64"), reordering.",
|
||||
manager->last_event->seqnum, event->seqnum);
|
||||
|
||||
event->manager = manager;
|
||||
TAKE_PTR(event);
|
||||
log_device_uevent(dev, "Device is queued");
|
||||
|
||||
Reference in New Issue
Block a user