multiple interface test case

Roman Kagan rkagan at mail.ru
Wed Apr 13 01:11:52 EDT 2005


On Tue, Apr 12, 2005 at 11:56:22PM +0400, Roman Kagan wrote:
> To make my point clear: list_for_each_safe() seems to be safe only
> w.r.t. the deletion of the current entry.  However, in our
> multi-interface scenario, we start with device_release_driver() for the
> first interface on the drv->devices list, and then (through
> drv->remove(), which calls disconnect(), which calls
> usb_driver_release_interface() for other interfaces) we call
> device_release_driver() for other interfaces and empty the drv->devices
> list, while list_for_each_safe() has already cached the (now invalid)
> next entry, and thus goes into an infinite loop.

The appended patch fixes it for me (written for 2.6.12-rc2, applied to
and run on 2.6.11).  I'm not yet fluent with klists so it'll take longer
to cook up one for -mm.

Still I wonder for how long it was there, because every
usb_driver_release_interface() during rmmod should have revealed that
problem.

Cheers,
  Roman.


--- linux-2.6.12-rc2/drivers/base/bus.c.orig	2005-03-18 04:34:06.000000000 +0300
+++ linux-2.6.12-rc2/drivers/base/bus.c	2005-04-13 08:45:48.000000000 +0400
@@ -405,9 +405,8 @@ void device_release_driver(struct device
 
 static void driver_detach(struct device_driver * drv)
 {
-	struct list_head * entry, * next;
-	list_for_each_safe(entry, next, &drv->devices) {
-		struct device * dev = container_of(entry, struct device, driver_list);
+	while (!list_empty(&drv->devices)) {
+		struct device * dev = container_of(drv->devices.next, struct device, driver_list);
 		device_release_driver(dev);
 	}
 }



More information about the Usbatm mailing list