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
509 lines (430 sloc) 13.7 KB
/*
* (C) 2003 Clemson University and The University of Chicago
*
* See COPYING in top-level directory.
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "client-state-machine.h"
#include "pvfs2-debug.h"
#include "pvfs2-util.h"
#include "job.h"
#include "gossip.h"
#include "str-utils.h"
#include "pint-util.h"
#include "pint-cached-config.h"
#include "PINT-reqproto-encode.h"
#include "osd-util/osd-sense.h"
#include "osd-initiator/sense.h"
extern job_context_id pint_client_sm_context;
static int server_parse_config(
struct server_configuration_s *config,
char *fs_config_buf,
uint32_t fs_config_buf_size);
static int server_get_config_comp_fn(
void *v_p, struct PVFS_server_resp *resp_p, int i);
enum {
OSD_MSGPAIR = 2001,
};
%%
nested machine pvfs2_server_get_config_nested_sm
{
state setup_msgpair
{
run server_get_config_setup_msgpair;
OSD_MSGPAIR => osd_xfer_msgpair;
success => xfer_msgpair;
default => cleanup;
}
state osd_xfer_msgpair
{
jump pvfs2_osd_msgpairarray_sm;
success => parse;
default => cleanup;
}
state xfer_msgpair
{
jump pvfs2_msgpairarray_sm;
success => parse;
default => cleanup;
}
state parse
{
run server_get_config_parse;
default => cleanup;
}
state cleanup
{
run server_get_config_cleanup;
default => return;
}
}
machine pvfs2_server_get_config_sm
{
state run_nested
{
jump pvfs2_server_get_config_nested_sm;
default => parent_cleanup;
}
state parent_cleanup
{
run server_get_config_parent_cleanup;
default => terminate;
}
}
%%
/*
given mount information, retrieve the server's configuration by
issuing a getconfig operation. on successful response, we parse the
configuration and fill in the config object specified.
returns 0 on success, -errno on error
*/
int PINT_server_get_config(
struct server_configuration_s *config,
struct PVFS_sys_mntent* mntent_p,
PVFS_hint hints)
{
int ret = -PVFS_EINVAL;
PINT_smcb *smcb = NULL;
PINT_client_sm *sm_p = NULL;
PVFS_error error = 0;
PVFS_credentials creds;
PVFS_sys_op_id op_id;
gossip_debug(GOSSIP_CLIENT_DEBUG,
"PINT_server_get_config entered\n");
if (!config || !mntent_p)
{
return ret;
}
PVFS_util_gen_credentials(&creds);
gossip_debug(GOSSIP_CLIENT_DEBUG, "asked for fs name = %s\n",
mntent_p->pvfs_fs_name);
PINT_smcb_alloc(&smcb, PVFS_SERVER_GET_CONFIG,
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);
/* NOTE: we set these fields manually here rather than use
* PINT_init_msgarray_params(), because we don't yet have a server
* configuration file to override default parameters.
*/
sm_p->msgarray_op.params.job_context = pint_client_sm_context;
sm_p->msgarray_op.params.job_timeout = 30; /* 30 second job timeout */
sm_p->msgarray_op.params.retry_delay = 2000; /* 2 second retry delay */
sm_p->msgarray_op.params.retry_limit = 5; /* retry up to 5 times */
PINT_msgpair_init(&sm_p->msgarray_op);
PINT_init_sysint_credentials(sm_p->cred_p, &creds);
sm_p->u.get_config.mntent = mntent_p;
sm_p->u.get_config.config = config;
PVFS_hint_copy(hints, &sm_p->hints);
ret = PINT_client_state_machine_post(smcb, &op_id, NULL);
if (ret)
{
PVFS_perror_gossip("PINT_client_state_machine_post call", ret);
error = ret;
}
else
{
ret = PVFS_sys_wait(op_id, "X-get_config", &error);
if (ret)
{
PVFS_perror_gossip("PVFS_sys_wait call", ret);
error = ret;
}
}
PINT_sys_release(op_id);
return(error);
}
#ifdef WIN32
static int server_parse_config(
struct server_configuration_s *config,
char *fs_config_buf,
uint32_t fs_config_buf_size)
{
int ret = 1, template_index = 1;
char temp_path[MAX_PATH], temp_file[MAX_PATH];
char *server_alias = NULL;
DWORD rc = 1, use_temp_path, bytes;
HANDLE hFile;
if (config == NULL)
{
return ret;
}
assert(fs_config_buf);
/* get the path to the TEMP directory */
use_temp_path = GetTempPath(MAX_PATH, temp_path);
if (use_temp_path)
{
/* get temporary file name in TEMP directory */
use_temp_path = GetTempFileName(temp_path,
"__pvfs_fs_config", 0, temp_file);
}
if (!use_temp_path)
{
/* get temporary file name in current directory */
rc = GetTempFileName(".", "__pvfs_fs_config", 0, temp_file);
}
if (!rc)
{
gossip_err("Error: Cannot create temporary "
"configuration files!\n");
return ret;
}
hFile = CreateFile(temp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
gossip_err("Error: Cannot create temporary "
"configuration files!\n");
return ret;
}
assert(!fs_config_buf[fs_config_buf_size - 1]);
rc = WriteFile(hFile, fs_config_buf, fs_config_buf_size - 1, &bytes, NULL);
CloseHandle(hFile);
if (rc && (bytes == fs_config_buf_size - 1))
{
server_alias = PINT_util_guess_alias();
ret = PINT_parse_config(config, temp_file, server_alias, 0);
}
else
{
gossip_err("Failed to write fs.conf buffer to temp file: %s: %d\n",
temp_file, GetLastError());
}
DeleteFile(temp_file);
return ret;
}
#else
static int server_parse_config(
struct server_configuration_s *config,
char *fs_config_buf,
uint32_t fs_config_buf_size)
{
int ret = 1, template_index = 1;
int fs_fd = 0;
char *server_alias = NULL;
char fs_template_array[2][64] =
{
".__pvfs_fs_configXXXXXX",
"/tmp/.__pvfs_fs_configXXXXXX"
};
char *fs_template = NULL;
if (config)
{
assert(fs_config_buf);
while(1)
{
assert(template_index > -1);
fs_template = fs_template_array[template_index];
fs_fd = mkstemp(fs_template);
if (fs_fd != -1)
{
break;
}
else if ((--template_index) < 0)
{
gossip_err("Error: Cannot create temporary "
"configuration files!\n");
return ret;
}
}
assert(!fs_config_buf[fs_config_buf_size - 1]);
if (write(fs_fd,fs_config_buf,
(fs_config_buf_size - 1)) == (fs_config_buf_size - 1))
{
server_alias = PINT_util_guess_alias();
ret = PINT_parse_config(config, fs_template, server_alias, 0);
}
else
{
gossip_err("Failed to write fs.conf buffer to temp file: %s: %s\n",
fs_template, strerror(errno));
}
close(fs_fd);
remove(fs_template);
}
return ret;
}
#endif
static PINT_sm_action server_get_config_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 ret = -PVFS_EINVAL;
PINT_sm_msgpair_state *msg_p = NULL;
PVFS_BMI_addr_t serv_addr;
gossip_debug(GOSSIP_CLIENT_DEBUG,
"get_config state: server_get_config_setup_msgpair\n");
PINT_msgpair_init(&sm_p->msgarray_op);
msg_p = &sm_p->msgarray_op.msgpair;
if (ENCODING_IS_VALID(sm_p->u.get_config.mntent->encoding))
{
msg_p->enc_type = sm_p->u.get_config.mntent->encoding;
}
ret = BMI_addr_lookup(&serv_addr,
sm_p->u.get_config.mntent->the_pvfs_config_server);
if (ret < 0)
{
gossip_lerr("Failed to resolve BMI address %s\n",
sm_p->u.get_config.mntent->the_pvfs_config_server);
js_p->error_code = ret;
return SM_ACTION_COMPLETE;
}
if (server_is_osd(serv_addr)) {
struct osd_command *command = &msg_p->osd_command;
int len = 64 * 1024;
ret = osd_command_set_read(command, PVFS_OSD_META_PID,
PVFS_OSD_FSCONF_OID, len, 0);
command->inlen_alloc = len;
command->indata = malloc(len);
if (!command->indata) {
js_p->error_code = -ENOMEM;
return SM_ACTION_COMPLETE;
}
js_p->error_code = OSD_MSGPAIR;
} else {
PINT_SERVREQ_GETCONFIG_FILL(msg_p->req, *sm_p->cred_p, sm_p->hints);
js_p->error_code = 0;
}
msg_p->fs_id = PVFS_FS_ID_NULL;
msg_p->handle = PVFS_HANDLE_NULL;
msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
msg_p->comp_fn = server_get_config_comp_fn;
msg_p->svr_addr = serv_addr;
PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
return SM_ACTION_COMPLETE;
}
static PINT_sm_action server_get_config_cleanup(
struct PINT_smcb *smcb, job_status_s *js_p)
{
struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
if (sm_p && !sm_p->u.get_config.persist_config_buffers)
{
free(sm_p->u.get_config.fs_config_buf);
sm_p->u.get_config.fs_config_buf = NULL;
}
/* preserve js_p->error_code */
return SM_ACTION_COMPLETE;
}
static PINT_sm_action server_get_config_parse(
struct PINT_smcb *smcb, job_status_s *js_p)
{
struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int ret = -1;
struct filesystem_configuration_s* cur_fs = NULL;
if(sm_p->u.get_config.config)
{
ret = server_parse_config(
sm_p->u.get_config.config, sm_p->u.get_config.fs_config_buf,
sm_p->u.get_config.fs_config_buf_size);
if (ret)
{
gossip_err("Failed to get_config from host %s\n",
sm_p->u.get_config.mntent->the_pvfs_config_server);
js_p->error_code = ret;
return SM_ACTION_COMPLETE;
}
}
if(sm_p->u.get_config.mntent->fs_id == PVFS_FS_ID_NULL)
{
cur_fs = PINT_config_find_fs_name(sm_p->u.get_config.config,
sm_p->u.get_config.mntent->pvfs_fs_name);
if (!cur_fs)
{
gossip_err("Warning:\n Cannot retrieve information about "
"filesystem %s at tab entry: %s\n",
sm_p->u.get_config.mntent->pvfs_fs_name,
sm_p->u.get_config.mntent->the_pvfs_config_server);
/*
if the device has no space left on it, we can't save
the config file for parsing and get a failure; make
a note of that possibility here
*/
gossip_err("\nHINTS: If you're sure that your pvfstab file "
"contains valid information,\n please make sure "
"that you are not out of disk space and that you "
"have\n write permissions in the current "
"directory or in the /tmp directory\n\n");
js_p->error_code = -PVFS_ENODEV;
return SM_ACTION_COMPLETE;
}
sm_p->u.get_config.mntent->fs_id = cur_fs->coll_id;
cur_fs->flowproto = sm_p->u.get_config.mntent->flowproto;
cur_fs->encoding = sm_p->u.get_config.mntent->encoding;
}
js_p->error_code = 0;
return SM_ACTION_COMPLETE;
}
static PINT_sm_action server_get_config_parent_cleanup(
struct PINT_smcb *smcb, job_status_s *js_p)
{
struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
sm_p->error_code = js_p->error_code;
PINT_SET_OP_COMPLETE;
return SM_ACTION_DEFERRED;
}
static int server_get_config_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);
PINT_sm_msgpair_state *msg_p = &sm_p->msgarray_op.msgarray[0];
if (server_is_osd(msg_p->svr_addr)) {
struct osd_command *command = &msg_p->osd_command;
if (command->status == SAM_STAT_CHECK_CONDITION) {
int key, code;
osd_sense_extract(command->sense, command->sense_len, &key, &code);
/* ignore "read past end of user object" */
if (key == OSD_SSK_RECOVERED_ERROR &&
code == OSD_ASC_READ_PAST_END_OF_USER_OBJECT) {
command->status = 0;
}
}
if (command->status != 0)
return osd_errno_from_status(command->status);
if (command->inlen == 0)
return -ENOENT;
sm_p->u.get_config.fs_config_buf = strdup(command->indata);
sm_p->u.get_config.fs_config_buf_size = command->inlen + 1;
free(command->indata);
return 0;
}
/* only posted one msgpair */
assert(i==0);
/* if this particular request was successful, then store the server
* response and let the caller sort it out */
if (sm_p->msgarray_op.msgarray[i].op_status == 0)
{
sm_p->u.get_config.fs_config_buf =
strdup(resp_p->u.getconfig.fs_config_buf);
sm_p->u.get_config.fs_config_buf_size =
resp_p->u.getconfig.fs_config_buf_size;
}
/* 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))
{
return PINT_msgarray_status(&sm_p->msgarray_op);
}
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
*/