diff options
author | mav <mav@FreeBSD.org> | 2014-12-05 07:24:17 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2014-12-05 07:24:17 +0000 |
commit | 0d78a1c549aca0c9e0ee3f559772568404b3f985 (patch) | |
tree | 4f04f3bca3c909bfe403e25f15845ced1f9c83b9 /sys/cam | |
parent | cc2f0f4af54e23d5cd1b038f9967f372ff24d709 (diff) | |
download | FreeBSD-src-0d78a1c549aca0c9e0ee3f559772568404b3f985.zip FreeBSD-src-0d78a1c549aca0c9e0ee3f559772568404b3f985.tar.gz |
MFC r274795:
Close race between cfiscsi_offline() and new connection arrival.
Incoming connection should be either rejected or accepted and terminated.
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl_frontend_iscsi.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index ef944e2..6308825 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -1064,6 +1064,8 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) union ctl_io *io; int error, last, wait; + if (cs->cs_target == NULL) + return; /* No target yet, so nothing to do. */ io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); if (io == NULL) { CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io"); @@ -1247,11 +1249,7 @@ cfiscsi_session_new(struct cfiscsi_softc *softc) } mtx_lock(&softc->lock); - cs->cs_id = softc->last_session_id + 1; - softc->last_session_id++; - mtx_unlock(&softc->lock); - - mtx_lock(&softc->lock); + cs->cs_id = ++softc->last_session_id; TAILQ_INSERT_TAIL(&softc->sessions, cs, cs_next); mtx_unlock(&softc->lock); @@ -1429,14 +1427,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci) return; } - if (ct->ct_online == 0) { - ci->status = CTL_ISCSI_ERROR; - snprintf(ci->error_str, sizeof(ci->error_str), - "%s: port offline", __func__); - cfiscsi_target_release(ct); - return; - } - #ifdef ICL_KERNEL_PROXY if (cihp->socket > 0 && cihp->connection_id > 0) { snprintf(ci->error_str, sizeof(ci->error_str), @@ -1448,7 +1438,7 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci) if (cihp->socket == 0) { mtx_lock(&cfiscsi_softc.lock); TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) { - if (cs->cs_id == cihp->socket) + if (cs->cs_id == cihp->connection_id) break; } if (cs == NULL) { @@ -1473,7 +1463,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci) #ifdef ICL_KERNEL_PROXY } #endif - cs->cs_target = ct; /* * First PDU of Full Feature phase has the same CmdSN as the last @@ -1505,6 +1494,19 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci) cihp->initiator_isid[2], cihp->initiator_isid[3], cihp->initiator_isid[4], cihp->initiator_isid[5]); + mtx_lock(&softc->lock); + if (ct->ct_online == 0) { + mtx_unlock(&softc->lock); + cfiscsi_session_terminate(cs); + cfiscsi_target_release(ct); + ci->status = CTL_ISCSI_ERROR; + snprintf(ci->error_str, sizeof(ci->error_str), + "%s: port offline", __func__); + return; + } + cs->cs_target = ct; + mtx_unlock(&softc->lock); + refcount_acquire(&cs->cs_outstanding_ctl_pdus); restart: if (!cs->cs_terminating) { |