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
This commit is contained in:
parent
3cfeca84b4
commit
9ff948d05f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=314338
@ -478,15 +478,15 @@ static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc,
|
||||
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, union ctl_ha_msg *msg, int len)
|
||||
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 *port, int iid)
|
||||
}
|
||||
|
||||
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, int iid, uint64_t wwpn, char *name)
|
||||
__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 @@ ctl_scsiio(struct ctl_scsiio *ctsio)
|
||||
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, union ctl_io *io,
|
||||
*
|
||||
* 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, union ctl_io *io)
|
||||
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, union ctl_io *io)
|
||||
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;
|
||||
|
@ -528,6 +528,7 @@ int ctl_get_lba_status(struct ctl_scsiio *ctsio);
|
||||
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);
|
||||
|
@ -221,6 +221,21 @@ ctl_tpc_lun_init(struct ctl_lun *lun)
|
||||
TAILQ_INIT(&lun->tpc_lists);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user