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