When new connection comes in, check whether we already have session from
the same intiator (Name+ISID). If so -- terminate the old session and let the new one take its place, as required by iSCSI RFC.
This commit is contained in:
parent
88e0a63961
commit
2c6c9e47b2
@ -1087,7 +1087,8 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
|
||||
break;
|
||||
CFISCSI_SESSION_WARN(cs, "waiting for CTL to terminate tasks, "
|
||||
"%d remaining", cs->cs_outstanding_ctl_pdus);
|
||||
pause("cfiscsi_terminate", hz / 100);
|
||||
tsleep(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus),
|
||||
0, "cfiscsi_terminate", hz / 100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1404,7 +1405,7 @@ static void
|
||||
cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
|
||||
{
|
||||
struct cfiscsi_softc *softc;
|
||||
struct cfiscsi_session *cs;
|
||||
struct cfiscsi_session *cs, *cs2;
|
||||
struct cfiscsi_target *ct;
|
||||
struct ctl_iscsi_handoff_params *cihp;
|
||||
int error;
|
||||
@ -1500,12 +1501,34 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
|
||||
cihp->initiator_isid[2], cihp->initiator_isid[3],
|
||||
cihp->initiator_isid[4], cihp->initiator_isid[5]);
|
||||
|
||||
refcount_acquire(&cs->cs_outstanding_ctl_pdus);
|
||||
restart:
|
||||
if (!cs->cs_terminating) {
|
||||
mtx_lock(&softc->lock);
|
||||
TAILQ_FOREACH(cs2, &softc->sessions, cs_next) {
|
||||
if (cs2 != cs && cs2->cs_tasks_aborted == false &&
|
||||
strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) == 0) {
|
||||
cfiscsi_session_terminate(cs2);
|
||||
mtx_unlock(&softc->lock);
|
||||
pause("cfiscsi_reinstate", 1);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&softc->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register initiator with CTL.
|
||||
*/
|
||||
cfiscsi_session_register_initiator(cs);
|
||||
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
if (cihp->socket > 0) {
|
||||
#endif
|
||||
error = icl_conn_handoff(cs->cs_conn, cihp->socket);
|
||||
if (error != 0) {
|
||||
cfiscsi_session_delete(cs);
|
||||
cfiscsi_session_terminate(cs);
|
||||
refcount_release(&cs->cs_outstanding_ctl_pdus);
|
||||
ci->status = CTL_ISCSI_ERROR;
|
||||
snprintf(ci->error_str, sizeof(ci->error_str),
|
||||
"%s: icl_conn_handoff failed with error %d",
|
||||
@ -1516,11 +1539,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register initiator with CTL.
|
||||
*/
|
||||
cfiscsi_session_register_initiator(cs);
|
||||
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
cs->cs_login_phase = false;
|
||||
|
||||
@ -1535,6 +1553,7 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
|
||||
}
|
||||
#endif
|
||||
|
||||
refcount_release(&cs->cs_outstanding_ctl_pdus);
|
||||
ci->status = CTL_ISCSI_OK;
|
||||
}
|
||||
|
||||
@ -2833,7 +2852,9 @@ cfiscsi_done(union ctl_io *io)
|
||||
* Implicit task termination has just completed; nothing to do.
|
||||
*/
|
||||
cs = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
|
||||
cs->cs_tasks_aborted = true;
|
||||
refcount_release(&cs->cs_outstanding_ctl_pdus);
|
||||
wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus));
|
||||
ctl_free_io(io);
|
||||
return;
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ struct cfiscsi_session {
|
||||
int cs_portal_group_tag;
|
||||
struct cv cs_maintenance_cv;
|
||||
bool cs_terminating;
|
||||
bool cs_tasks_aborted;
|
||||
size_t cs_max_data_segment_length;
|
||||
size_t cs_max_burst_length;
|
||||
bool cs_immediate_data;
|
||||
|
Loading…
Reference in New Issue
Block a user