svn commit: r268353 - head/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Mon Jul 7 03:10:58 UTC 2014


Author: mav
Date: Mon Jul  7 03:10:56 2014
New Revision: 268353
URL: http://svnweb.freebsd.org/changeset/base/268353

Log:
  Implement ABORT TASK SET and I_T NEXUS RESET task management functions.
  
  Use the last one to terminate active commands on iSCSI session termination.
  Previous code was aborting only commands doing some data moves.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl.h
  head/sys/cam/ctl/ctl_error.c
  head/sys/cam/ctl/ctl_frontend_iscsi.c
  head/sys/cam/ctl/ctl_io.h
  head/sys/cam/ctl/ctl_util.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl.c	Mon Jul  7 03:10:56 2014	(r268353)
@@ -407,6 +407,8 @@ static int ctl_target_reset(struct ctl_s
 static int ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io,
 			 ctl_ua_type ua_type);
 static int ctl_abort_task(union ctl_io *io);
+static int ctl_abort_task_set(union ctl_io *io);
+static int ctl_i_t_nexus_reset(union ctl_io *io);
 static void ctl_run_task(union ctl_io *io);
 #ifdef CTL_IO_DELAY
 static void ctl_datamove_timer_wakeup(void *arg);
@@ -7482,7 +7484,8 @@ ctl_report_supported_tmf(struct ctl_scsi
 	ctsio->kern_rel_offset = 0;
 
 	data = (struct scsi_report_supported_tmf_data *)ctsio->kern_data_ptr;
-	data->byte1 |= RST_ATS | RST_LURS | RST_TRS;
+	data->byte1 |= RST_ATS | RST_ATSS | RST_LURS | RST_TRS;
+	data->byte2 |= RST_ITNRS;
 
 	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
 	ctsio->be_move_done = ctl_config_move_done;
@@ -11673,6 +11676,97 @@ ctl_lun_reset(struct ctl_lun *lun, union
 }
 
 static int
+ctl_abort_tasks_lun(struct ctl_lun *lun, uint32_t targ_port, uint32_t init_id,
+    int other_sc)
+{
+	union ctl_io *xio;
+	int found;
+
+	mtx_assert(&lun->lun_lock, MA_OWNED);
+
+	/*
+	 * Run through the OOA queue and attempt to find the given I/O.
+	 * The target port, initiator ID, tag type and tag number have to
+	 * match the values that we got from the initiator.  If we have an
+	 * untagged command to abort, simply abort the first untagged command
+	 * we come to.  We only allow one untagged command at a time of course.
+	 */
+	for (xio = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); xio != NULL;
+	     xio = (union ctl_io *)TAILQ_NEXT(&xio->io_hdr, ooa_links)) {
+
+		if ((targ_port == xio->io_hdr.nexus.targ_port) &&
+		    (init_id == xio->io_hdr.nexus.initid.id)) {
+			xio->io_hdr.flags |= CTL_FLAG_ABORT;
+			found = 1;
+			if (!other_sc && !(lun->flags & CTL_LUN_PRIMARY_SC)) {
+				union ctl_ha_msg msg_info;
+
+				msg_info.hdr.nexus = xio->io_hdr.nexus;
+				msg_info.task.task_action = CTL_TASK_ABORT_TASK;
+				msg_info.task.tag_num = xio->scsiio.tag_num;
+				msg_info.task.tag_type = xio->scsiio.tag_type;
+				msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS;
+				msg_info.hdr.original_sc = NULL;
+				msg_info.hdr.serializing_sc = NULL;
+				ctl_ha_msg_send(CTL_HA_CHAN_CTL,
+				    (void *)&msg_info, sizeof(msg_info), 0);
+			}
+		}
+	}
+	return (found);
+}
+
+static int
+ctl_abort_task_set(union ctl_io *io)
+{
+	struct ctl_softc *softc = control_softc;
+	struct ctl_lun *lun;
+	uint32_t targ_lun;
+
+	/*
+	 * Look up the LUN.
+	 */
+	targ_lun = io->io_hdr.nexus.targ_mapped_lun;
+	mtx_lock(&softc->ctl_lock);
+	if ((targ_lun < CTL_MAX_LUNS) && (softc->ctl_luns[targ_lun] != NULL))
+		lun = softc->ctl_luns[targ_lun];
+	else {
+		mtx_unlock(&softc->ctl_lock);
+		return (1);
+	}
+
+	mtx_lock(&lun->lun_lock);
+	mtx_unlock(&softc->ctl_lock);
+	ctl_abort_tasks_lun(lun, io->io_hdr.nexus.targ_port,
+	    io->io_hdr.nexus.initid.id,
+	    (io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC) != 0);
+	mtx_unlock(&lun->lun_lock);
+	return (0);
+}
+
+static int
+ctl_i_t_nexus_reset(union ctl_io *io)
+{
+	struct ctl_softc *softc = control_softc;
+	struct ctl_lun *lun;
+	uint32_t initindex;
+
+	initindex = ctl_get_initindex(&io->io_hdr.nexus);
+	mtx_lock(&softc->ctl_lock);
+	STAILQ_FOREACH(lun, &softc->lun_list, links) {
+		mtx_lock(&lun->lun_lock);
+		ctl_abort_tasks_lun(lun, io->io_hdr.nexus.targ_port,
+		    io->io_hdr.nexus.initid.id,
+		    (io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC) != 0);
+		ctl_clear_mask(lun->have_ca, initindex);
+		lun->pending_sense[initindex].ua_pending |= CTL_UA_I_T_NEXUS_LOSS;
+		mtx_unlock(&lun->lun_lock);
+	}
+	mtx_unlock(&softc->ctl_lock);
+	return (0);
+}
+
+static int
 ctl_abort_task(union ctl_io *io)
 {
 	union ctl_io *xio;
@@ -11875,11 +11969,15 @@ ctl_run_task(union ctl_io *io)
 		retval = ctl_abort_task(io);
 		break;
 	case CTL_TASK_ABORT_TASK_SET:
+		retval = ctl_abort_task_set(io);
 		break;
 	case CTL_TASK_CLEAR_ACA:
 		break;
 	case CTL_TASK_CLEAR_TASK_SET:
 		break;
+	case CTL_TASK_I_T_NEXUS_RESET:
+		retval = ctl_i_t_nexus_reset(io);
+		break;
 	case CTL_TASK_LUN_RESET: {
 		struct ctl_lun *lun;
 		uint32_t targ_lun;

Modified: head/sys/cam/ctl/ctl.h
==============================================================================
--- head/sys/cam/ctl/ctl.h	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl.h	Mon Jul  7 03:10:56 2014	(r268353)
@@ -115,17 +115,18 @@ typedef enum {
 	CTL_UA_POWERON		= 0x0001,
 	CTL_UA_BUS_RESET	= 0x0002,
 	CTL_UA_TARG_RESET	= 0x0004,
-	CTL_UA_LUN_RESET	= 0x0008,
-	CTL_UA_LUN_CHANGE	= 0x0010,
-	CTL_UA_MODE_CHANGE	= 0x0020,
-	CTL_UA_LOG_CHANGE	= 0x0040,
-	CTL_UA_LVD		= 0x0080,
-	CTL_UA_SE		= 0x0100,
-	CTL_UA_RES_PREEMPT	= 0x0200,
-	CTL_UA_RES_RELEASE	= 0x0400,
-	CTL_UA_REG_PREEMPT  	= 0x0800,
-	CTL_UA_ASYM_ACC_CHANGE  = 0x1000,
-	CTL_UA_CAPACITY_CHANGED = 0x2000
+	CTL_UA_I_T_NEXUS_LOSS	= 0x0008,
+	CTL_UA_LUN_RESET	= 0x0010,
+	CTL_UA_LUN_CHANGE	= 0x0020,
+	CTL_UA_MODE_CHANGE	= 0x0030,
+	CTL_UA_LOG_CHANGE	= 0x0080,
+	CTL_UA_LVD		= 0x0100,
+	CTL_UA_SE		= 0x0200,
+	CTL_UA_RES_PREEMPT	= 0x0400,
+	CTL_UA_RES_RELEASE	= 0x0800,
+	CTL_UA_REG_PREEMPT  	= 0x1000,
+	CTL_UA_ASYM_ACC_CHANGE  = 0x2000,
+	CTL_UA_CAPACITY_CHANGED = 0x4000
 } ctl_ua_type;
 
 #ifdef	_KERNEL

Modified: head/sys/cam/ctl/ctl_error.c
==============================================================================
--- head/sys/cam/ctl/ctl_error.c	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl_error.c	Mon Jul  7 03:10:56 2014	(r268353)
@@ -401,6 +401,11 @@ ctl_build_ua(ctl_ua_type ua_type, struct
 		asc = 0x29;
 		ascq = 0x03;
 		break;
+	case CTL_UA_I_T_NEXUS_LOSS:
+		/* 29h/07h  I_T NEXUS LOSS OCCURRED */
+		asc = 0x29;
+		ascq = 0x07;
+		break;
 	case CTL_UA_LUN_RESET:
 		/* 29h/00h  POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
 		/*

Modified: head/sys/cam/ctl/ctl_frontend_iscsi.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_iscsi.c	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl_frontend_iscsi.c	Mon Jul  7 03:10:56 2014	(r268353)
@@ -627,6 +627,12 @@ cfiscsi_pdu_handle_task_request(struct i
 		io->taskio.task_action = CTL_TASK_ABORT_TASK;
 		io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag;
 		break;
+	case BHSTMR_FUNCTION_ABORT_TASK_SET:
+#if 0
+		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_ABORT_TASK_SET");
+#endif
+		io->taskio.task_action = CTL_TASK_ABORT_TASK_SET;
+		break;
 	case BHSTMR_FUNCTION_LOGICAL_UNIT_RESET:
 #if 0
 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_LOGICAL_UNIT_RESET");
@@ -1029,64 +1035,36 @@ cfiscsi_callout(void *context)
 static void
 cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
 {
-	struct cfiscsi_data_wait *cdw, *tmpcdw;
+	struct cfiscsi_data_wait *cdw;
 	union ctl_io *io;
 	int error, last;
 
-#ifdef notyet
 	io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref);
 	if (io == NULL) {
 		CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io");
 		return;
 	}
 	ctl_zero_io(io);
-	io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL;
+	io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = cs;
 	io->io_hdr.io_type = CTL_IO_TASK;
 	io->io_hdr.nexus.initid.id = cs->cs_ctl_initid;
 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
 	io->io_hdr.nexus.targ_target.id = 0;
-	io->io_hdr.nexus.targ_lun = lun;
+	io->io_hdr.nexus.targ_lun = 0;
 	io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
-	io->taskio.task_action = CTL_TASK_ABORT_TASK_SET;
+	io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET;
+	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
 	error = ctl_queue(io);
 	if (error != CTL_RETVAL_COMPLETE) {
 		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
+		refcount_release(&cs->cs_outstanding_ctl_pdus);
 		ctl_free_io(io);
 	}
-#else
-	/*
-	 * CTL doesn't currently support CTL_TASK_ABORT_TASK_SET, so instead
-	 * just iterate over tasks that are waiting for something - data - and
-	 * terminate those.
-	 */
+
 	CFISCSI_SESSION_LOCK(cs);
-	TAILQ_FOREACH_SAFE(cdw,
-	    &cs->cs_waiting_for_data_out, cdw_next, tmpcdw) {
-		io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref);
-		if (io == NULL) {
-			CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io");
-			return;
-		}
-		ctl_zero_io(io);
-		io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL;
-		io->io_hdr.io_type = CTL_IO_TASK;
-		io->io_hdr.nexus.initid.id = cs->cs_ctl_initid;
-		io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
-		io->io_hdr.nexus.targ_target.id = 0;
-		//io->io_hdr.nexus.targ_lun = lun; /* Not needed? */
-		io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
-		io->taskio.task_action = CTL_TASK_ABORT_TASK;
-		io->taskio.tag_num = cdw->cdw_initiator_task_tag;
-		error = ctl_queue(io);
-		if (error != CTL_RETVAL_COMPLETE) {
-			CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
-			ctl_free_io(io);
-			return;
-		}
-#if 0
-		CFISCSI_SESSION_DEBUG(cs, "removing csw for initiator task tag "
-		    "0x%x", cdw->cdw_initiator_task_tag);
-#endif
+	while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) {
+		TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
+		CFISCSI_SESSION_UNLOCK(cs);
 		/*
 		 * Set nonzero port status; this prevents backends from
 		 * assuming that the data transfer actually succeeded
@@ -1094,11 +1072,10 @@ cfiscsi_session_terminate_tasks(struct c
 		 */
 		cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42;
 		cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io);
-		TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
 		uma_zfree(cfiscsi_data_wait_zone, cdw);
+		CFISCSI_SESSION_LOCK(cs);
 	}
 	CFISCSI_SESSION_UNLOCK(cs);
-#endif
 
 	/*
 	 * Wait for CTL to terminate all the tasks.
@@ -1110,7 +1087,7 @@ cfiscsi_session_terminate_tasks(struct c
 			break;
 		CFISCSI_SESSION_WARN(cs, "waiting for CTL to terminate tasks, "
 		    "%d remaining", cs->cs_outstanding_ctl_pdus);
-		pause("cfiscsi_terminate", 1);
+		pause("cfiscsi_terminate", hz / 100);
 	}
 }
 
@@ -2850,14 +2827,18 @@ cfiscsi_done(union ctl_io *io)
 	KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE),
 		("invalid CTL status %#x", io->io_hdr.status));
 
-	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
-	if (request == NULL) {
+	if (io->io_hdr.io_type == CTL_IO_TASK &&
+	    io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) {
 		/*
 		 * Implicit task termination has just completed; nothing to do.
 		 */
+		cs = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
+		refcount_release(&cs->cs_outstanding_ctl_pdus);
+		ctl_free_io(io);
 		return;
 	}
 
