public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
       [not found] <b9df5fa10809280816u23ef3021k7eee287a237b72ae@mail.gmail.com>
@ 2008-09-28 16:32 ` Matthew Wilcox
  2008-10-21  1:13   ` Matthew Wilcox
  0 siblings, 1 reply; 13+ messages in thread
From: Matthew Wilcox @ 2008-09-28 16:32 UTC (permalink / raw)
  To: Rakib Mullick; +Cc: linux-pci, greg, akpm, linux-kernel

On Sun, Sep 28, 2008 at 09:16:45PM +0600, Rakib Mullick wrote:
> drivers/pci/search.c: In function `pci_get_dev_by_id':
> drivers/pci/search.c:284: warning: passing arg 1 of `pci_dev_put'
> discards qualifiers from pointer target type
> 
> The following patch removes the above compilation warning.
> Thanks.

Yes, but this compilation warning is pointing to a real problem.
We've told the compiler that the pci_dev is const (ie we won't modify
it), but pci_dev_put() is most assuredly going to modify and potentially
can even free the struct pci_dev.

In looking at this, I found another bug in the pci_find_device()
rewrite.  pci_get_subsys() will put the reference to 'from' (if
non-NULL), but the reference was already put by pci_find_device(),
so I suspect the reference count ends up going zero very quickly.
We can fix this by calling pci_dev_get() before calling
pci_get_subsys(), but then we also have to drop the const from
pci_find_device()'s argument.

Jesse, how does this patch look?  I think it's worth including in -rc
since it fixes a refcounting bug (admittedly one only triggered by
drivers using the deprecated pci_find_device() interface).

---

Subject: [PCI] Fix reference counting bug

pci_get_subsys() will decrement the reference count of the device that
it starts searching from.  Unfortunately, the pci_find_device() interface 
will already have decremented the reference count of the device earlier,
so the device will end up losing all reference counts and be freed.

We can fix this by incrementing the reference count of the device to
start searching from before calling pci_get_subsys().  Unfortunately,
this means we have to lose the 'const' on the arguments of several
functions.

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>

diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 3b3b5f1..5af8bd5 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -162,10 +162,11 @@ EXPORT_SYMBOL(pci_find_slot);
  * time.
  */
 struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
-				const struct pci_dev *from)
+				struct pci_dev *from)
 {
 	struct pci_dev *pdev;
 
+	pci_dev_get(from);
 	pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 	pci_dev_put(pdev);
 	return pdev;
@@ -263,19 +264,15 @@ static int match_pci_dev_by_id(struct device *dev, void *data)
  * this file.
  */
 static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
-					 const struct pci_dev *from)
+					 struct pci_dev *from)
 {
 	struct device *dev;
 	struct device *dev_start = NULL;
 	struct pci_dev *pdev = NULL;
 
 	WARN_ON(in_interrupt());
-	if (from) {
-		/* FIXME
-		 * take the cast off, when bus_find_device is made const.
-		 */
-		dev_start = (struct device *)&from->dev;
-	}
+	if (from)
+		dev_start = &from->dev;
 	dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
 			      match_pci_dev_by_id);
 	if (dev)
@@ -303,7 +300,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
  */
 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
 			       unsigned int ss_vendor, unsigned int ss_device,
-			       const struct pci_dev *from)
+			       struct pci_dev *from)
 {
 	struct pci_dev *pdev;
 	struct pci_device_id *id;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a27293a..b8a04c4 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -534,7 +534,7 @@ extern void pci_sort_breadthfirst(void);
 #ifdef CONFIG_PCI_LEGACY
 struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
 					     unsigned int device,
-					     const struct pci_dev *from);
+					     struct pci_dev *from);
 struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
 					   unsigned int devfn);
 #endif /* CONFIG_PCI_LEGACY */
@@ -550,7 +550,7 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 				struct pci_dev *from);
 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
 				unsigned int ss_vendor, unsigned int ss_device,
