pci/sriov: Hold rescan lock while enumerating

Message ID 20180809163356.18650-1-keith.busch@intel.com
State New
Delegated to: Bjorn Helgaas
Headers show
Series
  • pci/sriov: Hold rescan lock while enumerating
Related show

Commit Message

Keith Busch Aug. 9, 2018, 4:33 p.m.
PCI enumeration/de-enumeration needs to run single threaded to prevent
race conditions with other threads changing the topology. Altering the
number of virtual functions was not taking the rescan/remove lock hile
adding or removing those virtual functions, so this patch adds that.

Reported-by: Krzysztof Wierzbicki <krzysztof.wierzbicki@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Keith Busch <keith.busch@intel.com>
---
 drivers/pci/pci-sysfs.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Lukas Wunner Aug. 9, 2018, 5:58 p.m. | #1
On Thu, Aug 09, 2018 at 10:33:56AM -0600, Keith Busch wrote:
> --- a/drivers/pci/pci-sysfs.c
> +++ b/drivers/pci/pci-sysfs.c
> @@ -591,6 +591,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
>  	if (num_vfs > pci_sriov_get_totalvfs(pdev))
>  		return -ERANGE;
>  
> +	pci_lock_rescan_remove();
>  	device_lock(&pdev->dev);

Doesn't this obviate the need to hold the device_lock()?  What could
otherwise run concurrently that doesn't hold pci_lock_rescan_remove()
and would cause a race condition?

Thanks,

Lukas
Keith Busch Aug. 9, 2018, 6:05 p.m. | #2
On Thu, Aug 09, 2018 at 07:58:19PM +0200, Lukas Wunner wrote:
> On Thu, Aug 09, 2018 at 10:33:56AM -0600, Keith Busch wrote:
> > --- a/drivers/pci/pci-sysfs.c
> > +++ b/drivers/pci/pci-sysfs.c
> > @@ -591,6 +591,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
> >  	if (num_vfs > pci_sriov_get_totalvfs(pdev))
> >  		return -ERANGE;
> >  
> > +	pci_lock_rescan_remove();
> >  	device_lock(&pdev->dev);
> 
> Doesn't this obviate the need to hold the device_lock()?  What could
> otherwise run concurrently that doesn't hold pci_lock_rescan_remove()
> and would cause a race condition?

The device_lock is still needed to protect against concurrent
pci_reset_function.

Patch

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9ecfe13157c0..611abe220b6f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -591,6 +591,7 @@  static ssize_t sriov_numvfs_store(struct device *dev,
 	if (num_vfs > pci_sriov_get_totalvfs(pdev))
 		return -ERANGE;
 
+	pci_lock_rescan_remove();
 	device_lock(&pdev->dev);
 
 	if (num_vfs == pdev->sriov->num_VFs)
@@ -627,6 +628,7 @@  static ssize_t sriov_numvfs_store(struct device *dev,
 
 exit:
 	device_unlock(&pdev->dev);
+	pci_unlock_rescan_remove();
 
 	if (ret < 0)
 		return ret;