Skip to content
Permalink
1139b72d5e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
362 lines (313 sloc) 9.74 KB
/*
* (C) 2003 Clemson University and The University of Chicago
*
* See COPYING in top-level directory.
*/
/** \file
* \ingroup mgmtint
*
* PVFS2 management interface routines for setting run-time parameters
* on a list of servers. These are currently used primarily for file
* system repair purposes, specifically to put the servers in a special
* administrative mode to avoid file system changes while repairs are
* underway.
*/
#include <string.h>
#include <assert.h>
#include "client-state-machine.h"
#include "pvfs2-debug.h"
#include "job.h"
#include "gossip.h"
#include "str-utils.h"
#include "pint-cached-config.h"
#include "PINT-reqproto-encode.h"
extern job_context_id pint_client_sm_context;
static int root_check_comp_fn(
void *v_p, struct PVFS_server_resp *resp_p, int i);
static int collect_old_values_comp_fn(
void *v_p, struct PVFS_server_resp *resp_p, int i);
%%
machine pvfs2_client_mgmt_setparam_list_sm
{
state setup_msgpair
{
run mgmt_setparam_list_setup_msgpair;
success => xfer_msgpair;
default => cleanup;
}
state xfer_msgpair
{
jump pvfs2_msgpairarray_sm;
default => cleanup;
}
state cleanup
{
run mgmt_setparam_list_cleanup;
default => terminate;
}
}
%%
/** Initiate setting of a run-time server parameter on a list of servers.
*/
PVFS_error PVFS_imgmt_setparam_list(
PVFS_fs_id fs_id,
PVFS_credentials *credentials,
enum PVFS_server_param param,
struct PVFS_mgmt_setparam_value *value,
PVFS_BMI_addr_t *addr_array,
int count,
PVFS_error_details *details,
PVFS_hint hints,
PVFS_mgmt_op_id *op_id,
void *user_ptr)
{
PVFS_error ret = -PVFS_EINVAL;
PINT_smcb *smcb = NULL;
PINT_client_sm *sm_p = NULL;
gossip_debug(GOSSIP_CLIENT_DEBUG,
"PVFS_imgmt_setparam_list entered\n");
if (param == PVFS_SERV_PARAM_INVALID)
{
return ret;
}
PINT_smcb_alloc(&smcb, PVFS_MGMT_SETPARAM_LIST,
sizeof(struct PINT_client_sm),
client_op_state_get_machine,
client_state_machine_terminate,
pint_client_sm_context);
if (smcb == NULL)
{
return -PVFS_ENOMEM;
}
sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
PINT_init_msgarray_params(sm_p, fs_id);
PINT_init_sysint_credentials(sm_p->cred_p, credentials);
sm_p->u.setparam_list.fs_id = fs_id;
sm_p->u.setparam_list.param = param;
sm_p->u.setparam_list.value = value;
sm_p->u.setparam_list.addr_array = addr_array;
sm_p->u.setparam_list.count = count;
sm_p->u.setparam_list.details = details;
ret = PINT_msgpairarray_init(&sm_p->msgarray_op, count);
if(ret != 0)
{
PINT_smcb_free(smcb);
return ret;
}
if (sm_p->u.setparam_list.root_check_status_array)
{
free(sm_p->u.setparam_list.root_check_status_array);
sm_p->u.setparam_list.root_check_status_array = NULL;
}
return PINT_client_state_machine_post(
smcb, op_id, user_ptr);
}
/** Set a run-time parameter on a list of servers.
*/
PVFS_error PVFS_mgmt_setparam_list(
PVFS_fs_id fs_id,
PVFS_credentials *credentials,
enum PVFS_server_param param,
struct PVFS_mgmt_setparam_value *value,
PVFS_BMI_addr_t *addr_array,
int count,
PVFS_error_details *details,
PVFS_hint hints)
{
PVFS_error ret = -PVFS_EINVAL, error = 0;
PVFS_sys_op_id op_id;
gossip_debug(GOSSIP_CLIENT_DEBUG, "%s entered\n", __func__);
ret = PVFS_imgmt_setparam_list(
fs_id, credentials, param, value, addr_array,
count, details, hints, &op_id, NULL);
if (ret)
{
PVFS_perror_gossip("PVFS_imgmt_setparam_list call", ret);
error = ret;
}
else
{
ret = PVFS_mgmt_wait(op_id, "setparam_list", &error);
if (ret)
{
PVFS_perror_gossip("PVFS_mgmt_wait call", ret);
error = ret;
}
}
gossip_debug(GOSSIP_CLIENT_DEBUG, "%s completed\n", __func__);
PINT_mgmt_release(op_id);
return error;
}
static PINT_sm_action mgmt_setparam_list_setup_msgpair(
struct PINT_smcb *smcb, job_status_s *js_p)
{
struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int i = 0;
PINT_sm_msgpair_state *msg_p = NULL;
gossip_debug(GOSSIP_CLIENT_DEBUG, "setparam_list state: "
"mgmt_setparam_list_setup_msgpair\n");
/* setup msgpair array */
foreach_msgpair(&sm_p->msgarray_op, msg_p, i)
{
PINT_SERVREQ_MGMT_SETPARAM_FILL(
msg_p->req,
*sm_p->cred_p,
sm_p->u.setparam_list.fs_id,
sm_p->u.setparam_list.param,
sm_p->u.setparam_list.value,
sm_p->hints);
msg_p->fs_id = sm_p->u.setparam_list.fs_id;
msg_p->handle = PVFS_HANDLE_NULL;
msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
switch(sm_p->u.setparam_list.param)
{
case PVFS_SERV_PARAM_ROOT_CHECK:
msg_p->comp_fn = root_check_comp_fn;
sm_p->u.setparam_list.root_check_status_array = (int *)
malloc(sm_p->u.setparam_list.count * sizeof(int));
memset(sm_p->u.setparam_list.root_check_status_array, -1,
(sm_p->u.setparam_list.count * sizeof(int)));
break;
default:
msg_p->comp_fn = collect_old_values_comp_fn;
break;
}
msg_p->svr_addr = sm_p->u.setparam_list.addr_array[i];
if (server_is_osd(msg_p->svr_addr))
msg_p->suppress = 1;
}
/* immediate return: next state jumps to msgpairarray machine */
js_p->error_code = 0;
PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
return SM_ACTION_COMPLETE;
}
static PINT_sm_action mgmt_setparam_list_cleanup(
struct PINT_smcb *smcb, job_status_s *js_p)
{
struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int i = 0, errct = 0;
PVFS_error error = js_p->error_code;
/* store server-specific errors if requested and present */
if ((error != 0) && (sm_p->u.setparam_list.details != NULL))
{
sm_p->u.setparam_list.details->count_exceeded = 0;
for(i = 0; i < sm_p->u.setparam_list.count; i++)
{
int status;
if (sm_p->u.setparam_list.param == PVFS_SERV_PARAM_ROOT_CHECK)
{
status = sm_p->u.setparam_list.root_check_status_array[i];
}
else
{
status = sm_p->msgarray_op.msgarray[i].op_status;
}
if (errct < sm_p->u.setparam_list.details->count_allocated)
{
sm_p->u.setparam_list.details->error[errct].error = status;
sm_p->u.setparam_list.details->error[errct].addr =
sm_p->msgarray_op.msgarray[i].svr_addr;
errct++;
}
else
{
sm_p->u.setparam_list.details->count_exceeded = 1;
break;
}
}
sm_p->u.setparam_list.details->count_used = errct;
error = -PVFS_EDETAIL;
}
if(sm_p->u.setparam_list.param == PVFS_SERV_PARAM_ROOT_CHECK)
{
free(sm_p->u.setparam_list.root_check_status_array);
sm_p->u.setparam_list.root_check_status_array = NULL;
}
PINT_msgpairarray_destroy(&sm_p->msgarray_op);
sm_p->error_code = error;
PINT_SET_OP_COMPLETE;
return SM_ACTION_TERMINATE;
}
/* collect_old_values_comp_fn()
*
* completion function that assembles old values for parameters
* when appropriate
*
* returns 0 on success, -PVFS_error on failure
*/
static int collect_old_values_comp_fn(
void *v_p, struct PVFS_server_resp *resp_p, int i)
{
PINT_smcb *smcb = v_p;
PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_MSGPAIR_PARENT_SM);
int j;
/* if this is the last response, check all of the status values
* and return error code if any requests failed
*/
if (i == (sm_p->msgarray_op.count -1))
{
for (j = 0; j < sm_p->msgarray_op.count; j++)
{
if (sm_p->msgarray_op.msgarray[j].op_status != 0)
{
return sm_p->msgarray_op.msgarray[j].op_status;
}
}
}
return 0;
}
/* root_check_comp_fn()
*
* completion function for PVFS_SERV_PARAM_ROOT_CHECK parameter; it
* handles this special case operation in which we want just one
* server to return success and all others to return -PVFS_ENOENT.
*
* returns 0 if exactly one server claims ownership of root handle,
* -PVFS_error on failure
*/
static int root_check_comp_fn(
void *v_p, struct PVFS_server_resp *resp_p, int i)
{
int j = 0;
int owners = 0;
PINT_smcb *smcb = v_p;
PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_MSGPAIR_PARENT_SM);
/*
store the op_status before it's overwritten with the return
value of this comp_fn by the msgpairarray code
*/
sm_p->u.setparam_list.root_check_status_array[i] =
sm_p->msgarray_op.msgarray[i].op_status;
/* need to return non-zero status at the end if any of the statuses
* are nonzero
*/
if(i == (sm_p->u.setparam_list.count - 1))
{
for(; j < sm_p->u.setparam_list.count; ++j)
{
if(sm_p->u.setparam_list.root_check_status_array[j] == 0)
{
owners++;
}
else if(sm_p->u.setparam_list.root_check_status_array[j] !=
-PVFS_ENOENT)
{
return -PVFS_EDETAIL;
}
}
if(owners != 1)
{
return -PVFS_EDETAIL;
}
}
return 0;
}
/*
* Local variables:
* mode: c
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/