-				const struct pci_dev *from);
+				struct pci_dev *from);
 struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
 struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);



-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-09-28 16:32 ` [PATCH] pci: Fixing drivers/pci/search.c compilation warning Matthew Wilcox
@ 2008-10-21  1:13   ` Matthew Wilcox
  2008-10-21  1:29     ` Jesse Barnes
                       ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Matthew Wilcox @ 2008-10-21  1:13 UTC (permalink / raw)
  To: Jesse Barnes, linux-pci; +Cc: greg, akpm, linux-kernel, stable, Rakib Mullick


This patch seems to have been overlooked.  It also seems to have had
some kind of midair collision with a patch from Greg that ignored the
real bug I found.

Here's an updated version.  I think it should also be applied to
-stable.

----

Subject: [PCI] Fix reference counting bug

pci_get_subsys() will decrement the reference count of the device that
it starts searching from.  Unfortunately, the pci_find_device() interface 
will already have decremented the reference count of the device earlier,
so the device will end up losing all reference counts and be freed.

We can fix this by incrementing the reference count of the device to
start searching from before calling pci_get_subsys().

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>

diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 4edfc47..5af8bd5 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
 {
 	struct pci_dev *pdev;
 
+	pci_dev_get(from);
 	pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 	pci_dev_put(pdev);
 	return pdev;
@@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
 	struct pci_dev *pdev = NULL;
 
 	WARN_ON(in_interrupt());
-	if (from) {
-		/* FIXME
-		 * take the cast off, when bus_find_device is made const.
-		 */
-		dev_start = (struct device *)&from->dev;
-	}
+	if (from)
+		dev_start = &from->dev;
 	dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
 			      match_pci_dev_by_id);
 	if (dev)

On Sun, Sep 28, 2008 at 10:32:11AM -0600, Matthew Wilcox wrote:
> On Sun, Sep 28, 2008 at 09:16:45PM +0600, Rakib Mullick wrote:
> > drivers/pci/search.c: In function `pci_get_dev_by_id':
> > drivers/pci/search.c:284: warning: passing arg 1 of `pci_dev_put'
> > discards qualifiers from pointer target type
> > 
> > The following patch removes the above compilation warning.
> > Thanks.
> 
> Yes, but this compilation warning is pointing to a real problem.
> We've told the compiler that the pci_dev is const (ie we won't modify
> it), but pci_dev_put() is most assuredly going to modify and potentially
> can even free the struct pci_dev.
> 
> In looking at this, I found another bug in the pci_find_device()
> rewrite.  pci_get_subsys() will put the reference to 'from' (if
> non-NULL), but the reference was already put by pci_find_device(),
> so I suspect the reference count ends up going zero very quickly.
> We can fix this by calling pci_dev_get() before calling
> pci_get_subsys(), but then we also have to drop the const from
> pci_find_device()'s argument.
> 
> Jesse, how does this patch look?  I think it's worth including in -rc
> since it fixes a refcounting bug (admittedly one only triggered by
> drivers using the deprecated pci_find_device() interface).
> 
> ---
> 
> Subject: [PCI] Fix reference counting bug
> 
> pci_get_subsys() will decrement the reference count of the device that
> it starts searching from.  Unfortunately, the pci_find_device() interface 
> will already have decremented the reference count of the device earlier,
> so the device will end up losing all reference counts and be freed.
> 
> We can fix this by incrementing the reference count of the device to
> start searching from before calling pci_get_subsys().  Unfortunately,
> this means we have to lose the 'const' on the arguments of several
> functions.
> 
> Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
> 
> diff --git a/drivers/pci/search.c b/drivers/pci/search.c
> index 3b3b5f1..5af8bd5 100644
> --- a/drivers/pci/search.c
> +++ b/drivers/pci/search.c
> @@ -162,10 +162,11 @@ EXPORT_SYMBOL(pci_find_slot);
>   * time.
>   */
>  struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
> -				const struct pci_dev *from)
> +				struct pci_dev *from)
>  {
>  	struct pci_dev *pdev;
>  
> +	pci_dev_get(from);
>  	pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
>  	pci_dev_put(pdev);
>  	return pdev;
> @@ -263,19 +264,15 @@ static int match_pci_dev_by_id(struct device *dev, void *data)
>   * this file.
>   */
>  static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
> -					 const struct pci_dev *from)
> +					 struct pci_dev *from)
>  {
>  	struct device *dev;
>  	struct device *dev_start = NULL;
>  	struct pci_dev *pdev = NULL;
>  
>  	WARN_ON(in_interrupt());
> -	if (from) {
> -		/* FIXME
> -		 * take the cast off, when bus_find_device is made const.
> -		 */
> -		dev_start = (struct device *)&from->dev;
> -	}
> +	if (from)
> +		dev_start = &from->dev;
>  	dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
>  			      match_pci_dev_by_id);
>  	if (dev)
> @@ -303,7 +300,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
>   */
>  struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
>  			       unsigned int ss_vendor, unsigned int ss_device,
> -			       const struct pci_dev *from)
> +			       struct pci_dev *from)
>  {
>  	struct pci_dev *pdev;
>  	struct pci_device_id *id;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index a27293a..b8a04c4 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -534,7 +534,7 @@ extern void pci_sort_breadthfirst(void);
>  #ifdef CONFIG_PCI_LEGACY
>  struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
>  					     unsigned int device,
> -					     const struct pci_dev *from);
> +					     struct pci_dev *from);
>  struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
>  					   unsigned int devfn);
>  #endif /* CONFIG_PCI_LEGACY */
> @@ -550,7 +550,7 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
>  				struct pci_dev *from);
>  struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
>  				unsigned int ss_vendor, unsigned int ss_device,
> -				const struct pci_dev *from);
> +				struct pci_dev *from);
>  struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
>  struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
>  struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
> 
> 
> 
> -- 
> Matthew Wilcox				Intel Open Source Technology Centre
> "Bill, look, we understand that you're interested in selling us this
> operating system, but compare it to ours.  We can't possibly take such
> a retrograde step."

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-21  1:13   ` Matthew Wilcox
@ 2008-10-21  1:29     ` Jesse Barnes
  2008-10-21 17:24     ` Jesse Barnes
  2008-10-26 12:51     ` Yu Zhao
  2 siblings, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2008-10-21  1:29 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: linux-pci, greg, akpm, linux-kernel, stable, Rakib Mullick

On Monday, October 20, 2008 6:13 pm Matthew Wilcox wrote:
> This patch seems to have been overlooked.  It also seems to have had
> some kind of midair collision with a patch from Greg that ignored the
> real bug I found.
>
> Here's an updated version.  I think it should also be applied to
> -stable.

Ah I didn't get Cc'd but I should have seen it on linux-pci.  Queued up for my 
next pull, thanks Matthew.

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-21  1:13   ` Matthew Wilcox
  2008-10-21  1:29     ` Jesse Barnes
@ 2008-10-21 17:24     ` Jesse Barnes
  2008-10-26 12:51     ` Yu Zhao
  2 siblings, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2008-10-21 17:24 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: linux-pci, greg, akpm, linux-kernel, stable, Rakib Mullick

On Monday, October 20, 2008 6:13 pm Matthew Wilcox wrote:
> Subject: [PCI] Fix reference counting bug
>
> pci_get_subsys() will decrement the reference count of the device that
> it starts searching from.  Unfortunately, the pci_find_device() interface
> will already have decremented the reference count of the device earlier,
> so the device will end up losing all reference counts and be freed.
>
> We can fix this by incrementing the reference count of the device to
> start searching from before calling pci_get_subsys().
>
> Signed-off-by: Matthew Wilcox <willy@linux.intel.com>

Applied, thanks Matthew.

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-21  1:13   ` Matthew Wilcox
  2008-10-21  1:29     ` Jesse Barnes
  2008-10-21 17:24     ` Jesse Barnes
