5c796ae7a7
If the fakephp driver is used to emulate removal of a PCI device by writing text string "0" to the "power" sysfs attribute file, this causes its parent directory and its contents (including the "power" file) to be deleted before the write operation returns. Unfortunately, it ends up in a deadlock waiting for itself to complete. The deadlock is as follows: sysfs_write_file calls flush_write_buffer which calls sysfs_get_active_two before calling power_write_file in pci_hotplug_core.c via the sysfs store operation. The power_write_file function calls disable_slot in fakephp.c via the slot operation. The disable_slot function calls remove_slot which calls pci_hp_deregister (back in pci_hotplug_core.c) which calls fs_remove_slot which calls sysfs_remove_file to remove the "power" file. The sysfs_remove_file function calls sysfs_hash_and_remove which calls sysfs_addrm_finish which calls sysfs_deactivate. The sysfs_deactivate function sees that something has an active reference on the sysfs_dirent (from the previous call to sysfs_get_active_two back up the call stack somewhere) so waits for the active reference to go away, which is of course impossible. The problem has been present since 2.6.21. This patch breaks the deadlock by queuing work queue items on a single- threaded work queue to remove a slot from sysfs, and to rescan the PCI buses. There is also some protection against disabling a slot that is already being removed. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Cc: Kristen Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
||
---|---|---|
.. | ||
Kconfig | ||
Makefile | ||
acpi_pcihp.c | ||
acpiphp.h | ||
acpiphp_core.c | ||
acpiphp_glue.c | ||
acpiphp_ibm.c | ||
cpci_hotplug.h | ||
cpci_hotplug_core.c | ||
cpci_hotplug_pci.c | ||
cpcihp_generic.c | ||
cpcihp_zt5550.c | ||
cpcihp_zt5550.h | ||
cpqphp.h | ||
cpqphp_core.c | ||
cpqphp_ctrl.c | ||
cpqphp_nvram.c | ||
cpqphp_nvram.h | ||
cpqphp_pci.c | ||
cpqphp_sysfs.c | ||
fakephp.c | ||
ibmphp.h | ||
ibmphp_core.c | ||
ibmphp_ebda.c | ||
ibmphp_hpc.c | ||
ibmphp_pci.c | ||
ibmphp_res.c | ||
pci_hotplug_core.c | ||
pciehp.h | ||
pciehp_core.c | ||
pciehp_ctrl.c | ||
pciehp_hpc.c | ||
pciehp_pci.c | ||
pcihp_skeleton.c | ||
rpadlpar.h | ||
rpadlpar_core.c | ||
rpadlpar_sysfs.c | ||
rpaphp.h | ||
rpaphp_core.c | ||
rpaphp_pci.c | ||
rpaphp_slot.c | ||
sgi_hotplug.c | ||
shpchp.h | ||
shpchp_core.c | ||
shpchp_ctrl.c | ||
shpchp_hpc.c | ||
shpchp_pci.c | ||
shpchp_sysfs.c |