[stgt] stgt does not preempt SCSI-2 reservations; may break MS Cluster Service failover

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Sat Sep 5 10:53:29 CEST 2009


On Thu, 03 Sep 2009 07:40:43 +0200
Florian Haas <florian.haas at linbit.com> wrote:

> Fujita-san,
> 
> On 2009-09-02 07:02, FUJITA Tomonori wrote:
> > You mean that MSSC sends TARGET_WARM_RESET (or TARGET_COLD_RESET)?
> > Note that there is no 'bus reset' thing.
> 
> In SCSI2, TARGET_RESET was called BUS_DEVICE_RESET (at least in the
> defines inside the Linux source tree).
> 
> And yes, the Windows SCSI stack does a "SCSI bus reset", colloquially
> speaking, whatever that is translated to in iSCSI speak.

'SCSI bus reset' is really old and obsolete, I think.


> > I didn't implement TARGET_RESET thing mainly because it's obsolete in
> > SCSI-3 (and because I'm lazy).
> 
> But the SCSI-3 PRs are not there, either. And to preempt SCSI-2
> reservations, target reset seems a necessity, for many if not all
> initiators.

Yeah though I really love to have the PR support in tgt.


> > BTW, IET doesn't correctly handle any reset commands (i.e. it doesn't
> > handle UA). I wrote IET so I know exactly what it does.
> 
> Yes, I know you wrote it, and I know it does not handle the Unit
> Attention stuff, but at least it preempts the SCSI-2 reservations
> on target reset. Does it not?

If just preempting the reservation on target reset (as IET does) works
for you, the following patch might work (sorry, I've not tested the
path at all because open-iscsi doesn't support
TARGET_WARM|COLD_RESET):


diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index b952c08..f1ae7ea 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -1298,6 +1298,7 @@ static int iscsi_tm_done(struct mgmt_req *mreq)
 
 static int iscsi_tm_execute(struct iscsi_task *task)
 {
+	struct iscsi_session *session;
 	struct iscsi_connection *conn = task->conn;
 	struct iscsi_tm *req = (struct iscsi_tm *) &task->req;
 	int fn = 0, err = 0;
@@ -1318,8 +1319,18 @@ static int iscsi_tm_execute(struct iscsi_task *task)
 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
 		fn = LOGICAL_UNIT_RESET;
 		break;
-	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
+		list_for_each_entry(session,
+				    &conn->session->target->sessions_list,
+				    slist) {
+			struct iscsi_connection *c;
+
+			list_for_each_entry(c, &session->conn_list, clist)
+				conn_close(c);
+		}
+	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
+		fn = TARGET_RESET;
+		break;
 	case ISCSI_TM_FUNC_TASK_REASSIGN:
 		err = ISCSI_TMF_RSP_NOT_SUPPORTED;
 		break;
diff --git a/usr/scsi.h b/usr/scsi.h
index 84fadff..0da81da 100644
--- a/usr/scsi.h
+++ b/usr/scsi.h
@@ -140,6 +140,7 @@
 #define	MSG_HEAD_TAG	0x21
 #define	MSG_ORDERED_TAG	0x22
 
+#define TARGET_RESET        0x0c
 #define ABORT_TASK          0x0d
 #define ABORT_TASK_SET      0x06
 #define CLEAR_ACA           0x16
diff --git a/usr/target.c b/usr/target.c
index 08c0dca..babfa3b 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -979,7 +979,8 @@ static int abort_cmd(struct target* target, struct mgmt_req *mreq,
 }
 
 static int abort_task_set(struct mgmt_req *mreq, struct target* target,
-			  uint64_t itn_id, uint64_t tag, uint8_t *lun, int all)
+			  uint64_t itn_id, uint64_t tag, uint8_t *lun,
+			  int my_all, int all)
 {
 	struct scsi_cmd *cmd, *tmp;
 	struct it_nexus *itn;
@@ -991,7 +992,7 @@ static int abort_task_set(struct mgmt_req *mreq, struct target* target,
 		for (i = 0; i < ARRAY_SIZE(itn->cmd_hash_list); i++) {
 			struct list_head *list = &itn->cmd_hash_list[i];
 			list_for_each_entry_safe(cmd, tmp, list, c_hlist) {
-				if ((all && itn->itn_id == itn_id) ||
+				if (all || (my_all && itn->itn_id == itn_id) ||
 				    (cmd->tag == tag && itn->itn_id == itn_id) ||
 				    (lun && !memcmp(cmd->lun, lun, sizeof(cmd->lun)))) {
 					err = abort_cmd(target, mreq, cmd);
@@ -1009,6 +1010,7 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 			 int function, uint8_t *lun_buf, uint64_t tag, int host_no)
 {
 	struct target *target;
+	struct scsi_lu *lu;
 	struct mgmt_req *mreq;
 	int err = 0, count, send = 1;
 	struct it_nexus *itn;
@@ -1032,14 +1034,14 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 
 	switch (function) {
 	case ABORT_TASK:
-		count = abort_task_set(mreq, target, itn_id, tag, NULL, 0);
+		count = abort_task_set(mreq, target, itn_id, tag, NULL, 0, 0);
 		if (mreq->busy)
 			send = 0;
 		if (!count)
 			err = -EEXIST;
 		break;
 	case ABORT_TASK_SET:
-		count = abort_task_set(mreq, target, itn_id, 0, NULL, 1);
+		count = abort_task_set(mreq, target, itn_id, 0, NULL, 1, 0);
 		if (mreq->busy)
 			send = 0;
 		break;
@@ -1050,7 +1052,7 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 	case CLEAR_TASK_SET:
 		/* TAS bit is set to zero. */
 		lun = scsi_get_devid(target->lid, lun_buf);
-		count = abort_task_set(mreq, target, itn_id, 0, lun_buf, 0);
+		count = abort_task_set(mreq, target, itn_id, 0, lun_buf, 0, 0);
 		if (mreq->busy)
 			send = 0;
 
@@ -1072,7 +1074,7 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 	case LOGICAL_UNIT_RESET:
 		lun = scsi_get_devid(target->lid, lun_buf);
 		device_release(target->tid, itn_id, lun, 1);
-		count = abort_task_set(mreq, target, itn_id, 0, lun_buf, 0);
+		count = abort_task_set(mreq, target, itn_id, 0, lun_buf, 0, 0);
 		if (mreq->busy)
 			send = 0;
 
@@ -1086,6 +1088,27 @@ void target_mgmt_request(int tid, uint64_t itn_id, uint64_t req_id,
 			}
 		}
 		break;
+	case TARGET_RESET:
+		list_for_each_entry(lu, &target->device_list, device_siblings)
+			device_release(target->tid, itn_id, lu->lun, 1);
+
+		count = abort_task_set(mreq, target, itn_id, 0, lun_buf, 0, 1);
+		if (mreq->busy)
+			send = 0;
+
+		list_for_each_entry(lu, &target->device_list, device_siblings) {
+			list_for_each_entry(itn, &target->it_nexus_list, nexus_siblings) {
+				list_for_each_entry(itn_lu, &itn->it_nexus_lu_info_list,
+						    lu_info_siblings) {
+					if (itn_lu->lu->lun == lu->lun) {
+						ua_sense_add(itn_lu, ASC_POWERON_RESET);
+						break;
+					}
+				}
+			}
+		}
+
+		break;
 	default:
 		err = -EINVAL;
 		eprintf("Unknown task management %x\n", function);
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list