@ 2008-10-26 12:51     ` Yu Zhao
  2008-10-26 18:34       ` Matthew Wilcox
  2 siblings, 1 reply; 13+ messages in thread
From: Yu Zhao @ 2008-10-26 12:51 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Jesse Barnes, linux-pci, greg, akpm, linux-kernel, stable,
	Rakib Mullick

Matthew Wilcox wrote:
> This patch seems to have been overlooked.  It also seems to have had
> some kind of midair collision with a patch from Greg that ignored the
> real bug I found.
> 
> Here's an updated version.  I think it should also be applied to
> -stable.
> 
> ----
> 
> Subject: [PCI] Fix reference counting bug
> 
> pci_get_subsys() will decrement the reference count of the device that
> it starts searching from.  Unfortunately, the pci_find_device() interface 
> will already have decremented the reference count of the device earlier,
> so the device will end up losing all reference counts and be freed.
> 
> We can fix this by incrementing the reference count of the device to
> start searching from before calling pci_get_subsys().
> 
> Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
> 
> diff --git a/drivers/pci/search.c b/drivers/pci/search.c
> index 4edfc47..5af8bd5 100644
> --- a/drivers/pci/search.c
> +++ b/drivers/pci/search.c
> @@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
>  {
>  	struct pci_dev *pdev;
>  
> +	pci_dev_get(from);
>  	pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
>  	pci_dev_put(pdev);
>  	return pdev;
> @@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
>  	struct pci_dev *pdev = NULL;
>  
>  	WARN_ON(in_interrupt());
> -	if (from) {
> -		/* FIXME
> -		 * take the cast off, when bus_find_device is made const.
> -		 */
> -		dev_start = (struct device *)&from->dev;
> -	}
> +	if (from)
> +		dev_start = &from->dev;
>  	dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
>  			      match_pci_dev_by_id);
>  	if (dev)

