Mike Christie wrote:
> Hannes Reinecke wrote:
>> Sigh. Why do you have to make is so complicated ...
>> My patch was easy and simple originally. And now this :-)
>>
> 
> This gets really ugly if we do it in libiscsi_tcp. I moved the check to 
> libiscsi and I changed the abort task test to check for the rtt since 
> that works for data outs. I think the attached patch will do what you 
> wanted. It is only compile tested.
> 

Bah. The lun and itt is not set for scsi cmd pdus. This should fix it.

For the lu reset and requeue (r2t data-out handling) or scsi cmd case, 
the task sc lun is always going to be set.

For the abort and requeue or cmd case, we only need to check the itt/rtt 
for data outs when doing a abort task (the requeue case), because the 
cmd has already been sent (iscsi_eh_abort checks for it on the cmd queue 
before sending) so there is no point to check at that point (also the 
itt is not set for scsi cmd pdus yet).

It might be nicer to move the restrictions check after the prep scsi cmd 
pdu call but you need the cmdsn scsi_prep_scsi_cmd_pdu patch I sent the 
other day.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index a751f62..7fcba1e 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1207,6 +1207,49 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
 	return 0;
 }
 
+static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
+{
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tm *tmf = &conn->tmhdr;
+	unsigned int hdr_lun;
+
+	if (conn->tmf_state == TMF_INITIAL)
+		return 0;
+
+	if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC)
+		return 0;
+
+	switch (ISCSI_TM_FUNC_VALUE(tmf)) {
+	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
+		/*
+		 * all scsi cmd pdus and, if fast_abort is set, data-outs
+		 * in response to a r2t will fail to be sent here
+		 *
+		 * If we are sending a initial r2t with a scsi cmd pdu
+		 * we do not hit this test, but the tmf will be sent
+		 * after the scsi cmd pdu and data-out for the initial r2t.
+		 */
+		hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun);
+		if (hdr_lun == task->sc->device->lun)
+			return -EACCES;
+		break;
+	case ISCSI_TM_FUNC_ABORT_TASK:
+		/*
+		 * the caller has already checked if the task
+		 * they want to abort was in the pending queue so if
+		 * we are here the cmd pdu has gone out already, and
+		 * we will only hit this for data-outs
+		 */
+		if (opcode == ISCSI_OP_SCSI_DATA_OUT &&
+		    task->hdr_itt == tmf->rtt)
+			return -EACCES;
+		break;
+	}
+
+	return 0;
+}
+
+
 static int iscsi_xmit_task(struct iscsi_conn *conn)
 {
 	struct iscsi_task *task = conn->task;
@@ -1258,6 +1301,7 @@ EXPORT_SYMBOL_GPL(iscsi_requeue_task);
  **/
 static int iscsi_data_xmit(struct iscsi_conn *conn)
 {
+	struct iscsi_task *task;
 	int rc = 0;
 
 	spin_lock_bh(&conn->session->lock);
@@ -1295,12 +1339,14 @@ check_mgmt:
 
 	/* process pending command queue */
 	while (!list_empty(&conn->cmdqueue)) {
-		if (conn->tmf_state == TMF_QUEUED)
+		task = list_entry(conn->cmdqueue.next, struct iscsi_task,
+				  running);
+		if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_CMD))
 			break;
 
-		conn->task = list_entry(conn->cmdqueue.next,
-					 struct iscsi_task, running);
+		conn->task = task;
 		list_del_init(&conn->task->running);
+
 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
 			fail_scsi_task(conn->task, DID_IMM_RETRY);
 			continue;
@@ -1329,17 +1375,19 @@ check_mgmt:
 	}
 
 	while (!list_empty(&conn->requeue)) {
-		if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL)
-			break;
-
 		/*
 		 * we always do fastlogout - conn stop code will clean up.
 		 */
 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
 			break;
 
-		conn->task = list_entry(conn->requeue.next,
-					 struct iscsi_task, running);
+		task = list_entry(conn->requeue.next, struct iscsi_task,
+				  running);
+		if (conn->session->fast_abort &&
+		    iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
+			break;
+
+		conn->task = task;
 		list_del_init(&conn->task->running);
 		conn->task->state = ISCSI_TASK_RUNNING;
 		rc = iscsi_xmit_task(conn);
@@ -1977,6 +2025,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
 		spin_lock_bh(&session->lock);
 		fail_scsi_task(task, DID_ABORT);
 		conn->tmf_state = TMF_INITIAL;
+		memset(hdr, 0, sizeof(*hdr));
 		spin_unlock_bh(&session->lock);
 		iscsi_start_tx(conn);
 		goto success_unlocked;
@@ -1987,6 +2036,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
 	case TMF_NOT_FOUND:
 		if (!sc->SCp.ptr) {
 			conn->tmf_state = TMF_INITIAL;
+			memset(hdr, 0, sizeof(*hdr));
 			/* task completed before tmf abort response */
 			ISCSI_DBG_EH(session, "sc completed while abort	in "
 					      "progress\n");
@@ -2083,6 +2133,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
 	spin_lock_bh(&session->lock);
 	fail_scsi_tasks(conn, sc->device->lun, DID_ERROR);
 	conn->tmf_state = TMF_INITIAL;
+	memset(hdr, 0, sizeof(*hdr));
 	spin_unlock_bh(&session->lock);
 
 	iscsi_start_tx(conn);
@@ -2723,6 +2774,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
 	spin_lock_bh(&session->lock);
 	fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
 	fail_mgmt_tasks(session, conn);
+	memset(&conn->tmhdr, 0, sizeof(conn->tmhdr));
 	spin_unlock_bh(&session->lock);
 	mutex_unlock(&session->eh_mutex);
 }
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index f2a2c11..4395148 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -250,6 +250,8 @@ struct iscsi_nopin {
 	uint8_t rsvd4[12];
 };
 
+#define ISCSI_TM_FUNC_VALUE(_hdr) ((_hdr)->flags & ISCSI_FLAG_TM_FUNC_MASK)
+
 /* SCSI Task Management Message Header */
 struct iscsi_tm {
 	uint8_t opcode;

Reply via email to