/* * iser_tgt_svc_create() * Establish the CM service for inbound iSER service requests on the port * indicated by sr->sr_port. * idm_svc_req_t contains the service parameters. */ idm_status_t iser_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is) { iser_svc_t *iser_svc; int rc; iser_svc = kmem_zalloc(sizeof (iser_svc_t), KM_SLEEP); is->is_iser_svc = (void *)iser_svc; idm_refcnt_init(&iser_svc->is_refcnt, iser_svc); list_create(&iser_svc->is_sbindlist, sizeof (iser_sbind_t), offsetof(iser_sbind_t, is_list_node)); iser_svc->is_svcid = ibt_get_ip_sid(IPPROTO_TCP, sr->sr_port); /* * Register an iSER target service for the requested port * and set the iser_svc structure in the idm_svc handle. */ rc = iser_register_service(is); if (rc != DDI_SUCCESS) { ISER_LOG(CE_NOTE, "iser_tgt_svc_create: iser_register_service " "failed on port (%d): rc (0x%x)", sr->sr_port, rc); (void) ibt_release_ip_sid(iser_svc->is_svcid); list_destroy(&iser_svc->is_sbindlist); idm_refcnt_destroy(&iser_svc->is_refcnt); kmem_free(iser_svc, sizeof (iser_svc_t)); return (IDM_STATUS_FAIL); } return (IDM_STATUS_SUCCESS); }
iscsit_sess_t * iscsit_sess_create(iscsit_tgt_t *tgt, iscsit_conn_t *ict, uint32_t cmdsn, uint8_t *isid, uint16_t tag, char *initiator_name, char *target_name, uint8_t *error_class, uint8_t *error_detail) { iscsit_sess_t *result; *error_class = ISCSI_STATUS_CLASS_SUCCESS; /* * Even if this session create "fails" for some reason we still need * to return a valid session pointer so that we can send the failed * login response. */ result = kmem_zalloc(sizeof (*result), KM_SLEEP); /* Allocate TSIH */ if ((result->ist_tsih = iscsit_tsih_alloc()) == ISCSI_UNSPEC_TSIH) { /* Out of TSIH's */ *error_class = ISCSI_STATUS_CLASS_TARGET_ERR; *error_detail = ISCSI_LOGIN_STATUS_NO_RESOURCES; /* * Continue initializing this session so we can use it * to complete the login process. */ } idm_sm_audit_init(&result->ist_state_audit); mutex_init(&result->ist_sn_mutex, NULL, MUTEX_DEFAULT, NULL); mutex_init(&result->ist_mutex, NULL, MUTEX_DEFAULT, NULL); cv_init(&result->ist_cv, NULL, CV_DEFAULT, NULL); list_create(&result->ist_events, sizeof (sess_event_ctx_t), offsetof(sess_event_ctx_t, se_ctx_node)); list_create(&result->ist_conn_list, sizeof (iscsit_conn_t), offsetof(iscsit_conn_t, ict_sess_ln)); avl_create(&result->ist_task_list, iscsit_task_itt_compare, sizeof (iscsit_task_t), offsetof(iscsit_task_t, it_sess_ln)); result->ist_rxpdu_queue = kmem_zalloc(sizeof (iscsit_cbuf_t), KM_SLEEP); result->ist_state = SS_Q1_FREE; result->ist_last_state = SS_Q1_FREE; bcopy(isid, result->ist_isid, ISCSI_ISID_LEN); result->ist_tpgt_tag = tag; result->ist_tgt = tgt; /* * cmdsn/expcmdsn do not advance during login phase. */ result->ist_expcmdsn = cmdsn; result->ist_maxcmdsn = result->ist_expcmdsn + 1; result->ist_initiator_name = kmem_alloc(strlen(initiator_name) + 1, KM_SLEEP); (void) strcpy(result->ist_initiator_name, initiator_name); if (target_name) { /* A discovery session might not have a target name */ result->ist_target_name = kmem_alloc(strlen(target_name) + 1, KM_SLEEP); (void) strcpy(result->ist_target_name, target_name); } idm_refcnt_init(&result->ist_refcnt, result); /* Login code will fill in ist_stmf_sess if necessary */ if (*error_class == ISCSI_STATUS_CLASS_SUCCESS) { /* * Make sure the service is still enabled and if so get a global * hold to represent this session. */ mutex_enter(&iscsit_global.global_state_mutex); if (iscsit_global.global_svc_state == ISE_ENABLED) { iscsit_global_hold(); mutex_exit(&iscsit_global.global_state_mutex); /* * Kick session state machine (also binds connection * to session) */ iscsit_sess_sm_event(result, SE_CONN_IN_LOGIN, ict); *error_class = ISCSI_STATUS_CLASS_SUCCESS; } else { mutex_exit(&iscsit_global.global_state_mutex); *error_class = ISCSI_STATUS_CLASS_TARGET_ERR; *error_detail = ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE; } } /* * As noted above we must return a session pointer even if something * failed. The resources will get freed later. */ return (result); }