This reminds me of other problems of PCI search functions.

The 'dev_start' is passed to bus_find_device(), and its 'knode_bus' 
reference count is decreased by klist_iter_init_node() in that function. 
The problem is the reference count may be already decrease to 0 because 
the PCI device 'from' is hot-plugged off (e.g., pci_remove_bus) when the 
search goes. A warning is fired when klist_iter_init_node() detects the 
reference count becomes 0.

Some code uses pci_find_device() in a way that is not safe with the 
hotplug, because a device may be destroyed after bus_find_device() 
returns it and before it's held by pci_dev_get() in the next round. 
Following is an example from a random grep:

for ( ;; )
{
	if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
		ret = njs_pci_probe(dev_netjet, cs);
		...
	}
	...
}

And some others use pci_get_bus_and_slot(), which has similar problem as 
above.


Thanks,
Yu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-26 12:51     ` Yu Zhao
@ 2008-10-26 18:34       ` Matthew Wilcox
  2008-10-27  3:18         ` Zhao, Yu
  0 siblings, 1 reply; 13+ messages in thread
From: Matthew Wilcox @ 2008-10-26 18:34 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Jesse Barnes, linux-pci, greg, akpm, linux-kernel, stable,
	Rakib Mullick

On Sun, Oct 26, 2008 at 08:51:25PM +0800, Yu Zhao wrote:
> This reminds me of other problems of PCI search functions.
> 
> The 'dev_start' is passed to bus_find_device(), and its 'knode_bus' 
> reference count is decreased by klist_iter_init_node() in that function. 
> The problem is the reference count may be already decrease to 0 because 
> the PCI device 'from' is hot-plugged off (e.g., pci_remove_bus) when the 
> search goes. A warning is fired when klist_iter_init_node() detects the 
> reference count becomes 0.
> 
> Some code uses pci_find_device() in a way that is not safe with the 
> hotplug, because a device may be destroyed after bus_find_device() 
> returns it and before it's held by pci_dev_get() in the next round. 
> Following is an example from a random grep:

Yes, that's why pci_find_device() is deprecated.  But it doesn't also
need to be buggy ;-)

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-26 18:34       ` Matthew Wilcox
@ 2008-10-27  3:18         ` Zhao, Yu
  2008-10-27  7:07           ` Matthew Wilcox
  0 siblings, 1 reply; 13+ messages in thread
