[SCSI] zfcp: fix logging during device reset

Avoid access to old fsf_requests if device reset is logged.

Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 4d7d47c..a5f2ba9 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -710,10 +710,9 @@
 _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
 			    struct zfcp_adapter *adapter,
 			    struct scsi_cmnd *scsi_cmnd,
-			    struct zfcp_fsf_req *new_fsf_req)
+			    struct zfcp_fsf_req *fsf_req,
+			    struct zfcp_fsf_req *old_fsf_req)
 {
-	struct zfcp_fsf_req *fsf_req =
-	    (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
 	struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
 	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
 	unsigned long flags;
@@ -727,19 +726,20 @@
 		if (offset == 0) {
 			strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
 			strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
-			if (scsi_cmnd->device) {
-				rec->scsi_id = scsi_cmnd->device->id;
-				rec->scsi_lun = scsi_cmnd->device->lun;
+			if (scsi_cmnd != NULL) {
+				if (scsi_cmnd->device) {
+					rec->scsi_id = scsi_cmnd->device->id;
+					rec->scsi_lun = scsi_cmnd->device->lun;
+				}
+				rec->scsi_result = scsi_cmnd->result;
+				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+				rec->scsi_serial = scsi_cmnd->serial_number;
+				memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+					min((int)scsi_cmnd->cmd_len,
+						ZFCP_DBF_SCSI_OPCODE));
+				rec->scsi_retries = scsi_cmnd->retries;
+				rec->scsi_allowed = scsi_cmnd->allowed;
 			}
-			rec->scsi_result = scsi_cmnd->result;
-			rec->scsi_cmnd = (unsigned long)scsi_cmnd;
-			rec->scsi_serial = scsi_cmnd->serial_number;
-			memcpy(rec->scsi_opcode,
-			       &scsi_cmnd->cmnd,
-			       min((int)scsi_cmnd->cmd_len,
-				   ZFCP_DBF_SCSI_OPCODE));
-			rec->scsi_retries = scsi_cmnd->retries;
-			rec->scsi_allowed = scsi_cmnd->allowed;
 			if (fsf_req != NULL) {
 				fcp_rsp = (struct fcp_rsp_iu *)
 				    &(fsf_req->qtcb->bottom.io.fcp_rsp);
@@ -772,15 +772,8 @@
 				rec->fsf_seqno = fsf_req->seq_no;
 				rec->fsf_issued = fsf_req->issued;
 			}
-			if (new_fsf_req != NULL) {
-				rec->type.new_fsf_req.fsf_reqid =
-				    (unsigned long)
-				    new_fsf_req;
-				rec->type.new_fsf_req.fsf_seqno =
-				    new_fsf_req->seq_no;
-				rec->type.new_fsf_req.fsf_issued =
-				    new_fsf_req->issued;
-			}
+			rec->type.old_fsf_reqid =
+				    (unsigned long) old_fsf_req;
 		} else {
 			strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
 			dump->total_size = buflen;
@@ -801,19 +794,21 @@
 inline void
 zfcp_scsi_dbf_event_result(const char *tag, int level,
 			   struct zfcp_adapter *adapter,
-			   struct scsi_cmnd *scsi_cmnd)
+			   struct scsi_cmnd *scsi_cmnd,
+			   struct zfcp_fsf_req *fsf_req)
 {
-	_zfcp_scsi_dbf_event_common("rslt",
-				    tag, level, adapter, scsi_cmnd, NULL);
+	_zfcp_scsi_dbf_event_common("rslt", tag, level,
+			adapter, scsi_cmnd, fsf_req, NULL);
 }
 
 inline void
 zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
 			  struct scsi_cmnd *scsi_cmnd,
-			  struct zfcp_fsf_req *new_fsf_req)
+			  struct zfcp_fsf_req *new_fsf_req,
+			  struct zfcp_fsf_req *old_fsf_req)
 {
-	_zfcp_scsi_dbf_event_common("abrt",
-				    tag, 1, adapter, scsi_cmnd, new_fsf_req);
+	_zfcp_scsi_dbf_event_common("abrt", tag, 1,
+			adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
 }
 
 inline void
@@ -823,7 +818,7 @@
 	struct zfcp_adapter *adapter = unit->port->adapter;
 
 	_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
-				    tag, 1, adapter, scsi_cmnd, NULL);
+			tag, 1, adapter, scsi_cmnd, NULL, NULL);
 }
 
 static int
