On Thu, 03 Sep 2009 07:40:43 +0200 Florian Haas <florian.haas@xxxxxxxxxx> 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html