diff options
author | Danny Kukawka <danny.kukawka@web.de> | 2009-08-01 14:33:32 +0200 |
---|---|---|
committer | Danny Kukawka <danny.kukawka@web.de> | 2010-04-16 15:02:23 +0200 |
commit | cc2d4e777e6adeb730a27544d8276fe2c0c6d606 (patch) | |
tree | 5ee49cbe9bd79f408701247fceffd1c3ca151396 | |
parent | 4a079bb7c20ff0928829f923205966cb01fcee0d (diff) |
fix hotplug_event_process_queue() to get reprobe working
Fixed hotplug_event_process_queue() to get reprobe working.
Added new function to check if there is still a REMOVE/ADD event
for the same device (sysfs_path) in the queue of the running
hotplug events. Wait for those events to prevent trouble if
e.g. a HOTPLUG_ACTION_REMOVE is still running and a
HOTPLUG_ACTION_ADD is the next event.
-rw-r--r-- | hald/linux/hotplug.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/hald/linux/hotplug.c b/hald/linux/hotplug.c index 9e802528..63d7cc2f 100644 --- a/hald/linux/hotplug.c +++ b/hald/linux/hotplug.c @@ -393,8 +393,10 @@ compare_events (HotplugEvent *hotplug_event, GList *events) for (lp = events; lp; lp = g_list_next (lp)) { loop_event = (HotplugEvent*) lp->data; /* skip ourselves and all later events*/ - if (loop_event->sysfs.seqnum >= hotplug_event->sysfs.seqnum) + if (loop_event->sysfs.seqnum >= hotplug_event->sysfs.seqnum) { + HAL_DEBUG (("event %s: skip ourselves and all later events", hotplug_event->sysfs.sysfs_path)); break; + } if (compare_event (hotplug_event, loop_event)) { HAL_DEBUG (("event %s dependant on %s", hotplug_event->sysfs.sysfs_path, loop_event->sysfs.sysfs_path)); return TRUE; @@ -413,6 +415,43 @@ compare_events (HotplugEvent *hotplug_event, GList *events) } } +/* + * Returns TRUE if @hotplug_event depends on any running event in @events + * This function checks if there is a running remove/add event for the same + * sysfs_path/device. (for more see fd.o#23060) + */ +static gboolean +compare_events_running (HotplugEvent *hotplug_event, GList *events) +{ + GList *lp; + HotplugEvent *loop_event; + + switch (hotplug_event->type) { + + /* explicit fallthrough */ + case HOTPLUG_EVENT_SYSFS: + case HOTPLUG_EVENT_SYSFS_DEVICE: + case HOTPLUG_EVENT_SYSFS_BLOCK: + + for (lp = events; lp; lp = g_list_next (lp)) { + loop_event = (HotplugEvent*) lp->data; + /* skip ourselves and all later events*/ + if (!strcmp (hotplug_event->sysfs.sysfs_path, loop_event->sysfs.sysfs_path)) { + if (loop_event->action != hotplug_event->action) { + HAL_DEBUG (("there is still a event running for this device, wait!")); + return TRUE; + } + + } + } + return FALSE; + + default: + return FALSE; + } +} + + void hotplug_event_process_queue (void) @@ -432,9 +471,17 @@ hotplug_event_process_queue (void) lp = hotplug_event_queue->head; while (lp != NULL) { hotplug_event = lp->data; - HAL_INFO (("checking event %s", hotplug_event->sysfs.sysfs_path)); - if (!compare_events (hotplug_event, hotplug_event_queue->head) - && !compare_events (hotplug_event, hotplug_events_in_progress)) { + + if (hotplug_event->action == HOTPLUG_ACTION_ADD) + HAL_DEBUG (("checking ADD event %s", hotplug_event->sysfs.sysfs_path)); + else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) + HAL_DEBUG (("checking REMOVE event %s", hotplug_event->sysfs.sysfs_path)); + else + HAL_DEBUG (("checking event %s, action: %d", hotplug_event->sysfs.sysfs_path, hotplug_event->action)); + + if (!compare_events (hotplug_event, hotplug_event_queue->head) && + !compare_events (hotplug_event, hotplug_events_in_progress) && + !compare_events_running (hotplug_event, hotplug_events_in_progress)) { lp2 = lp->prev; g_queue_unlink(hotplug_event_queue, lp); hotplug_events_in_progress = g_list_concat (hotplug_events_in_progress, lp); |