summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Kukawka <danny.kukawka@web.de>2009-08-01 14:33:32 +0200
committerDanny Kukawka <danny.kukawka@web.de>2010-04-16 15:02:23 +0200
commitcc2d4e777e6adeb730a27544d8276fe2c0c6d606 (patch)
tree5ee49cbe9bd79f408701247fceffd1c3ca151396
parent4a079bb7c20ff0928829f923205966cb01fcee0d (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.c55
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);