multiple interface test case

Roman Kagan rkagan at mail.ru
Tue Apr 12 14:08:56 EDT 2005


On Tue, Apr 12, 2005 at 07:07:46PM +0200, Duncan Sands wrote:
> Hi Roman, with latest -mm it hangs here:
> 
> void driver_unregister(struct device_driver * drv)
> {
>         bus_remove_driver(drv);
>         wait_for_completion(&drv->unloaded); <=== waits for ever
> }
> 
> The completion happens when driver_release is called.
> Just how this gets called isn't too clear to me, but
> presumably it happens automagically when the driver
> refcount drops to zero.  The driver refcount gets
> down to 1 only.

I'm looking at 2.6.12-rc2, and here's what I see:

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?

Still trying,
  Roman.



More information about the Usbatm mailing list