svn commit: r314727 - stable/10/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Mon Mar 6 06:19:05 UTC 2017


Author: mav
Date: Mon Mar  6 06:19:02 2017
New Revision: 314727
URL: https://svnweb.freebsd.org/changeset/base/314727

Log:
  MFC r314027: Do not blindly free completed ATIOs/INOTs on invalidation.
  
  When LUN is disabled, SIM starts returning queued ATIOs/INOTs.  But at the
  same time there can be some ATIOs/INOTs still carrying real new requests.
  If we free those, SIM may leak some resources, forever expecting for any
  response from us.  So try to be careful, separating ATIOs/INOTs carrying
  requests which still must be processed, from ATIOs/INOTs completed with
  errors which can be freed.

Modified:
  stable/10/sys/cam/ctl/scsi_ctl.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/scsi_ctl.c	Mon Mar  6 06:18:30 2017	(r314726)
+++ stable/10/sys/cam/ctl/scsi_ctl.c	Mon Mar  6 06:19:02 2017	(r314727)
@@ -1102,6 +1102,7 @@ ctlfedone(struct cam_periph *periph, uni
 	struct ccb_accept_tio *atio = NULL;
 	union ctl_io *io = NULL;
 	struct mtx *mtx;
+	cam_status status;
 
 	KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
 	    ("CCB in ctlfedone() without CAM_UNLOCKED flag"));
@@ -1128,30 +1129,15 @@ ctlfedone(struct cam_periph *periph, uni
 	mtx = cam_periph_mtx(periph);
 	mtx_lock(mtx);
 
-	/*
-	 * If the peripheral is invalid, ATIOs and immediate notify CCBs
-	 * need to be freed.  Most of the ATIOs and INOTs that come back
-	 * will be CCBs that are being returned from the SIM as a result of
-	 * our disabling the LUN.
-	 *
-	 * Other CCB types are handled in their respective cases below.
-	 */
-	if (periph->flags & CAM_PERIPH_INVALID) {
-		switch (done_ccb->ccb_h.func_code) {
-		case XPT_ACCEPT_TARGET_IO:
-		case XPT_IMMEDIATE_NOTIFY:
-		case XPT_NOTIFY_ACKNOWLEDGE:
-			ctlfe_free_ccb(periph, done_ccb);
-			goto out;
-		default:
-			break;
-		}
-
-	}
 	switch (done_ccb->ccb_h.func_code) {
 	case XPT_ACCEPT_TARGET_IO: {
 
 		atio = &done_ccb->atio;
+		status = atio->ccb_h.status & CAM_STATUS_MASK;
+		if (status != CAM_CDB_RECVD) {
+			ctlfe_free_ccb(periph, done_ccb);
+			goto out;
+		}
 
  resubmit:
 		/*
@@ -1430,14 +1416,9 @@ ctlfedone(struct cam_periph *periph, uni
 	case XPT_IMMEDIATE_NOTIFY: {
 		union ctl_io *io;
 		struct ccb_immediate_notify *inot;
-		cam_status status;
 		int send_ctl_io;
 
 		inot = &done_ccb->cin1;
-		printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x "
-		       "seq %#x\n", __func__, inot->ccb_h.status,
-		       inot->tag_id, inot->seq_id);
-
 		io = done_ccb->ccb_h.io_ptr;
 		ctl_zero_io(io);
 
@@ -1503,40 +1484,22 @@ ctlfedone(struct cam_periph *periph, uni
 				break;
 			default:
 				xpt_print(periph->path,
-					  "%s: unsupported message 0x%x\n",
-					  __func__, inot->arg);
+				    "%s: unsupported INOT message 0x%x\n",
+				    __func__, inot->arg);
 				send_ctl_io = 0;
 				break;
 			}
 			break;
+		default:
+			xpt_print(periph->path,
+			    "%s: unsupported INOT status 0x%x\n",
+			    __func__, status);
+			/* FALLTHROUGH */
 		case CAM_REQ_ABORTED:
-			/*
-			 * This request was sent back by the driver.
-			 * XXX KDM what do we do here?
-			 */
-			send_ctl_io = 0;
-			break;
 		case CAM_REQ_INVALID:
+		case CAM_DEV_NOT_THERE:
 		case CAM_PROVIDE_FAIL:
-		default:
-			/*
-			 * We should only get here if we're talking
-			 * to a talking to a SIM that is target
-			 * capable but supports the old API.  In
-			 * that case, we need to just free the CCB.
-			 * If we actually send a notify acknowledge,
-			 * it will send that back with an error as
-			 * well.
-			 */
-
-			if ((status != CAM_REQ_INVALID)
-			 && (status != CAM_PROVIDE_FAIL))
-				xpt_print(periph->path,
-					  "%s: unsupported CAM status 0x%x\n",
-					  __func__, status);
-
 			ctlfe_free_ccb(periph, done_ccb);
-
 			goto out;
 		}
 		if (send_ctl_io != 0) {
@@ -1549,6 +1512,11 @@ ctlfedone(struct cam_periph *periph, uni
 		break;
 	}
 	case XPT_NOTIFY_ACKNOWLEDGE:
+		if (periph->flags & CAM_PERIPH_INVALID) {
+			ctlfe_free_ccb(periph, done_ccb);
+			goto out;
+		}
+
 		/*
 		 * Queue this back down to the SIM as an immediate notify.
 		 */
@@ -2029,14 +1997,6 @@ ctlfe_done(union ctl_io *io)
 
 	if (io->io_hdr.io_type == CTL_IO_TASK) {
 		/*
-		 * Task management commands don't require any further
-		 * communication back to the adapter.  Requeue the CCB
-		 * to the adapter, and free the CTL I/O.
-		 */
-		xpt_print(ccb->ccb_h.path, "%s: returning task I/O "
-			  "tag %#x seq %#x\n", __func__,
-			  ccb->cin1.tag_id, ccb->cin1.seq_id);
-		/*
 		 * Send the notify acknowledge down to the SIM, to let it
 		 * know we processed the task management command.
 		 */


More information about the svn-src-all mailing list