/***********************************************************************//** * @brief This routine gets MDS handle for PLMA. * * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. ***************************************************************************/ uint32_t plma_mds_get_handle() { NCSADA_INFO arg; uint32_t rc; PLMA_CB *plma_cb = plma_ctrlblk; TRACE_ENTER(); memset(&arg, 0, sizeof(NCSADA_INFO)); arg.req = NCSADA_GET_HDLS; rc = ncsada_api(&arg); if (rc != NCSCC_RC_SUCCESS) { return rc; } plma_cb->mds_hdl = arg.info.adest_get_hdls.o_mds_pwe1_hdl; plma_cb->mdest_id = arg.info.adest_get_hdls.o_adest; TRACE_5("PLM agent handle got : %d", plma_cb->mds_hdl); TRACE_5("PLM agent mdest ID got : %" PRIu64, plma_cb->mdest_id); TRACE_LEAVE(); return rc; }
/***********************************************************************//** * @brief PLMA is informed when MDS events occur that he has * subscribed to * * @param[in] svc_evt - MDS Svc evt info. * * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. ***************************************************************************/ static uint32_t plma_mds_svc_evt(MDS_CALLBACK_SVC_EVENT_INFO *svc_evt) { uint32_t rc = NCSCC_RC_SUCCESS; PLMA_CB *plma_cb = plma_ctrlblk; TRACE_ENTER(); if (svc_evt->i_svc_id != NCSMDS_SVC_ID_PLMS) { return NCSCC_RC_SUCCESS; } switch(svc_evt->i_change) { case NCSMDS_RED_UP: break; case NCSMDS_NEW_ACTIVE: TRACE_5("Received NCSMDS_NEW_ACTIVE for PLMS"); case NCSMDS_UP: TRACE_5("Received MDSUP EVT for PLMS"); m_NCS_LOCK(&plma_cb->cb_lock, NCS_LOCK_WRITE); plma_cb->plms_mdest_id = svc_evt->i_dest; plma_cb->plms_svc_up = true; if (plma_cb->plms_sync_awaited == true) { m_NCS_SEL_OBJ_IND(plma_cb->sel_obj); } m_NCS_UNLOCK(&plma_cb->cb_lock, NCS_LOCK_WRITE); break; case NCSMDS_NO_ACTIVE: TRACE_5("Received NCSMDS_NO_ACTIVE for PLMS"); case NCSMDS_DOWN: TRACE_5("Received MDSDOWN EVT for PLMS"); plma_cb->plms_mdest_id = 0; plma_cb->plms_svc_up = false; break; default: TRACE_5("Received unknown event"); break; } TRACE_LEAVE(); return rc; }
void immd_db_save_fevs(IMMD_CB *cb, IMMSV_FEVS *fevs_msg) { uns16 nrof_msgs = 1; IMMD_SAVED_FEVS_MSG *prior = NULL; IMMD_SAVED_FEVS_MSG *new_msg = calloc(1, sizeof(IMMD_SAVED_FEVS_MSG)); TRACE_ENTER(); assert(new_msg); /*new_msg->fevsMsg = *fevs_msg; */ new_msg->fevsMsg.sender_count = fevs_msg->sender_count; new_msg->fevsMsg.reply_dest = fevs_msg->reply_dest; new_msg->fevsMsg.client_hdl = fevs_msg->client_hdl; new_msg->fevsMsg.msg.size = fevs_msg->msg.size; new_msg->fevsMsg.msg.buf = fevs_msg->msg.buf; fevs_msg->msg.buf = NULL; /* steal the message */ fevs_msg->msg.size = 0; prior = cb->saved_msgs; if (prior) { while (prior->next) { ++nrof_msgs; prior = prior->next; } ++nrof_msgs; TRACE_5("%u'th message added. Message no %llu", nrof_msgs, new_msg->fevsMsg.sender_count); prior->next = new_msg; if (nrof_msgs > IMMD_MBCSV_MAX_MSG_CNT) { /* Discard oldest message */ prior = cb->saved_msgs; cb->saved_msgs = cb->saved_msgs->next; TRACE_5("Message no %llu discarded", prior->fevsMsg.sender_count); free(prior->fevsMsg.msg.buf); prior->fevsMsg.msg.buf = NULL; prior->fevsMsg.msg.size = 0; free(prior); } } else { /* first time */ TRACE_5("First message no %llu", new_msg->fevsMsg.sender_count); cb->saved_msgs = new_msg; } TRACE_LEAVE(); }
void immd_db_purge_fevs(IMMD_CB *cb) { TRACE_ENTER(); while (cb->saved_msgs) { IMMD_SAVED_FEVS_MSG *old = cb->saved_msgs; cb->saved_msgs = cb->saved_msgs->next; TRACE_5("Message no %llu discarded", old->fevsMsg.sender_count); free(old->fevsMsg.msg.buf); old->fevsMsg.msg.buf = NULL; old->fevsMsg.msg.size = 0; free(old); } TRACE_LEAVE(); }
/****************************************************************************\ PROCEDURE NAME : immd_saf_csi_set_cb DESCRIPTION : This is a SAF callback function which will be called when there is any change in the HA state. ARGUMENTS : invocation - This parameter designated a particular invocation of this callback function. The invoke process return invocation when it responds to the Avilability Management FrameWork using the saAmfResponse() function. compName - A pointer to the name of the component whose readiness stae the Availability Management Framework is setting. haState - The new HA state to be assumeb by the component service instance identified by csiName. csiDescriptor - RETURNS : Nothing. \*****************************************************************************/ static void immd_saf_csi_set_cb(SaInvocationT invocation, const SaNameT *compName, SaAmfHAStateT new_haState, SaAmfCSIDescriptorT csiDescriptor) { SaAisErrorT error = SA_AIS_OK; SaAmfHAStateT prev_ha_state; bool role_change = true; uint32_t rc = NCSCC_RC_SUCCESS; IMMD_CB *cb = immd_cb; TRACE_ENTER(); prev_ha_state = cb->ha_state; /* Invoke the appropriate state handler routine */ switch (new_haState) { case SA_AMF_HA_ACTIVE: error = amf_active_state_handler(cb, invocation); break; case SA_AMF_HA_STANDBY: error = amf_standby_state_handler(cb, invocation); break; case SA_AMF_HA_QUIESCED: /* switch over */ error = amf_quiesced_state_handler(cb, invocation); break; case SA_AMF_HA_QUIESCING: /* shut down */ error = amf_quiescing_state_handler(cb, invocation); break; default: LOG_WA("invalid state: %d ", new_haState); error = SA_AIS_ERR_FAILED_OPERATION; break; } if (error != SA_AIS_OK) goto response; if (new_haState == SA_AMF_HA_QUIESCED) { /*Note: should we not change state in cb->ha_state here. This is done in immd_mds_quiesced_ack_process */ goto done; } /* Update control block */ cb->ha_state = new_haState; TRACE_5("New-state: %s, prev-state: %s", ha_state_name(new_haState), ha_state_name(prev_ha_state)); /* Handle active to active role change. */ if (prev_ha_state == new_haState) { TRACE_5("No role change!"); /* bug? */ role_change = false; } if (role_change) { if ((rc = immd_mds_change_role(cb)) != NCSCC_RC_SUCCESS) { LOG_WA("immd_mds_change_role FAILED"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } TRACE_5("Inform MBCSV of HA state change to %s", (new_haState == SA_AMF_HA_ACTIVE) ? "ACTIVE" : "STANDBY"); if (immd_mbcsv_chgrole(cb) != NCSCC_RC_SUCCESS) { LOG_WA("immd_mbcsv_chgrole FAILED"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } if (new_haState == SA_AMF_HA_ACTIVE) { /* Change of role to active => We may need to elect new coord */ if(immd_cb->m2PbeCanLoad) { LOG_IN("Electing coord in immd_saf_csi_set_cb() to ACTIVE"); immd_proc_elect_coord(cb, true); } immd_db_purge_fevs(cb); } } response: saAmfResponse(cb->amf_hdl, invocation, error); done: TRACE_LEAVE(); }
/**************************************************************************** * Name : plms_amf_CSI_set_callback * * Description : AMF callback function called * when there is any change in the HA state. * * Arguments : invocation - This parameter designated a particular * invocation of this callback function. The * invoke process return invocation when it * responds to the Avilability Management * FrameWork using the saAmfResponse() * function. * compName - A pointer to the name of the component * whose readiness stae the Availability * Management Framework is setting. * haState - The new HA state to be assumeb by the * component service instance identified by * csiName. * csiDescriptor - This will indicate whether or not the * component service instance for * ativeCompName went through quiescing. * * Return Values : None. * * Notes : None. *****************************************************************************/ void plms_amf_CSI_set_callback(SaInvocationT invocation, const SaNameT *compName, SaAmfHAStateT new_haState, SaAmfCSIDescriptorT csiDescriptor) { PLMS_CB *cb = plms_cb; SaAisErrorT error = SA_AIS_OK; SaAmfHAStateT prev_haState; bool role_change = true; uint32_t rc = NCSCC_RC_SUCCESS; TRACE_ENTER(); m_NCS_LOCK(&cb->cb_lock,NCS_LOCK_WRITE); prev_haState = cb->ha_state; /* Invoke the appropriate state handler routine */ switch (new_haState) { case SA_AMF_HA_ACTIVE: cb->mds_role = V_DEST_RL_ACTIVE; TRACE("MY HA ROLE : AMF ACTIVE\n"); if (prev_haState == SA_AMF_HA_QUIESCED) { plms_proc_quiesced_active_role_change(); } else if (prev_haState == SA_AMF_HA_STANDBY) { plms_proc_standby_active_role_change(); } if(cb->hpi_cfg.hpi_support){ if (cb->hpi_intf_up == false) { TRACE("Got Active role, spawning HSM & HRB"); rc = plms_hsm_hrb_init(); if(NCSCC_RC_FAILURE == rc) { LOG_ER("hsm & hrb initialization failed"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } cb->hpi_intf_up = true; } if (prev_haState == SA_AMF_HA_STANDBY) { /* Build entity_path_to_entity mapping tree */ rc = plms_build_epath_to_entity_map_tree(); if( NCSCC_RC_SUCCESS != rc ){ LOG_ER("Failed to build entity_path_to_entity mapping tree"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } } } if( cb->hpi_intf_up ) { TRACE("PLMS sending Active role to HSM"); pthread_mutex_lock(&hsm_ha_state.mutex); hsm_ha_state.state = V_DEST_RL_ACTIVE; pthread_cond_signal(&hsm_ha_state.cond); pthread_mutex_unlock(&hsm_ha_state.mutex); TRACE("PLMS sending Active role to HRB"); pthread_mutex_lock(&hrb_ha_state.mutex); hrb_ha_state.state = SA_AMF_HA_ACTIVE; pthread_cond_signal(&hrb_ha_state.cond); pthread_mutex_unlock(&hrb_ha_state.mutex); } /* PLMC initialize */ if(!cb->hpi_cfg.hpi_support && !cb->plmc_initialized){ TRACE("Initializing PLMC"); rc = plmc_initialize(plms_plmc_connect_cbk, plms_plmc_udp_cbk, plms_plmc_error_cbk); if (rc){ LOG_ER("PLMC initialize failed."); rc = NCSCC_RC_FAILURE; goto response; } TRACE("PLMC initialize success."); cb->plmc_initialized = true; } cb->mds_role = V_DEST_RL_ACTIVE; break; case SA_AMF_HA_STANDBY: cb->mds_role = V_DEST_RL_STANDBY; LOG_IN("MY HA ROLE : AMF STANDBY\n"); TRACE("Send signal to HSM indicating standby state"); pthread_mutex_lock(&hsm_ha_state.mutex); hsm_ha_state.state = SA_AMF_HA_STANDBY; pthread_mutex_unlock(&hsm_ha_state.mutex); TRACE("Send signal to HRB indicating standby state"); pthread_mutex_lock(&hrb_ha_state.mutex); hrb_ha_state.state = SA_AMF_HA_STANDBY; pthread_mutex_unlock(&hrb_ha_state.mutex); SaUint32T (* hsm_func_ptr)() = NULL; if(cb->hpi_cfg.hpi_support){ /* Get the hsm Init func ptr */ hsm_func_ptr = dlsym(cb->hpi_intf_hdl, "plms_hsm_session_close"); if ( NULL == hsm_func_ptr ) { LOG_ER("dlsym() failed to get the hsm_func_ptr,error %s", dlerror()); goto response; } /* Initialize HSM */ rc = (* hsm_func_ptr)(); if ( NCSCC_RC_SUCCESS != rc ) { LOG_ER("plms_session_close failed"); goto response; } } /* PLMC finalize */ if(cb->plmc_initialized){ rc = plmc_destroy(); if (rc){ LOG_ER("PLMC destroy failed."); rc = NCSCC_RC_FAILURE; } cb->plmc_initialized = false; } if (prev_haState == SA_AMF_HA_QUIESCED) { plms_proc_quiesced_standby_role_change(); } break; case SA_AMF_HA_QUIESCED: plms_quiesced_state_handler(invocation); break; case SA_AMF_HA_QUIESCING: plms_quiescing_state_handler(invocation); break; default: LOG_IN("INVALID HA AMF STATE\n"); plms_invalid_state_handler(invocation); } if (new_haState == SA_AMF_HA_QUIESCED) return; /* Update control block */ cb->ha_state = new_haState; if (cb->csi_assigned == false) { cb->csi_assigned = true; /* We shall open checkpoint only once in our life time. currently doing at lib init */ } else if ((new_haState == SA_AMF_HA_ACTIVE) || (new_haState == SA_AMF_HA_STANDBY)) { /* It is a switch over */ /* check if this step is required */ /* cb->ckpt_state = COLD_SYNC_IDLE; */ } if ((prev_haState == SA_AMF_HA_ACTIVE) && (new_haState == SA_AMF_HA_ACTIVE)) { role_change = false; } if ((prev_haState == SA_AMF_HA_STANDBY) && (new_haState == SA_AMF_HA_STANDBY)) { role_change = false; } if (role_change == true) { if ((rc = plms_mds_change_role()) != NCSCC_RC_SUCCESS) { LOG_ER("plms_mds_change_role FAILED"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } else { if (cb->ha_state == SA_AMF_HA_ACTIVE) { /* FIXME: Is there any overhead to be done on New Active */ // if (plms_imm_declare_implementer(cb->immOiHandle) != SA_AIS_OK) // printf("ClassImplementer Set Failed\n"); } if (cb->ha_state == SA_AMF_HA_STANDBY) { /* FIXME : Do the over head processing needed to be done for standby state */ } } TRACE_5("Inform MBCSV of HA state change to %s", (new_haState == SA_AMF_HA_ACTIVE) ? "ACTIVE" : "STANDBY"); if (plms_mbcsv_chgrole() != NCSCC_RC_SUCCESS) { LOG_ER("Failed to change role"); error = SA_AIS_ERR_FAILED_OPERATION; goto response; } } response: /* Send the response to AMF */ saAmfResponse(cb->amf_hdl, invocation, error); m_NCS_UNLOCK(&cb->cb_lock,NCS_LOCK_WRITE); TRACE_LEAVE(); } /* End of PLMS CSI Set callback */
/**************************************************************************** Name : plms_mds_register Description : This routine registers the PLMS Service with MDS. Arguments : NULL Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None. ****************************************************************************/ SaUint32T plms_mds_register() { uns32 rc = NCSCC_RC_SUCCESS; NCSMDS_INFO svc_info; MDS_SVC_ID svc_id[1] = { NCSMDS_SVC_ID_PLMA }; MDS_SVC_ID plms_id[1] = { NCSMDS_SVC_ID_PLMS }; MDS_SVC_ID plms_hrb_id[1] = { NCSMDS_SVC_ID_PLMS_HRB }; PLMS_CB *cb = plms_cb; TRACE_ENTER(); /* Create the virtual Destination for PLMS */ rc = plms_mds_vdest_create(); if (NCSCC_RC_SUCCESS != rc) { LOG_ER("PLMS - VDEST CREATE FAILED"); return rc; } /* Set the role of MDS */ if (cb->ha_state == SA_AMF_HA_ACTIVE) { TRACE_5("Set MDS role to ACTIVE"); cb->mds_role = V_DEST_RL_ACTIVE; } else if (cb->ha_state == SA_AMF_HA_STANDBY) { TRACE_5("Set MDS role to STANDBY"); cb->mds_role = V_DEST_RL_STANDBY; } else { TRACE_5("Could not set MDS role"); } if (NCSCC_RC_SUCCESS != (rc = plms_mds_change_role())) { LOG_ER("MDS role change to %d FAILED", cb->mds_role); return rc; } memset(&svc_info, 0, sizeof(NCSMDS_INFO)); /* STEP 2 : Install with MDS with service ID NCSMDS_SVC_ID_PLMS. */ svc_info.i_mds_hdl = cb->mds_hdl; svc_info.i_svc_id = NCSMDS_SVC_ID_PLMS; svc_info.i_op = MDS_INSTALL; svc_info.info.svc_install.i_yr_svc_hdl = 0; svc_info.info.svc_install.i_install_scope = NCSMDS_SCOPE_NONE; /*node specific */ svc_info.info.svc_install.i_svc_cb = plms_mds_callback; /* callback */ svc_info.info.svc_install.i_mds_q_ownership = FALSE; svc_info.info.svc_install.i_mds_svc_pvt_ver = PLMS_MDS_PVT_SUBPART_VERSION; if (ncsmds_api(&svc_info) == NCSCC_RC_FAILURE) { LOG_ER("PLMS - MDS Install Failed"); return NCSCC_RC_FAILURE; } /* STEP 3: Subscribe to PLMS for redundancy events */ memset(&svc_info, 0, sizeof(NCSMDS_INFO)); svc_info.i_mds_hdl = cb->mds_hdl; svc_info.i_svc_id = NCSMDS_SVC_ID_PLMS; svc_info.i_op = MDS_RED_SUBSCRIBE; svc_info.info.svc_subscribe.i_num_svcs = 1; svc_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_NONE; svc_info.info.svc_subscribe.i_svc_ids = plms_id; if (ncsmds_api(&svc_info) == NCSCC_RC_FAILURE) { LOG_ER("PLMS - MDS Subscribe for redundancy Failed"); plms_mds_unregister(); return NCSCC_RC_FAILURE; } /* STEP 4: Subscribe to PLMA up/down events */ memset(&svc_info, 0, sizeof(NCSMDS_INFO)); svc_info.i_mds_hdl = cb->mds_hdl; svc_info.i_svc_id = NCSMDS_SVC_ID_PLMS; svc_info.i_op = MDS_SUBSCRIBE; svc_info.info.svc_subscribe.i_num_svcs = 1; svc_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_NONE; svc_info.info.svc_subscribe.i_svc_ids = svc_id; if (ncsmds_api(&svc_info) == NCSCC_RC_FAILURE) { LOG_ER("PLMS - MDS Subscribe for PLMA up/down Failed"); plms_mds_unregister(); return NCSCC_RC_FAILURE; } /* STEP 5: Subscribe to HRB up/down events */ memset(&svc_info, 0, sizeof(NCSMDS_INFO)); svc_info.i_mds_hdl = cb->mds_hdl; svc_info.i_svc_id = NCSMDS_SVC_ID_PLMS; svc_info.i_op = MDS_SUBSCRIBE; svc_info.info.svc_subscribe.i_num_svcs = 1; svc_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_NONE; svc_info.info.svc_subscribe.i_svc_ids = plms_hrb_id; if (ncsmds_api(&svc_info) == NCSCC_RC_FAILURE) { LOG_ER("PLMS - MDS Subscribe for PLMS_HRB up/down Failed"); plms_mds_unregister(); return NCSCC_RC_FAILURE; } /* Get the node id of local PLMS */ cb->node_id = m_NCS_GET_NODE_ID; cb->plms_self_id = plms_get_slot_and_subslot_id_from_node_id(cb->node_id); TRACE_5("NodeId:%x SelfId:%x", cb->node_id, cb->plms_self_id); TRACE_LEAVE(); return NCSCC_RC_SUCCESS; }
/* * This does the real work of segkp allocation. * Return to client base addr. len must be page-aligned. A null value is * returned if there are no more vm resources (e.g. pages, swap). The len * and base recorded in the private data structure include the redzone * and the redzone length (if applicable). If the user requests a redzone * either the first or last page is left unmapped depending whether stacks * grow to low or high memory. * * The client may also specify a no-wait flag. If that is set then the * request will choose a non-blocking path when requesting resources. * The default is make the client wait. */ static caddr_t segkp_get_internal( struct seg *seg, size_t len, uint_t flags, struct segkp_data **tkpd, struct anon_map *amp) { struct segkp_segdata *kpsd = (struct segkp_segdata *)seg->s_data; struct segkp_data *kpd; caddr_t vbase = NULL; /* always first virtual, may not be mapped */ pgcnt_t np = 0; /* number of pages in the resource */ pgcnt_t segkpindex; long i; caddr_t va; pgcnt_t pages = 0; ulong_t anon_idx = 0; int kmflag = (flags & KPD_NOWAIT) ? KM_NOSLEEP : KM_SLEEP; caddr_t s_base = (segkp_fromheap) ? kvseg.s_base : seg->s_base; if (len & PAGEOFFSET) { panic("segkp_get: len is not page-aligned"); /*NOTREACHED*/ } ASSERT(((flags & KPD_HASAMP) == 0) == (amp == NULL)); /* Only allow KPD_NO_ANON if we are going to lock it down */ if ((flags & (KPD_LOCKED|KPD_NO_ANON)) == KPD_NO_ANON) return (NULL); if ((kpd = kmem_zalloc(sizeof (struct segkp_data), kmflag)) == NULL) return (NULL); /* * Fix up the len to reflect the REDZONE if applicable */ if (flags & KPD_HASREDZONE) len += PAGESIZE; np = btop(len); vbase = vmem_alloc(SEGKP_VMEM(seg), len, kmflag | VM_BESTFIT); if (vbase == NULL) { kmem_free(kpd, sizeof (struct segkp_data)); return (NULL); } /* If locking, reserve physical memory */ if (flags & KPD_LOCKED) { pages = btop(SEGKP_MAPLEN(len, flags)); if (page_resv(pages, kmflag) == 0) { vmem_free(SEGKP_VMEM(seg), vbase, len); kmem_free(kpd, sizeof (struct segkp_data)); return (NULL); } if ((flags & KPD_NO_ANON) == 0) atomic_add_long(&anon_segkp_pages_locked, pages); } /* * Reserve sufficient swap space for this vm resource. We'll * actually allocate it in the loop below, but reserving it * here allows us to back out more gracefully than if we * had an allocation failure in the body of the loop. * * Note that we don't need swap space for the red zone page. */ if (amp != NULL) { /* * The swap reservation has been done, if required, and the * anon_hdr is separate. */ anon_idx = 0; kpd->kp_anon_idx = anon_idx; kpd->kp_anon = amp->ahp; TRACE_5(TR_FAC_VM, TR_ANON_SEGKP, "anon segkp:%p %p %lu %u %u", kpd, vbase, len, flags, 1); } else if ((flags & KPD_NO_ANON) == 0) { if (anon_resv_zone(SEGKP_MAPLEN(len, flags), NULL) == 0) { if (flags & KPD_LOCKED) { atomic_add_long(&anon_segkp_pages_locked, -pages); page_unresv(pages); } vmem_free(SEGKP_VMEM(seg), vbase, len); kmem_free(kpd, sizeof (struct segkp_data)); return (NULL); } atomic_add_long(&anon_segkp_pages_resv, btop(SEGKP_MAPLEN(len, flags))); anon_idx = ((uintptr_t)(vbase - s_base)) >> PAGESHIFT; kpd->kp_anon_idx = anon_idx; kpd->kp_anon = kpsd->kpsd_anon; TRACE_5(TR_FAC_VM, TR_ANON_SEGKP, "anon segkp:%p %p %lu %u %u", kpd, vbase, len, flags, 1); } else {