From owner-svn-src-head@freebsd.org Mon Feb 27 14:59:01 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B0A99CEFB81; Mon, 27 Feb 2017 14:59:01 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8AE61BE5; Mon, 27 Feb 2017 14:59:01 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1REx0bB023767; Mon, 27 Feb 2017 14:59:00 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1REx0sn023764; Mon, 27 Feb 2017 14:59:00 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201702271459.v1REx0sn023764@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Mon, 27 Feb 2017 14:59:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314338 - head/sys/cam/ctl X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Feb 2017 14:59:01 -0000 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;