Re: PCI driver module unload race?

From: Greg KH (greg@kroah.com)
Date: Sat Mar 08 2003 - 14:12:37 EST


On Sat, Mar 08, 2003 at 10:47:49AM +0000, Russell King wrote:
> Hi,
>
> What prevents the following scenario from happening? It's purely
> theoretical - I haven't seen this occuring.
>
> - Load PCI driver.
>
> - PCI driver registers using pci_module_init(), and adds itself to sysfs.
>
> - Hot-plugin a PCI device which uses this driver. sysfs matches the PCI
> driver, and calls the PCI drivers probe function.

Ugh, yes you are correct, I can't believe I missed this before.

How does this patch look?

thanks,

greg k-h

===== drivers/pci/pci-driver.c 1.17 vs edited =====
--- 1.17/drivers/pci/pci-driver.c Sat Nov 23 13:23:03 2002
+++ edited/drivers/pci/pci-driver.c Sat Mar 8 11:21:06 2003
@@ -48,6 +48,12 @@
         if (!pci_dev->driver && drv->probe) {
                 const struct pci_device_id *id;
 
+ if (!try_module_get(drv->owner)) {
+ dev_err(dev, "Can't get a module reference for %s\n",
+ drv->name);
+ error = -ENODEV;
+ goto exit;
+ }
                 id = pci_match_device(drv->id_table, pci_dev);
                 if (id)
                         error = drv->probe(pci_dev, id);
@@ -55,7 +61,9 @@
                         pci_dev->driver = drv;
                         error = 0;
                 }
+ module_put(drv->owner);
         }
+exit:
         return error;
 }
 
@@ -66,7 +74,10 @@
 
         if (drv) {
                 if (drv->remove)
- drv->remove(pci_dev);
+ if (try_module_get(drv->owner)) {
+ drv->remove(pci_dev);
+ module_put(drv->owner);
+ }
                 pci_dev->driver = NULL;
         }
         return 0;
===== include/linux/pci.h 1.36 vs edited =====
--- 1.36/include/linux/pci.h Tue Mar 4 21:09:58 2003
+++ edited/include/linux/pci.h Sat Mar 8 11:20:15 2003
@@ -493,6 +493,7 @@
 
 struct pci_driver {
         struct list_head node;
+ struct module *owner;
         char *name;
         const struct pci_device_id *id_table; /* NULL if wants all devices */
         int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Mar 15 2003 - 22:00:16 EST