/* * iser_conn_disconnect() * Shutdown this iSER connection */ static void iser_conn_disconnect(idm_conn_t *ic) { iser_conn_t *iser_conn; iser_conn = (iser_conn_t *)ic->ic_transport_private; mutex_enter(&iser_conn->ic_lock); iser_conn->ic_stage = ISER_CONN_STAGE_CLOSING; mutex_exit(&iser_conn->ic_lock); /* Close the channel */ iser_channel_close(iser_conn->ic_chan); /* Free our reference held on the IDM conn handle, and set CLOSED */ mutex_enter(&iser_conn->ic_lock); idm_conn_rele(iser_conn->ic_idmc); iser_conn->ic_stage = ISER_CONN_STAGE_CLOSED; mutex_exit(&iser_conn->ic_lock); }
static void idm_conn_event_handler(void *event_ctx_opaque) { idm_conn_event_ctx_t *event_ctx = event_ctx_opaque; idm_conn_t *ic = event_ctx->iec_ic; idm_pdu_t *pdu = (idm_pdu_t *)event_ctx->iec_info; idm_pdu_event_action_t action; IDM_SM_LOG(CE_NOTE, "idm_conn_event_handler: conn %p event %s(%d)", (void *)ic, idm_ce_name[event_ctx->iec_event], event_ctx->iec_event); DTRACE_PROBE2(conn__event, idm_conn_t *, ic, idm_conn_event_ctx_t *, event_ctx); /* * Validate event */ ASSERT(event_ctx->iec_event != CE_UNDEFINED); ASSERT3U(event_ctx->iec_event, <, CE_MAX_EVENT); /* * Validate current state */ ASSERT(ic->ic_state != CS_S0_UNDEFINED); ASSERT3U(ic->ic_state, <, CS_MAX_STATE); /* * Validate PDU-related events against the current state. If a PDU * is not allowed in the current state we change the event to a * protocol error. This simplifies the state-specific event handlers. * For example the CS_S2_XPT_WAIT state only needs to handle the * CE_TX_PROTOCOL_ERROR and CE_RX_PROTOCOL_ERROR events since * no PDU's can be transmitted or received in that state. */ event_ctx->iec_pdu_forwarded = B_FALSE; if (event_ctx->iec_pdu_event_type != CT_NONE) { ASSERT(pdu != NULL); action = idm_conn_sm_validate_pdu(ic, event_ctx, pdu); switch (action) { case CA_TX_PROTOCOL_ERROR: /* * Change event and forward the PDU */ event_ctx->iec_event = CE_TX_PROTOCOL_ERROR; break; case CA_RX_PROTOCOL_ERROR: /* * Change event and forward the PDU. */ event_ctx->iec_event = CE_RX_PROTOCOL_ERROR; break; case CA_FORWARD: /* * Let the state-specific event handlers take * care of it. */ break; case CA_DROP: /* * It never even happened */ IDM_SM_LOG(CE_NOTE, "*** drop PDU %p", (void *) pdu); idm_pdu_complete(pdu, IDM_STATUS_FAIL); break; default: ASSERT(0); break; } } switch (ic->ic_state) { case CS_S1_FREE: idm_state_s1_free(ic, event_ctx); break; case CS_S2_XPT_WAIT: idm_state_s2_xpt_wait(ic, event_ctx); break; case CS_S3_XPT_UP: idm_state_s3_xpt_up(ic, event_ctx); break; case CS_S4_IN_LOGIN: idm_state_s4_in_login(ic, event_ctx); break; case CS_S5_LOGGED_IN: idm_state_s5_logged_in(ic, event_ctx); break; case CS_S6_IN_LOGOUT: idm_state_s6_in_logout(ic, event_ctx); break; case CS_S7_LOGOUT_REQ: idm_state_s7_logout_req(ic, event_ctx); break; case CS_S8_CLEANUP: idm_state_s8_cleanup(ic, event_ctx); break; case CS_S9A_REJECTED: idm_state_s9a_rejected(ic, event_ctx); break; case CS_S9B_WAIT_SND_DONE: idm_state_s9b_wait_snd_done(ic, event_ctx); break; case CS_S9_INIT_ERROR: idm_state_s9_init_error(ic, event_ctx); break; case CS_S10_IN_CLEANUP: idm_state_s10_in_cleanup(ic, event_ctx); break; case CS_S11_COMPLETE: idm_state_s11_complete(ic, event_ctx); break; case CS_S12_ENABLE_DM: idm_state_s12_enable_dm(ic, event_ctx); break; default: ASSERT(0); break; } /* * Now that we've updated the state machine, if this was * a PDU-related event take the appropriate action on the PDU * (transmit it, forward it to the clients RX callback, drop * it, etc). */ if (event_ctx->iec_pdu_event_type != CT_NONE) { switch (action) { case CA_TX_PROTOCOL_ERROR: idm_pdu_tx_protocol_error(ic, pdu); break; case CA_RX_PROTOCOL_ERROR: idm_pdu_rx_protocol_error(ic, pdu); break; case CA_FORWARD: if (!event_ctx->iec_pdu_forwarded) { if (event_ctx->iec_pdu_event_type == CT_RX_PDU) { idm_pdu_rx_forward(ic, pdu); } else { idm_pdu_tx_forward(ic, pdu); } } break; default: ASSERT(0); break; } } /* * Update outstanding PDU event count (see idm_pdu_tx for * how this is used) */ if ((event_ctx->iec_pdu_event_type == CT_TX_PDU) || (event_ctx->iec_pdu_event_type == CT_RX_PDU)) { mutex_enter(&ic->ic_state_mutex); ic->ic_pdu_events--; mutex_exit(&ic->ic_state_mutex); } idm_conn_rele(ic); kmem_free(event_ctx, sizeof (*event_ctx)); }