From: Zhao, Yu @ 2008-10-27  3:18 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

Matthew Wilcox wrote:
> On Sun, Oct 26, 2008 at 08:51:25PM +0800, Yu Zhao wrote:
>> This reminds me of other problems of PCI search functions.
>>
>> The 'dev_start' is passed to bus_find_device(), and its 'knode_bus' 
>> reference count is decreased by klist_iter_init_node() in that function. 
>> The problem is the reference count may be already decrease to 0 because 
>> the PCI device 'from' is hot-plugged off (e.g., pci_remove_bus) when the 
>> search goes. A warning is fired when klist_iter_init_node() detects the 
>> reference count becomes 0.
>>
>> Some code uses pci_find_device() in a way that is not safe with the 
>> hotplug, because a device may be destroyed after bus_find_device() 
>> returns it and before it's held by pci_dev_get() in the next round. 
>> Following is an example from a random grep:
> 
> Yes, that's why pci_find_device() is deprecated.  But it doesn't also
> need to be buggy ;-)
> 

How about pci_get_bus_and_slot()? People would meet the problem with it 
anyway.

Thanks,
Yu

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  3:18         ` Zhao, Yu
@ 2008-10-27  7:07           ` Matthew Wilcox
  2008-10-27  7:13             ` Zhao, Yu
  0 siblings, 1 reply; 13+ messages in thread
From: Matthew Wilcox @ 2008-10-27  7:07 UTC (permalink / raw)
  To: Zhao, Yu
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

On Mon, Oct 27, 2008 at 11:18:43AM +0800, Zhao, Yu wrote:
> Matthew Wilcox wrote:
> >Yes, that's why pci_find_device() is deprecated.  But it doesn't also
> >need to be buggy ;-)
> 
> How about pci_get_bus_and_slot()? People would meet the problem with it 
> anyway.

What problem with it?  It's documented to return the device with an
increased refcount, and the implementation appears to do exactly that:

struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
{
        struct pci_dev *dev = NULL;

        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                if (pci_domain_nr(dev->bus) == 0 &&
                   (dev->bus->number == bus && dev->devfn == devfn))
                        return dev;
        }
        return NULL;
}

Are you saying some users of it neglect to decrement the refcount before
disposing of the device?

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  7:07           ` Matthew Wilcox
@ 2008-10-27  7:13             ` Zhao, Yu
  2008-10-27  7:21               ` Matthew Wilcox
  0 siblings, 1 reply; 13+ messages in thread
From: Zhao, Yu @ 2008-10-27  7:13 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

Matthew Wilcox wrote:
> On Mon, Oct 27, 2008 at 11:18:43AM +0800, Zhao, Yu wrote:
>> Matthew Wilcox wrote:
>>> Yes, that's why pci_find_device() is deprecated.  But it doesn't also
>>> need to be buggy ;-)
>> How about pci_get_bus_and_slot()? People would meet the problem with it 
>> anyway.
> 
> What problem with it?  It's documented to return the device with an
> increased refcount, and the implementation appears to do exactly that:
> 
> struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
> {
>         struct pci_dev *dev = NULL;
> 
>         while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
>                 if (pci_domain_nr(dev->bus) == 0 &&
>                    (dev->bus->number == bus && dev->devfn == devfn))
>                         return dev;
>         }
>         return NULL;
> }
> 
> Are you saying some users of it neglect to decrement the refcount before
> disposing of the device?
> 