@@ -856,6 +851,10 @@
 			     rec->scsi_retries);
 	len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
 			     rec->scsi_allowed);
+	if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+		len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+				     rec->type.old_fsf_reqid);
+	}
 	len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
 			     rec->fsf_reqid);
 	len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
@@ -883,21 +882,6 @@
 				       min((int)rec->type.fcp.sns_info_len,
 					   ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
 				       rec->type.fcp.sns_info_len);
-	} else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
-		len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
-				     rec->type.new_fsf_req.fsf_reqid);
-		len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
-				     rec->type.new_fsf_req.fsf_seqno);
-		len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
-				     rec->type.new_fsf_req.fsf_issued);
-	} else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
-		   (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
-		len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
-				     rec->type.new_fsf_req.fsf_reqid);
-		len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
-				     rec->type.new_fsf_req.fsf_seqno);
-		len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
-				     rec->type.new_fsf_req.fsf_issued);
 	}
 
 	len += sprintf(out_buf + len, "\n");
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index f031199..7f551d6 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -424,11 +424,7 @@
 	u32 fsf_seqno;
 	u64 fsf_issued;
 	union {
-		struct {
-			u64 fsf_reqid;
-			u32 fsf_seqno;
-			u64 fsf_issued;
-		} new_fsf_req;
+		u64 old_fsf_reqid;
 		struct {
 			u8 rsp_validity;
 			u8 rsp_scsi_status;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index c1ba7cf..700f540 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -194,9 +194,10 @@
 extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
 
 extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
-				       struct scsi_cmnd *);
+				       struct scsi_cmnd *,
+				       struct zfcp_fsf_req *);
 extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
-				      struct scsi_cmnd *,
+				      struct scsi_cmnd *, struct zfcp_fsf_req *,
 				      struct zfcp_fsf_req *);
 extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
 					 struct scsi_cmnd *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index bd8cd4d..662ec57 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4211,11 +4211,11 @@
 	ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
 
 	if (scpnt->result != 0)
-		zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+		zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req);
 	else if (scpnt->retries > 0)
-		zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+		zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req);
 	else
-		zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
+		zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req);
 
 	/* cleanup pointer (need this especially for abort) */
 	scpnt->host_scribble = NULL;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e080375..9f6b4d7 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -242,7 +242,7 @@
 	if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
 		zfcp_scsi_dbf_event_result("fail", 4,
 			(struct zfcp_adapter*) scpnt->device->host->hostdata[0],
-			scpnt);
+			scpnt, NULL);
 	/* return directly */
 	scpnt->scsi_done(scpnt);
 }
@@ -446,7 +446,7 @@
 	old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
 	if (!old_fsf_req) {
 		write_unlock_irqrestore(&adapter->abort_lock, flags);
-		zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+		zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
 		retval = SUCCESS;
 		goto out;
 	}
@@ -460,6 +460,8 @@
 						 adapter, unit, 0);
 	if (!new_fsf_req) {
 		ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
+		zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
+					  old_fsf_req);
 		retval = FAILED;
 		goto out;
 	}
@@ -470,13 +472,16 @@
 
 	/* status should be valid since signals were not permitted */
 	if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
-		zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
+		zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
+					  NULL);
 		retval = SUCCESS;
 	} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
-		zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
+		zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
+					  NULL);
 		retval = SUCCESS;
 	} else {
-		zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
+		zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
+					  NULL);
 		retval = FAILED;
 	}
 	zfcp_fsf_req_free(new_fsf_req);