Greg:
Linus has said that waiting for a device's release() method to be called
is evil, with a possible exception for unloadable kernel modules. He
feels that rmmod is generally unnecessary -- it's mostly an aid for
developers and not very important for users. My feeling is that as long
as rmmod is there, it should work safely.
This patch helps USB host driver modules to unload by waiting for the
bus's release() method. Rather than duplicate the functionality in each
HCD, it is centralized in usbcore. It's basically just a home-brewed
version of the defunct device_unregister_wait().
The usual arguments against waiting for release apply, of course. Here's
how I see it:
If we do wait for release, then we provide a way for the superuser
to cause a deadlock by deliberately doing something foolish like
"rmmod uhci_hcd </sys/devices/pci/0000:07.2/usb1/serial".
If we don't wait for release, then we provide a way for any old
user to cause an oops by getting a reference to a device on the
USB bus and not releasing the reference until rmmod finishes.
If you don't believe that, try it yourself. Sysfs provides a great way to
obtain references to devices. Find a sysfs attribute file for the root
hub in the bus you want to remove, and as a regular user do:
sleep 10 <sysfs_file
While that's waiting, in another window as root rmmod the bus's HCD. When
the sleep command finishes you'll get a dandy oops.
I think the choice of which alternative to prefer is clear. This patch
implements it.
Alan Stern
===== include/linux/usb.h 1.175 vs edited =====
--- 1.175/include/linux/usb.h Mon Mar 8 12:27:12 2004
+++ edited/include/linux/usb.h Mon Mar 15 11:32:52 2004
@@ -240,6 +240,7 @@
struct class_device class_dev; /* class device for this bus */
void (*release)(struct usb_bus *bus); /* function to destroy this bus's
memory */
+ struct completion *released; /* wait for release */
};
#define to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
===== drivers/usb/core/hcd.c 1.131 vs edited =====
--- 1.131/drivers/usb/core/hcd.c Sun Mar 7 14:29:08 2004
+++ edited/drivers/usb/core/hcd.c Mon Mar 15 11:32:52 2004
@@ -588,9 +588,11 @@
static void usb_host_release(struct class_device *class_dev)
{
struct usb_bus *bus = to_usb_bus(class_dev);
+ struct completion *released = bus->released;
if (bus->release)
bus->release(bus);
+ complete(released);
}
static struct class usb_host_class = {
@@ -712,6 +714,8 @@
*/
void usb_deregister_bus (struct usb_bus *bus)
{
+ struct completion released;
+
dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum);
/*
@@ -727,7 +731,10 @@
clear_bit (bus->busnum, busmap.busmap);
+ init_completion(&released);
+ bus->released = &released;
class_device_unregister(&bus->class_dev);
+ wait_for_completion(&released);
}
EXPORT_SYMBOL (usb_deregister_bus);
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel