summaryrefslogtreecommitdiffstats
path: root/drivers/misc/enclosure.c
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2015-03-18 23:56:16 +0100
committerJames Bottomley <JBottomley@Parallels.com>2015-03-31 07:53:36 +0200
commit11e52a699afff576606ceb6cf697270459f1a4aa (patch)
tree7b70436fc1ce49d16fe4b669bf8c1394d6fa35e1 /drivers/misc/enclosure.c
parentlibsas: Fix Kernel Crash in smp_execute_task (diff)
downloadlinux-11e52a699afff576606ceb6cf697270459f1a4aa.tar.xz
linux-11e52a699afff576606ceb6cf697270459f1a4aa.zip
enclosure: fix WARN_ON removing an adapter in multi-path devices
We have peculiar problems with multi-path and enclosures: physically, we know each bay can only be occupied by a single disk device. However in multi-path, it appears we have many (because each path to the device appears in Linux as a different kernel device). We try to fix this by only having the last seen device show up in the bay. Sysfs gets very annoyed if we try to manipulate links when the kobject sysfs directory (kobj.sd) doesn't exist and drops a huge WARN_ON which most users panic and report an oops for. This happens on a few path removal situations and IBM reports seeing it when one of their multi-path adapters is removed. Add a check to enclosure device removal for the existence the sysfs directory containing both the forward and back links so that the remnants (if any) get removed in either direction but no scary warnings are dumped. Reported-by: Wen Xiong <wenxiong@linux.vnet.ibm.com> Tested-by: Wen Xiong <wenxiong@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/misc/enclosure.c')
-rw-r--r--drivers/misc/enclosure.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 38552a31304a..65fed7146e9b 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -202,16 +202,17 @@ static void enclosure_remove_links(struct enclosure_component *cdev)
{
char name[ENCLOSURE_NAME_SIZE];
+ enclosure_link_name(cdev, name);
+
/*
* In odd circumstances, like multipath devices, something else may
* already have removed the links, so check for this condition first.
*/
- if (!cdev->dev->kobj.sd)
- return;
+ if (cdev->dev->kobj.sd)
+ sysfs_remove_link(&cdev->dev->kobj, name);
- enclosure_link_name(cdev, name);
- sysfs_remove_link(&cdev->dev->kobj, name);
- sysfs_remove_link(&cdev->cdev.kobj, "device");
+ if (cdev->cdev.kobj.sd)
+ sysfs_remove_link(&cdev->cdev.kobj, "device");
}
static int enclosure_add_links(struct enclosure_component *cdev)