diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2008-02-21 15:24:16 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-21 15:34:39 -0800 |
commit | 79df4c60c5b24ebc90f591d5991b22782813fcfe (patch) | |
tree | c8ff2e37d969c3961c64340eda242c6a2cc74ef5 | |
parent | 13d36c248379ca09c269f5dbed6dce1e3a326a48 (diff) | |
download | lwn-79df4c60c5b24ebc90f591d5991b22782813fcfe.tar.gz lwn-79df4c60c5b24ebc90f591d5991b22782813fcfe.zip |
PCI: Fix wrong reference counter check for proc_dir_entry
Fix wrong counter check for proc_dir_entry in pci_proc_detach_device().
The pci_proc_detach_device() returns with -EBUSY before calling
remove_proc_entry() if the reference counter of proc_dir_entry is not
0. But this check is wrong and pci_proc_detach_device() always fails
because the reference counter of proc_dir_entry is initialized with 1
at creating time and decremented in remove_proc_entry(). This bug
cause strange behaviour as followings:
- Accessing /proc/bus/pci/XXXX/YY file after hot-removing pci adapter
card causes kernel panic.
- Repeating hot-add/hot-remove of pci adapter card increases files
with the same name under /proc/bus/pci/XXXX/ directory. For example:
# pwd
/proc/bus/pci/0002:09
# ls
01.0
# for i in `seq 5`
> do
> echo 0 > /sys/bus/pci/slots/0009_0032/power
> echo 1 > /sys/bus/pci/slots/0009_0032/power
> done
# ls
01.0 01.0 01.0 01.0 01.0 01.0
The pci_proc_detach_device() should check if the reference counter is
not larger than 1 instead.
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/pci/proc.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 68aeeb7206de..ef18fcd641e2 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -422,7 +422,7 @@ int pci_proc_detach_device(struct pci_dev *dev) struct proc_dir_entry *e; if ((e = dev->procent)) { - if (atomic_read(&e->count)) + if (atomic_read(&e->count) > 1) return -EBUSY; remove_proc_entry(e->name, dev->bus->procdir); dev->procent = NULL; |