Re: [RFC] races in access to pci_devices

Andrew Morton (akpm@zip.com.au)
Thu, 15 Nov 2001 00:28:22 -0800


Jeff Garzik wrote:
>
> I haven't looked at it in over a year, but from a quick look, all the
> list access look like they can be protected by a simple spinlock.

I don't think so? We do things like calling driver probe methods
in the middle of a driver list walk.

An rwsem _may_ be suitable, but I'm not sure that we don't do
a nested walk in some circumstances, and AFAIK our rwsems
still are not safe for the same thread to do a down_read() twice.

Then there's the bus list, and the order of its lock wrt the device
list.

One approach would be to use a spinlock and a per-device refcount.
So something like:

spin_lock(&pci_dev_lock);
dev = pci_dev_g(pci_devices.next);
while (dev != pci_dev_g(&pci_devices)) {
struct pci_dev *next;

pci_dev_get(dev);
spin_unlock(&pci_dev_lock);
diddle(dev);
spin_lock(&pci_dev_lock);
next = pci_dev_g(dev->global_list.next);
pci_dev_put(dev);
dev = next;
}
spin_unlock(&pci_dev_lock);

pci_dev_get(struct pci_dev *dev)
{
#ifdef CONFIG_SMP
if (!spin_is_locked(&pci_dev_lock))
BUG();
#endif
dev->refcount++;
}

pci_dev_put(struct pci_dev *dev)
{
#ifdef CONFIG_SMP
if (!spin_is_locked(&pci_dev_lock))
BUG();
#endif
dev->refcount--;
if (dev->refcount == 0)
kfree(dev);
}

I _think_ all this list traversal happens in process context now.
Not sure about the PCI hotplug driver though.

It's really sticky. Which is why it isn't fixed :(

Sigh. Maybe go for an rwsem in 2.5, backport when it stops
deadlocking?

-
-
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/