Example #1
0
/***********************************************************************//**
* @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;
}
Example #2
0
/***********************************************************************//**
* @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;
}
Example #3
0
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();
}
Example #4
0
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();
}
Example #5
0
/****************************************************************************\
 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();
}
Example #6
0
/****************************************************************************
 * 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 */	
Example #7
0
/****************************************************************************
  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;
}
Example #8
0
/*
 * 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 {