+	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
 	cs = PDU_SESSION(request);
 	refcount_release(&cs->cs_outstanding_ctl_pdus);
 

Modified: head/sys/cam/ctl/ctl_io.h
==============================================================================
--- head/sys/cam/ctl/ctl_io.h	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl_io.h	Mon Jul  7 03:10:56 2014	(r268353)
@@ -364,6 +364,7 @@ typedef enum {
 	CTL_TASK_ABORT_TASK_SET,
 	CTL_TASK_CLEAR_ACA,
 	CTL_TASK_CLEAR_TASK_SET,
+	CTL_TASK_I_T_NEXUS_RESET,
 	CTL_TASK_LUN_RESET,
 	CTL_TASK_TARGET_RESET,
 	CTL_TASK_BUS_RESET,

Modified: head/sys/cam/ctl/ctl_util.c
==============================================================================
--- head/sys/cam/ctl/ctl_util.c	Mon Jul  7 02:47:41 2014	(r268352)
+++ head/sys/cam/ctl/ctl_util.c	Mon Jul  7 03:10:56 2014	(r268353)
@@ -84,6 +84,7 @@ static struct ctl_task_desc ctl_task_tab
 	{CTL_TASK_ABORT_TASK_SET, "Abort Task Set"},
 	{CTL_TASK_CLEAR_ACA, "Clear ACA"},
 	{CTL_TASK_CLEAR_TASK_SET, "Clear Task Set"},
+	{CTL_TASK_I_T_NEXUS_RESET, "I_T Nexus Reset"},
 	{CTL_TASK_LUN_RESET, "LUN Reset"},
 	{CTL_TASK_TARGET_RESET, "Target Reset"},
 	{CTL_TASK_BUS_RESET, "Bus Reset"},


More information about the svn-src-head mailing list