The 'dev' returned by pci_get_device() may be destroyed by PCI hotplug. 
I suppose that passing this 'dev' to pci_get_device() in the next loop 
would crash the system, right?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  7:13             ` Zhao, Yu
@ 2008-10-27  7:21               ` Matthew Wilcox
  2008-10-27  7:34                 ` Zhao, Yu
  0 siblings, 1 reply; 13+ messages in thread
From: Matthew Wilcox @ 2008-10-27  7:21 UTC (permalink / raw)
  To: Zhao, Yu
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

On Mon, Oct 27, 2008 at 03:13:51PM +0800, Zhao, Yu wrote:
> Matthew Wilcox wrote:
> >On Mon, Oct 27, 2008 at 11:18:43AM +0800, Zhao, Yu wrote:
> >>Matthew Wilcox wrote:
> >>>Yes, that's why pci_find_device() is deprecated.  But it doesn't also
> >>>need to be buggy ;-)
> >>How about pci_get_bus_and_slot()? People would meet the problem with it 
> >>anyway.
> >
> >What problem with it?  It's documented to return the device with an
> >increased refcount, and the implementation appears to do exactly that:
> >
> 
> The 'dev' returned by pci_get_device() may be destroyed by PCI hotplug. 
> I suppose that passing this 'dev' to pci_get_device() in the next loop 
> would crash the system, right?

Erm, no, the 'dev' cannot be destroyed because the caller has a refcount
on it.  The physical device backing it might have gone away.  The dev
won't be destroyed until its reference count reaches zero, which could
be any time someone calls pci_dev_put() on it.  In the scenario you're
postulating, it would happen in pci_get_dev_by_id():

        if (from)
                pci_dev_put(from);

which is the last time that 'from' is referred to in that callchain.

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  7:21               ` Matthew Wilcox
@ 2008-10-27  7:34                 ` Zhao, Yu
  2008-10-27  7:43                   ` Zhao, Yu
  2008-10-27  7:45                   ` Matthew Wilcox
  0 siblings, 2 replies; 13+ messages in thread
From: Zhao, Yu @ 2008-10-27  7:34 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

Matthew Wilcox wrote:
> On Mon, Oct 27, 2008 at 03:13:51PM +0800, Zhao, Yu wrote:
>> Matthew Wilcox wrote:
>>> On Mon, Oct 27, 2008 at 11:18:43AM +0800, Zhao, Yu wrote:
>>>> Matthew Wilcox wrote:
>>>>> Yes, that's why pci_find_device() is deprecated.  But it doesn't also
>>>>> need to be buggy ;-)
>>>> How about pci_get_bus_and_slot()? People would meet the problem with it 
>>>> anyway.
>>> What problem with it?  It's documented to return the device with an
>>> increased refcount, and the implementation appears to do exactly that:
>>>
>> The 'dev' returned by pci_get_device() may be destroyed by PCI hotplug. 
>> I suppose that passing this 'dev' to pci_get_device() in the next loop 
>> would crash the system, right?
> 
> Erm, no, the 'dev' cannot be destroyed because the caller has a refcount
> on it.  The physical device backing it might have gone away.  The dev

Why does the caller have a reference count? I don't see we increase the 
reference count after the 'dev' is returned by following in 
pci_get_dev_by_id():

         dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
                               match_pci_dev_by_id);

And this 'dev' becomes the 'from' in the next loop, but it may be 
destroyed before the 'pci_dev_get(from)', isn't it?


> won't be destroyed until its reference count reaches zero, which could
> be any time someone calls pci_dev_put() on it.  In the scenario you're
> postulating, it would happen in pci_get_dev_by_id():
> 
>         if (from)
>                 pci_dev_put(from);
> 
> which is the last time that 'from' is referred to in that callchain.
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  7:34                 ` Zhao, Yu
@ 2008-10-27  7:43                   ` Zhao, Yu
  2008-10-27  7:45                   ` Matthew Wilcox
  1 sibling, 0 replies; 13+ messages in thread
From: Zhao, Yu @ 2008-10-27  7:43 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

