[PATCH] mpt3sas: Fix kernel panic occurs during expander reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



During expander reset handling, the driver invokes kernel function
scsi_host_find_tag() to obtain outstanding requests associated with
the scsi host managed by the driver. Driver loops from tag value
zero to hba queue depth to obtain the outstanding scmds. But when
blk-mq is enabled then Kernel’s block layer may return stale entry
for one or more requests. This may lead to Kernel panic if the
returned value is inaccessible or the memory pointed by the
returned value is reused.

Reference of upstream discussion -
https://patchwork.kernel.org/patch/10734933/

Fix:
Instead of calling scsi_host_find_tag() API for each and every
smid(smid is tag +1) from one to shost->can_queue, now driver
will call this API (to obtain the outstanding scmd) for only
those smid's which are outstanding at the driver level.

Driver will determine whether this smid is outstanding at driver
level by looking into it's corresponding MPI request frame,
if it's MPI request frame is empty then it means that this
smid is free and no need to call scsi_host_find_tag() API for
this smid.
By doing this driver will invoke scsi_host_find_tag() for only
those tags which are outstanding at the driver level.

Driver will check whether particular MPI request frame is empty
or not by looking into the "DevHandle" field. If this field is
zero then it means that this MPI request is empty. For active
MPI request DevHandle must be non-zero.

Also driver will memset the MPI request frame once the
corresponding scmd is processed (i.e. just before calling
scmd->done function).

Signed-off-by: Sreekanth Reddy <sreekanth.reddy@xxxxxxxxxxxx>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  |  6 ++++++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index e577744..1d8c584 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -3281,12 +3281,18 @@ void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc,
 
 	if (smid < ioc->hi_priority_smid) {
 		struct scsiio_tracker *st;
+		void *request;
 
 		st = _get_st_from_smid(ioc, smid);
 		if (!st) {
 			_base_recovery_check(ioc);
 			return;
 		}
+
+		/* Clear MPI request frame */
+		request = mpt3sas_base_get_msg_frame(ioc, smid);
+		memset(request, 0, ioc->request_sz);
+
 		mpt3sas_base_clear_st(ioc, st);
 		_base_recovery_check(ioc);
 		return;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8bb5b8f..1ccfbc7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1462,11 +1462,23 @@ struct scsi_cmnd *
 {
 	struct scsi_cmnd *scmd = NULL;
 	struct scsiio_tracker *st;
+	Mpi25SCSIIORequest_t *mpi_request;
 
 	if (smid > 0  &&
 	    smid <= ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT) {
 		u32 unique_tag = smid - 1;
 
+		mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+		/*
+		 * If SCSI IO request is outstanding at driver level then
+		 * DevHandle filed must be non-zero. If DevHandle is zero
+		 * then it means that this smid is free at driver level,
+		 * so return NULL.
+		 */
+		if (!mpi_request->DevHandle)
+			return scmd;
+
 		scmd = scsi_host_find_tag(ioc->shost, unique_tag);
 		if (scmd) {
 			st = scsi_cmd_priv(scmd);
-- 
1.8.3.1




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux