Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Feb 2017 14:59:00 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314338 - head/sys/cam/ctl
Message-ID:  <201702271459.v1REx0sn023764@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Feb 27 14:59:00 2017
New Revision: 314338
URL: https://svnweb.freebsd.org/changeset/base/314338

Log:
  Polish handling of different reset flavours.
  
  The biggest change is that ctl_remove_initiator() now generates I_T NEXUS
  LOSS event, cleaning part of LUs state related to the initiator.
  
  MFC after:	2 weeks

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_private.h
  head/sys/cam/ctl/ctl_tpc.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Mon Feb 27 14:38:17 2017	(r314337)
+++ head/sys/cam/ctl/ctl.c	Mon Feb 27 14:59:00 2017	(r314338)
@@ -478,15 +478,15 @@ static int ctl_scsiio_precheck(struct ct
 			       struct ctl_scsiio *ctsio);
 static int ctl_scsiio(struct ctl_scsiio *ctsio);
 
-static int ctl_bus_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
-static int ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
-			    ctl_ua_type ua_type);
-static int ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io,
+static int ctl_target_reset(union ctl_io *io);
+static void ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx,
 			 ctl_ua_type ua_type);
-static int ctl_lun_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
+static int ctl_lun_reset(union ctl_io *io);
 static int ctl_abort_task(union ctl_io *io);
 static int ctl_abort_task_set(union ctl_io *io);
 static int ctl_query_task(union ctl_io *io, int task_set);
+static void ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
+			      ctl_ua_type ua_type);
 static int ctl_i_t_nexus_reset(union ctl_io *io);
 static int ctl_query_async_event(union ctl_io *io);
 static void ctl_run_task(union ctl_io *io);
@@ -1288,6 +1288,9 @@ ctl_isc_iid_sync(struct ctl_softc *softc
 		return;
 	}
 	iid = msg->hdr.nexus.initid;
+	if (port->wwpn_iid[iid].in_use != 0 &&
+	    msg->iid.in_use == 0)
+		ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
 	port->wwpn_iid[iid].in_use = msg->iid.in_use;
 	port->wwpn_iid[iid].wwpn = msg->iid.wwpn;
 	free(port->wwpn_iid[iid].name, M_CTL);
@@ -2027,6 +2030,7 @@ int
 ctl_remove_initiator(struct ctl_port *port, int iid)
 {
 	struct ctl_softc *softc = port->ctl_softc;
+	int last;
 
 	mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
 
@@ -2037,9 +2041,11 @@ ctl_remove_initiator(struct ctl_port *po
 	}
 
 	mtx_lock(&softc->ctl_lock);
-	port->wwpn_iid[iid].in_use--;
+	last = (--port->wwpn_iid[iid].in_use == 0);
 	port->wwpn_iid[iid].last_use = time_uptime;
 	mtx_unlock(&softc->ctl_lock);
+	if (last)
+		ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
 	ctl_isc_announce_iid(port, iid);
 
 	return (0);
@@ -2144,11 +2150,6 @@ ctl_add_initiator(struct ctl_port *port,
 		    __func__, port->targ_port, iid, wwpn, name,
 		    (uintmax_t)port->wwpn_iid[iid].wwpn,
 		    port->wwpn_iid[iid].name);
-
-		/*
-		 * XXX KDM clear pending_sense and pending_ua on each LUN
-		 * for this initiator.
-		 */
 	}
 take:
 	free(port->wwpn_iid[iid].name, M_CTL);
@@ -11603,50 +11604,42 @@ bailout:
 	return (retval);
 }
 
-/*
- * Since we only implement one target right now, a bus reset simply resets
- * our single target.
- */
 static int
-ctl_bus_reset(struct ctl_softc *softc, union ctl_io *io)
-{
-	return(ctl_target_reset(softc, io, CTL_UA_BUS_RESET));
-}
-
-static int
-ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
-		 ctl_ua_type ua_type)
+ctl_target_reset(union ctl_io *io)
 {
+	struct ctl_softc *softc = CTL_SOFTC(io);
 	struct ctl_port *port = CTL_PORT(io);
 	struct ctl_lun *lun;
-	int retval;
+	uint32_t initidx;
+	ctl_ua_type ua_type;
 
 	if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
 		union ctl_ha_msg msg_info;
 
 		msg_info.hdr.nexus = io->io_hdr.nexus;
-		if (ua_type==CTL_UA_TARG_RESET)
-			msg_info.task.task_action = CTL_TASK_TARGET_RESET;
-		else
-			msg_info.task.task_action = CTL_TASK_BUS_RESET;
+		msg_info.task.task_action = io->taskio.task_action;
 		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, &msg_info,
 		    sizeof(msg_info.task), M_WAITOK);
 	}
-	retval = 0;
 
+	initidx = ctl_get_initindex(&io->io_hdr.nexus);
+	if (io->taskio.task_action == CTL_TASK_TARGET_RESET)
+		ua_type = CTL_UA_TARG_RESET;
+	else
+		ua_type = CTL_UA_BUS_RESET;
 	mtx_lock(&softc->ctl_lock);
 	STAILQ_FOREACH(lun, &softc->lun_list, links) {
 		if (port != NULL &&
 		    ctl_lun_map_to_port(port, lun->lun) == UINT32_MAX)
 			continue;
-		retval += ctl_do_lun_reset(lun, io, ua_type);
+		ctl_do_lun_reset(lun, initidx, ua_type);
 	}
 	mtx_unlock(&softc->ctl_lock);
 	io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
-	return (retval);
+	return (0);
 }
 
 /*
@@ -11670,66 +11663,51 @@ ctl_target_reset(struct ctl_softc *softc
  *
  * XXX KDM for now, we're setting unit attention for all initiators.
  */
-static int
-ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
+static void
+ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua_type)
 {
 	union ctl_io *xio;
-#if 0
-	uint32_t initidx;
-#endif
 	int i;
 
 	mtx_lock(&lun->lun_lock);
-	/*
-	 * Run through the OOA queue and abort each I/O.
-	 */
+	/* Abort tasks. */
 	for (xio = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); xio != NULL;
 	     xio = (union ctl_io *)TAILQ_NEXT(&xio->io_hdr, ooa_links)) {
 		xio->io_hdr.flags |= CTL_FLAG_ABORT | CTL_FLAG_ABORT_STATUS;
 	}
-
-	/*
-	 * This version sets unit attention for every
-	 */
-#if 0
-	initidx = ctl_get_initindex(&io->io_hdr.nexus);
-	ctl_est_ua_all(lun, initidx, ua_type);
-#else
-	ctl_est_ua_all(lun, -1, ua_type);
-#endif
-
-	/*
-	 * A reset (any kind, really) clears reservations established with
-	 * RESERVE/RELEASE.  It does not clear reservations established
-	 * with PERSISTENT RESERVE OUT, but we don't support that at the
-	 * moment anyway.  See SPC-2, section 5.6.  SPC-3 doesn't address
-	 * reservations made with the RESERVE/RELEASE commands, because
-	 * those commands are obsolete in SPC-3.
-	 */
-	lun->flags &= ~CTL_LUN_RESERVED;
-
+	/* Clear CA. */
 	for (i = 0; i < CTL_MAX_PORTS; i++) {
 		free(lun->pending_sense[i], M_CTL);
 		lun->pending_sense[i] = NULL;
 	}
-	lun->prevent_count = 0;
+	/* Clear reservation. */
+	lun->flags &= ~CTL_LUN_RESERVED;
+	/* Clear prevent media removal. */
 	if (lun->prevent) {
 		for (i = 0; i < CTL_MAX_INITIATORS; i++)
 			ctl_clear_mask(lun->prevent, i);
+		lun->prevent_count = 0;
 	}
+	/* Clear TPC status */
+	ctl_tpc_lun_clear(lun, -1);
+	/* Establish UA. */
+#if 0
+	ctl_est_ua_all(lun, initidx, ua_type);
+#else
+	ctl_est_ua_all(lun, -1, ua_type);
+#endif
 	mtx_unlock(&lun->lun_lock);
-
-	return (0);
 }
 
 static int
-ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
+ctl_lun_reset(union ctl_io *io)
 {
+	struct ctl_softc *softc = CTL_SOFTC(io);
 	struct ctl_lun *lun;
-	uint32_t targ_lun;
-	int retval;
+	uint32_t targ_lun, initidx;
 
 	targ_lun = io->io_hdr.nexus.targ_mapped_lun;
+	initidx = ctl_get_initindex(&io->io_hdr.nexus);
 	mtx_lock(&softc->ctl_lock);
 	if (targ_lun >= CTL_MAX_LUNS ||
 	    (lun = softc->ctl_luns[targ_lun]) == NULL) {
@@ -11737,7 +11715,7 @@ ctl_lun_reset(struct ctl_softc *softc, u
 		io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
 		return (1);
 	}
-	retval = ctl_do_lun_reset(lun, io, CTL_UA_LUN_RESET);
+	ctl_do_lun_reset(lun, initidx, CTL_UA_LUN_RESET);
 	mtx_unlock(&softc->ctl_lock);
 	io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
 
@@ -11752,7 +11730,7 @@ ctl_lun_reset(struct ctl_softc *softc, u
 		ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
 		    sizeof(msg_info.task), M_WAITOK);
 	}
-	return (retval);
+	return (0);
 }
 
 static void
@@ -11832,12 +11810,46 @@ ctl_abort_task_set(union ctl_io *io)
 	return (0);
 }
 
+static void
+ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
+    ctl_ua_type ua_type)
+{
+	struct ctl_lun *lun;
+	struct scsi_sense_data *ps;
+	uint32_t p, i;
+
+	p = initidx / CTL_MAX_INIT_PER_PORT;
+	i = initidx % CTL_MAX_INIT_PER_PORT;
+	mtx_lock(&softc->ctl_lock);
+	STAILQ_FOREACH(lun, &softc->lun_list, links) {
+		mtx_lock(&lun->lun_lock);
+		/* Abort tasks. */
+		ctl_abort_tasks_lun(lun, p, i, 1);
+		/* Clear CA. */
+		ps = lun->pending_sense[p];
+		if (ps != NULL)
+			ps[i].error_code = 0;
+		/* Clear reservation. */
+		if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
+			lun->flags &= ~CTL_LUN_RESERVED;
+		/* Clear prevent media removal. */
+		if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
+			ctl_clear_mask(lun->prevent, initidx);
+			lun->prevent_count--;
+		}
+		/* Clear TPC status */
+		ctl_tpc_lun_clear(lun, initidx);
+		/* Establish UA. */
+		ctl_est_ua(lun, initidx, ua_type);
+		mtx_unlock(&lun->lun_lock);
+	}
+	mtx_unlock(&softc->ctl_lock);
+}
+
 static int
 ctl_i_t_nexus_reset(union ctl_io *io)
 {
 	struct ctl_softc *softc = CTL_SOFTC(io);
-	struct ctl_lun *lun;
-	struct scsi_sense_data *ps;
 	uint32_t initidx;
 
 	if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
@@ -11853,24 +11865,7 @@ ctl_i_t_nexus_reset(union ctl_io *io)
 	}
 
 	initidx = 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, 1);
-		ps = lun->pending_sense[initidx / CTL_MAX_INIT_PER_PORT];
-		if (ps != NULL)
-			ps[initidx % CTL_MAX_INIT_PER_PORT].error_code = 0;
-		if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
-			lun->flags &= ~CTL_LUN_RESERVED;
-		if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
-			ctl_clear_mask(lun->prevent, initidx);
-			lun->prevent_count--;
-		}
-		ctl_est_ua(lun, initidx, CTL_UA_I_T_NEXUS_LOSS);
-		mtx_unlock(&lun->lun_lock);
-	}
-	mtx_unlock(&softc->ctl_lock);
+	ctl_i_t_nexus_loss(softc, initidx, CTL_UA_I_T_NEXUS_LOSS);
 	io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
 	return (0);
 }
@@ -12079,7 +12074,6 @@ ctl_query_async_event(union ctl_io *io)
 static void
 ctl_run_task(union ctl_io *io)
 {
-	struct ctl_softc *softc = CTL_SOFTC(io);
 	int retval = 1;
 
 	CTL_DEBUG_PRINT(("ctl_run_task\n"));
@@ -12101,13 +12095,11 @@ ctl_run_task(union ctl_io *io)
 		retval = ctl_i_t_nexus_reset(io);
 		break;
 	case CTL_TASK_LUN_RESET:
-		retval = ctl_lun_reset(softc, io);
+		retval = ctl_lun_reset(io);
 		break;
 	case CTL_TASK_TARGET_RESET:
-		retval = ctl_target_reset(softc, io, CTL_UA_TARG_RESET);
-		break;
 	case CTL_TASK_BUS_RESET:
-		retval = ctl_bus_reset(softc, io);
+		retval = ctl_target_reset(io);
 		break;
 	case CTL_TASK_PORT_LOGIN:
 		break;

Modified: head/sys/cam/ctl/ctl_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Mon Feb 27 14:38:17 2017	(r314337)
+++ head/sys/cam/ctl/ctl_private.h	Mon Feb 27 14:59:00 2017	(r314338)
@@ -528,6 +528,7 @@ int ctl_get_lba_status(struct ctl_scsiio
 void ctl_tpc_init(struct ctl_softc *softc);
 void ctl_tpc_shutdown(struct ctl_softc *softc);
 void ctl_tpc_lun_init(struct ctl_lun *lun);
+void ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx);
 void ctl_tpc_lun_shutdown(struct ctl_lun *lun);
 int ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len);
 int ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio);

Modified: head/sys/cam/ctl/ctl_tpc.c
==============================================================================
--- head/sys/cam/ctl/ctl_tpc.c	Mon Feb 27 14:38:17 2017	(r314337)
+++ head/sys/cam/ctl/ctl_tpc.c	Mon Feb 27 14:59:00 2017	(r314338)
@@ -222,6 +222,21 @@ ctl_tpc_lun_init(struct ctl_lun *lun)
 }
 
 void
+ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx)
+{
+	struct tpc_list *list, *tlist;
+
+	TAILQ_FOREACH_SAFE(list, &lun->tpc_lists, links, tlist) {
+		if (initidx != -1 && list->init_idx != initidx)
+			continue;
+		if (!list->completed)
+			continue;
+		TAILQ_REMOVE(&lun->tpc_lists, list, links);
+		free(list, M_CTL);
+	}
+}
+
+void
 ctl_tpc_lun_shutdown(struct ctl_lun *lun)
 {
 	struct ctl_softc *softc = lun->ctl_softc;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702271459.v1REx0sn023764>