multiple interface test case

Roman Kagan rkagan at mail.ru
Tue Apr 12 15:08:27 EDT 2005


On Tue, Apr 12, 2005 at 10:08:56PM +0400, Roman Kagan wrote:
> in drivers/base/bus.c:
> 
> void device_release_driver(struct device * dev)
> {
>         struct device_driver * drv = dev->driver;
>         if (drv) {
>                 sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
>                 sysfs_remove_link(&dev->kobj, "driver");
>                 list_del_init(&dev->driver_list);
>                 device_detach_shutdown(dev);
>                 if (drv->remove)
>                         drv->remove(dev);
>                 dev->driver = NULL;
>         }
> }
> 
> 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);
>                 device_release_driver(dev);
>         }
> }
> 
> void bus_remove_driver(struct device_driver * drv)
> {
>         if (drv->bus) {
>                 driver_remove_attrs(drv->bus, drv);
>                 down_write(&drv->bus->subsys.rwsem);
>                 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
>                 driver_detach(drv);
>                 up_write(&drv->bus->subsys.rwsem);
>                 module_remove_driver(drv);
>                 kobject_unregister(&drv->kobj);
>                 put_bus(drv->bus);
>         }
> }
> 
> in kernel/module.c:
> 
> void module_remove_driver(struct device_driver *drv)
> {
>         if (!drv)
>                 return;
>         sysfs_remove_link(&drv->kobj, "module");
> }
> 
> When modprobe hangs, the "driver" links in sysfs directories for the
> interfaces are already gone, meaning that device_release_driver() has
> been called for each interface, but the "module" link in the driver
> directory is still there, so module_remove_driver() hasn't been reached
> yet.  Can't it be that list_for_each_safe() is not that safe against
> removal of the entries inside the loop body?

Hmm, looks fishy to me:

#define list_for_each_safe(pos, n, head) \
        for (pos = (head)->next, n = pos->next; pos != (head); \
                pos = n, n = pos->next)

So if entries are deleted inside the loop body (with list_del_init() in
our case), the loop is screwed up?

Roman.



More information about the Usbatm mailing list