Author: mav
Date: Tue Feb 21 06:10:11 2017
New Revision: 314027
URL: https://svnweb.freebsd.org/changeset/base/314027

Log:
  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.
  
  MFC after:    2 weeks

Modified:
  head/sys/cam/ctl/scsi_ctl.c

Modified: head/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- head/sys/cam/ctl/scsi_ctl.c Tue Feb 21 05:13:16 2017        (r314026)
+++ head/sys/cam/ctl/scsi_ctl.c Tue Feb 21 06:10:11 2017        (r314027)
@@ -1096,6 +1096,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"));
@@ -1122,30 +1123,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:
                /*
@@ -1424,14 +1410,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);
 
@@ -1497,40 +1478,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) {
@@ -1543,6 +1506,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.
                 */
@@ -2024,14 +1992,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.
                 */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to