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"