From 11e52a699afff576606ceb6cf697270459f1a4aa Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 18 Mar 2015 15:56:16 -0700 Subject: [PATCH 1/3] 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 Tested-by: Wen Xiong Signed-off-by: James Bottomley --- drivers/misc/enclosure.c | 11 ++++++----- 1 file 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) From 2e7cee027b26cbe7e6685a7a14bd2850bfe55d33 Mon Sep 17 00:00:00 2001 From: John Soni Jose Date: Thu, 12 Feb 2015 06:45:47 +0530 Subject: [PATCH 2/3] be2iscsi: Fix kernel panic when device initialization fails Kernel panic was happening as iscsi_host_remove() was called on a host which was not yet added. Signed-off-by: John Soni Jose Reviewed-by: Mike Christie Cc: Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a7cc61837818..923a2b5a2439 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5734,9 +5734,9 @@ free_port: hba_free: if (phba->msix_enabled) pci_disable_msix(phba->pcidev); - iscsi_host_remove(phba->shost); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); + pci_set_drvdata(pcidev, NULL); disable_pci: pci_disable_device(pcidev); return ret; From bba0bdd7ad4713d82338bcd9b72d57e9335a664b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 4 Mar 2015 10:31:47 +0100 Subject: [PATCH 3/3] Defer processing of REQ_PREEMPT requests for blocked devices SCSI transport drivers and SCSI LLDs block a SCSI device if the transport layer is not operational. This means that in this state no requests should be processed, even if the REQ_PREEMPT flag has been set. This patch avoids that a rescan shortly after a cable pull sporadically triggers the following kernel oops: BUG: unable to handle kernel paging request at ffffc9001a6bc084 IP: [] mlx4_ib_post_send+0xd2/0xb30 [mlx4_ib] Process rescan-scsi-bus (pid: 9241, threadinfo ffff88053484a000, task ffff880534aae100) Call Trace: [] srp_post_send+0x65/0x70 [ib_srp] [] srp_queuecommand+0x1cf/0x3e0 [ib_srp] [] scsi_dispatch_cmd+0x101/0x280 [scsi_mod] [] scsi_request_fn+0x411/0x4d0 [scsi_mod] [] __blk_run_queue+0x27/0x30 [] blk_execute_rq_nowait+0x82/0x110 [] blk_execute_rq+0x62/0xf0 [] scsi_execute+0xe8/0x190 [scsi_mod] [] scsi_execute_req+0xa3/0x130 [scsi_mod] [] scsi_probe_lun+0x17a/0x450 [scsi_mod] [] scsi_probe_and_add_lun+0x156/0x480 [scsi_mod] [] __scsi_scan_target+0xdf/0x1f0 [scsi_mod] [] scsi_scan_host_selected+0x183/0x1c0 [scsi_mod] [] scsi_scan+0xdb/0xe0 [scsi_mod] [] store_scan+0x13/0x20 [scsi_mod] [] sysfs_write_file+0xcb/0x160 [] vfs_write+0xce/0x140 [] sys_write+0x53/0xa0 [] system_call_fastpath+0x16/0x1b [<00007f611c9d9300>] 0x7f611c9d92ff Reported-by: Max Gurtuvoy Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Cc: Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 4 +++- include/linux/blk_types.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 54d7a6cbb98a..b1a263137a23 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1311,9 +1311,11 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) "rejecting I/O to dead device\n"); ret = BLKPREP_KILL; break; - case SDEV_QUIESCE: case SDEV_BLOCK: case SDEV_CREATED_BLOCK: + ret = BLKPREP_DEFER; + break; + case SDEV_QUIESCE: /* * If the devices is blocked we defer normal commands. */ diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index c294e3e25e37..a1b25e35ea5f 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -181,7 +181,9 @@ enum rq_flag_bits { __REQ_ELVPRIV, /* elevator private data attached */ __REQ_FAILED, /* set if the request failed */ __REQ_QUIET, /* don't worry about errors */ - __REQ_PREEMPT, /* set for "ide_preempt" requests */ + __REQ_PREEMPT, /* set for "ide_preempt" requests and also + for requests for which the SCSI "quiesce" + state must be ignored. */ __REQ_ALLOCED, /* request came from our alloc pool */ __REQ_COPY_USER, /* contains copies of user pages */ __REQ_FLUSH_SEQ, /* request for flush sequence */