Zhao, Yu wrote:
> Matthew Wilcox wrote:
>> On Mon, Oct 27, 2008 at 03:13:51PM +0800, Zhao, Yu wrote:
>>> Matthew Wilcox wrote:
>>>> On Mon, Oct 27, 2008 at 11:18:43AM +0800, Zhao, Yu wrote:
>>>>> Matthew Wilcox wrote:
>>>>>> Yes, that's why pci_find_device() is deprecated.  But it doesn't also
>>>>>> need to be buggy ;-)
>>>>> How about pci_get_bus_and_slot()? People would meet the problem with it 
>>>>> anyway.
>>>> What problem with it?  It's documented to return the device with an
>>>> increased refcount, and the implementation appears to do exactly that:
>>>>
>>> The 'dev' returned by pci_get_device() may be destroyed by PCI hotplug. 
>>> I suppose that passing this 'dev' to pci_get_device() in the next loop 
>>> would crash the system, right?
>> Erm, no, the 'dev' cannot be destroyed because the caller has a refcount
>> on it.  The physical device backing it might have gone away.  The dev
> 
> Why does the caller have a reference count? I don't see we increase the 
> reference count after the 'dev' is returned by following in 
> pci_get_dev_by_id():
> 
>          dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
>                                match_pci_dev_by_id);
> 
> And this 'dev' becomes the 'from' in the next loop, but it may be 
> destroyed before the 'pci_dev_get(from)', isn't it?

I checked the source code, there is no 'pci_dev_get(from)', the 
reference count is increased in bus_find_device().

         while ((dev = next_device(&i)))
                 if (match(dev, data) && get_device(dev))

But the essential problem is same: the reference count of 'dev' above 
may be decreased before the 'get_device(dev)', I guess.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] pci: Fixing drivers/pci/search.c compilation warning.
  2008-10-27  7:34                 ` Zhao, Yu
  2008-10-27  7:43                   ` Zhao, Yu
@ 2008-10-27  7:45                   ` Matthew Wilcox
  1 sibling, 0 replies; 13+ messages in thread
From: Matthew Wilcox @ 2008-10-27  7:45 UTC (permalink / raw)
  To: Zhao, Yu
  Cc: Yu Zhao, Jesse Barnes, linux-pci@vger.kernel.org, greg@kroah.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	stable@kernel.org, Rakib Mullick

On Mon, Oct 27, 2008 at 03:34:14PM +0800, Zhao, Yu wrote:
> >Erm, no, the 'dev' cannot be destroyed because the caller has a refcount
> >on it.  The physical device backing it might have gone away.  The dev
> 
> Why does the caller have a reference count? I don't see we increase the 
> reference count after the 'dev' is returned by following in 
> pci_get_dev_by_id():
> 
>         dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
>                               match_pci_dev_by_id);
> 
> And this 'dev' becomes the 'from' in the next loop, but it may be 
> destroyed before the 'pci_dev_get(from)', isn't it?

Either you've gone back to talking about pci_find_device() [which, yes, is
vulnerable to race conditions, we know that, it's not interesting to talk
about it], or you're refusing to take it on faith that pci_get_dev_by_id()
returns a device with an increased refcount.  And if you don't believe
that is true, please follow the code in bus_find_device() to prove it.

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-10-27  7:45 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <b9df5fa10809280816u23ef3021k7eee287a237b72ae@mail.gmail.com>
2008-09-28 16:32 ` [PATCH] pci: Fixing drivers/pci/search.c compilation warning Matthew Wilcox
2008-10-21  1:13   ` Matthew Wilcox
2008-10-21  1:29     ` Jesse Barnes
2008-10-21 17:24     ` Jesse Barnes
2008-10-26 12:51     ` Yu Zhao
2008-10-26 18:34       ` Matthew Wilcox
2008-10-27  3:18         ` Zhao, Yu
2008-10-27  7:07           ` Matthew Wilcox
2008-10-27  7:13             ` Zhao, Yu
2008-10-27  7:21               ` Matthew Wilcox
2008-10-27  7:34                 ` Zhao, Yu
2008-10-27  7:43                   ` Zhao, Yu
2008-10-27  7:45                   ` Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox