Beispiel #1
0
/*
 * iser_conn_destroy()
 * Tear down an initiator or target connection.
 */
static void
iser_conn_destroy(idm_conn_t *ic)
{
    iser_conn_t	*iser_conn;
    iser_conn = (iser_conn_t *)ic->ic_transport_private;

    iser_internal_conn_destroy(iser_conn);
    ic->ic_transport_private = NULL;
}
/*
 * Handle EVENT FAILURE
 */
static ibt_cm_status_t
iser_handle_cm_event_failure(ibt_cm_event_t *evp)
{
	iser_chan_t	*chan;

	chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);

	ISER_LOG(CE_NOTE, "iser_handle_cm_event_failure: chan (0x%p): "
	    "code: %d msg: %d reason: %d", (void *)chan,
	    evp->cm_event.failed.cf_code, evp->cm_event.failed.cf_msg,
	    evp->cm_event.failed.cf_reason);

	if ((evp->cm_channel == NULL) || (chan == NULL)) {
		/* channel not established yet */
		return (IBT_CM_ACCEPT);
	}

	if ((evp->cm_event.failed.cf_code != IBT_CM_FAILURE_STALE) &&
	    (evp->cm_event.failed.cf_msg == IBT_CM_FAILURE_REQ)) {
		/*
		 * This end is active, just ignore, ibt_open_rc_channel()
		 * caller will take care of cleanup.
		 */
		return (IBT_CM_ACCEPT);
	}

	/* handle depending upon our connection state */
	mutex_enter(&chan->ic_conn->ic_lock);
	switch (chan->ic_conn->ic_stage) {
	case ISER_CONN_STAGE_UNDEFINED:
	case ISER_CONN_STAGE_CLOSED:
		/* do nothing, just drop the lock */
		mutex_exit(&chan->ic_conn->ic_lock);
		break;

	case ISER_CONN_STAGE_ALLOCATED:
		/*
		 * We blew up or were offlined during connection
		 * establishment. Teardown the iSER conn and chan
		 * handles.
		 */
		mutex_exit(&chan->ic_conn->ic_lock);
		iser_internal_conn_destroy(chan->ic_conn);
		break;

	case ISER_CONN_STAGE_IC_DISCONNECTED:
	case ISER_CONN_STAGE_IC_FREED:
	case ISER_CONN_STAGE_CLOSING:
		/* update to CLOSED, then drop the lock */
		chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
		mutex_exit(&chan->ic_conn->ic_lock);
		break;

	case ISER_CONN_STAGE_IC_CONNECTED:
	case ISER_CONN_STAGE_HELLO_SENT:
	case ISER_CONN_STAGE_HELLO_SENT_FAIL:
	case ISER_CONN_STAGE_HELLO_WAIT:
	case ISER_CONN_STAGE_HELLO_RCV:
	case ISER_CONN_STAGE_HELLO_RCV_FAIL:
	case ISER_CONN_STAGE_HELLOREPLY_SENT:
	case ISER_CONN_STAGE_HELLOREPLY_SENT_FAIL:
	case ISER_CONN_STAGE_HELLOREPLY_RCV:
	case ISER_CONN_STAGE_HELLOREPLY_RCV_FAIL:
	case ISER_CONN_STAGE_LOGGED_IN:
		/* fail the transport and move the conn to CLOSING */
		idm_conn_event(chan->ic_conn->ic_idmc, CE_TRANSPORT_FAIL,
		    IDM_STATUS_FAIL);
		chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
		mutex_exit(&chan->ic_conn->ic_lock);
		break;

	default:
		mutex_exit(&chan->ic_conn->ic_lock);
		ASSERT(0);
	}

	/* accept the event */
	return (IBT_CM_ACCEPT);
}
static ibt_cm_status_t
iser_handle_cm_conn_closed(ibt_cm_event_t *evp)
{

	iser_chan_t	*chan;

	chan = (iser_chan_t *)ibt_get_chan_private(evp->cm_channel);

	ISER_LOG(CE_NOTE, "iser_handle_cm_conn_closed: chan (0x%p) "
	    "reason (0x%x)", (void *)chan, evp->cm_event.closed);

	switch (evp->cm_event.closed) {
	case IBT_CM_CLOSED_DREP_RCVD:	/* we requested a disconnect */
	case IBT_CM_CLOSED_ALREADY:	/* duplicate close */
		/* ignore these */
		return (IBT_CM_ACCEPT);

	case IBT_CM_CLOSED_DREQ_RCVD:	/* request to close the channel */
	case IBT_CM_CLOSED_REJ_RCVD:	/* reject after conn establishment */
	case IBT_CM_CLOSED_DREQ_TIMEOUT: /* our close request timed out */
	case IBT_CM_CLOSED_DUP:		/* duplicate close request */
	case IBT_CM_CLOSED_ABORT:	/* aborted connection establishment */
	case IBT_CM_CLOSED_STALE:	/* stale / unref connection */
		/* handle these depending upon our connection state */
		mutex_enter(&chan->ic_conn->ic_lock);
		switch (chan->ic_conn->ic_stage) {
		case ISER_CONN_STAGE_UNDEFINED:
		case ISER_CONN_STAGE_CLOSED:
			/* do nothing, just drop the lock */
			mutex_exit(&chan->ic_conn->ic_lock);
			break;

		case ISER_CONN_STAGE_ALLOCATED:
			/*
			 * We blew up or were offlined during connection
			 * establishment. Teardown the iSER conn and chan
			 * handles.
			 */
			mutex_exit(&chan->ic_conn->ic_lock);
			iser_internal_conn_destroy(chan->ic_conn);
			break;

		case ISER_CONN_STAGE_IC_DISCONNECTED:
		case ISER_CONN_STAGE_IC_FREED:
		case ISER_CONN_STAGE_CLOSING:
			/* we're down, set CLOSED */
			chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSED;
			mutex_exit(&chan->ic_conn->ic_lock);
			break;

		case ISER_CONN_STAGE_IC_CONNECTED:
		case ISER_CONN_STAGE_HELLO_SENT:
		case ISER_CONN_STAGE_HELLO_SENT_FAIL:
		case ISER_CONN_STAGE_HELLO_WAIT:
		case ISER_CONN_STAGE_HELLO_RCV:
		case ISER_CONN_STAGE_HELLO_RCV_FAIL:
		case ISER_CONN_STAGE_HELLOREPLY_SENT:
		case ISER_CONN_STAGE_HELLOREPLY_SENT_FAIL:
		case ISER_CONN_STAGE_HELLOREPLY_RCV:
		case ISER_CONN_STAGE_HELLOREPLY_RCV_FAIL:
		case ISER_CONN_STAGE_LOGGED_IN:
			/* for all other stages, fail the transport */
			idm_conn_event(chan->ic_conn->ic_idmc,
			    CE_TRANSPORT_FAIL, IDM_STATUS_FAIL);
			chan->ic_conn->ic_stage = ISER_CONN_STAGE_CLOSING;
			mutex_exit(&chan->ic_conn->ic_lock);
			break;

		default:
			mutex_exit(&chan->ic_conn->ic_lock);
			ASSERT(0);

		}

		/* accept the event */
		return (IBT_CM_ACCEPT);

	default:
		/* unknown event */
		ISER_LOG(CE_NOTE, "iser_handle_cm_conn_closed: unknown closed "
		    "event: (0x%x)", evp->cm_event.closed);
		return (IBT_CM_REJECT);
	}
}