[Pvfs2-cvs] commit by aching in pvfs2-1/src/common/misc:
fsck-utils.c fsck-utils.h pint-eattr.c pint-eattr.h
pint-hint.h state-machine-fns.c void.sm digest.c
errno-mapping.c mkspace.c mmap-ra-cache.c module.mk.in
msgpairarray.h msgpairarray.sm pint-cached-config.c
pint-cached-config.h pint-perf-counter.c pint-perf-counter.h
pint-util.c pint-util.h pvfs2-debug.c pvfs2-internal.h
pvfs2-util.c server-config-mgr.c server-config-mgr.h
server-config.c server-config.h state-machine.h str-utils.c
str-utils.h xattr-utils.c xattr-utils.h state-machine-fns.h
state-machine-values.h
CVS commit program
cvs at parl.clemson.edu
Mon Jul 21 14:19:55 EDT 2008
Update of /projects/cvsroot/pvfs2-1/src/common/misc
In directory parlweb1:/tmp/cvs-serv19729/common/misc
Modified Files:
Tag: locking-branch
digest.c errno-mapping.c mkspace.c mmap-ra-cache.c
module.mk.in msgpairarray.h msgpairarray.sm
pint-cached-config.c pint-cached-config.h pint-perf-counter.c
pint-perf-counter.h pint-util.c pint-util.h pvfs2-debug.c
pvfs2-internal.h pvfs2-util.c server-config-mgr.c
server-config-mgr.h server-config.c server-config.h
state-machine.h str-utils.c str-utils.h xattr-utils.c
xattr-utils.h
Added Files:
Tag: locking-branch
fsck-utils.c fsck-utils.h pint-eattr.c pint-eattr.h
pint-hint.h state-machine-fns.c void.sm
Removed Files:
Tag: locking-branch
state-machine-fns.h state-machine-values.h
Log Message:
Reverse merged and ported to HEAD.
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ fsck-utils.c 2008-07-21 14:19:55.000000000 -0400
@@ -0,0 +1,1609 @@
+/*
+ * Copyright © Acxiom Corporation, 2005
+ *
+ * See COPYING in top-level directory.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "fsck-utils.h"
+
+#define HANDLE_BATCH 1000
+#define MAX_DIR_ENTS 64
+
+#define SERVER_CONFIG_BUFFER_SIZE 5000
+#define FS_CONFIG_BUFFER_SIZE 10000
+
+/** \file
+ * \ingroup fsckutils
+ * Implementation of the fsck-utils component.
+ *
+ * TODO's:
+ * - What action should be taken to recover broken on missing PVFS2 objects? Can
+ * we recover pieces and zero out unknown? Can we create missing metadata
+ * for data files that are orphaned? Do we automatically move to lost+found
+ * directory, and/or allow option to simply remove and delete?
+ * - What needs to be done for extended attributes
+ * - What needs to be done for access control lists (extended attributes &
+ * accounts)
+ * .
+ *
+ * Terminology:
+ * - Orphaned bstreams: bstreams with no dfiles/attributes
+ * - Stranded Object: An object exists with no way to get to it
+ * - Datafile missing metadata
+ * - Metadata missing directory entry
+ * - Dirdata missing directory object
+ * - Dangling directory entry: directory entry exists, but object/attributes don't
+ * .
+ */
+
+static void set_return_code(
+ int *ret,
+ const int retval);
+
+static int compare_handles(
+ const void *handle1,
+ const void *handle2);
+
+/** The following declarations deal with the option to check for stranded objects */
+struct PINT_handle_wrangler_handlelist
+{
+ int num_servers;
+ PVFS_handle **list_array;
+ char **list_array_seen;
+ int *size_array;
+ int *used_array;
+ int *stranded_array;
+ PVFS_BMI_addr_t *addr_array;
+} PINT_handle_wrangler_handlelist;
+
+#if 0
+/* not used yet */
+static int PINT_handle_wrangler_get_stranded_handles(
+ const PVFS_fs_id * cur_fs,
+ int *num_stranded_handles,
+ PVFS_handle ** stranded_handles);
+#endif
+
+static int PINT_handle_wrangler_display_stranded_handles(
+ const struct PINT_fsck_options *fsck_options,
+ const PVFS_fs_id * cur_fs,
+ const PVFS_credentials * creds);
+
+static int PINT_handle_wrangler_load_handles(
+ const struct PINT_fsck_options *fsck_options,
+ const PVFS_fs_id * cur_fs,
+ const PVFS_credentials * creds);
+
+static int PINT_handle_wrangler_remove_handle(
+ const PVFS_handle * handle,
+ const PVFS_fs_id * cur_fs);
+
+/**
+ * Initializes API and checks options for correctness
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_initialize(
+ const struct PINT_fsck_options *fsck_options, /**< Populated options */
+ const PVFS_credentials * creds, /**< Populated creditials structure */
+ const PVFS_fs_id * cur_fs) /**< filesystem id */
+{
+ int ret = 0;
+
+ if(fsck_options->fix_errors)
+ {
+ return(-PVFS_ENOSYS);
+ }
+
+ /* If check stranded objects... Setup handle stuff */
+ if (fsck_options->check_stranded_objects)
+ {
+ /* get all handles from all servers */
+ ret = PINT_handle_wrangler_load_handles(fsck_options, cur_fs, creds);
+ }
+
+ return ret;
+}
+
+/**
+ * Verifies the same fs config is present on each pvfs2 server.
+ * Ignores extraneous whitespace and comments begining with #. Does not stop
+ * on the first problem- will show any config differences, using the first
+ * server as the golden standard.
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_check_server_configs(
+ const struct PINT_fsck_options *fsck_options, /**< Populated options */
+ const PVFS_credentials * creds, /**< pvfs2 credentials structure */
+ const PVFS_fs_id * cur_fs) /**< the current fs */
+{
+ int ret = 0;
+ int num_servers = 0;
+ int i = 0;
+ int server_type = 0;
+ PVFS_BMI_addr_t *addresses = NULL;
+ char *fs_config = NULL;
+ char *fs_config_diff = NULL;
+ char *reference_config_server = NULL;
+ const char *server_name = NULL;
+ FILE *pin = NULL;
+ char line[130] = { 0 };
+ char *cmd = NULL;
+ /* temp file name and file descriptor to store our reference config */
+ char reference_fs_config_tmp_file[] = "/tmp/pvfs2-fsck.XXXXXX";
+ int fout = 0;
+ int final_ret = 0;
+
+ /* count how many servers we have */
+ ret = PVFS_mgmt_count_servers(*cur_fs,
+ (PVFS_credentials *) creds,
+ PVFS_MGMT_IO_SERVER | PVFS_MGMT_META_SERVER,
+ &num_servers);
+ if(ret < 0)
+ {
+ PVFS_perror_gossip("PVFS_mgmt_count_servers", ret);
+ return ret;
+ }
+
+ addresses =
+ (PVFS_BMI_addr_t *) calloc(num_servers, sizeof(PVFS_BMI_addr_t));
+ if (addresses == NULL)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ /* get a list of the pvfs2 servers */
+ ret = PVFS_mgmt_get_server_array(
+ *cur_fs,
+ (PVFS_credentials *) creds,
+ PVFS_MGMT_IO_SERVER | PVFS_MGMT_META_SERVER,
+ addresses, &num_servers);
+ if(ret < 0)
+ {
+ free(addresses);
+ PVFS_perror_gossip("PVFS_mgmt_get_server_array", ret);
+ return ret;
+ }
+
+ for (i = 0; i < num_servers; i++)
+ {
+ server_type = 0;
+ server_name = NULL;
+
+ /* get the pretty server name */
+ server_name = PINT_cached_config_map_addr(
+ *cur_fs, addresses[i], &server_type);
+ assert(server_name);
+
+ fs_config = calloc(FS_CONFIG_BUFFER_SIZE, sizeof(char));
+ if (fs_config == NULL)
+ {
+ free(addresses);
+ return -PVFS_ENOMEM;
+ }
+
+ ret = PVFS_mgmt_get_config(cur_fs,
+ &addresses[i],
+ fs_config,
+ FS_CONFIG_BUFFER_SIZE);
+ if (ret < 0)
+ {
+ PVFS_perror_gossip("PVFS_mgmt_get_config", ret);
+ gossip_err("Error: failed to retrieve configuration on server %d of %d.\n",
+ i, num_servers);
+ free(addresses);
+ free(fs_config);
+ return(ret);
+ }
+
+ if (i == 0)
+ {
+ /* store the "reference" server name for nice output later */
+ reference_config_server = calloc(1, strlen(server_name) + 1);
+ if (reference_config_server == NULL)
+ {
+ free(addresses);
+ free(fs_config);
+ return -PVFS_ENOMEM;
+ }
+ strcpy(reference_config_server, server_name);
+
+ /* store the first server config as the reference */
+ fout = mkstemp(reference_fs_config_tmp_file);
+ if (fout < 0)
+ {
+ ret = -errno;
+ gossip_err("Error opening temp file [%s]\n",
+ reference_fs_config_tmp_file);
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ return ret;
+ }
+
+ ret = write(fout, fs_config, strlen(fs_config));
+ if (ret < 0)
+ {
+ ret = -errno;
+ gossip_err("Error: could not write reference configuration.\n");
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ return(ret);
+ }
+
+ close(fout);
+ }
+ else
+ {
+ /* allocate enough space to hold our diff command */
+ cmd = calloc(1,
+ strlen(fs_config) + strlen(reference_config_server) +
+ strlen(server_name) + 1000);
+ if (cmd == NULL)
+ {
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ return -PVFS_ENOMEM;
+ }
+
+ /* build the diff command */
+ sprintf(cmd,
+ "echo \"%s\"| diff -EbBu -I '^#.*' -L %s -L %s %s -",
+ fs_config,
+ reference_config_server,
+ server_name, reference_fs_config_tmp_file);
+
+ pin = popen(cmd, "r");
+ if (pin == NULL)
+ {
+ ret = -errno;
+ gossip_err("Error: failed popen() for command: %s\n", cmd);
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ free(cmd);
+ return ret;
+ }
+
+ fs_config_diff = calloc(1, strlen(fs_config) + 100);
+ if (fs_config_diff == NULL)
+ {
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ free(cmd);
+ return -PVFS_ENOMEM;
+ }
+
+ /* get the output from diff */
+ while (fgets(line, sizeof line, pin))
+ {
+ strcat(fs_config_diff, line);
+ }
+
+ ret = pclose(pin);
+ if(ret != 0)
+ {
+ gossip_err("Error: failed popen() for command: %s\n", cmd);
+ free(addresses);
+ free(fs_config);
+ free(reference_config_server);
+ free(cmd);
+ free(fs_config_diff);
+ return(-PVFS_EINVAL);
+ }
+
+ /* if diff shows any problems, display it but keep going (we want
+ * to see all config file problems if there is more than one)
+ */
+ if (strlen(fs_config_diff) > 0)
+ {
+ gossip_err("Error: File system config on [%s] doesn't\n",
+ server_name);
+ gossip_err(" match reference config from [%s]:\n\n%s\n",
+ reference_config_server, fs_config_diff);
+
+ final_ret = -PVFS_EINVAL;
+ }
+
+ free(fs_config_diff);
+ free(cmd);
+ }
+
+ free(fs_config);
+ }
+
+ unlink(reference_fs_config_tmp_file);
+ free(reference_config_server);
+ free(addresses);
+
+ return final_ret;
+}
+
+/**
+ * Performs sanity checking on the PVFS_TYPE_DATAFILE PVFS_Object type
+ * Checks the following:
+ * - Existence of attributes
+ * .
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dfile(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_handle * handle, /**< The dfile handle */
+ const PVFS_fs_id * cur_fs, /**< The fsid the handle belongs to */
+ const PVFS_credentials * creds, /**< Populated creditials structure */
+ PVFS_size * dfiles_total_size) /**< Total size of all dfiles */
+{
+ int ret = 0;
+ PVFS_object_ref obj_ref;
+ PVFS_sysresp_getattr dfile_attributes;
+ int err = 0;
+
+ memset(&dfile_attributes, 0, sizeof(dfile_attributes));
+
+ if (fsck_options->check_stranded_objects)
+ {
+ if (PINT_handle_wrangler_remove_handle(handle, cur_fs))
+ {
+ gossip_err("WARNING: unable to remove handle [%llu] from handle list while verifying stranded objects\n",
+ llu(*handle));
+ }
+ }
+
+ /* Build the needed PVFS_Object reference needed for API calls */
+ obj_ref.handle = *handle;
+ obj_ref.fs_id = *cur_fs;
+
+ /* Check for existence of attributes */
+ err = PVFS_fsck_get_attributes(fsck_options, &obj_ref, creds,
+ &dfile_attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: unable to get dfile attributes\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ /* total up the dfile sizes. */
+ *dfiles_total_size += dfile_attributes.attr.size;
+
+ /* Do attributes contain valid data */
+ err = PVFS_fsck_validate_dfile_attr(fsck_options, &dfile_attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: dfile has invalid attributes\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ return ret;
+}
+
+/**
+ * Performs validity checking for the attributes for PVFS_TYPE_DATAFILE
+ * Checks the following:
+ * - Object Type must be PVFS_TYPE_DFILE
+ * - size >= 0
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dfile_attr(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * getattr_resp) /**< DFILE attributes */
+{
+ int ret = 0;
+
+ if (getattr_resp->attr.objtype != PVFS_TYPE_DATAFILE)
+ {
+ gossip_err(
+ "dfile object type [%d] does not match expected type PVFS_TYPE_DATAFILE %d\n",
+ getattr_resp->attr.objtype, PVFS_TYPE_DATAFILE);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ if (getattr_resp->attr.size < 0)
+ {
+ /* invalid size attribute */
+ gossip_err("Error: dfile size [%lld] is invalid.\n",
+ lld(getattr_resp->attr.size));
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ return ret;
+}
+
+/**
+ * Performs sanity checking on the PVFS_TYPE_METAFILE PVFS_Object type
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_metafile(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_object_ref * obj_ref, /**< PVFS_Object reference */
+ const PVFS_sysresp_getattr * attributes, /**< METAFILE attributes */
+ const PVFS_credentials * creds) /**< Populated creditials structure */
+{
+ int ret = 0;
+ int i = 0;
+ PVFS_handle *df_handles;
+ PVFS_size dfiles_total_size = 0;
+ int err = 0;
+
+ if (fsck_options->check_stranded_objects)
+ {
+ if (PINT_handle_wrangler_remove_handle
+ (&obj_ref->handle, &obj_ref->fs_id))
+ {
+ gossip_err("WARNING: unable to remove handle [%llu] from \
+ handle list while verifying stranded objects\n", llu(obj_ref->handle));
+ }
+ }
+
+ /* Check for validity of attributes */
+ err = PVFS_fsck_validate_metafile_attr(fsck_options, attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: metafile has invalid attributes\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ df_handles = (PVFS_handle *) calloc(attributes->attr.dfile_count,
+ sizeof(PVFS_handle));
+ if (df_handles == NULL)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ err = PVFS_mgmt_get_dfile_array(*obj_ref,
+ (PVFS_credentials *) creds,
+ df_handles, attributes->attr.dfile_count);
+ if(err < 0)
+ {
+ PVFS_perror("PVFS_mgmt_get_dfile_array", err);
+ free(df_handles);
+ return(err);
+ }
+
+ /* verify dfiles */
+ for (i = 0; i < attributes->attr.dfile_count; i++)
+ {
+ err = PVFS_fsck_validate_dfile(fsck_options,
+ &df_handles[i],
+ &obj_ref->fs_id,
+ creds, &dfiles_total_size);
+ if(err < 0)
+ {
+ gossip_err("Error: metafile dfile [%d] is invalid\n", i);
+ free(df_handles);
+ return(err);
+ }
+ set_return_code(&ret, err);
+ }
+
+ if (dfiles_total_size > attributes->attr.size)
+ {
+ gossip_err(
+ "Error: sum size of dfiles [%lld] is greater than expected size of [%lld]\n",
+ lld(dfiles_total_size), lld(attributes->attr.size));
+
+ free(df_handles);
+ return(-PVFS_EINVAL);
+ }
+
+ free(df_handles);
+ return ret;
+}
+
+/**
+ * Performs validity checking for the attributes for PVFS_TYPE_METAFILE
+ * Checks the following:
+ * - Object type must be PVFS_TYPE_METAFILE
+ * - Existence of dfiles
+ * - Existence of distribution
+ * - size >= 0
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_metafile_attr(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * attributes) /**< METAFILE attributes */
+{
+ int ret = 0;
+
+ /* check attributes */
+ if (attributes->attr.objtype != PVFS_TYPE_METAFILE)
+ {
+ gossip_err(
+ "Error: metafile type [%d] does not match expected type PVFS_TYPE_METAFILE %d\n",
+ attributes->attr.objtype, PVFS_TYPE_METAFILE);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ /* verify we have dfiles */
+ if (attributes->attr.dfile_count <= 0)
+ {
+ gossip_err("Error: metafile has an invalid number of dfiles [%d]\n",
+ attributes->attr.dfile_count);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ /* TODO: check to make sure that dfile array and dist is present. */
+
+ return ret;
+}
+
+/**
+ * Performs sanity checking on the PVFS_TYPE_SYMLINK PVFS_Object type
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_symlink(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_object_ref * obj_ref, /**< PVFS_Object reference */
+ const PVFS_sysresp_getattr * attributes) /**< SYMLINK attributes */
+{
+ int ret = 0;
+
+ if (fsck_options->check_stranded_objects)
+ {
+ if (PINT_handle_wrangler_remove_handle
+ (&obj_ref->handle, &obj_ref->fs_id))
+ {
+ gossip_err("WARNING: unable to remove handle [%llu] from handle \
+ list while verifying stranded objects\n", llu(obj_ref->handle));
+ }
+ }
+
+ ret = PVFS_fsck_validate_symlink_attr(fsck_options, attributes);
+
+ return ret;
+}
+
+/**
+ * Performs validity checking for the attributes for PVFS_TYPE_SYMLINK
+ * Checks the following:
+ * - Object type must be PVFS_TYPE_SYMLINK
+ * - Target must be non-null
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_symlink_attr(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * attributes) /**< SYMLINK attributes */
+{
+ int ret = 0;
+ int err = 0;
+
+ /* check attributes */
+ if (attributes->attr.objtype != PVFS_TYPE_SYMLINK)
+ {
+ gossip_err(
+ "Error: symlink type [%d] does not match expected type PVFS_TYPE_SYMLINK [%d]\n",
+ attributes->attr.objtype, PVFS_TYPE_SYMLINK);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ if (attributes->attr.link_target)
+ {
+ if (fsck_options->check_symlink_target)
+ {
+ /* we do have a target, make sure it's valid */
+ err = PVFS_fsck_validate_symlink_target(fsck_options, attributes);
+ if (err < 0)
+ {
+ gossip_err("Error: symlink target [%s] is invalid\n",
+ attributes->attr.link_target);
+ return(err);
+ }
+ set_return_code(&ret, err);
+ }
+ }
+ else
+ {
+ gossip_err("Error: symlink missing target attribute\n");
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ return ret;
+}
+
+/**
+ * Performs "bad practice" warning checks for the target attributes for
+ * PVFS_TYPE_SYMLINK. Checks the following:
+ * - Does target exist
+ * - Does target back out of PVFS2 filesystem
+ * - Does target use absolute path
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_symlink_target(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * attributes) /**< SYMLINK attributes */
+{
+ int ret = 0;
+
+ /* TODO: finish other tests */
+
+ if (attributes->attr.link_target[0] == '/')
+ {
+ gossip_err("WARNING: symlink target [%s] uses absolute path\n",
+ attributes->attr.link_target);
+ }
+
+ return ret;
+}
+
+/**
+ * Performs sanity checking on the PVFS_TYPE_DIRDATA PVFS_Object type.
+ * Checks the following:
+ * - Do attributes exist
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dirdata(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_handle * handle, /**< The dirdata handle */
+ const PVFS_fs_id * cur_fs, /**< The fsid the handle belongs to */
+ const PVFS_credentials * creds) /**< Populated creditials structure */
+{
+ int ret = 0;
+ int err = 0;
+ PVFS_sysresp_getattr dirdata_attributes;
+ PVFS_object_ref obj_ref;
+
+ memset(&dirdata_attributes, 0, sizeof(dirdata_attributes));
+
+ obj_ref.handle = *handle;
+ obj_ref.fs_id = *cur_fs;
+
+ if (fsck_options->check_stranded_objects)
+ {
+ if (PINT_handle_wrangler_remove_handle(handle, cur_fs))
+ {
+ gossip_err("WARNING: unable to remove handle [%llu] from handle \
+ list while verifying stranded objects\n", llu(*handle));
+ }
+ }
+
+ err = PVFS_fsck_get_attributes
+ (fsck_options, &obj_ref, creds, &dirdata_attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: failed to get attributes for dirdata object\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ err = PVFS_fsck_validate_dirdata_attr(fsck_options, &dirdata_attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: dirdata entry has invalid attributes\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ return ret;
+}
+
+/**
+ * Performs validity checking for the attributes for PVFS_TYPE_DIRDATA.
+ * Checks the following:
+ * - Object type must be PVFS_TYPE_DIRDATA
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dirdata_attr(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * attributes) /**< DIRDATA attributes */
+{
+ int ret = 0;
+
+ if (attributes->attr.objtype != PVFS_TYPE_DIRDATA)
+ {
+ gossip_err(
+ "Error: dirdata type [%d] does not match expected type PVFS_TYPE_DIRDATA %d\n",
+ attributes->attr.objtype, PVFS_TYPE_DIRDATA);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ return ret;
+}
+
+/**
+ * Performs sanity checking on the PVFS_TYPE_DIRECTORY PVFS_Object type.
+ * Checks the following:
+ * - gets and validates directory entry filenames
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dir(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_object_ref * obj_ref, /**< DIRECTORY object reference */
+ const PVFS_sysresp_getattr * attributes, /**< DIRECTORY attributes */
+ const PVFS_credentials * creds, /**< populated creditials structure */
+ PVFS_dirent * directory_entries) /**< \return readdir response */
+{
+ int ret = 0;
+ int i = 0;
+ int err = 0;
+ int current_dir_entry = 0;
+ PVFS_ds_position token = PVFS_READDIR_START;
+ PVFS_sysresp_readdir readdir_resp;
+ PVFS_handle dirdata_handle;
+
+ if (fsck_options->check_stranded_objects)
+ {
+ if (PINT_handle_wrangler_remove_handle
+ (&obj_ref->handle, &obj_ref->fs_id))
+ {
+ gossip_err("WARNING: unable to remove handle [%llu] from \
+ handle list while verifying stranded objects\n", llu(obj_ref->handle));
+ }
+ }
+
+ err = PVFS_fsck_validate_dir_attr(fsck_options, attributes);
+ if(err < 0)
+ {
+ gossip_err("Error: directory has invalid attributes\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ /* get the dirdata handle and validate */
+ err = PVFS_mgmt_get_dirdata_handle
+ (*obj_ref, &dirdata_handle, (PVFS_credentials *) creds);
+ if(err < 0)
+ {
+ gossip_err("Error: unable to get dirdata handle\n");
+ return(err);
+ }
+
+ err = PVFS_fsck_validate_dirdata
+ (fsck_options, &dirdata_handle, &obj_ref->fs_id, creds);
+ if(err < 0)
+ {
+ gossip_err("Error: directory dirdata is invalid\n");
+ return(err);
+ }
+ set_return_code(&ret, err);
+
+ /* get and validate all directory entries */
+ do
+ {
+ memset(&readdir_resp, 0, sizeof(PVFS_sysresp_readdir));
+
+ err = PVFS_sys_readdir(*obj_ref,
+ token,
+ MAX_DIR_ENTS,
+ (PVFS_credentials *) creds, &readdir_resp);
+ if(err < 0)
+ {
+ gossip_err("Error: could not read directory entries\n");
+ return(err);
+ }
+
+ for (i = 0; i < readdir_resp.pvfs_dirent_outcount; i++)
+ {
+ strncpy(directory_entries[current_dir_entry].d_name,
+ readdir_resp.dirent_array[i].d_name, PVFS_NAME_MAX + 1);
+
+ directory_entries[current_dir_entry].handle =
+ readdir_resp.dirent_array[i].handle;
+ current_dir_entry++;
+
+ if (fsck_options->check_dir_entry_names)
+ {
+ err = PVFS_fsck_validate_dir_ent(fsck_options,
+ readdir_resp.
+ dirent_array[i].d_name);
+ /* continue even if we hit errors; we want to see all entries */
+ if (err < 0)
+ {
+ gossip_err("Error: directory entry [%s] is invalid\n",
+ readdir_resp.dirent_array[i].d_name);
+ }
+ set_return_code(&ret, err);
+ }
+ }
+
+ free(readdir_resp.dirent_array);
+ token = readdir_resp.token;
+
+ } while (readdir_resp.pvfs_dirent_outcount == MAX_DIR_ENTS);
+
+ return ret;
+}
+
+/**
+ * Performs validity checking for the attributes for PVFS_TYPE_DIRECTORY.
+ * Checks the following:
+ * - Object type must be PVFS_TYPE_DIRECTORY
+ * - dirent_count must be >= 0
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dir_attr(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_sysresp_getattr * attributes) /**< DIRECTORY attributes */
+{
+ int ret = 0;
+
+ if (attributes->attr.objtype != PVFS_TYPE_DIRECTORY)
+ {
+ gossip_err("Error: directory type [%d] does not \
+ match expected type PVFS_TYPE_DIRECTORY %d\n", attributes->attr.objtype, PVFS_TYPE_DIRECTORY);
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ if (attributes->attr.dirent_count < 0)
+ {
+ gossip_err("Error: directory entry count [%lld] is invalid\n",
+ lld(attributes->attr.dirent_count));
+
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ return ret;
+}
+
+/**
+ * Performs validity checking for the PVFS_TYPE_DIRECTORY directory entries
+ * Checks the following:
+ * - invalid characters in entry names
+ * - entry_names <= PVFS2_SEGMENT_MAX
+ * - warnings for characters that tend to confuse shells
+ * .
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_validate_dir_ent(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const char *filename) /**< Filename associated with handle */
+{
+ const char *cp;
+ int ret = 0;
+
+ if (strlen(filename) > PVFS_SEGMENT_MAX)
+ {
+ gossip_err(
+ "Error: directory entry [%s] length is > PVFS_SEGMENT_MAX [%d]\n",
+ filename, PVFS_SEGMENT_MAX);
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ if (strspn(filename, "/") > 0)
+ {
+ gossip_err("Error: directory entry [%s] contains invalid / character \n",
+ filename);
+ set_return_code(&ret, -PVFS_EINVAL);
+ }
+
+ cp = filename;
+ while (*cp)
+ {
+ /* isprint is ' ' through ~ in ASCII; no tabs or newlines */
+ if (!isprint(*cp))
+ {
+ gossip_err("WARNING: directory entry [%s] contains odd character\n",
+ filename);
+ break;
+ }
+ cp++;
+ }
+
+ return ret;
+}
+
+/**
+ * Get a pvfs2 objects attributes.
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_get_attributes(
+ const struct PINT_fsck_options *fsck_options, /**< generic fsck options */
+ const PVFS_object_ref * pref, /**< object reference requesting attributes */
+ const PVFS_credentials * creds, /**< populated credentials structure */
+ PVFS_sysresp_getattr * getattr_resp) /**< attribute structure to populate */
+{
+ time_t r_atime, r_mtime, r_ctime;
+ int ret = 0;
+
+ ret = PVFS_sys_getattr
+ (*pref, PVFS_ATTR_SYS_ALL, (PVFS_credentials *) creds, getattr_resp);
+ if(ret < 0)
+ {
+ gossip_err("Error: unable to retrieve attributes\n");
+ return(ret);
+ }
+
+ r_atime = (time_t) getattr_resp->attr.atime;
+ r_mtime = (time_t) getattr_resp->attr.mtime;
+ r_ctime = (time_t) getattr_resp->attr.ctime;
+
+ /* if the gossip fsck debug mask is enabled, then print detailed
+ * information about the attributes
+ */
+ gossip_debug(GOSSIP_FSCK_DEBUG, "\tFSID : %d\n", (int) pref->fs_id);
+ gossip_debug(GOSSIP_FSCK_DEBUG, "\tHandle : %llu\n", llu(pref->handle));
+
+ if (getattr_resp->attr.mask & PVFS_ATTR_SYS_COMMON_ALL)
+ {
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tuid : %d\n", getattr_resp->attr.owner);
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tgid : %d\n", getattr_resp->attr.group);
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tperms : %o\n", getattr_resp->attr.perms);
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tatime : %s", ctime(&r_atime));
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tmtime : %s", ctime(&r_mtime));
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tctime : %s", ctime(&r_ctime));
+
+ }
+
+ if (getattr_resp->attr.objtype == PVFS_TYPE_SYMLINK)
+ {
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\ttarget: : %s\n", getattr_resp->attr.link_target);
+ }
+
+ if (getattr_resp->attr.mask & PVFS_ATTR_SYS_SIZE)
+ {
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tfile size : %lld\n", lld(getattr_resp->attr.size));
+ }
+
+ if (getattr_resp->attr.mask & PVFS_ATTR_SYS_DFILE_COUNT)
+ {
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "\tdfile count : %d\n", getattr_resp->attr.dfile_count);
+ }
+
+ gossip_debug(GOSSIP_FSCK_DEBUG, "\tobject type : ");
+
+ switch (getattr_resp->attr.objtype)
+ {
+ case PVFS_TYPE_NONE:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "none\n");
+ break;
+ case PVFS_TYPE_METAFILE:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "meta file\n");
+ break;
+ case PVFS_TYPE_DATAFILE:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "data file\n");
+ break;
+ case PVFS_TYPE_DIRECTORY:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "directory\n");
+ break;
+ case PVFS_TYPE_SYMLINK:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "symlink\n");
+ break;
+ case PVFS_TYPE_DIRDATA:
+ gossip_debug(GOSSIP_FSCK_DEBUG, "dirdata\n");
+ break;
+ }
+ gossip_debug(GOSSIP_FSCK_DEBUG, "\n");
+
+ return ret;
+}
+
+/**
+ * Performs final steps of fsck. If option was enabled to check for stranded
+ * objects, then it will print any leftover objects.
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+int PVFS_fsck_finalize(
+ const struct PINT_fsck_options *fsck_options, /**< Populated options */
+ const PVFS_fs_id * cur_fs, /**< The fsid the handle belongs to */
+ const PVFS_credentials * creds) /**< populated credentials structure */
+{
+ /* display leftover handles */
+ if (fsck_options->check_stranded_objects)
+ {
+ PINT_handle_wrangler_display_stranded_handles(fsck_options, cur_fs,
+ creds);
+ }
+
+ return(0);
+}
+
+/**
+ * Gets a list of all the handles used from the PVFS2 servers. The PVFS2 system
+ * interface must have already been initialized.
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+static int PINT_handle_wrangler_load_handles(
+ const struct PINT_fsck_options *fsck_options, /**< Populated options */
+ const PVFS_fs_id * cur_fs, /**< fs_id */
+ const PVFS_credentials * creds) /**< populdated credentials structure */
+{
+ int ret = 0;
+ int server_count;
+ struct PVFS_mgmt_server_stat *stat_array = NULL;
+ PVFS_handle **handle_matrix = NULL;
+ int i = 0;
+ int *handle_count_array = NULL;
+ PVFS_ds_position *position_array = NULL;
+ int more_handles = 0;
+ int err = 0;
+
+ gossip_debug(GOSSIP_FSCK_DEBUG,
+ "getting all file handles from filesystem\n");
+
+ memset(&PINT_handle_wrangler_handlelist, 0,
+ sizeof(PINT_handle_wrangler_handlelist));
+
+ /* count how many servers we have */
+ err = PVFS_mgmt_count_servers(*cur_fs,
+ (PVFS_credentials *) creds,
+ PVFS_MGMT_IO_SERVER | PVFS_MGMT_META_SERVER,
+ &server_count);
+ if(err < 0)
+ {
+ PVFS_perror_gossip("PVFS_mgmt_count_servers", err);
+ return err;
+ }
+
+ PINT_handle_wrangler_handlelist.num_servers = server_count;
+
+ PINT_handle_wrangler_handlelist.addr_array =
+ (PVFS_BMI_addr_t *) calloc(server_count, sizeof(PVFS_BMI_addr_t));
+ if (PINT_handle_wrangler_handlelist.addr_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ /* get a list of the pvfs2 servers */
+ err = PVFS_mgmt_get_server_array(*cur_fs,
+ (PVFS_credentials *) creds,
+ PVFS_MGMT_IO_SERVER | PVFS_MGMT_META_SERVER,
+ PINT_handle_wrangler_handlelist.addr_array,
+ &server_count);
+ if(err < 0)
+ {
+ PVFS_perror_gossip("PVFS_mgmt_get_server_array", err);
+ ret = err;
+ goto load_handles_error;
+ }
+
+ stat_array = (struct PVFS_mgmt_server_stat *)
+ calloc(server_count, sizeof(struct PVFS_mgmt_server_stat));
+ if (stat_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ /* this gives us a count of the handles on each server */
+ err = PVFS_mgmt_statfs_list(*cur_fs,
+ (PVFS_credentials *) creds,
+ stat_array,
+ PINT_handle_wrangler_handlelist.addr_array,
+ server_count, NULL);
+ if(err < 0)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ /* allocate big chunks of memory to keep up with handles */
+ handle_count_array = (int *) calloc(server_count, sizeof(int));
+ if (handle_count_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ position_array = (PVFS_ds_position *) calloc(server_count,
+ sizeof(PVFS_ds_position));
+ if (position_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ PINT_handle_wrangler_handlelist.list_array =
+ (PVFS_handle **) calloc(server_count, sizeof(PVFS_handle *));
+ if (PINT_handle_wrangler_handlelist.list_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+ memset(PINT_handle_wrangler_handlelist.list_array, 0,
+ server_count*sizeof(PVFS_handle*));
+
+ PINT_handle_wrangler_handlelist.list_array_seen =
+ (char **) calloc(server_count, sizeof(char *));
+ if (PINT_handle_wrangler_handlelist.list_array_seen == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+ memset(PINT_handle_wrangler_handlelist.list_array_seen, 0,
+ server_count*sizeof(char*));
+
+ PINT_handle_wrangler_handlelist.size_array =
+ (int *) calloc(server_count, sizeof(int));
+ if (PINT_handle_wrangler_handlelist.size_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ PINT_handle_wrangler_handlelist.used_array =
+ (int *) calloc(server_count, sizeof(int));
+ if (PINT_handle_wrangler_handlelist.used_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ PINT_handle_wrangler_handlelist.stranded_array =
+ (int *) calloc(server_count, sizeof(int));
+ if (PINT_handle_wrangler_handlelist.stranded_array == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ /* temporary array to keep state while fetching handles */
+ handle_matrix =
+ (PVFS_handle **) calloc(server_count, sizeof(PVFS_handle *));
+ if (handle_matrix == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+ memset(handle_matrix, 0, server_count*sizeof(PVFS_handle*));
+
+ /* populating a nice "handlelist" struct with all this various handle data */
+ for (i = 0; i < server_count; i++)
+ {
+ PINT_handle_wrangler_handlelist.size_array[i] =
+ stat_array[i].handles_total_count -
+ stat_array[i].handles_available_count;
+
+ PINT_handle_wrangler_handlelist.used_array[i] = 0;
+
+ PINT_handle_wrangler_handlelist.list_array[i] =
+ (PVFS_handle *) calloc(PINT_handle_wrangler_handlelist.size_array[i],
+ sizeof(PVFS_handle));
+ if (PINT_handle_wrangler_handlelist.list_array[i] == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ PINT_handle_wrangler_handlelist.list_array_seen[i] =
+ (char *) calloc(PINT_handle_wrangler_handlelist.size_array[i],
+ sizeof(char));
+ if (PINT_handle_wrangler_handlelist.list_array_seen[i] == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ handle_matrix[i] =
+ (PVFS_handle *) calloc(PINT_handle_wrangler_handlelist.size_array[i],
+ sizeof(PVFS_handle));
+ if (handle_matrix[i] == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ goto load_handles_error;
+ }
+
+ position_array[i] = PVFS_ITERATE_START;
+ handle_count_array[i] = HANDLE_BATCH;
+ }
+
+ /* repeatedly grab handles until we get them all */
+ do
+ {
+ /* mgmt call to get block of handles */
+ err = PVFS_mgmt_iterate_handles_list(*cur_fs,
+ (PVFS_credentials *) creds,
+ handle_matrix,
+ handle_count_array,
+ position_array,
+ PINT_handle_wrangler_handlelist.
+ addr_array, server_count, NULL);
+ if(err < 0)
+ {
+ PVFS_perror_gossip("PVFS_mgmt_iterate_handles", err);
+ ret = err;
+ goto load_handles_error;
+ }
+
+ more_handles = 0;
+
+ for (i = 0; i < server_count; i++)
+ {
+ /* add this block of handles to the full list */
+ int j = 0;
+ for (j = 0; j < handle_count_array[i]; j++)
+ {
+ PINT_handle_wrangler_handlelist.list_array[i]
+ [PINT_handle_wrangler_handlelist.used_array[i] + j] =
+ handle_matrix[i][j];
+ }
+
+ PINT_handle_wrangler_handlelist.used_array[i] +=
+ handle_count_array[i];
+
+ /* are there more handles? */
+ if (position_array[i] != PVFS_ITERATE_END)
+ {
+ more_handles = 1;
+ }
+ }
+ } while (more_handles != 0);
+
+ for (i = 0; i < server_count; i++)
+ {
+ /* sort the list of handles */
+ qsort(PINT_handle_wrangler_handlelist.list_array[i],
+ PINT_handle_wrangler_handlelist.used_array[i],
+ sizeof(PVFS_size), compare_handles);
+
+ /* we will decrement this during the actual fsck as we check each handle */
+ PINT_handle_wrangler_handlelist.stranded_array[i] =
+ PINT_handle_wrangler_handlelist.used_array[i];
+ }
+ ret = 0;
+ goto load_handles_success;
+
+load_handles_error:
+ if(PINT_handle_wrangler_handlelist.stranded_array)
+ free(PINT_handle_wrangler_handlelist.stranded_array);
+ if(PINT_handle_wrangler_handlelist.used_array)
+ free(PINT_handle_wrangler_handlelist.used_array);
+ if(PINT_handle_wrangler_handlelist.size_array)
+ free(PINT_handle_wrangler_handlelist.size_array);
+ if(PINT_handle_wrangler_handlelist.addr_array)
+ free(PINT_handle_wrangler_handlelist.addr_array);
+ if(PINT_handle_wrangler_handlelist.list_array)
+ {
+ for(i=0; i<server_count; i++)
+ {
+ if(PINT_handle_wrangler_handlelist.list_array[i])
+ free(PINT_handle_wrangler_handlelist.list_array[i]);
+ }
+ free(PINT_handle_wrangler_handlelist.list_array);
+ }
+ if(PINT_handle_wrangler_handlelist.list_array_seen)
+ {
+ for(i=0; i<server_count; i++)
+ {
+ if(PINT_handle_wrangler_handlelist.list_array_seen[i])
+ free(PINT_handle_wrangler_handlelist.list_array_seen[i]);
+ }
+ free(PINT_handle_wrangler_handlelist.list_array_seen);
+ }
+
+ /* fall through on purpose */
+
+load_handles_success:
+ if(handle_matrix)
+ {
+ for(i=0; i<server_count; i++)
+ {
+ if(handle_matrix[i])
+ free(handle_matrix[i]);
+ }
+ free(handle_matrix);
+ }
+ if(position_array)
+ free(position_array);
+ if(handle_count_array)
+ free(handle_count_array);
+ if(stat_array)
+ free(stat_array);
+
+ return ret;
+}
+
+/**
+ * Removes the given handle from the list of handles stored. Each check in
+ * the fsck calls this function as it sees a handle. The end result is a
+ * list of left over "stranded" handles.
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+static int PINT_handle_wrangler_remove_handle(
+ const PVFS_handle * handle, /**< handle to remove */
+ const PVFS_fs_id * cur_fs) /**< fs_id */
+{
+ int ret = 0;
+ int i = 0;
+ int j = 0;
+ PVFS_BMI_addr_t server_addr;
+ int found = 0;
+
+ /* find which server the handle is on */
+ ret = PINT_cached_config_map_to_server(&server_addr, *handle, *cur_fs);
+ if(ret < 0)
+ {
+ PVFS_perror_gossip("PINT_cached_config_map_to_server", ret);
+ gossip_err("Error: could not resolve handle [%llu] to server\n",
+ llu(*handle));
+ return(ret);
+ }
+
+ /* get the index of the server this handle is located on */
+ for (i = 0; i < PINT_handle_wrangler_handlelist.num_servers; i++)
+ {
+ if (PINT_handle_wrangler_handlelist.addr_array[i] == server_addr)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(!found)
+ {
+ gossip_err("Error: could not find matching server for handle [%llu]\n",
+ llu(*handle));
+ return(-PVFS_EINVAL);
+ }
+
+ /* keep up with which handles have been "seen" */
+ found = 0;
+ for (j = 0; j < PINT_handle_wrangler_handlelist.used_array[i]; j++)
+ {
+ if (PINT_handle_wrangler_handlelist.list_array[i][j] == *handle)
+ {
+ PINT_handle_wrangler_handlelist.list_array_seen[i][j] = 'x';
+ PINT_handle_wrangler_handlelist.stranded_array[i]--;
+ found = 1;
+ break;
+ }
+ }
+ if(!found)
+ {
+ gossip_err("Error: could not find handle [%llu]\n",
+ llu(*handle));
+ return(-PVFS_EINVAL);
+ }
+
+ return ret;
+}
+
+#if 0
+/**
+ * Returns the handles left over from the fsck
+ */
+static int PINT_handle_wrangler_get_stranded_handles(
+ const PVFS_fs_id * cur_fs, /**< filesystem id */
+ int *num_stranded_handles, /**< number of handles in array of handles returned */
+ PVFS_handle ** stranded_handles) /**< array of stranded handles on fs cur_fs */
+{
+ int ret = 0;
+ int i = 0;
+ int j = 0;
+ int position = 0;
+
+ *num_stranded_handles = 0;
+
+ for (i = 0; i < PINT_handle_wrangler_handlelist.num_servers; i++)
+ {
+ (*num_stranded_handles) +=
+ PINT_handle_wrangler_handlelist.stranded_array[i];
+ }
+
+ *stranded_handles = (PVFS_handle *) calloc((*num_stranded_handles), sizeof(PVFS_handle));
+ if (*stranded_handles == NULL)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ for (i = 0; i < PINT_handle_wrangler_handlelist.num_servers; i++)
+ {
+ for (j = 0; j < PINT_handle_wrangler_handlelist.used_array[i]; j++)
+ {
+ if (!PINT_handle_wrangler_handlelist.list_array_seen[i][j])
+ {
+ (*stranded_handles)[position] =
+ PINT_handle_wrangler_handlelist.list_array[i][j];
+ position++;
+ }
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/**
+ * Displays the handles left over from the fsck
+ *
+ * \retval 0 on success
+ * \retval -PVFS_error on failure
+ */
+static int PINT_handle_wrangler_display_stranded_handles(
+ const struct PINT_fsck_options *fsck_options, /**< populated fsck options */
+ const PVFS_fs_id * cur_fs, /**< filesystem id */
+ const PVFS_credentials * creds) /**< populated credentials structure */
+{
+ int ret = 0;
+ int i = 0;
+ int j = 0;
+ int server_type = 0;
+ PVFS_sysresp_getattr attributes;
+ PVFS_object_ref pref;
+ const char *server_name = NULL;
+ int header = 0;
+
+ for (i = 0; i < PINT_handle_wrangler_handlelist.num_servers; i++)
+ {
+ /* get the pretty server name */
+ server_name = PINT_cached_config_map_addr(
+ *cur_fs, PINT_handle_wrangler_handlelist.
+ addr_array[i], &server_type);
+
+ for (j = 0; j < PINT_handle_wrangler_handlelist.size_array[i]; j++)
+ {
+ if (!PINT_handle_wrangler_handlelist.list_array_seen[i][j])
+ {
+ pref.handle = PINT_handle_wrangler_handlelist.list_array[i][j];
+ pref.fs_id = *cur_fs;
+
+ if(!header)
+ {
+ printf("\n");
+ printf("Stranded Objects:\n");
+ printf
+ ("[ Handle ] [ FSID ] [ Size ] [File Type] [ PVFS2 Server ]\n");
+ header = 1;
+ }
+
+ /* get this objects attributes */
+ ret = PVFS_fsck_get_attributes(fsck_options, &pref, creds,
+ &attributes);
+ if(ret < 0)
+ {
+ PVFS_perror_gossip("PVFS_fsck_get_attributes", ret);
+ gossip_err("Error: unable to retrieve attributes for handle [%llu]\n",
+ llu(pref.handle));
+ return(ret);
+ }
+
+ printf(" %llu %d ",
+ llu(PINT_handle_wrangler_handlelist.list_array[i][j]),
+ *cur_fs);
+
+ if (attributes.attr.mask & PVFS_ATTR_SYS_SIZE)
+ {
+ printf("%13lld ", lld(attributes.attr.size));
+ }
+
+ switch (attributes.attr.objtype)
+ {
+ case PVFS_TYPE_NONE:
+ printf("none ");
+ break;
+ case PVFS_TYPE_METAFILE:
+ printf("meta file");
+ break;
+ case PVFS_TYPE_DATAFILE:
+ printf("data file");
+ break;
+ case PVFS_TYPE_DIRECTORY:
+ printf("directory");
+ break;
+ case PVFS_TYPE_SYMLINK:
+ printf("symlink ");
+ free(attributes.attr.link_target);
+ break;
+ case PVFS_TYPE_DIRDATA:
+ printf("dirdata ");
+ break;
+ }
+ printf(" %s\n", server_name);
+ }
+ }
+ }
+
+ if(!header)
+ {
+ printf("No stranded objects found.\n");
+ }
+
+ return ret;
+}
+
+/**
+ * Compares two handles, for qsort()
+ *
+ * \retval 0 if equal
+ * \retval <0 if handle1 less than handle2
+ * \retval >0 if handle1 greater than handle2
+ */
+static int compare_handles(
+ const void *handle1, /**< handle 1*/
+ const void *handle2) /**< handle 2*/
+{
+ PVFS_size temp_handle =
+ *((PVFS_handle *) handle1) - *((PVFS_handle *) handle2);
+
+ if (temp_handle > 0)
+ {
+ return 1;
+ }
+ else if (temp_handle < 0)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/**
+ * Set the return code for a function, taking previous return values into
+ * account. The purpose of this is to make sure when we are propigating
+ * errors that warnings do not take precident over standard error codes.
+ */
+static void set_return_code(
+ int *ret, /**< error code to populate */
+ const int retval) /**< the value we are proposing to set the error code to */
+{
+ if (*ret >= 0)
+ {
+ *ret = retval;
+ }
+ else if (retval != 0)
+ {
+ *ret = retval;
+ }
+}
+
+/* @} */
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ fsck-utils.h 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ * Copyright © Acxiom Corporation, 2005
+ *
+ * See COPYING in top-level directory.
+ */
+
+#ifndef __FSCK_UTILS_H
+#define __FSCK_UTILS_H
+
+#include "pvfs2.h"
+#include "pvfs2-mgmt.h"
+#include "pvfs2-internal.h"
+#include "pint-cached-config.h"
+#include "pint-sysint-utils.h"
+
+#include <stdlib.h>
+
+/** \defgroup fsckutils FSCK Utilities
+ *
+ * The fsck-utils implements a API for checking validity of different PVFS_objects.
+ *
+ * List of PVFS_Object types with API's allowing validity checks:
+ * - PVFS_TYPE_METAFILE
+ * - PVFS_TYPE_DIRECTORY
+ * - PVFS_TYPE_DATAFILE
+ * - PVFS_TYPE_DIRDATA
+ * - PVFS_TYPE_SYMLINK
+ * .
+ * The API is broken up into two sections. The first section simply validates
+ * whether an object is valid. The second section will perform some action
+ * in attempt to either fix or remove the problem.
+ *
+ * @see PINT_fsck_options for optional file system checks
+ *
+ * Any driver program calling this will need to initialize the PVFS system
+ * interface first.
+ * @{
+ */
+
+/** \file
+ * Declarations for the fsck utility component.
+ */
+
+/** FSCK options */
+struct PINT_fsck_options
+{
+ unsigned int fix_errors; /**< fix errors found */
+ unsigned int check_stranded_objects; /**< check for stranded objects */
+ unsigned int check_symlink_target; /**< checks symlink target for bad practice */
+ unsigned int check_dir_entry_names; /**< checks dirent names for bad practice */
+ unsigned int verbose; /**< enable verbose output */
+ unsigned int check_fs_configs; /**< verify fs config files */
+ char* start_path; /**< PVFS2 path to begin check */
+};
+
+int PVFS_fsck_initialize(
+ const struct PINT_fsck_options* options,
+ const PVFS_credentials* creds,
+ const PVFS_fs_id* cur_fs);
+
+int PVFS_fsck_validate_dfile(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_handle* handle,
+ const PVFS_fs_id* cur_fs,
+ const PVFS_credentials* creds,
+ PVFS_size* dfile_total_size);
+
+int PVFS_fsck_validate_dfile_attr(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_metafile(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_object_ref* obj_ref,
+ const PVFS_sysresp_getattr* attributes,
+ const PVFS_credentials* creds);
+
+int PVFS_fsck_validate_metafile_attr(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_symlink(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_object_ref* obj_ref,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_symlink_attr(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_symlink_target(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_dirdata(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_handle* handle,
+ const PVFS_fs_id* cur_fs,
+ const PVFS_credentials* creds);
+
+int PVFS_fsck_validate_dirdata_attr(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_dir(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_object_ref* obj_ref,
+ const PVFS_sysresp_getattr* attributes,
+ const PVFS_credentials* creds,
+ PVFS_dirent* directory_entries);
+
+int PVFS_fsck_validate_dir_attr(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_sysresp_getattr* attributes);
+
+int PVFS_fsck_validate_dir_ent(
+ const struct PINT_fsck_options* fsck_options,
+ const char* filename);
+
+int PVFS_fsck_finalize(
+ const struct PINT_fsck_options* fsck_options,
+ const PVFS_fs_id* cur_fs,
+ const PVFS_credentials*);
+
+int PVFS_fsck_get_attributes(
+ const struct PINT_fsck_options*,
+ const PVFS_object_ref*,
+ const PVFS_credentials*,
+ PVFS_sysresp_getattr* );
+
+int PVFS_fsck_check_server_configs(
+ const struct PINT_fsck_options*,
+ const PVFS_credentials*,
+ const PVFS_fs_id*);
+
+/** TODO:
+ * Need to add functions to repair problems. (PVFS2_fsck_fix_XXXX() ?)
+ */
+
+#endif
+
+/* @} */
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ pint-eattr.c 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,359 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define __PINT_REQPROTO_ENCODE_FUNCS_C
+#include "endecode-funcs.h"
+#include "pvfs2.h"
+#include "pint-eattr.h"
+#include "pvfs2-req-proto.h"
+#include "pvfs2-internal.h"
+
+#define PVFS_EATTR_SYSTEM_NS "system.pvfs2."
+
+/* This is used to encode/decode the datafile handles array when its retrieved
+ * as an extended attribute (viewdist does this)
+ */
+struct PINT_handle_array
+{
+ int32_t count;
+ PVFS_handle *handles;
+};
+endecode_fields_1a_struct(PINT_handle_array,
+ skip4,,
+ int32_t, count,
+ PVFS_handle, handles);
+
+/* extended attribute name spaces supported in PVFS2 */
+struct PINT_eattr_check
+{
+ const char * ns;
+ int ret;
+ int (* check) (PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+};
+
+/* PINT_eattr_strip_prefix
+ *
+ * Remove the 'system.pvfs2.' prefix from attributes before querying.
+ * These specific attributes are stored without the prefix.
+ */
+static int PINT_eattr_strip_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+static struct PINT_eattr_check PINT_eattr_access[] =
+{
+ {PVFS_EATTR_SYSTEM_NS, 0, PINT_eattr_strip_prefix},
+ {"system.", 0, NULL},
+ {"user.", 0, NULL},
+ {"trusted.", 0, NULL},
+ {"security.", 0, NULL},
+ {NULL, -PVFS_ENOENT, NULL}
+};
+
+/* PINT_eattr_system_verify
+ *
+ * Check the eattrs with system. namespace prefixes. Right now this
+ * only checks that acls are formatted properly.
+ */
+static int PINT_eattr_system_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v);
+
+/* We provide namespace structures that include error codes
+ * or checking functions. For an extended attribute, the
+ * namespace is checked by iterating from top to bottom
+ * through this list. If a namespace matches and the error
+ * code is non-zero, the error code is returned, otherwise,
+ * the checking function is called (if non-null). If none of the namespaces
+ * in the list match (or the eattr isn't prefixed with
+ * a namespace, the last entry in the list is triggered,
+ * and EOPNOTSUPP is returned. Since we don't allow
+ * eattrs with system.pvfs2. prefixes to be set by the
+ * set-eattr operation, we return EINVAL in that case.
+ */
+static struct PINT_eattr_check PINT_eattr_namespaces[] =
+{
+ {PVFS_EATTR_SYSTEM_NS, -PVFS_EINVAL, NULL},
+ {"system.", 0, PINT_eattr_system_verify},
+ {"user.", 0, NULL},
+ {"trusted.", 0, NULL},
+ {"security.", 0, NULL},
+ {NULL, -PVFS_EOPNOTSUPP, NULL}
+};
+
+static int PINT_eattr_verify_acl_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* Used to verify that acls are correctly formatted before plopping
+ * them in storage
+ */
+static struct PINT_eattr_check PINT_eattr_system[] =
+{
+ {"system.posix_acl_access", 0, PINT_eattr_verify_acl_access},
+ {NULL, 0, NULL}};
+
+static int PINT_eattr_add_pvfs_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* check that the eattr in the list matches a valid namespace. If
+ * it doesn't, assume its in the system.pvfs2. namespace, and tack
+ * on that prefix (using the PINT_eattr_add_pvfs_prefix function).
+ */
+static struct PINT_eattr_check PINT_eattr_list[] =
+{
+ {"system.", 0, NULL},
+ {"user.", 0, NULL},
+ {"trusted.", 0, NULL},
+ {"security.", 0, NULL},
+ {NULL, 0, PINT_eattr_add_pvfs_prefix}
+};
+
+static int PINT_eattr_encode_datafile_handle_array(
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+static struct PINT_eattr_check PINT_eattr_encode_keyvals[] =
+{
+ {DATAFILE_HANDLES_KEYSTR, 0,
+ PINT_eattr_encode_datafile_handle_array},
+ {NULL, 0, NULL}
+};
+
+static int PINT_eattr_decode_datafile_handle_array(
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+static struct PINT_eattr_check PINT_eattr_decode_keyvals[] =
+{
+ {PVFS_EATTR_SYSTEM_NS DATAFILE_HANDLES_KEYSTR, 0,
+ PINT_eattr_decode_datafile_handle_array},
+ {NULL, 0, NULL}
+};
+
+/* PINT_eattr_verify
+ *
+ * Useful as a basic function that does verification given an array of
+ * extended attribute checking structures. It essentially iterates
+ * through the array and compares the key's buffer with each element.
+ * If one matches, it uses the other fields in that checking structure
+ * to verify the eattr.
+ */
+static inline int PINT_eattr_verify(
+ struct PINT_eattr_check * eattr_array,
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+int PINT_eattr_check_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ return PINT_eattr_verify(PINT_eattr_access, key, val);
+}
+
+static int PINT_eattr_strip_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ char * tmp_buffer = NULL;
+ int tmp_len;
+ int ret;
+
+ tmp_buffer = (char*)malloc(PVFS_REQ_LIMIT_KEY_LEN);
+ if(!tmp_buffer)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ /* look for keys in the special "system.pvfs2." prefix and strip the
+ * prefix off; they are stored as keyvals with no prefix within
+ * trove.
+ */
+ ret = sscanf(key->buffer,
+ PVFS_EATTR_SYSTEM_NS "%s", tmp_buffer);
+ if(ret != 1)
+ {
+ free(tmp_buffer);
+ return -PVFS_ENOENT;
+ }
+
+ tmp_len = strlen(tmp_buffer) + 1;
+ memcpy(key->buffer, tmp_buffer, tmp_len);
+ key->buffer_sz = tmp_len;
+ free(tmp_buffer);
+ return 0;
+}
+
+static int PINT_eattr_encode_datafile_handle_array(
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ char *tmp_buffer = NULL;
+ char *ptr;
+ struct PINT_handle_array harray;
+
+ harray.count = val->read_sz / sizeof(PVFS_handle);
+ harray.handles = (PVFS_handle *)val->buffer;
+
+ /* allocate twice as much as we probably need here */
+ tmp_buffer = malloc(harray.count * 2 * sizeof(int64_t));
+ if(!tmp_buffer)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ ptr = tmp_buffer;
+ encode_PINT_handle_array(&ptr, &harray);
+
+ free(val->buffer);
+ val->buffer = tmp_buffer;
+ val->buffer_sz = val->read_sz = (ptr - tmp_buffer);
+ return 0;
+}
+
+static int PINT_eattr_decode_datafile_handle_array(
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ char *ptr;
+ struct PINT_handle_array harray;
+
+ ptr = val->buffer;
+ decode_PINT_handle_array(&ptr, &harray);
+
+ if(val->buffer_sz < (harray.count * sizeof(PVFS_handle)))
+ {
+ decode_free(harray.handles);
+ return -PVFS_EMSGSIZE;
+ }
+
+ val->read_sz = val->buffer_sz = (harray.count * sizeof(PVFS_handle));
+ memcpy(val->buffer, (void *)harray.handles, val->read_sz);
+
+ return 0;
+}
+
+static inline int PINT_eattr_verify(
+ struct PINT_eattr_check * eattr_array,
+ PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ int i = 0;
+ while(1)
+ {
+ /* if we get to the NULL ns at the end of the list, return
+ * the error code
+ */
+ if(!eattr_array[i].ns)
+ {
+ if(eattr_array[i].ret == 0 && eattr_array[i].check)
+ {
+ return eattr_array[i].check(key, val);
+ }
+ return eattr_array[i].ret;
+ }
+
+ if(strncmp(eattr_array[i].ns, key->buffer,
+ strlen(eattr_array[i].ns)) == 0)
+ {
+ /* if the return value for this namespace is non-zero,
+ * return that value
+ */
+ if(eattr_array[i].ret != 0)
+ {
+ return eattr_array[i].ret;
+ }
+
+ /* if the checking function for this namespace is non-null,
+ * invoke that checking function and return the result.
+ */
+ if(eattr_array[i].check)
+ {
+ return eattr_array[i].check(key, val);
+ }
+
+ /* looks like the namespace is otherwise acceptable */
+ return 0;
+ }
+ i++;
+ }
+
+ /* this shouldn't be possible */
+ return(0);
+}
+
+int PINT_eattr_system_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v)
+{
+ return PINT_eattr_verify(PINT_eattr_system, k, v);
+}
+
+int PINT_eattr_namespace_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v)
+{
+ return PINT_eattr_verify(PINT_eattr_namespaces, k, v);
+}
+
+static int PINT_eattr_verify_acl_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+
+ assert(!strcmp(key->buffer, "system.posix_acl_access"));
+
+ /* verify that the acl is formatted properly. Right now
+ * all we can do is make sure the size matches a non-zero
+ * number of pvfs acl entries. The remainder should be 1
+ * because the keyvals are padded with a null terminator
+ */
+ if(val->buffer_sz == 0 ||
+ val->buffer_sz % sizeof(pvfs2_acl_entry) != 1)
+ {
+ return -PVFS_EINVAL;
+ }
+
+ return 0;
+}
+
+int PINT_eattr_list_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ return PINT_eattr_verify(PINT_eattr_list, key, val);
+}
+
+/* PINT_eattr_add_pvfs_prefix
+ *
+ * Tack on the system.pvfs2. prefix to any eattrs that don't have it.
+ * This is used by the eattr list operation for pvfs specific attributes,
+ * such as 'dh' (datafile handles) or 'md' (metafile distribution).
+ */
+static int PINT_eattr_add_pvfs_prefix(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ char * tmp_buffer = NULL;
+ int ret;
+
+ if(key->buffer_sz < (key->read_sz + sizeof(PVFS_EATTR_SYSTEM_NS)))
+ {
+ return -PVFS_EMSGSIZE;
+ }
+
+ tmp_buffer = (char*)malloc(key->read_sz + sizeof(PVFS_EATTR_SYSTEM_NS));
+ if(!tmp_buffer)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ ret = sprintf(tmp_buffer, "%s%.*s",
+ PVFS_EATTR_SYSTEM_NS, key->read_sz, (char *)key->buffer);
+ memcpy(key->buffer, tmp_buffer, ret+1);
+ key->read_sz = ret+1;
+
+ free(tmp_buffer);
+ return 0;
+}
+
+int PINT_eattr_encode(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ return PINT_eattr_verify(PINT_eattr_encode_keyvals, key, val);
+}
+
+int PINT_eattr_decode(PVFS_ds_keyval *key, PVFS_ds_keyval *val)
+{
+ return PINT_eattr_verify(PINT_eattr_decode_keyvals, key, val);
+}
+
+/*
+ * Local variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ pint-eattr.h 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+#ifndef PINT_EATTR_H
+#define PINT_EATTR_H
+
+#include "pvfs2-types.h"
+
+/* Extended Attributes
+ *
+ * These functions provide checking of extended attributes formats
+ * and namespaces
+ */
+
+/* PINT_eattr_list_verify
+ *
+ * Verify the extended attribute using the check access structure array
+ */
+int PINT_eattr_list_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* PINT_eattr_check_access
+ *
+ * Check that a request extended attribute is correctly formatted and
+ * within a valid namespace
+ */
+int PINT_eattr_check_access(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+/* PINT_eattr_namespace_verify
+ *
+ * Checks that the eattr has a valid namespace that PVFS accepts
+ */
+int PINT_eattr_namespace_verify(PVFS_ds_keyval *k, PVFS_ds_keyval *v);
+
+/* PINT_eattr_encode
+ *
+ * Encode eattrs that we know about (system.pvfs2.*) so that clients
+ * with different endianness can handle the extended attributes properly.
+ * Right now we only care about datafile handles.
+ */
+int PINT_eattr_encode(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+int PINT_eattr_decode(PVFS_ds_keyval *key, PVFS_ds_keyval *val);
+
+#endif
+/*
+ * Local variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
+
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ pint-hint.h 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,82 @@
+
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#ifndef __PINT_HINT_H__
+#define __PINT_HINT_H__
+
+#define PVFS_HINT_MAX 24
+#define PVFS_HINT_MAX_LENGTH 1024
+#define PVFS_HINT_MAX_NAME_LENGTH 512
+
+#include "pvfs2-hint.h"
+
+enum PINT_hint_type
+{
+ PINT_HINT_UNKNOWN = 0,
+ PINT_HINT_REQUEST_ID,
+ PINT_HINT_CLIENT_ID,
+ PINT_HINT_HANDLE,
+ PINT_HINT_OP_ID,
+};
+
+typedef struct PVFS_hint_s
+{
+ enum PINT_hint_type type;
+ char *type_string;
+ char *value;
+ int32_t length;
+
+ void (*encode)(char **pptr, void *value);
+ void (*decode)(char **pptr, void *value);
+
+ int flags;
+ struct PVFS_hint_s *next;
+
+} PINT_hint;
+
+void encode_PINT_hint(char **pptr, const PINT_hint *hint);
+void decode_PINT_hint(char **pptr, PINT_hint **hint);
+
+void *PINT_hint_get_value_by_type(PINT_hint *hint, enum PINT_hint_type type,
+ int *length);
+
+void *PINT_hint_get_value_by_name(
+ PINT_hint *hint, const char *name, int *length);
+
+int PVFS_hint_add_internal(
+ PVFS_hint *hint,
+ enum PINT_hint_type type,
+ int length,
+ void *value);
+
+#define PINT_HINT_GET_REQUEST_ID(hints) \
+ PINT_hint_get_value_by_type(hints, PINT_HINT_REQUEST_ID, NULL) ? \
+ *(uint32_t *)PINT_hint_get_value_by_type(hints, PINT_HINT_REQUEST_ID, NULL) : 0
+
+#define PINT_HINT_GET_CLIENT_ID(hints) \
+ PINT_hint_get_value_by_type(hints, PINT_HINT_CLIENT_ID, NULL) ? \
+ *(uint32_t *)PINT_hint_get_value_by_type(hints, PINT_HINT_CLIENT_ID, NULL) : 0
+
+#define PINT_HINT_GET_HANDLE(hints) \
+ PINT_hint_get_value_by_type(hints, PINT_HINT_HANDLE, NULL) ? \
+ *(uint64_t *)PINT_hint_get_value_by_type(hints, PINT_HINT_HANDLE, NULL) : 0
+
+#define PINT_HINT_GET_OP_ID(hints) \
+ PINT_hint_get_value_by_type(hints, PINT_HINT_OP_ID, NULL) ? \
+ *(uint32_t *)PINT_hint_get_value_by_type(hints, PINT_HINT_OP_ID, NULL) : 0
+
+#endif /* __PINT_HINT_H__ */
+
+/*
+ * Local variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ state-machine-fns.c 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,829 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#ifndef __STATE_MACHINE_FNS_H
+#define __STATE_MACHINE_FNS_H
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gossip.h"
+#include "pvfs2-debug.h"
+#include "state-machine.h"
+#include "client-state-machine.h"
+
+struct PINT_frame_s
+{
+ int task_id;
+ void *frame;
+ int error;
+ struct qlist_head link;
+};
+
+static struct PINT_state_s *PINT_pop_state(struct PINT_smcb *);
+static void PINT_push_state(struct PINT_smcb *, struct PINT_state_s *);
+static struct PINT_state_s *PINT_sm_task_map(struct PINT_smcb *smcb, int task_id);
+static void PINT_sm_start_child_frames(struct PINT_smcb *smcb, int* children_started);
+
+/* Function: PINT_state_machine_halt(void)
+ Params: None
+ Returns: True
+ Synopsis: This function is used to shutdown the state machine
+ */
+int PINT_state_machine_halt(void)
+{
+ return 0;
+}
+
+/* Function: PINT_state_machine_terminate
+ Params: smcb, job status
+ Returns: 0 on sucess, otherwise error
+ Synopsis: This function cleans up and terminates a SM
+ in some cases we may need to keep the SM alive until
+ its children terminate or something - in which case we
+ will post the relevant job here.
+ */
+int PINT_state_machine_terminate(struct PINT_smcb *smcb, job_status_s *r)
+{
+ struct PINT_frame_s *f;
+ void *my_frame;
+ job_id_t id;
+
+ /* notify parent */
+ if (smcb->parent_smcb)
+ {
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Terminating Child]: (%p) (error_code: %d)\n",
+ smcb,
+ /* skip pvfs2_ */
+ (int32_t)r->error_code);
+ assert(smcb->parent_smcb->children_running > 0);
+
+ my_frame = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
+ /* this will loop from TOS down to the base frame */
+ /* base frame will not be processed */
+ qlist_for_each_entry(f, &smcb->parent_smcb->frames, link)
+ {
+ if(my_frame == f->frame)
+ {
+ f->error = r->error_code;
+ break;
+ }
+ }
+
+ if (--smcb->parent_smcb->children_running <= 0)
+ {
+ /* no more child state machines running, so we can
+ * start up the parent state machine again
+ */
+ job_null(0, smcb->parent_smcb, 0, r, &id, smcb->context);
+ }
+ return SM_ACTION_DEFERRED;
+ }
+ /* call state machine completion function */
+ if (smcb->terminate_fn)
+ {
+ (*smcb->terminate_fn)(smcb, r);
+ }
+ return 0;
+}
+
+/* Function: PINT_state_machine_invoke
+ Params: smcb pointer and job status pointer
+ Returns: return value of state action
+ Synopsis: runs the current state action, produces debugging
+ output if needed, checls return value and takes action
+ if needed (sets op_terminate if SM_ACTION_TERMINATED is
+ returned)
+ */
+PINT_sm_action PINT_state_machine_invoke(struct PINT_smcb *smcb,
+ job_status_s *r)
+{
+ PINT_sm_action retval;
+ const char * state_name;
+ const char * machine_name;
+ int children_started = 0;
+
+ if (!(smcb) || !(smcb->current_state) ||
+ !(smcb->current_state->flag == SM_RUN ||
+ smcb->current_state->flag == SM_PJMP) ||
+ !(smcb->current_state->action.func))
+ {
+ gossip_err("SM invoke called on invalid smcb or state\n");
+ return SM_ERROR;
+ }
+
+ state_name = PINT_state_machine_current_state_name(smcb);
+ machine_name = PINT_state_machine_current_machine_name(smcb);
+
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Entering]: (%p) %s:%s (status: %d)\n",
+ smcb,
+ /* skip pvfs2_ */
+ machine_name,
+ state_name,
+ (int32_t)r->status_user_tag);
+
+ /* call state action function */
+ retval = (smcb->current_state->action.func)(smcb,r);
+ /* process return code */
+ switch (retval)
+ {
+ case SM_ACTION_TERMINATE :
+ smcb->op_terminate = 1;
+ break;
+ case SM_ACTION_COMPLETE :
+ case SM_ACTION_DEFERRED :
+ break;
+ default :
+ /* error */
+ gossip_err("SM Action %s:%s returned invalid return code %d (%p)\n",
+ machine_name, state_name, retval, smcb);
+ break;
+ }
+
+ /* print post-call debugging info */
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Exiting]: (%p) %s:%s (error code: %d), (action: %s)\n",
+ smcb,
+ /* skip pvfs2_ */
+ machine_name,
+ state_name,
+ r->error_code,
+ SM_ACTION_STRING(retval));
+
+ if (retval == SM_ACTION_COMPLETE && smcb->current_state->flag == SM_PJMP)
+ {
+ /* start child SMs */
+ PINT_sm_start_child_frames(smcb, &children_started);
+ /* if any children were started, then we return DEFERRED (even
+ * though they may have all completed immediately). The last child
+ * issues a job_null that will drive progress from here and we don't
+ * want to cause a double transition.
+ */
+ if (children_started > 0)
+ retval = SM_ACTION_DEFERRED;
+ else
+ retval = SM_ACTION_COMPLETE;
+ }
+
+ return retval;
+}
+
+/* Function: PINT_state_machine_start()
+ Params: smcb pointer and job status pointer
+ Returns: return value of last state action
+ Synopsis: Runs the state action pointed to by the
+ current state, then continues to run the SM
+ as long as return code is SM_ACTION_COMPLETE.
+ */
+
+PINT_sm_action PINT_state_machine_start(struct PINT_smcb *smcb, job_status_s *r)
+{
+ PINT_sm_action ret;
+
+ /* set the state machine to being completed immediately. We
+ * unset this bit once the state machine is deferred.
+ */
+ smcb->immediate = 1;
+
+ /* set the base frame to be the current TOS, which should be 0 */
+ smcb->base_frame = smcb->frame_count - 1;
+
+ /* run the current state action function */
+ ret = PINT_state_machine_invoke(smcb, r);
+ if (ret == SM_ACTION_COMPLETE || ret == SM_ACTION_TERMINATE)
+ {
+ /* keep running until state machine deferrs or terminates */
+ ret = PINT_state_machine_continue(smcb, r);
+ }
+
+ if(ret == SM_ACTION_DEFERRED)
+ {
+ /* this state machine isn't completing immediately */
+ smcb->immediate = 0;
+ }
+
+ return ret;
+}
+
+/* Function: PINT_state_machine_next()
+ Params: smcb pointer and job status pointer
+ Returns: return value of last state action
+ Synopsis: Runs through a list of return values to find the next function to
+ call. Calls that function. If that function returned COMPLETED loop
+ and repeat.
+ */
+PINT_sm_action PINT_state_machine_next(struct PINT_smcb *smcb, job_status_s *r)
+{
+ int i; /* index for transition table */
+ struct PINT_tran_tbl_s *transtbl;
+ PINT_sm_action ret; /* holds state action return code */
+
+ if (!smcb)
+ {
+ gossip_err("SM next called on invald smcb\n");
+ return -1;
+ }
+ /* loop while invoke of new state returns COMPLETED */
+ do {
+ /* loop while returning from nested SM */
+ do {
+ if (!smcb->current_state || !smcb->current_state->trtbl)
+ {
+ gossip_err("SM current state or trtbl is invalid "
+ "(smcb = %p)\n", smcb);
+ gossip_backtrace();
+ assert(0);
+ return -1;
+ }
+ transtbl = smcb->current_state->trtbl;
+
+ /* for each entry in the transition table there is a return
+ * code followed by a next state pointer to the new state.
+ * This loops through each entry, checking for a match on the
+ * return address, and then sets the new current_state and calls
+ * the new state action function */
+ for (i = 0; transtbl[i].return_value != DEFAULT_ERROR; i++)
+ {
+ if (transtbl[i].return_value == r->error_code)
+ break;
+ }
+ /* we expect the last state action function to return
+ * SM_ACTION_TERMINATE which sets the smcb->op_terminate
+ * flag. ALSO the state machine must direct the next state
+ * to be terminate, which sets loc->flag to SM_TERMINATE.
+ * We'll terminate for EITHER, but print an error if not
+ * both.
+ */
+ if(transtbl[i].flag == SM_TERM || smcb->op_terminate)
+ {
+ if (!(transtbl[i].flag == SM_TERM))
+ {
+ gossip_lerr("Error: state machine returned"
+ " SM_ACTION_TERMINATE but didn't reach terminate\n");
+ }
+ if (!smcb->op_terminate)
+ {
+ gossip_lerr("Error: state machine reached terminate"
+ " without returning SM_ACTION_TERMINATE\n");
+ smcb->op_terminate = 1;
+ }
+ return SM_ACTION_TERMINATE;
+ }
+ if (transtbl[i].flag == SM_RETURN)
+ {
+ /* if this is a return pop the stack
+ * and we'll continue from the state returned to
+ */
+ smcb->current_state = PINT_pop_state(smcb);
+ if(!smcb->current_state ||
+ smcb->current_state->trtbl[0].flag == SM_TERM)
+ {
+ /* assume nested state machine was invoked without
+ * a parent */
+ return SM_ACTION_TERMINATE;
+ }
+ }
+ } while (transtbl[i].flag == SM_RETURN);
+ smcb->current_state = transtbl[i].next_state;
+ /* To do nested states, we check to see if the next state is
+ * a nested state machine, and if so we push the return state
+ * onto a stack */
+ while (smcb->current_state->flag == SM_JUMP)
+ {
+ PINT_push_state(smcb, smcb->current_state);
+ smcb->current_state =
+ smcb->current_state->action.nested->first_state;
+ }
+ /* runs state_action and returns the return code */
+ ret = PINT_state_machine_invoke(smcb, r);
+ } while (ret == SM_ACTION_COMPLETE || ret == SM_ACTION_TERMINATE);
+ return ret;
+}
+
+/* Function: PINT_state_machine_continue
+ Params: smcb pointer and job status pointer
+ Returns: return value of last state action
+ Synopsis: This function essentially calls next, and if the state
+ machine terminates, calls terminate to perform cleanup.
+ This allows separation from the start call (which calls
+ next but does not call terminate if the state machine
+ terminates).
+*/
+PINT_sm_action PINT_state_machine_continue(struct PINT_smcb *smcb, job_status_s *r)
+{
+ PINT_sm_action ret;
+
+ ret = PINT_state_machine_next(smcb, r);
+
+ if(ret == SM_ACTION_TERMINATE)
+ {
+ /* process terminating SM */
+ PINT_state_machine_terminate(smcb, r);
+ }
+
+ return ret;
+}
+
+/* Function: PINT_state_machine_locate(void)
+ Params: smcb pointer with op correctly set
+ Returns: 1 on successful locate, 0 on locate failure, <0 on error
+ Synopsis: This function locates the state associated with the op
+ specified in smcb->op in order to start a state machine's
+ execution.
+ */
+int PINT_state_machine_locate(struct PINT_smcb *smcb)
+{
+ struct PINT_state_s *current_tmp;
+ struct PINT_state_machine_s *op_sm;
+ const char *state_name;
+ const char *machine_name;
+
+ /* check for valid inputs */
+ if (!smcb || smcb->op < 0 || !smcb->op_get_state_machine)
+ {
+ gossip_err("State machine requested not valid\n");
+ return -PVFS_EINVAL;
+ }
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Locating]: (%p) op-id: %d\n",smcb,(smcb)->op);
+ /* this is a the usage dependant routine to look up the SM */
+ op_sm = (*smcb->op_get_state_machine)(smcb->op);
+ if (op_sm != NULL)
+ {
+ current_tmp = op_sm->first_state;
+ /* handle the case in which the first state points to a nested
+ * machine, rather than a simple function
+ */
+ while(current_tmp->flag == SM_JUMP)
+ {
+ PINT_push_state(smcb, current_tmp);
+ current_tmp = ((struct PINT_state_machine_s *)
+ current_tmp->action.nested)->first_state;
+ }
+ smcb->current_state = current_tmp;
+
+ state_name = PINT_state_machine_current_state_name(smcb);
+ machine_name = PINT_state_machine_current_machine_name(smcb);
+
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Locating]: (%p) located: %s:%s\n",
+ smcb, machine_name, state_name);
+
+ return 1; /* indicates successful locate */
+ }
+ gossip_err("State machine not found for operation %d\n",smcb->op);
+ return 0; /* indicates failed to locate */
+}
+
+/* Function: PINT_smcb_set_op
+ Params: pointer to an smcb pointer, and an op code (int)
+ Returns: nothing
+ Synopsis: sets op on existing smcb and reruns locate if
+ we have a valid locate func
+ */
+int PINT_smcb_set_op(struct PINT_smcb *smcb, int op)
+{
+ smcb->op = op;
+ return PINT_state_machine_locate(smcb);
+}
+
+int PINT_smcb_immediate_completion(struct PINT_smcb *smcb)
+{
+ return smcb->immediate;
+}
+
+/* Function: PINT_smcb_op
+ Params: pointer to an smcb pointer
+ Returns: op (int)
+ Synopsis: returns the op currently set in the smcb
+ */
+int PINT_smcb_op(struct PINT_smcb *smcb)
+{
+ return smcb->op;
+}
+
+static int PINT_smcb_sys_op(struct PINT_smcb *smcb)
+{
+ if (smcb->op > 0 && smcb->op < PVFS_OP_SYS_MAXVALID)
+ return 1;
+ return 0;
+}
+
+static int PINT_smcb_mgmt_op(struct PINT_smcb *smcb)
+{
+ if (smcb->op > PVFS_OP_SYS_MAXVAL && smcb->op < PVFS_OP_MGMT_MAXVALID)
+ return 1;
+ return 0;
+}
+
+static int PINT_smcb_misc_op(struct PINT_smcb *smcb)
+{
+ return smcb->op == PVFS_SERVER_GET_CONFIG
+ || smcb->op == PVFS_SERVER_FETCH_CONFIG
+ || smcb->op == PVFS_CLIENT_JOB_TIMER
+ || smcb->op == PVFS_CLIENT_PERF_COUNT_TIMER
+ || smcb->op == PVFS_DEV_UNEXPECTED;
+}
+
+int PINT_smcb_invalid_op(struct PINT_smcb *smcb)
+{
+ if (!PINT_smcb_sys_op(smcb) && !PINT_smcb_mgmt_op(smcb) && !PINT_smcb_misc_op(smcb))
+ return 1;
+ return 0;
+}
+
+/* Function: PINT_smcb_set_complete
+ Params: pointer to an smcb pointer
+ Returns: nothing
+ Synopsis: sets op_terminate on existing smcb
+ */
+void PINT_smcb_set_complete(struct PINT_smcb *smcb)
+{
+ smcb->op_terminate = 1;
+}
+
+/* Function: PINT_smcb_complete
+ Params: pointer to an smcb pointer
+ Returns: op (int)
+ Synopsis: returns the op_terminate currently set in the smcb
+ */
+int PINT_smcb_complete(struct PINT_smcb *smcb)
+{
+ return smcb->op_terminate;
+}
+
+/* Function: PINT_smcb_set_cancelled
+ Params: pointer to an smcb pointer
+ Returns: nothing
+ Synopsis: sets op_cancelled on existing smcb
+ */
+void PINT_smcb_set_cancelled(struct PINT_smcb *smcb)
+{
+ smcb->op_cancelled = 1;
+}
+
+/* Function: PINT_smcb_cancelled
+ Params: pointer to an smcb pointer
+ Returns: op (int)
+ Synopsis: returns the op_cancelled currently set in the smcb
+ */
+int PINT_smcb_cancelled(struct PINT_smcb *smcb)
+{
+ return smcb->op_cancelled;
+}
+
+/* Function: PINT_smcb_alloc
+ Params: pointer to an smcb pointer, an op code (int), size of frame
+ (int), pinter to function to locate SM
+ Returns: nothing, but fills in pointer argument
+ Synopsis: this allocates an smcb struct, including its frame stack
+ and sets the op code so you can start the state machine
+ */
+int PINT_smcb_alloc(
+ struct PINT_smcb **smcb,
+ int op,
+ int frame_size,
+ struct PINT_state_machine_s *(*getmach)(int),
+ int (*term_fn)(struct PINT_smcb *, job_status_s *),
+ job_context_id context_id)
+{
+ *smcb = (struct PINT_smcb *)malloc(sizeof(struct PINT_smcb));
+ if (!(*smcb))
+ {
+ return -PVFS_ENOMEM;
+ }
+ /* zero out all members */
+ memset(*smcb, 0, sizeof(struct PINT_smcb));
+
+ INIT_QLIST_HEAD(&(*smcb)->frames);
+ (*smcb)->base_frame = -1; /* no frames yet */
+ (*smcb)->frame_count = 0;
+
+ /* if frame_size given, allocate a frame */
+ if (frame_size > 0)
+ {
+ void *new_frame = malloc(frame_size);
+ if (!new_frame)
+ {
+ free(*smcb);
+ *smcb = NULL;
+ return -PVFS_ENOMEM;
+ }
+ /* zero out all members */
+ memset(new_frame, 0, frame_size);
+ PINT_sm_push_frame(*smcb, 0, new_frame);
+ (*smcb)->base_frame = 0;
+ }
+ (*smcb)->op = op;
+ (*smcb)->op_get_state_machine = getmach;
+ (*smcb)->terminate_fn = term_fn;
+ (*smcb)->context = context_id;
+ /* if a getmach given, lookup state machine */
+ if (getmach)
+ return PINT_state_machine_locate(*smcb);
+ return 0; /* success */
+}
+
+/* Function: PINT_smcb_free
+ * Params: pointer to an smcb pointer
+ * Returns: nothing, but sets the pointer to NULL
+ * Synopsis: this frees an smcb struct, including
+ * anything on the frame stack with a zero task_id
+ */
+void PINT_smcb_free(struct PINT_smcb *smcb)
+{
+ struct PINT_frame_s *frame_entry, *tmp;
+ assert(smcb);
+ qlist_for_each_entry_safe(frame_entry, tmp, &smcb->frames, link)
+ {
+ if (frame_entry->frame && frame_entry->task_id == 0)
+ {
+ /* only free if task_id is 0 */
+ free(frame_entry->frame);
+ }
+ qlist_del(&frame_entry->link);
+ free(frame_entry);
+ }
+ free(smcb);
+}
+
+/* Function: PINT_pop_state
+ * Params: pointer to an smcb pointer
+ * Returns:
+ * Synopsis: pops a SM pointer off of a stack for
+ * implementing nested SMs - called by the
+ * "next" routine above
+ */
+static struct PINT_state_s *PINT_pop_state(struct PINT_smcb *smcb)
+{
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM pop_state]: (%p) op-id: %d stk-ptr: %d base-frm: %d\n",
+ smcb, smcb->op, smcb->stackptr, smcb->base_frame);
+
+ if(smcb->stackptr == 0)
+ {
+ /* this is not an error, we terminate if we return NULL */
+ /* this is return from main */
+ return NULL;
+ }
+
+ smcb->stackptr--;
+ smcb->base_frame = smcb->state_stack[smcb->stackptr].prev_base_frame;
+ return smcb->state_stack[smcb->stackptr].state;
+}
+
+/* Function: PINT_push_state
+ * Params: pointer to an smcb pointer
+ * Returns:
+ * Synopsis: pushes a SM pointer into a stack for
+ * implementing nested SMs - called by the
+ * "next" routine above
+ */
+static void PINT_push_state(struct PINT_smcb *smcb,
+ struct PINT_state_s *p)
+{
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM push_state]: (%p) op-id: %d stk-ptr: %d base-frm: %d\n",
+ smcb, smcb->op, smcb->stackptr, smcb->base_frame);
+
+ assert(smcb->stackptr < PINT_STATE_STACK_SIZE);
+
+ smcb->state_stack[smcb->stackptr].prev_base_frame = smcb->base_frame;
+ smcb->base_frame = smcb->frame_count - 1;
+ smcb->state_stack[smcb->stackptr].state = p;
+ smcb->stackptr++;
+}
+
+/* Function: PINT_sm_frame
+ * Params: pointer to smcb, stack index
+ * Returns: pointer to frame
+ * Synopsis: returns a frame off of the frame stack
+ * An index of 0 indicates the base frame specified in the SMCB
+ * A +'ve index indicates a frame pushed by this SM
+ * A -'ve index indicates a frame from a prior SM
+ * smcb->frames.next is the top of stack
+ * smcb->frames.prev is the bottom of stack
+ */
+void *PINT_sm_frame(struct PINT_smcb *smcb, int index)
+{
+ struct PINT_frame_s *frame_entry;
+ struct qlist_head *prev;
+ int target = smcb->base_frame + index;
+
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM frame get]: (%p) op-id: %d index: %d base-frm: %d\n",
+ smcb, smcb->op, index, smcb->base_frame);
+
+ if(qlist_empty(&smcb->frames))
+ {
+ gossip_err("FRAME GET smcb %p index %d target %d -> List empty\n",
+ smcb, index, target);
+ return NULL;
+ }
+ else
+ {
+ /* target should be 0 .. frame_count-1 now */
+ if (target < 0 || target >= smcb->frame_count)
+ {
+ gossip_err("FRAME GET smcb %p index %d target %d -> Out of range\n",
+ smcb, index, target);
+ return NULL;
+ }
+ prev = smcb->frames.prev;
+ while(target)
+ {
+ target--;
+ prev = prev->prev;
+ }
+ frame_entry = qlist_entry(prev, struct PINT_frame_s, link);
+ return frame_entry->frame;
+ }
+}
+
+/* Function: PINT_sm_push_frame
+ * Params: pointer to smcb, void pointer for new frame
+ * Returns:
+ * Synopsis: pushes a new frame pointer onto the frame_stack
+ */
+int PINT_sm_push_frame(struct PINT_smcb *smcb, int task_id, void *frame_p)
+{
+ struct PINT_frame_s *newframe;
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Frame PUSH]: (%p) frame: %p\n",
+ smcb, frame_p);
+ newframe = malloc(sizeof(struct PINT_frame_s));
+ if(!newframe)
+ {
+ return -PVFS_ENOMEM;
+ }
+ newframe->task_id = task_id;
+ newframe->frame = frame_p;
+ newframe->error = 0;
+ qlist_add(&newframe->link, &smcb->frames);
+ smcb->frame_count++;
+ return 0;
+}
+
+/* Function: PINT_sm_pop_frame
+ * Params: smcb - pointer to an smcb pointer
+ * task_id - the task id of this frame
+ * error_code - the frame's error if there was one.
+ * remaining - count of remaining frames on the smcb.
+ * Returns: frame pointer
+ * Synopsis: pops a frame pointer from the frame_stack and returns it
+ */
+void *PINT_sm_pop_frame(struct PINT_smcb *smcb,
+ int *task_id,
+ int *error_code,
+ int *remaining)
+{
+ struct PINT_frame_s *frame_entry;
+ void *frame;
+
+ if(qlist_empty(&smcb->frames))
+ {
+ return NULL;
+ }
+
+ frame_entry = qlist_entry(smcb->frames.next, struct PINT_frame_s, link);
+ qlist_del(smcb->frames.next);
+ smcb->frame_count--;
+
+ if(remaining)
+ {
+ *remaining = smcb->frame_count;
+ }
+
+ frame = frame_entry->frame;
+ *error_code = frame_entry->error;
+ *task_id = frame_entry->task_id;
+
+ free(frame_entry);
+
+ gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
+ "[SM Frame POP]: (%p) frame: %p\n",
+ smcb, frame);
+ return frame;
+}
+
+/* Function: PINT_sm_task_map
+ * Params: smcb and an integer task_id
+ * Returns: The state machine a new child state should execute
+ * Synopsis: Uses the task_id and task jump table from the SM
+ * code to decide which SM a new child should run. Called
+ * by the start_child_frames function
+ */
+static struct PINT_state_s *PINT_sm_task_map(struct PINT_smcb *smcb, int task_id)
+{
+ struct PINT_pjmp_tbl_s *pjmptbl;
+ int i;
+
+ pjmptbl = smcb->current_state->pjtbl;
+ for (i = 0; ; i++)
+ { if (pjmptbl[i].return_value == task_id ||
+ pjmptbl[i].return_value == -1)
+ return pjmptbl[i].state_machine->first_state;
+ }
+}
+
+static int child_sm_frame_terminate(struct PINT_smcb * smcb, job_status_s * js_p)
+{
+ PINT_smcb_free(smcb);
+ return 0;
+}
+
+/* Function: PINT_sm_start_child_frames
+ * Params: pointer to an smcb pointer and pointer to count of children
+ * started
+ * Returns: number of children started
+ * Synopsis: This starts all the enw child SMs based on the frame_stack
+ * This is called by the invoke function above which expects the
+ * number of children to be returned to decide if the state is
+ * deferred or not.
+ */
+static void PINT_sm_start_child_frames(struct PINT_smcb *smcb, int* children_started)
+{
+ int retval;
+ struct PINT_smcb *new_sm;
+ job_status_s r;
+ struct PINT_frame_s *f;
+ void *my_frame;
+
+ assert(smcb);
+
+ memset(&r, 0, sizeof(job_status_s));
+
+ *children_started = 0;
+
+ my_frame = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
+ /* Iterate once up front to determine how many children we are going to
+ * run. This has to be set before starting any children, otherwise if
+ * the first one immediately completes it will mistakenly believe it is
+ * the last one and signal the parent.
+ */
+ qlist_for_each_entry(f, &smcb->frames, link)
+ {
+ /* run from TOS until the parent frame */
+ if(f->frame == my_frame)
+ {
+ break;
+ }
+ /* increment parent's counter */
+ smcb->children_running++;
+ }
+
+ /* let the caller know how many children are being started; it won't be
+ * able to tell from the running_count because they may all immediately
+ * complete before we leave this function.
+ */
+ *children_started = smcb->children_running;
+
+ qlist_for_each_entry(f, &smcb->frames, link)
+ {
+ /* run from TOS until the parent frame */
+ if(f->frame == my_frame)
+ {
+ break;
+ }
+ /* allocate smcb */
+ PINT_smcb_alloc(&new_sm, smcb->op, 0, NULL,
+ child_sm_frame_terminate, smcb->context);
+ /* set parent smcb pointer */
+ new_sm->parent_smcb = smcb;
+ /* assign frame */
+ PINT_sm_push_frame(new_sm, f->task_id, f->frame);
+ /* locate SM to run */
+ new_sm->current_state = PINT_sm_task_map(smcb, f->task_id);
+ /* invoke SM */
+ retval = PINT_state_machine_start(new_sm, &r);
+ if(retval < 0)
+ {
+ gossip_err("PJMP child state machine failed to start.\n");
+ }
+ }
+}
+
+char * PINT_sm_action_string[3] =
+{
+ "DEFERRED",
+ "COMPLETE",
+ "TERMINATE"
+};
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
+
+#endif
+
--- /dev/null 2004-06-24 14:04:38.000000000 -0400
+++ void.sm 2008-07-21 14:19:56.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * (C) 2003 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include "pvfs2-debug.h"
+#include "job.h"
+#include "gossip.h"
+#include "str-utils.h"
+#include "state-machine.h"
+
+
+%%
+
+machine pvfs2_void_sm
+{
+ state void_action_state
+ {
+ run void_action;
+ default => terminate;
+ }
+}
+
+%%
+
+static PINT_sm_action void_action(
+ struct PINT_smcb *smcb, job_status_s *js_p)
+{
+ gossip_err("This pvfs2_void state machine should never run!\n");
+ PINT_smcb_set_complete(smcb);
+ return SM_ACTION_COMPLETE;
+}
+
+/*
+ * Local variables:
+ * mode: c
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
Index: digest.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/digest.c,v
diff -p -u -r1.1 -r1.1.4.1
--- digest.c 11 Sep 2006 00:38:45 -0000 1.1
+++ digest.c 21 Jul 2008 18:19:54 -0000 1.1.4.1
@@ -1,12 +1,20 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
#include "pvfs2-config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pvfs2-types.h"
#include "pvfs2-util.h"
+#include "pint-util.h"
#ifdef WITH_OPENSSL
+
#ifdef HAVE_OPENSSL_EVP_H
#include <openssl/evp.h>
#endif
@@ -19,8 +27,10 @@
#ifdef __GEN_POSIX_LOCKING__
#include <pthread.h>
#include <linux/unistd.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
-static _syscall0(pid_t,gettid)
static gen_mutex_t *mutex = NULL;
static pthread_once_t once_initialize = PTHREAD_ONCE_INIT;
@@ -28,68 +38,73 @@ static pthread_once_t once_finalize = PT
static void do_lock(int mode, int n, const char *file, int line)
{
- if (mode & CRYPTO_LOCK) {
- gen_mutex_lock(&mutex[n]);
- }
- else {
- gen_mutex_unlock(&mutex[n]);
- }
- return;
+ if (mode & CRYPTO_LOCK) {
+ gen_mutex_lock(&mutex[n]);
+ }
+ else {
+ gen_mutex_unlock(&mutex[n]);
+ }
+ return;
}
static unsigned long get_tid(void)
{
- /* NOTE:
- * This could fail on non 2.6 kernels, since gettid()
- * probably does not exist?
- */
- return gettid();
+ /* If gettid syscall does not exist, fall back to getpid, which I
+ * think will do something similar to gettid on non-ntpl
+ * implementations */
+#if defined(__NR_gettid)
+ return syscall(__NR_gettid);
+#else
+ return getpid();
+#endif
}
static void callback_init(void)
{
- int i, num_locks = 0;
+ int i, num_locks = 0;
- OpenSSL_add_all_digests();
- num_locks = CRYPTO_num_locks();
- mutex = (gen_mutex_t *) calloc(num_locks, sizeof(gen_mutex_t));
- for (i = 0; i < num_locks; i++) {
- gen_mutex_init(&mutex[i]);
- }
- CRYPTO_set_locking_callback(do_lock);
- CRYPTO_set_id_callback(get_tid);
- return;
+ OpenSSL_add_all_digests();
+ num_locks = CRYPTO_num_locks();
+ mutex = (gen_mutex_t *) calloc(num_locks, sizeof(gen_mutex_t));
+ for (i = 0; i < num_locks; i++) {
+ gen_mutex_init(&mutex[i]);
+ }
+ CRYPTO_set_locking_callback(do_lock);
+ CRYPTO_set_id_callback(get_tid);
+ return;
}
void PINT_util_digest_init(void)
{
- pthread_once(&once_initialize, callback_init);
- return;
+ pthread_once(&once_initialize, callback_init);
+ return;
}
static void callback_finalize(void)
{
- free(mutex);
- mutex = NULL;
+ free(mutex);
+ mutex = NULL;
+ EVP_cleanup();
}
void PINT_util_digest_finalize(void)
{
- pthread_once(&once_finalize, callback_finalize);
- return;
+ pthread_once(&once_finalize, callback_finalize);
+ return;
}
#else
void PINT_util_digest_init(void)
{
- OpenSSL_add_all_digests();
- return;
+ OpenSSL_add_all_digests();
+ return;
}
void PINT_util_digest_finalize(void)
{
- return;
+ EVP_cleanup();
+ return;
}
#endif
@@ -101,40 +116,46 @@ void PINT_util_digest_finalize(void)
* Also returns errors in case there are any.
*/
static int digest(const char *digest_name,
- const void *buf, const size_t buf_len,
- char **output, size_t *output_len)
+ const void *buf, const size_t buf_len,
+ char **output, size_t *output_len)
{
EVP_MD_CTX mdctx;
const EVP_MD *md;
- size_t digest_len;
- void *digest_value;
+ unsigned int digest_len;
+ void *digest_value;
- if (!digest_name)
- {
- return -PVFS_EINVAL;
- }
- md = EVP_get_digestbyname(digest_name);
- if (!md)
- {
- return -PVFS_EINVAL;
- }
+ if (!digest_name)
+ {
+ return -PVFS_EINVAL;
+ }
+ md = EVP_get_digestbyname(digest_name);
+ if (!md)
+ {
+ return -PVFS_EINVAL;
+ }
digest_value = (void *) malloc(EVP_MAX_MD_SIZE);
- if (!digest_value)
- {
- return -PVFS_ENOMEM;
- }
-
- EVP_MD_CTX_init(&mdctx);
- EVP_DigestInit_ex(&mdctx, md, NULL);
+ if (!digest_value)
+ {
+ return -PVFS_ENOMEM;
+ }
+
+ /* Instead of checking for different versions of openssl with
+ * #ifdefds (nasty nasty ifdefs), we just skip calling
+ * EVP_MD_CTX_init/cleanup (0.9.7 has them, 0.9.6 doesn't),
+ * since in our case (md5 and sha1),
+ * the digests don't define cleanup callbacks and init is just
+ * a memset.
+ */
+ memset(&mdctx, 0, sizeof(mdctx));
+ EVP_DigestInit(&mdctx, md);
EVP_DigestUpdate(&mdctx, buf, buf_len);
- EVP_DigestFinal_ex(&mdctx, digest_value, &digest_len);
- EVP_MD_CTX_cleanup(&mdctx);
+ EVP_DigestFinal(&mdctx, digest_value, &digest_len);
- if (output)
- *output = digest_value;
- if (output_len)
- *output_len = digest_len;
+ if (output)
+ *output = digest_value;
+ if (output_len)
+ *output_len = digest_len;
return 0;
}
@@ -142,36 +163,45 @@ static int digest(const char *digest_nam
void PINT_util_digest_init(void)
{
- return;
+ return;
}
void PINT_util_digest_finalize(void)
{
- return;
+ return;
}
/*
* returns -PVFS_EOPNOTSUPP
*/
static int digest(const char *digest_name,
- const void *buf, const size_t buf_len,
- char **output, size_t *output_len)
+ const void *buf, const size_t buf_len,
+ char **output, size_t *output_len)
{
- return -PVFS_EOPNOTSUPP;
+ return -PVFS_EOPNOTSUPP;
}
#endif
int PINT_util_digest_sha1(const void *input_message, size_t input_length,
- char **output, size_t *output_length)
+ char **output, size_t *output_length)
{
- return digest("sha1", input_message, input_length,
- output, output_length);
+ return digest("sha1", input_message, input_length,
+ output, output_length);
}
int PINT_util_digest_md5(const void *input_message, size_t input_length,
- char **output, size_t *output_length)
+ char **output, size_t *output_length)
{
- return digest("md5", input_message, input_length,
- output, output_length);
+ return digest("md5", input_message, input_length,
+ output, output_length);
}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
Index: errno-mapping.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/errno-mapping.c,v
diff -p -u -r1.15 -r1.15.28.1
--- errno-mapping.c 29 May 2006 16:21:11 -0000 1.15
+++ errno-mapping.c 21 Jul 2008 18:19:54 -0000 1.15.28.1
@@ -62,18 +62,19 @@ void PVFS_perror(const char *text, int r
char buf[MAX_PVFS_STRERROR_LEN] = {0};
int index = PVFS_get_errno_mapping(-retcode);
- snprintf(buf,MAX_PVFS_STRERROR_LEN,"%s: %s\n",text,
- PINT_non_errno_strerror_mapping[index]);
+ snprintf(buf,MAX_PVFS_STRERROR_LEN,"%s: %s (error class: %d)\n",text,
+ PINT_non_errno_strerror_mapping[index], PVFS_ERROR_CLASS(-retcode));
fprintf(stderr, "%s", buf);
}
else if (IS_PVFS_ERROR(-retcode))
{
- fprintf(stderr, "%s: %s\n", text,
- strerror(PVFS_ERROR_TO_ERRNO(-retcode)));
+ fprintf(stderr, "%s: %s (error class: %d)\n", text,
+ strerror(PVFS_ERROR_TO_ERRNO(-retcode)),
+ PVFS_ERROR_CLASS(-retcode));
}
else
{
- fprintf(stderr, "Warning: non PVFS2 error code (%x):\n",
+ fprintf(stderr, "Warning: non PVFS2 error code (%d):\n",
-retcode);
fprintf(stderr, "%s: %s\n", text, strerror(-retcode));
}
@@ -103,7 +104,7 @@ void PVFS_perror_gossip(const char *text
}
else
{
- gossip_err("Warning: non PVFS2 error code (%x):\n", -retcode);
+ gossip_err("Warning: non PVFS2 error code (%d):\n", -retcode);
gossip_err("%s: %s\n", text, strerror(-retcode));
}
return;
Index: mkspace.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/mkspace.c,v
diff -p -u -r1.39 -r1.39.14.1
--- mkspace.c 13 Jul 2006 05:11:40 -0000 1.39
+++ mkspace.c 21 Jul 2008 18:19:54 -0000 1.39.14.1
@@ -23,9 +23,8 @@
#include "extent-utils.h"
#include "pvfs2-util.h"
#include "pvfs2-internal.h"
+#include "pint-util.h"
-static char *dir_ent_string = DIRECTORY_ENTRY_KEYSTR;
-static char *root_handle_string = ROOT_HANDLE_KEYSTR;
static char *lost_and_found_string = "lost+found";
static TROVE_handle s_used_handles[4] =
@@ -128,7 +127,6 @@ int pvfs2_mkspace(
TROVE_handle_extent cur_extent;
TROVE_handle_extent_array extent_array;
TROVE_context_id trove_context = -1;
- char *method_name = NULL;
char *merged_handle_ranges = NULL;
TROVE_handle new_root_handle = TROVE_HANDLE_NULL;
TROVE_handle root_dirdata_handle = TROVE_HANDLE_NULL;
@@ -158,7 +156,10 @@ int pvfs2_mkspace(
try to initialize; fails if storage space isn't there, which
is exactly what we're expecting in this case.
*/
- ret = trove_initialize(storage_space, 0, &method_name, 0);
+ ret = trove_initialize(TROVE_METHOD_DBPF,
+ NULL,
+ storage_space,
+ 0);
if (ret > -1)
{
gossip_err("error: storage space %s already "
@@ -166,7 +167,7 @@ int pvfs2_mkspace(
return -1;
}
- ret = trove_storage_create(storage_space, NULL, &op_id);
+ ret = trove_storage_create(TROVE_METHOD_DBPF, storage_space, NULL, &op_id);
if (ret != 1)
{
gossip_err("error: storage create failed; aborting!\n");
@@ -175,7 +176,9 @@ int pvfs2_mkspace(
}
/* now that the storage space exists, initialize trove properly */
- ret = trove_initialize(storage_space, 0, &method_name, 0);
+ ret = trove_initialize(
+ TROVE_METHOD_DBPF, NULL,
+ storage_space, 0);
if (ret < 0)
{
gossip_err("error: trove initialize failed; aborting!\n");
@@ -186,12 +189,13 @@ int pvfs2_mkspace(
storage_space);
/* try to look up collection used to store file system */
- ret = trove_collection_lookup(collection, &coll_id, NULL, &op_id);
+ ret = trove_collection_lookup(
+ TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
if (ret == 1)
{
mkspace_print(verbose, "warning: collection lookup succeeded "
"before it should; aborting!\n");
- trove_finalize();
+ trove_finalize(TROVE_METHOD_DBPF);
return -1;
}
@@ -205,7 +209,8 @@ int pvfs2_mkspace(
}
/* make sure a collection lookup succeeds */
- ret = trove_collection_lookup(collection, &coll_id, NULL, &op_id);
+ ret = trove_collection_lookup(
+ TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
if (ret != 1)
{
mkspace_print(verbose,"error: collection lookup failed for "
@@ -302,8 +307,8 @@ int pvfs2_mkspace(
s_used_handles[0] = new_root_handle;
/* set collection attribute for root handle */
- key.buffer = root_handle_string;
- key.buffer_sz = strlen(root_handle_string) + 1;
+ key.buffer = ROOT_HANDLE_KEYSTR;
+ key.buffer_sz = ROOT_HANDLE_KEYLEN;
val.buffer = &new_root_handle;
val.buffer_sz = sizeof(new_root_handle);
ret = trove_collection_seteattr(coll_id, &key, &val, 0,
@@ -328,8 +333,8 @@ int pvfs2_mkspace(
attr.gid = getgid();
attr.mode = 0777;
attr.type = PVFS_TYPE_DIRECTORY;
- attr.atime = attr.ctime = PVFS_util_get_current_time();
- attr.mtime = PVFS_util_mktime_version(attr.ctime);
+ attr.atime = attr.ctime = PINT_util_get_current_time();
+ attr.mtime = PINT_util_mktime_version(attr.ctime);
ret = trove_dspace_setattr(
coll_id, new_root_handle, &attr, TROVE_SYNC, NULL,
@@ -404,8 +409,8 @@ int pvfs2_mkspace(
"with handle %llu\n", llu(root_dirdata_handle));
s_used_handles[1] = root_dirdata_handle;
- key.buffer = dir_ent_string;
- key.buffer_sz = strlen(dir_ent_string) + 1;
+ key.buffer = DIRECTORY_ENTRY_KEYSTR;
+ key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
val.buffer = &root_dirdata_handle;
val.buffer_sz = sizeof(TROVE_handle);
@@ -487,8 +492,8 @@ int pvfs2_mkspace(
attr.gid = getgid();
attr.mode = 0777;
attr.type = PVFS_TYPE_DIRECTORY;
- attr.atime = attr.ctime = PVFS_util_get_current_time();
- attr.mtime = PVFS_util_mktime_version(attr.ctime);
+ attr.atime = attr.ctime = PINT_util_get_current_time();
+ attr.mtime = PINT_util_mktime_version(attr.ctime);
ret = trove_dspace_setattr(
coll_id, lost_and_found_handle, &attr, TROVE_SYNC, NULL,
@@ -555,8 +560,8 @@ int pvfs2_mkspace(
"with handle %llu\n", llu(lost_and_found_dirdata_handle));
s_used_handles[3] = lost_and_found_dirdata_handle;
- key.buffer = dir_ent_string;
- key.buffer_sz = strlen(dir_ent_string) + 1;
+ key.buffer = DIRECTORY_ENTRY_KEYSTR;
+ key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
val.buffer = &lost_and_found_dirdata_handle;
val.buffer_sz = sizeof(TROVE_handle);
@@ -620,12 +625,12 @@ int pvfs2_mkspace(
{
trove_close_context(coll_id, trove_context);
}
- trove_finalize();
+ trove_finalize(TROVE_METHOD_DBPF);
mkspace_print(verbose, "collection created:\n"
"\troot handle = %llu, coll id = %d, "
"root string = \"%s\"\n",
- llu(root_handle), coll_id, root_handle_string);
+ llu(root_handle), coll_id, ROOT_HANDLE_KEYSTR);
return 0;
}
@@ -637,14 +642,15 @@ int pvfs2_rmspace(
int verbose)
{
int ret = -1;
- char *method_name = NULL;
TROVE_op_id op_id;
static int trove_is_initialized = 0;
/* try to initialize; fails if storage space isn't there */
if (!trove_is_initialized)
{
- ret = trove_initialize(storage_space, 0, &method_name, 0);
+ ret = trove_initialize(
+ TROVE_METHOD_DBPF, NULL,
+ storage_space, 0);
if (ret == -1)
{
gossip_err("error: storage space %s does not "
@@ -657,7 +663,8 @@ int pvfs2_rmspace(
mkspace_print(verbose, "Attempting to remove collection %s\n",
collection);
- ret = trove_collection_remove(collection, NULL, &op_id);
+ ret = trove_collection_remove(
+ TROVE_METHOD_DBPF, collection, NULL, &op_id);
mkspace_print(
verbose, "PVFS2 Collection %s removed %s\n", collection,
(((ret == 1) || (ret == -TROVE_ENOENT)) ? "successfully" :
@@ -665,22 +672,21 @@ int pvfs2_rmspace(
if (!remove_collection_only)
{
- ret = trove_storage_remove(storage_space, NULL, &op_id);
+ ret = trove_storage_remove(
+ TROVE_METHOD_DBPF, storage_space, NULL, &op_id);
+ /*
+ * it is a bit weird to do a trove_finaliz() prior to blowing away
+ * the storage space, but this allows the __db files of the DB env
+ * to be blown away for the rmdir() to work correctly!
+ */
+ trove_finalize(TROVE_METHOD_DBPF);
mkspace_print(
verbose, "PVFS2 Storage Space %s removed %s\n",
storage_space, (((ret == 1) || (ret == -TROVE_ENOENT)) ?
"successfully" : "with errors"));
- /*
- we should be doing a trove finalize here, but for now we
- can't because it will fail horribly during the sync/close
- calls to files that we've just removed.
-
- an extra flag to finalize, or a static var in the dbpf-mgmt
- methods could resolve this.
- */
-/* trove_finalize(); */
trove_is_initialized = 0;
}
return ret;
}
+
Index: mmap-ra-cache.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/mmap-ra-cache.c,v
diff -p -u -r1.17 -r1.17.40.1
--- mmap-ra-cache.c 11 Nov 2005 21:31:02 -0000 1.17
+++ mmap-ra-cache.c 21 Jul 2008 18:19:54 -0000 1.17.40.1
@@ -21,11 +21,11 @@
static int hash_key(void *key, int table_size);
static int hash_key_compare(void *key, struct qlist_head *link);
-static gen_mutex_t *s_mmap_ra_cache_mutex = NULL;
+static gen_mutex_t s_mmap_ra_cache_mutex = GEN_MUTEX_INITIALIZER;
static struct qhash_table *s_key_to_data_table = NULL;
#define MMAP_RA_CACHE_INITIALIZED() \
-(s_key_to_data_table && s_mmap_ra_cache_mutex)
+(s_key_to_data_table)
#define DEFAULT_MMAP_RA_CACHE_HTABLE_SIZE 19
@@ -43,14 +43,6 @@ int pvfs2_mmap_ra_cache_initialize(void)
goto return_error;
}
- s_mmap_ra_cache_mutex = gen_mutex_build();
- if (!s_mmap_ra_cache_mutex)
- {
- qhash_finalize(s_key_to_data_table);
- s_key_to_data_table = NULL;
- goto return_error;
- }
-
gossip_debug(GOSSIP_MMAP_RCACHE_DEBUG,
"mmap_ra_cache_initialized\n");
ret = 0;
@@ -92,10 +84,10 @@ int pvfs2_mmap_ra_cache_register(PVFS_ob
memcpy(cache_elem->data, data, data_len);
cache_elem->data_sz = data_len;
- gen_mutex_lock(s_mmap_ra_cache_mutex);
+ gen_mutex_lock(&s_mmap_ra_cache_mutex);
qhash_add(s_key_to_data_table,
&refn, &cache_elem->hash_link);
- gen_mutex_unlock(s_mmap_ra_cache_mutex);
+ gen_mutex_unlock(&s_mmap_ra_cache_mutex);
gossip_debug(GOSSIP_MMAP_RCACHE_DEBUG, "Inserted mmap ra cache "
"element %llu, %d of size %llu\n",
@@ -121,7 +113,7 @@ int pvfs2_mmap_ra_cache_get_block(
if (MMAP_RA_CACHE_INITIALIZED())
{
- gen_mutex_lock(s_mmap_ra_cache_mutex);
+ gen_mutex_lock(&s_mmap_ra_cache_mutex);
hash_link = qhash_search(s_key_to_data_table, &refn);
if (hash_link)
{
@@ -180,7 +172,7 @@ int pvfs2_mmap_ra_cache_get_block(
GOSSIP_MMAP_RCACHE_DEBUG, "mmap_ra_cache_get_block "
"clean cache miss (nothing here)\n");
}
- gen_mutex_unlock(s_mmap_ra_cache_mutex);
+ gen_mutex_unlock(&s_mmap_ra_cache_mutex);
}
return ret;
}
@@ -193,7 +185,7 @@ int pvfs2_mmap_ra_cache_flush(PVFS_objec
if (MMAP_RA_CACHE_INITIALIZED())
{
- gen_mutex_lock(s_mmap_ra_cache_mutex);
+ gen_mutex_lock(&s_mmap_ra_cache_mutex);
hash_link = qhash_search_and_remove(s_key_to_data_table, &refn);
if (hash_link)
{
@@ -212,7 +204,7 @@ int pvfs2_mmap_ra_cache_flush(PVFS_objec
free(cache_elem);
ret = 0;
}
- gen_mutex_unlock(s_mmap_ra_cache_mutex);
+ gen_mutex_unlock(&s_mmap_ra_cache_mutex);
}
return ret;
}
@@ -226,7 +218,7 @@ int pvfs2_mmap_ra_cache_finalize(void)
if (MMAP_RA_CACHE_INITIALIZED())
{
- gen_mutex_lock(s_mmap_ra_cache_mutex);
+ gen_mutex_lock(&s_mmap_ra_cache_mutex);
for(i = 0; i < s_key_to_data_table->table_size; i++)
{
do
@@ -250,11 +242,10 @@ int pvfs2_mmap_ra_cache_finalize(void)
ret = 0;
qhash_finalize(s_key_to_data_table);
s_key_to_data_table = NULL;
- gen_mutex_unlock(s_mmap_ra_cache_mutex);
+ gen_mutex_unlock(&s_mmap_ra_cache_mutex);
/* FIXME: race condition here */
- gen_mutex_destroy(s_mmap_ra_cache_mutex);
- s_mmap_ra_cache_mutex = NULL;
+ gen_mutex_destroy(&s_mmap_ra_cache_mutex);
gossip_debug(GOSSIP_MMAP_RCACHE_DEBUG, "mmap_ra_cache_finalized\n");
}
return ret;
Index: module.mk.in
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/module.mk.in,v
diff -p -u -r1.27 -r1.27.4.1
--- module.mk.in 11 Sep 2006 00:38:45 -0000 1.27
+++ module.mk.in 21 Jul 2008 18:19:54 -0000 1.27.4.1
@@ -2,7 +2,7 @@ DIR := src/common/misc
LIBSRC += $(DIR)/server-config.c \
$(DIR)/server-config-mgr.c \
$(DIR)/str-utils.c \
- $(DIR)/digest.c \
+ $(DIR)/digest.c \
$(DIR)/xattr-utils.c \
$(DIR)/mmap-ra-cache.c \
$(DIR)/extent-utils.c \
@@ -12,10 +12,14 @@ LIBSRC += $(DIR)/server-config.c \
$(DIR)/pint-perf-counter.c \
$(DIR)/pint-event.c \
$(DIR)/pint-cached-config.c \
- $(DIR)/msgpairarray.c \
$(DIR)/pint-util.c \
+ $(DIR)/msgpairarray.c \
+ $(DIR)/void.c \
$(DIR)/realpath.c \
- $(DIR)/tcache.c
+ $(DIR)/tcache.c \
+ $(DIR)/state-machine-fns.c \
+ $(DIR)/fsck-utils.c \
+ $(DIR)/pint-eattr.c
SERVERSRC += $(DIR)/server-config.c \
$(DIR)/server-config-mgr.c \
$(DIR)/str-utils.c \
@@ -26,12 +30,15 @@ SERVERSRC += $(DIR)/server-config.c \
$(DIR)/pint-perf-counter.c \
$(DIR)/pint-event.c \
$(DIR)/pint-cached-config.c \
- $(DIR)/msgpairarray.c \
$(DIR)/pint-util.c \
- $(DIR)/tcache.c
+ $(DIR)/tcache.c \
+ $(DIR)/state-machine-fns.c \
+ $(DIR)/void.c \
+ $(DIR)/pint-eattr.c
MODCFLAGS_$(DIR)/server-config.c = \
-I$(srcdir)/src/server
# autogenerated files
-SMCGEN += $(DIR)/msgpairarray.c
+SMCGEN += $(DIR)/msgpairarray.c \
+ $(DIR)/void.c
Index: msgpairarray.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/msgpairarray.h,v
diff -p -u -r1.11.26.1 -r1.11.26.1.2.1
--- msgpairarray.h 14 Jul 2008 08:33:37 -0000 1.11.26.1
+++ msgpairarray.h 21 Jul 2008 18:19:54 -0000 1.11.26.1.2.1
@@ -22,6 +22,8 @@ extern struct PINT_state_machine_s pvfs2
#define PVFS_MSGPAIR_RETRY 0xFE
#define PVFS_MSGPAIR_NO_RETRY 0xFF
+#define PINT_MSGPAIR_PARENT_SM -1
+
/*
* This structure holds everything that we need for the state of a
* message pair. We need arrays of these in some cases, so it's
@@ -80,7 +82,7 @@ typedef struct PINT_sm_msgpair_state_s
} PINT_sm_msgpair_state;
/* used to pass in parameters that apply to every entry in a msgpair array */
-typedef struct PINT_sm_msgpair_params_s
+typedef struct
{
int job_timeout;
int retry_delay;
@@ -92,14 +94,40 @@ typedef struct PINT_sm_msgpair_params_s
} PINT_sm_msgpair_params;
+typedef struct
+{
+ PINT_sm_msgpair_params params;
+ int count;
+ PINT_sm_msgpair_state *msgarray;
+ PINT_sm_msgpair_state msgpair;
+} PINT_sm_msgarray_op;
+
+#define PINT_msgpair_init(op) \
+ do { \
+ memset(&(op)->msgpair, 0, sizeof(PINT_sm_msgpair_state)); \
+ if((op)->msgarray != &(op)->msgpair) \
+ { \
+ free((op)->msgarray); \
+ (op)->msgarray = NULL; \
+ } \
+ (op)->count = 1; \
+ (op)->msgarray = &(op)->msgpair; \
+ } while(0)
+
+#define foreach_msgpair(__msgarray_op, __msg_p, __i) \
+ for(__i = 0, __msg_p = &((__msgarray_op)->msgarray[__i]); \
+ __i < (__msgarray_op)->count; \
+ ++__i, __msg_p = &((__msgarray_op)->msgarray[__i]))
/* helper functions */
int PINT_msgpairarray_init(
- PINT_sm_msgpair_state ** msgpairarray,
+ PINT_sm_msgarray_op *op,
int count);
-void PINT_msgpairarray_destroy(PINT_sm_msgpair_state * msgpairarray);
+void PINT_msgpairarray_destroy(PINT_sm_msgarray_op *op);
+
+int PINT_msgarray_status(PINT_sm_msgarray_op *op);
int PINT_serv_decode_resp(
PVFS_fs_id fs_id,
@@ -116,9 +144,7 @@ int PINT_serv_free_msgpair_resources(
PVFS_BMI_addr_t *svr_addr_p,
int max_resp_sz);
-int PINT_serv_msgpairarray_resolve_addrs(
- int count,
- PINT_sm_msgpair_state* msgarray);
+int PINT_serv_msgpairarray_resolve_addrs(PINT_sm_msgarray_op *op);
#define PRINT_ENCODING_ERROR(type_str, type) \
do { \
Index: msgpairarray.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/msgpairarray.sm,v
diff -p -u -r1.36 -r1.36.12.1
--- msgpairarray.sm 18 Aug 2006 15:25:12 -0000 1.36
+++ msgpairarray.sm 21 Jul 2008 18:19:54 -0000 1.36.12.1
@@ -13,26 +13,6 @@
#include <string.h>
#include <assert.h>
-/* conditionally include different headers to get the type of the state
- * machine struct that contains the msgpair state structs we need to access;
- * this is done to allow the reuse of this nested machine on both client and
- * server side where completely different primary state machine structures
- * are used
- */
-#if defined(__PVFS2_CLIENT__)
-#include "client-state-machine.h"
-#define PARENT_SM PINT_client_sm
-#elif defined(__PVFS2_SERVER__)
-#include "src/server/pvfs2-server.h"
-#define PARENT_SM PINT_server_op
-#else
-/* this condition is only included for dependency building step; will not
- * actually compile cleanly
- */
-#define __SM_CHECK_DEP
-#include "client-state-machine.h"
-#include "src/server/pvfs2-server.h"
-#endif
#include "msgpairarray.h"
#include "pvfs2-debug.h"
#include "pint-cached-config.h"
@@ -43,32 +23,18 @@
#include "pint-util.h"
#include "server-config-mgr.h"
#include "pvfs2-internal.h"
+#include "state-machine.h"
enum
{
MSGPAIRS_COMPLETE = 190,
- MSGPAIRS_RETRY = 191
+ MSGPAIRS_RETRY = 191,
+ MSGPAIRS_RETRY_NODELAY = 192
};
-static int msgpairarray_init(
- PARENT_SM *sm_p, job_status_s *js_p);
-static int msgpairarray_post(
- PARENT_SM *sm_p, job_status_s *js_p);
-static int msgpairarray_post_retry(
- PARENT_SM *sm_p, job_status_s *js_p);
-static int msgpairarray_complete(
- PARENT_SM *sm_p, job_status_s *js_p);
-static int msgpairarray_completion_fn(
- PARENT_SM *sm_p, job_status_s *js_p);
-
%%
-nested machine pvfs2_msgpairarray_sm(
- init,
- post,
- post_retry,
- complete,
- completion_fn)
+nested machine pvfs2_msgpairarray_sm
{
state init
{
@@ -100,31 +66,39 @@ nested machine pvfs2_msgpairarray_sm(
{
run msgpairarray_completion_fn;
MSGPAIRS_RETRY => post_retry;
+ MSGPAIRS_RETRY_NODELAY => post;
+ default => done;
+ }
+
+ state done
+ {
+ run msgpairarray_done;
default => return;
}
}
%%
-static int msgpairarray_init(PARENT_SM *sm_p,
- job_status_s *js_p)
+static PINT_sm_action msgpairarray_init(
+ struct PINT_smcb *smcb, job_status_s *js_p)
{
+ PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int i = 0;
PINT_sm_msgpair_state *msg_p = NULL;
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: init "
- "(%d msgpair(s))\n", sm_p, sm_p->msgarray_count);
+ "(%d msgpair(s))\n", smcb, mop->count);
- assert(sm_p->msgarray_count > 0);
+ assert(mop->count > 0);
js_p->error_code = 0;
/* set number of operations that must complete. */
- sm_p->msgarray_params.comp_ct = (2 * sm_p->msgarray_count);
+ mop->params.comp_ct = (2 * mop->count);
- for(i = 0; i < sm_p->msgarray_count; i++)
+ for(i = 0; i < mop->count; i++)
{
- msg_p = &sm_p->msgarray[i];
+ msg_p = &mop->msgarray[i];
assert(msg_p);
assert((msg_p->retry_flag == PVFS_MSGPAIR_RETRY) ||
@@ -134,7 +108,7 @@ static int msgpairarray_init(PARENT_SM *
msg_p->retry_count = 0;
msg_p->complete = 0;
}
- return 1;
+ return SM_ACTION_COMPLETE;
}
/* msgpairarray_post()
@@ -155,31 +129,31 @@ static int msgpairarray_init(PARENT_SM *
* (7) stores job ids for later matching
*
*/
-static int msgpairarray_post(PARENT_SM *sm_p,
- job_status_s *js_p)
+static PINT_sm_action msgpairarray_post(
+ struct PINT_smcb *smcb, job_status_s *js_p)
{
+ PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int ret = -PVFS_EINVAL, i = 0, tmp = 0;
struct server_configuration_s *server_config = NULL;
PVFS_msg_tag_t session_tag;
PINT_sm_msgpair_state *msg_p = NULL;
struct filesystem_configuration_s *cur_fs = NULL;
- int num_incomplete_msgpairs = (sm_p->msgarray_params.comp_ct / 2);
int must_loop_encodings = 0;
int local_enc_and_alloc = 0;
gossip_debug(
GOSSIP_MSGPAIR_DEBUG, "%s: sm %p "
- "%d total message(s) with %d incomplete\n", __func__, sm_p,
- sm_p->msgarray_count * 2, num_incomplete_msgpairs * 2);
+ "%d total message(s) with %d incomplete\n", __func__, smcb,
+ mop->count * 2, mop->params.comp_ct);
js_p->error_code = 0;
- assert(sm_p->msgarray_count > 0);
- assert(num_incomplete_msgpairs && sm_p->msgarray_params.comp_ct);
+ assert(mop->count > 0);
+ assert(mop->params.comp_ct >= 2);
- for (i = 0; i < sm_p->msgarray_count; i++)
+ for (i = 0; i < mop->count; i++)
{
- msg_p = &sm_p->msgarray[i];
+ msg_p = &mop->msgarray[i];
assert(msg_p);
/*
@@ -243,7 +217,7 @@ static int msgpairarray_post(PARENT_SM *
}
gossip_lerr("msgpairarray_post: PINT_encode failed\n");
js_p->error_code = ret;
- return 1;
+ return SM_ACTION_COMPLETE;
}
/* calculate max response msg size and allocate space */
@@ -256,7 +230,7 @@ static int msgpairarray_post(PARENT_SM *
if (msg_p->encoded_resp_p == NULL)
{
js_p->error_code = -PVFS_ENOMEM;
- return 1;
+ return SM_ACTION_COMPLETE;
}
local_enc_and_alloc = 1;
}
@@ -264,7 +238,7 @@ static int msgpairarray_post(PARENT_SM *
session_tag = PINT_util_get_next_tag();
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d: "
- "posting recv\n", __func__, sm_p, i);
+ "posting recv\n", __func__, smcb, i);
/* post receive of response; job_id stored in recv_id */
ret = job_bmi_recv(msg_p->svr_addr,
@@ -272,12 +246,12 @@ static int msgpairarray_post(PARENT_SM *
msg_p->max_resp_sz,
session_tag,
BMI_PRE_ALLOC,
- sm_p,
+ smcb,
i,
&msg_p->recv_status,
&msg_p->recv_id,
- sm_p->msgarray_params.job_context,
- sm_p->msgarray_params.job_timeout);
+ mop->params.job_context,
+ mop->params.job_timeout);
if (ret == 0)
{
/* perform a quick test to see if the recv failed before posting
@@ -287,7 +261,7 @@ static int msgpairarray_post(PARENT_SM *
*/
ret = job_test(msg_p->recv_id, &tmp, NULL,
&msg_p->recv_status, 0,
- sm_p->msgarray_params.job_context);
+ mop->params.job_context);
}
if ((ret < 0) || (ret == 1))
@@ -312,7 +286,7 @@ static int msgpairarray_post(PARENT_SM *
/* mark send as bad too and don't post it */
msg_p->send_status.error_code = msg_p->recv_status.error_code;
msg_p->op_status = msg_p->recv_status.error_code;
- sm_p->msgarray_params.comp_ct -= 2;
+ mop->params.comp_ct -= 2;
if (local_enc_and_alloc)
{
@@ -333,7 +307,7 @@ static int msgpairarray_post(PARENT_SM *
assert(ret == 0);
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d: "
- "posting send\n", __func__, sm_p, i);
+ "posting send\n", __func__, smcb, i);
/* post send of request; job_id stored in send_id */
ret = job_bmi_send_list(msg_p->encoded_req.dest,
@@ -344,12 +318,12 @@ static int msgpairarray_post(PARENT_SM *
session_tag,
msg_p->encoded_req.buffer_type,
1,
- sm_p,
- sm_p->msgarray_count+i,
+ smcb,
+ mop->count+i,
&msg_p->send_status,
&msg_p->send_id,
- sm_p->msgarray_params.job_context,
- sm_p->msgarray_params.job_timeout);
+ mop->params.job_context,
+ mop->params.job_timeout);
if ((ret < 0) ||
((ret == 1) && (msg_p->send_status.error_code != 0)))
@@ -366,70 +340,73 @@ static int msgpairarray_post(PARENT_SM *
gossip_err("Send error: cancelling recv.\n");
- job_bmi_cancel(msg_p->recv_id, sm_p->msgarray_params.job_context);
+ job_bmi_cancel(msg_p->recv_id, mop->params.job_context);
/* we still have to wait for recv completion, so just decrement
* comp_ct by one and keep going
*/
msg_p->op_status = msg_p->send_status.error_code;
msg_p->send_id = 0;
- sm_p->msgarray_params.comp_ct--;
+ mop->params.comp_ct--;
}
else if (ret == 1)
{
/* immediate completion */
msg_p->send_id = 0;
/* decrement our count, since send is already done. */
- sm_p->msgarray_params.comp_ct--;
+ mop->params.comp_ct--;
}
/* else: successful post, no immediate completion */
}
- if (sm_p->msgarray_params.comp_ct == 0)
+ if (mop->params.comp_ct == 0)
{
/* everything is completed already (could happen in some failure
* cases); jump straight to final completion function.
*/
js_p->error_code = MSGPAIRS_COMPLETE;
- return 1;
+ return SM_ACTION_COMPLETE;
}
/* we are still waiting on operations to complete, next state
* transition will handle them
*/
- return 0;
+ return SM_ACTION_DEFERRED;
}
-static int msgpairarray_post_retry(PARENT_SM *sm_p,
- job_status_s *js_p)
+static PINT_sm_action msgpairarray_post_retry(
+ struct PINT_smcb *smcb, job_status_s *js_p)
{
+ PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
job_id_t tmp_id;
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p, wait %d ms\n",
- __func__, sm_p, sm_p->msgarray_params.retry_delay);
+ __func__, smcb, mop->params.retry_delay);
+ js_p->error_code = 0; /* do not leak MSGPAIRS_RETRY through to wait */
return job_req_sched_post_timer(
- sm_p->msgarray_params.retry_delay,
- sm_p, 0, js_p, &tmp_id,
- sm_p->msgarray_params.job_context);
+ mop->params.retry_delay,
+ smcb, 0, js_p, &tmp_id,
+ mop->params.job_context);
}
-static int msgpairarray_complete(PARENT_SM *sm_p,
- job_status_s *js_p)
+static PINT_sm_action msgpairarray_complete(
+ struct PINT_smcb *smcb, job_status_s *js_p)
{
+ PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
gossip_debug(GOSSIP_MSGPAIR_DEBUG,
"%s: sm %p status_user_tag %d msgarray_count %d\n",
- __func__, sm_p, (int) js_p->status_user_tag, sm_p->msgarray_count);
+ __func__, smcb, (int) js_p->status_user_tag, mop->count);
/* match operation with something in the msgpair array */
/* the first N tags are receives, the second N are sends */
- assert(js_p->status_user_tag < sm_p->msgarray_count*2);
+ assert(js_p->status_user_tag < mop->count*2);
- if (js_p->status_user_tag < sm_p->msgarray_count)
+ if (js_p->status_user_tag < mop->count)
{
PINT_sm_msgpair_state *msg_p =
- &sm_p->msgarray[js_p->status_user_tag];
+ &mop->msgarray[js_p->status_user_tag];
msg_p->recv_id = 0;
msg_p->recv_status = *js_p;
@@ -443,13 +420,13 @@ static int msgpairarray_complete(PARENT_
/* we got a receive error, but send is still pending. Cancel
* the send
*/
- job_bmi_cancel(msg_p->send_id, sm_p->msgarray_params.job_context);
+ job_bmi_cancel(msg_p->send_id, mop->params.job_context);
}
}
else
{
- PINT_sm_msgpair_state *msg_p = &sm_p->msgarray[
- js_p->status_user_tag - sm_p->msgarray_count];
+ PINT_sm_msgpair_state *msg_p = &mop->msgarray[
+ js_p->status_user_tag - mop->count];
msg_p->send_id = 0;
msg_p->send_status = *js_p;
@@ -463,32 +440,35 @@ static int msgpairarray_complete(PARENT_
/* we got a send error, but recv is still pending. Cancel
* the recv
*/
- job_bmi_cancel(msg_p->recv_id, sm_p->msgarray_params.job_context);
+ job_bmi_cancel(msg_p->recv_id, mop->params.job_context);
}
}
/* decrement comp_ct until all operations have completed */
- if (--sm_p->msgarray_params.comp_ct > 0)
+ if (--mop->params.comp_ct > 0)
{
- return 0;
+ gossip_debug(GOSSIP_MSGPAIR_DEBUG,
+ " msgpairarray: %d operations remain\n",
+ mop->params.comp_ct);
+ return SM_ACTION_DEFERRED;
}
- assert(sm_p->msgarray_params.comp_ct == 0);
+ assert(mop->params.comp_ct == 0);
gossip_debug(GOSSIP_MSGPAIR_DEBUG,
" msgpairarray: all operations complete\n");
js_p->error_code = MSGPAIRS_COMPLETE;
- return 1;
+ return SM_ACTION_COMPLETE;
}
-static int msgpairarray_completion_fn(PARENT_SM *sm_p,
- job_status_s *js_p)
+static PINT_sm_action msgpairarray_completion_fn(
+ struct PINT_smcb *smcb, job_status_s *js_p)
{
+ PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
int ret = -PVFS_EINVAL, i = 0;
int need_retry = 0;
struct PINT_decoded_msg decoded_resp;
const char* server_string = NULL;
- struct server_configuration_s *server_config = NULL;
int server_type;
/* response structure (decoded) */
@@ -497,11 +477,11 @@ static int msgpairarray_completion_fn(PA
js_p->error_code = 0;
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: "
- "completion_fn\n", sm_p);
+ "completion_fn\n", smcb);
- for (i = 0; i < sm_p->msgarray_count; i++)
+ for (i = 0; i < mop->count; i++)
{
- PINT_sm_msgpair_state *msg_p = &sm_p->msgarray[i];
+ PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
assert(msg_p);
/*
@@ -550,7 +530,7 @@ static int msgpairarray_completion_fn(PA
* a per message pair basis. Also store some non-zero
* (failure) value in js_p->error_code if we see one.
*/
- msg_p->op_status = msg_p->comp_fn(sm_p, resp_p, i);
+ msg_p->op_status = msg_p->comp_fn(smcb, resp_p, i);
if (msg_p->op_status != 0)
{
js_p->error_code = msg_p->op_status;
@@ -587,7 +567,7 @@ static int msgpairarray_completion_fn(PA
{
PVFS_perror_gossip("Failed to free msgpair resources", ret);
js_p->error_code = ret;
- return 1;
+ return SM_ACTION_COMPLETE;
}
msg_p->encoded_resp_p = NULL;
@@ -600,7 +580,7 @@ static int msgpairarray_completion_fn(PA
msg_p->complete = 1;
gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d "
- "marked complete\n", __func__, sm_p, i);
+ "marked complete\n", __func__, smcb, i);
}
if (need_retry) {
@@ -609,37 +589,46 @@ static int msgpairarray_completion_fn(PA
* of two since they are pairs. If over the count, do not
* retry, just return one of the error codes.
*/
- sm_p->msgarray_params.comp_ct = 0;
+ mop->params.comp_ct = 0;
js_p->error_code = 0;
- for (i=0; i < sm_p->msgarray_count; i++) {
+ for (i=0; i < mop->count; i++) {
- PINT_sm_msgpair_state *msg_p = &sm_p->msgarray[i];
+ PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
if (msg_p->complete)
continue;
if (msg_p->retry_flag == PVFS_MSGPAIR_RETRY
&& PVFS_ERROR_CLASS(-msg_p->op_status) == PVFS_ERROR_BMI
- && msg_p->retry_count < sm_p->msgarray_params.retry_limit) {
+ && msg_p->retry_count < mop->params.retry_limit) {
++msg_p->retry_count;
- sm_p->msgarray_params.comp_ct += 2;
+ mop->params.comp_ct += 2;
gossip_debug(GOSSIP_MSGPAIR_DEBUG,
"*** %s: msgpair %d failed, retry %d\n",
__func__, i, msg_p->retry_count);
- js_p->error_code = MSGPAIRS_RETRY;
-
- } else {
- char s[1024];
- server_config = PINT_server_config_mgr_get_config(msg_p->fs_id);
- if(server_config)
+ if(msg_p->op_status == -BMI_ECANCEL)
{
- server_string = PINT_cached_config_map_addr(
- server_config, msg_p->fs_id, msg_p->svr_addr, &server_type);
- PINT_server_config_mgr_put_config(server_config);
+ /* if the error code indicates cancel, then skip the
+ * delay. We have probably already been waiting a while
+ */
+ gossip_debug(GOSSIP_MSGPAIR_DEBUG,
+ "*** %s: msgpair skipping retry delay.\n", __func__);
+ js_p->error_code = MSGPAIRS_RETRY_NODELAY;
}
else
{
+ gossip_debug(GOSSIP_MSGPAIR_DEBUG,
+ "*** %s: msgpair retrying after delay.\n", __func__);
+ js_p->error_code = MSGPAIRS_RETRY;
+ }
+
+ } else {
+ char s[1024];
+ server_string = PINT_cached_config_map_addr(
+ msg_p->fs_id, msg_p->svr_addr, &server_type);
+ if(!server_string)
+ {
server_string = "[UNKNOWN]";
}
PVFS_strerror_r(msg_p->op_status, s, sizeof(s));
@@ -664,7 +653,15 @@ static int msgpairarray_completion_fn(PA
}
}
- return 1;
+ return SM_ACTION_COMPLETE;
+}
+
+static PINT_sm_action msgpairarray_done(
+ struct PINT_smcb *smcb, job_status_s *js_p)
+{
+ int task_id, error_code, remaining;
+ PINT_sm_pop_frame(smcb, &task_id, &error_code, &remaining);
+ return SM_ACTION_COMPLETE;
}
/*********************************************************************
@@ -672,25 +669,44 @@ static int msgpairarray_completion_fn(PA
*/
int PINT_msgpairarray_init(
- PINT_sm_msgpair_state ** msgpairarray,
+ PINT_sm_msgarray_op *op,
int count)
{
- *msgpairarray = (PINT_sm_msgpair_state *)malloc(
+ op->msgarray = (PINT_sm_msgpair_state *)malloc(
count * sizeof(PINT_sm_msgpair_state));
- if(!*msgpairarray)
+ if(!op->msgarray)
{
return -PVFS_ENOMEM;
}
- memset(*msgpairarray, 0, (count * sizeof(PINT_sm_msgpair_state)));
+ memset(op->msgarray, 0, (count * sizeof(PINT_sm_msgpair_state)));
+ op->count = count;
return 0;
}
/* we pass in a pointer to the array so that we can set it to NULL */
void PINT_msgpairarray_destroy(
- PINT_sm_msgpair_state * msgpairarray)
+ PINT_sm_msgarray_op *op)
+{
+ if(op->msgarray && (&op->msgpair) != op->msgarray)
+ {
+ free(op->msgarray);
+ }
+ op->msgarray = NULL;
+ op->count = 0;
+}
+
+int PINT_msgarray_status(PINT_sm_msgarray_op *op)
{
- free(msgpairarray);
+ int i;
+ for (i = 0; i < op->count; i++)
+ {
+ if (op->msgarray[i].op_status != 0)
+ {
+ return op->msgarray[i].op_status;
+ }
+ }
+ return 0;
}
int PINT_serv_decode_resp(PVFS_fs_id fs_id,
@@ -701,7 +717,6 @@ int PINT_serv_decode_resp(PVFS_fs_id fs_
struct PVFS_server_resp **resp_out_pp)
{
int ret = -1, server_type = 0;
- struct server_configuration_s *server_config;
const char *server_string;
ret = PINT_decode(encoded_resp_p, PINT_DECODE_RESP,
@@ -720,10 +735,8 @@ int PINT_serv_decode_resp(PVFS_fs_id fs_
if (fs_id != PVFS_FS_ID_NULL)
{
- server_config = PINT_server_config_mgr_get_config(fs_id);
server_string = PINT_cached_config_map_addr(
- server_config, fs_id, *svr_addr_p, &server_type);
- PINT_server_config_mgr_put_config(server_config);
+ fs_id, *svr_addr_p, &server_type);
gossip_err(" Server: %s.\n", server_string);
}
else
@@ -768,16 +781,16 @@ int PINT_serv_free_msgpair_resources(
* returns 0 on success, -PVFS_error on failure
*/
int PINT_serv_msgpairarray_resolve_addrs(
- int count, PINT_sm_msgpair_state *msgarray)
+ PINT_sm_msgarray_op *mop)
{
int i = 0;
int ret = -PVFS_EINVAL;
- if ((count > 0) && msgarray)
+ if ((mop->count > 0) && mop->msgarray)
{
- for(i = 0; i < count; i++)
+ for(i = 0; i < mop->count; i++)
{
- PINT_sm_msgpair_state *msg_p = &msgarray[i];
+ PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
assert(msg_p);
ret = PINT_cached_config_map_to_server(
@@ -796,7 +809,7 @@ int PINT_serv_msgpairarray_resolve_addrs
}
return ret;
}
-
+
/*
* Local variables:
* mode: c
@@ -806,3 +819,4 @@ int PINT_serv_msgpairarray_resolve_addrs
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/
+
Index: pint-cached-config.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-cached-config.c,v
diff -p -u -r1.19 -r1.19.12.1
--- pint-cached-config.c 18 Aug 2006 15:32:39 -0000 1.19
+++ pint-cached-config.c 21 Jul 2008 18:19:54 -0000 1.19.12.1
@@ -8,7 +8,10 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
+#include <sys/time.h>
#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
#include "pvfs2-types.h"
#include "pvfs2-attr.h"
@@ -20,6 +23,11 @@
#include "extent-utils.h"
#include "pint-cached-config.h"
+/* really old linux distributions (jazz's RHEL 3) don't have this(!?) */
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 64
+#endif
+
/* maps bmi address to handle ranges/extents */
struct bmi_host_extent_table_s
{
@@ -71,8 +79,7 @@ do { cur = hrange_list;
break; \
} \
cur_host_extent_table->bmi_address = \
- PINT_config_get_host_addr_ptr( \
- config,cur_mapping->alias_mapping->host_alias); \
+ cur_mapping->alias_mapping->bmi_address; \
assert(cur_host_extent_table->bmi_address); \
cur_host_extent_table->extent_list = \
PINT_create_extent_list(cur_mapping->handle_range); \
@@ -102,8 +109,7 @@ static int hash_fsid_compare(
void *key, struct qlist_head *link);
static void free_host_extent_table(void *ptr);
-static int cache_server_array(
- struct server_configuration_s *config, PVFS_fs_id fsid);
+static int cache_server_array(PVFS_fs_id fsid);
static int meta_randomized = 0;
static int io_randomized = 0;
@@ -116,12 +122,41 @@ static int io_randomized = 0;
*/
int PINT_cached_config_initialize(void)
{
+ struct timeval tv;
+ unsigned int seed = 0;
+ char hostname[HOST_NAME_MAX];
+ int ret;
+ int i;
+ int hostnamelen;
+
if (!PINT_fsid_config_cache_table)
{
PINT_fsid_config_cache_table =
qhash_init(hash_fsid_compare,hash_fsid,11);
}
- srand((unsigned int)time(NULL));
+
+ /* include time, pid, and hostname in random seed in order to help avoid
+ * collisions on object placement when many clients are launched
+ * concurrently
+ */
+ gettimeofday(&tv, NULL);
+ seed += tv.tv_sec;
+ seed += tv.tv_usec;
+
+ seed += getpid();
+
+ ret = gethostname(hostname, HOST_NAME_MAX);
+ if(ret == 0)
+ {
+ hostnamelen = strlen(hostname);
+ for(i=0; i<hostnamelen; i++)
+ {
+ seed += (hostname[hostnamelen - i - 1] + i*256);
+ }
+ }
+
+ srand(seed);
+
return (PINT_fsid_config_cache_table ? 0 : -PVFS_ENOMEM);
}
@@ -221,7 +256,7 @@ int PINT_cached_config_reinitialize(
break;
}
- ret = PINT_handle_load_mapping(config, cur_fs);
+ ret = PINT_cached_config_handle_load_mapping(cur_fs);
if (ret)
{
break;
@@ -232,7 +267,7 @@ int PINT_cached_config_reinitialize(
return 0;
}
-/* PINT_handle_load_mapping()
+/* PINT_cached_config_handle_load_mapping()
*
* loads a new mapping of servers to handle into this interface. This
* function may be called multiple times in order to add new file
@@ -240,8 +275,7 @@ int PINT_cached_config_reinitialize(
*
* returns 0 on success, -errno on failure
*/
-int PINT_handle_load_mapping(
- struct server_configuration_s *config,
+int PINT_cached_config_handle_load_mapping(
struct filesystem_configuration_s *fs)
{
int ret = -PVFS_EINVAL;
@@ -250,7 +284,7 @@ int PINT_handle_load_mapping(
struct config_fs_cache_s *cur_config_fs_cache = NULL;
struct bmi_host_extent_table_s *cur_host_extent_table = NULL;
- if (config && fs)
+ if (fs)
{
cur_config_fs_cache = (struct config_fs_cache_s *)
malloc(sizeof(struct config_fs_cache_s));
@@ -315,7 +349,6 @@ int PINT_handle_load_mapping(
* returns 0 on success, -errno on failure
*/
int PINT_cached_config_get_next_meta(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
PVFS_BMI_addr_t *meta_addr,
PVFS_handle_extent_array *ext_array)
@@ -326,7 +359,7 @@ int PINT_cached_config_get_next_meta(
struct qlist_head *hash_link = NULL;
struct config_fs_cache_s *cur_config_cache = NULL;
- if (config && ext_array)
+ if (ext_array)
{
hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
if (hash_link)
@@ -367,8 +400,7 @@ int PINT_cached_config_get_next_meta(
cur_config_cache->meta_server_cursor = PINT_llist_next(
cur_config_cache->meta_server_cursor);
}
- meta_server_bmi_str = PINT_config_get_host_addr_ptr(
- config,cur_mapping->alias_mapping->host_alias);
+ meta_server_bmi_str = cur_mapping->alias_mapping->bmi_address;
ext_array->extent_count =
cur_mapping->handle_extent_array.extent_count;
@@ -388,6 +420,238 @@ int PINT_cached_config_get_next_meta(
return ret;
}
+static int PINT_cached_config_get_extents(
+ PVFS_fs_id fsid,
+ PVFS_BMI_addr_t *addr,
+ PVFS_handle_extent_array *handle_extents)
+{
+ struct qhash_head *hash_link;
+ struct PINT_llist *server_list;
+ PVFS_BMI_addr_t tmp_addr;
+ struct config_fs_cache_s *cur_config_cache = NULL;
+ struct host_handle_mapping_s *cur_mapping = NULL;
+ int num_io_servers, ret;
+
+ hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
+ if(!hash_link)
+ {
+ gossip_err("Failed to find a file system matching fsid: %d\n", fsid);
+ return -PVFS_EINVAL;
+ }
+
+ cur_config_cache = qlist_entry(
+ hash_link, struct config_fs_cache_s, hash_link);
+
+ assert(cur_config_cache);
+ assert(cur_config_cache->fs);
+
+ server_list = cur_config_cache->fs->data_handle_ranges;
+ num_io_servers = PINT_llist_count(server_list);
+
+ while(!PINT_llist_empty(server_list))
+ {
+ cur_mapping = PINT_llist_head(server_list);
+ assert(cur_mapping);
+ server_list = PINT_llist_next(server_list);
+
+ ret = BMI_addr_lookup(
+ &tmp_addr, cur_mapping->alias_mapping->bmi_address);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ if(tmp_addr == *addr)
+ {
+ handle_extents->extent_count =
+ cur_mapping->handle_extent_array.extent_count;
+ handle_extents->extent_array =
+ cur_mapping->handle_extent_array.extent_array;
+
+ return 0;
+ }
+ }
+ return -PVFS_ENOENT;
+}
+
+int PINT_cached_config_map_servers(
+ PVFS_fs_id fsid,
+ int *inout_num_datafiles,
+ PVFS_sys_layout *layout,
+ PVFS_BMI_addr_t *addr_array,
+ PVFS_handle_extent_array *handle_extent_array)
+{
+ struct qhash_head *hash_link;
+ struct PINT_llist *server_list;
+ struct host_handle_mapping_s *cur_mapping = NULL;
+ struct config_fs_cache_s *cur_config_cache = NULL;
+ int num_io_servers, i, ret;
+ int start_index = -1;
+ int index;
+ int random_attempts;
+
+ assert(inout_num_datafiles);
+
+ hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
+ if(!hash_link)
+ {
+ gossip_err("Failed to find a file system matching fsid: %d\n", fsid);
+ return -PVFS_EINVAL;
+ }
+
+ cur_config_cache = qlist_entry(
+ hash_link, struct config_fs_cache_s, hash_link);
+
+ assert(cur_config_cache);
+ assert(cur_config_cache->fs);
+
+ server_list = cur_config_cache->fs->data_handle_ranges;
+ num_io_servers = PINT_llist_count(server_list);
+
+ switch(layout->algorithm)
+ {
+ case PVFS_SYS_LAYOUT_LIST:
+
+ if(*inout_num_datafiles < layout->server_list.count)
+ {
+ gossip_err("The specified datafile layout is larger"
+ " than the number of requested datafiles\n");
+ return -PVFS_EINVAL;
+ }
+
+ *inout_num_datafiles = layout->server_list.count;
+ for(i = 0; i < layout->server_list.count; ++i)
+ {
+ if(handle_extent_array)
+ {
+ ret = PINT_cached_config_get_extents(
+ fsid,
+ &layout->server_list.servers[i],
+ &handle_extent_array[i]);
+ if(ret < 0)
+ {
+ gossip_err("The address specified in the datafile "
+ "layout is invalid\n");
+ return ret;
+ }
+ }
+
+ addr_array[i] = layout->server_list.servers[i];
+ }
+ break;
+
+ case PVFS_SYS_LAYOUT_NONE:
+ start_index = 0;
+ /* fall through */
+
+ case PVFS_SYS_LAYOUT_ROUND_ROBIN:
+
+ if(num_io_servers < *inout_num_datafiles)
+ {
+ *inout_num_datafiles = num_io_servers;
+ }
+
+ if(start_index == -1)
+ {
+ start_index = rand() % *inout_num_datafiles;
+ }
+
+ for(i = 0; i < *inout_num_datafiles; ++i)
+ {
+ cur_mapping = PINT_llist_head(server_list);
+ assert(cur_mapping);
+ server_list = PINT_llist_next(server_list);
+
+ index = (i + start_index) % *inout_num_datafiles;
+ ret = BMI_addr_lookup(
+ &addr_array[index],
+ cur_mapping->alias_mapping->bmi_address);
+ if (ret)
+ {
+ return ret;
+ }
+
+ if(handle_extent_array)
+ {
+ handle_extent_array[index].extent_count =
+ cur_mapping->handle_extent_array.extent_count;
+ handle_extent_array[index].extent_array =
+ cur_mapping->handle_extent_array.extent_array;
+ }
+ }
+ break;
+
+ case PVFS_SYS_LAYOUT_RANDOM:
+ /* this layout randomizes the order but still uses each server
+ * only once
+ */
+
+ /* limit this layout to a number of datafiles no greater than
+ * the number of servers
+ */
+ if(num_io_servers < *inout_num_datafiles)
+ {
+ *inout_num_datafiles = num_io_servers;
+ }
+
+ /* init all the addrs to 0, so we know whether we've set an
+ * address at a particular index or not
+ */
+ memset(addr_array, 0, (*inout_num_datafiles)*sizeof(*addr_array));
+
+ for(i = 0; i < *inout_num_datafiles; ++i)
+ {
+ /* go through server list in order */
+ cur_mapping = PINT_llist_head(server_list);
+ assert(cur_mapping);
+ server_list = PINT_llist_next(server_list);
+
+ /* select random index into caller's list */
+ index = rand() % *inout_num_datafiles;
+ random_attempts = 1;
+
+ /* if we have already filled that index, try another random
+ * index
+ */
+ while(addr_array[index] != 0 && random_attempts < 6)
+ {
+ index = rand() % *inout_num_datafiles;
+ random_attempts++;
+ }
+
+ /* if we exhausted a max number of randomization attempts,
+ * then just go linearly through list
+ */
+ while(addr_array[index] != 0)
+ {
+ index = (index + 1) % *inout_num_datafiles;
+ }
+
+ /* found an unused index */
+ ret = BMI_addr_lookup(
+ &addr_array[index],
+ cur_mapping->alias_mapping->bmi_address);
+ if (ret)
+ {
+ return ret;
+ }
+
+ if(handle_extent_array)
+ {
+ handle_extent_array[index].extent_count =
+ cur_mapping->handle_extent_array.extent_count;
+ handle_extent_array[index].extent_array =
+ cur_mapping->handle_extent_array.extent_array;
+ }
+ }
+ break;
+ default:
+ gossip_err("Unknown datafile mapping algorithm\n");
+ return -PVFS_EINVAL;
+ }
+ return 0;
+}
+
/* PINT_cached_config_get_next_io()
*
* returns the address of a set of servers that should be used to
@@ -399,7 +663,6 @@ int PINT_cached_config_get_next_meta(
* returns 0 on success, -errno on failure
*/
int PINT_cached_config_get_next_io(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int num_servers,
PVFS_BMI_addr_t *io_addr_array,
@@ -413,7 +676,7 @@ int PINT_cached_config_get_next_io(
int jitter = 0, num_io_servers = 0;
PINT_llist* old_data_server_cursor = NULL;
- if (config && num_servers && io_handle_extent_array)
+ if (num_servers && io_handle_extent_array)
{
hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
if (hash_link)
@@ -470,8 +733,7 @@ int PINT_cached_config_get_next_io(
cur_config_cache->data_server_cursor = PINT_llist_next(
cur_config_cache->data_server_cursor);
- data_server_bmi_str = PINT_config_get_host_addr_ptr(
- config,cur_mapping->alias_mapping->host_alias);
+ data_server_bmi_str = cur_mapping->alias_mapping->bmi_address;
if (io_addr_array != NULL)
{
@@ -511,7 +773,6 @@ int PINT_cached_config_get_next_io(
* returns pointer to string on success, NULL on failure
*/
const char *PINT_cached_config_map_addr(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
PVFS_BMI_addr_t addr,
int *server_type)
@@ -520,11 +781,6 @@ const char *PINT_cached_config_map_addr(
struct qlist_head *hash_link = NULL;
struct config_fs_cache_s *cur_config_cache = NULL;
- if (!(config && server_type))
- {
- return NULL;
- }
-
hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
if (!hash_link)
{
@@ -535,7 +791,7 @@ const char *PINT_cached_config_map_addr(
assert(cur_config_cache);
assert(cur_config_cache->fs);
- ret = cache_server_array(config, fsid);
+ ret = cache_server_array(fsid);
if (ret < 0)
{
return NULL;
@@ -546,7 +802,10 @@ const char *PINT_cached_config_map_addr(
{
if (cur_config_cache->server_array[i].addr == addr)
{
- *server_type = cur_config_cache->server_array[i].server_type;
+ if(server_type)
+ {
+ *server_type = cur_config_cache->server_array[i].server_type;
+ }
return (cur_config_cache->server_array[i].addr_string);
}
}
@@ -560,7 +819,6 @@ const char *PINT_cached_config_map_addr(
* returns 0 on success, -errno on failure
*/
int PINT_cached_config_count_servers(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int server_type,
int *count)
@@ -569,7 +827,7 @@ int PINT_cached_config_count_servers(
struct qlist_head *hash_link = NULL;
struct config_fs_cache_s *cur_config_cache = NULL;
- if (!config || !server_type)
+ if (!server_type)
{
return ret;
}
@@ -585,7 +843,7 @@ int PINT_cached_config_count_servers(
assert(cur_config_cache);
assert(cur_config_cache->fs);
- ret = cache_server_array(config, fsid);
+ ret = cache_server_array(fsid);
if (ret == 0)
{
if (server_type == PINT_SERVER_TYPE_META)
@@ -617,7 +875,6 @@ int PINT_cached_config_count_servers(
* returns 0 on success, -errno on failure
*/
int PINT_cached_config_get_server_array(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int server_type,
PVFS_BMI_addr_t *addr_array,
@@ -627,7 +884,7 @@ int PINT_cached_config_get_server_array(
struct qlist_head *hash_link = NULL;
struct config_fs_cache_s *cur_config_cache = NULL;
- if (!config || !inout_count_p || !*inout_count_p ||
+ if (!inout_count_p || !*inout_count_p ||
!addr_array || !server_type)
{
return ret;
@@ -644,7 +901,7 @@ int PINT_cached_config_get_server_array(
assert(cur_config_cache);
assert(cur_config_cache->fs);
- ret = cache_server_array(config, fsid);
+ ret = cache_server_array(fsid);
if (ret < 0)
{
return ret;
@@ -740,7 +997,6 @@ int PINT_cached_config_get_num_dfiles(
int num_dfiles_requested,
int *num_dfiles)
{
- int ret = -PVFS_EINVAL;
int rc;
int num_io_servers;
@@ -765,17 +1021,23 @@ int PINT_cached_config_get_num_dfiles(
/* Determine the number of I/O servers available */
rc = PINT_cached_config_get_num_io(fsid, &num_io_servers);
+ if(rc < 0)
+ {
+ return(rc);
+ }
- if (0 == rc)
+ /* Allow the distribution to apply its hint to the number of
+ dfiles requested and the number of I/O servers available */
+ *num_dfiles = dist->methods->get_num_dfiles(dist->params,
+ num_io_servers,
+ num_dfiles_requested);
+ if(*num_dfiles < 1)
{
- /* Allow the distribution to apply its hint to the number of
- dfiles requested and the number of I/O servers available */
- *num_dfiles = dist->methods->get_num_dfiles(dist->params,
- num_io_servers,
- num_dfiles_requested);
- ret = 0;
+ gossip_err("Error: distribution failure for %d servers and %d requested datafiles.\n", num_io_servers, num_dfiles_requested);
+ return(-PVFS_EINVAL);
}
- return ret;
+
+ return 0;
}
/* PINT_cached_config_get_num_meta()
@@ -1032,7 +1294,6 @@ int PINT_cached_config_get_handle_timeou
* returns 0 on success, -errno on failure
*/
static int cache_server_array(
- struct server_configuration_s *config,
PVFS_fs_id fsid)
{
int ret = -PVFS_EINVAL, i = 0, j = 0;
@@ -1046,11 +1307,6 @@ static int cache_server_array(
int current = 0;
int array_index = 0, array_index2 = 0;
- if (!config)
- {
- return ret;
- }
-
hash_link = qhash_search(PINT_fsid_config_cache_table,&(fsid));
if (!hash_link)
{
@@ -1131,8 +1387,7 @@ static int cache_server_array(
while ((cur_mapping = PINT_llist_head(tmp_server)))
{
tmp_server = PINT_llist_next(tmp_server);
- server_bmi_str = PINT_config_get_host_addr_ptr(
- config,cur_mapping->alias_mapping->host_alias);
+ server_bmi_str = cur_mapping->alias_mapping->bmi_address;
ret = BMI_addr_lookup(&tmp_bmi_addr,server_bmi_str);
if (ret < 0)
Index: pint-cached-config.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-cached-config.h,v
diff -p -u -r1.9 -r1.9.22.1
--- pint-cached-config.h 18 Aug 2006 15:32:39 -0000 1.9
+++ pint-cached-config.h 21 Jul 2008 18:19:54 -0000 1.9.22.1
@@ -28,38 +28,36 @@ int PINT_cached_config_initialize(void);
int PINT_cached_config_finalize(void);
-int PINT_handle_load_mapping(
- struct server_configuration_s *config,
+int PINT_cached_config_handle_load_mapping(
struct filesystem_configuration_s *fs);
+int PINT_cached_config_map_alias(
+ const char *alias,
+ PVFS_BMI_addr_t *addr);
+
int PINT_cached_config_get_next_meta(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
PVFS_BMI_addr_t *meta_addr,
PVFS_handle_extent_array *meta_extent_array);
int PINT_cached_config_get_next_io(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int num_servers,
PVFS_BMI_addr_t *io_addr_array,
PVFS_handle_extent_array *io_handle_extent_array);
const char *PINT_cached_config_map_addr(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
PVFS_BMI_addr_t addr,
int *server_type);
int PINT_cached_config_get_server_array(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int server_type,
PVFS_BMI_addr_t *addr_array,
int *inout_count_p);
int PINT_cached_config_count_servers(
- struct server_configuration_s *config,
PVFS_fs_id fsid,
int server_type,
int *count);
@@ -67,7 +65,14 @@ int PINT_cached_config_count_servers(
int PINT_cached_config_map_to_server(
PVFS_BMI_addr_t *server_addr,
PVFS_handle handle,
- PVFS_fs_id fsid);
+ PVFS_fs_id fs_id);
+
+int PINT_cached_config_map_servers(
+ PVFS_fs_id fsid,
+ int *inout_num_datafiles,
+ PVFS_sys_layout *layout,
+ PVFS_BMI_addr_t *addr_array,
+ PVFS_handle_extent_array *handle_extent_array);
int PINT_cached_config_get_num_dfiles(
PVFS_fs_id fsid,
Index: pint-perf-counter.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-perf-counter.c,v
diff -p -u -r1.11 -r1.11.18.1
--- pint-perf-counter.c 27 May 2006 23:46:04 -0000 1.11
+++ pint-perf-counter.c 21 Jul 2008 18:19:54 -0000 1.11.18.1
@@ -9,6 +9,7 @@
#include <sys/time.h>
#include <assert.h>
#include <stdio.h>
+#include <time.h>
#include "pvfs2-types.h"
#include "pvfs2-util.h"
@@ -48,13 +49,7 @@ struct PINT_perf_counter* PINT_perf_init
return(NULL);
}
memset(pc, 0, sizeof(struct PINT_perf_counter));
- pc->mutex = gen_mutex_build();
- if(!pc->mutex)
- {
- free(pc);
- return(NULL);
- }
-
+ gen_mutex_init(&pc->mutex);
pc->key_array = key_array;
key = &key_array[pc->key_count];
@@ -64,7 +59,7 @@ struct PINT_perf_counter* PINT_perf_init
if(key->key != pc->key_count)
{
gossip_err("Error: PINT_perf_initialize(): key out of order.\n");
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -75,7 +70,7 @@ struct PINT_perf_counter* PINT_perf_init
if(pc->key_count < 1)
{
gossip_err("Error: PINT_perf_initialize(): no keys specified.\n");
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -87,7 +82,7 @@ struct PINT_perf_counter* PINT_perf_init
(uint64_t*)malloc(PERF_DEFAULT_HISTORY_SIZE*sizeof(uint64_t));
if(!pc->start_time_array_ms)
{
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -96,7 +91,7 @@ struct PINT_perf_counter* PINT_perf_init
if(!pc->interval_array_ms)
{
free(pc->start_time_array_ms);
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -111,7 +106,7 @@ struct PINT_perf_counter* PINT_perf_init
{
free(pc->start_time_array_ms);
free(pc->interval_array_ms);
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -129,7 +124,7 @@ struct PINT_perf_counter* PINT_perf_init
free(pc->value_matrix);
free(pc->start_time_array_ms);
free(pc->interval_array_ms);
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
return(NULL);
}
@@ -154,7 +149,7 @@ void PINT_perf_reset(
int i;
struct timeval tv;
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
/* zero out all fields */
memset(pc->start_time_array_ms, 0,
@@ -174,7 +169,7 @@ void PINT_perf_reset(
pc->start_time_array_ms[0] = ((uint64_t)tv.tv_sec)*1000 +
tv.tv_usec/1000;
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return;
}
@@ -194,7 +189,7 @@ void PINT_perf_finalize(
free(pc->value_matrix);
free(pc->start_time_array_ms);
free(pc->interval_array_ms);
- gen_mutex_destroy(pc->mutex);
+ gen_mutex_destroy(&pc->mutex);
free(pc);
pc = NULL;
@@ -217,7 +212,7 @@ void __PINT_perf_count(
return;
}
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
if(key >= pc->key_count)
{
@@ -238,7 +233,7 @@ void __PINT_perf_count(
break;
}
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return;
}
@@ -267,7 +262,7 @@ void PINT_perf_rollover(
gettimeofday(&tv, NULL);
int_time = ((uint64_t)tv.tv_sec)*1000 + tv.tv_usec/1000;
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
/* rotate all values back one */
if(pc->history_size > 1)
@@ -300,7 +295,7 @@ void PINT_perf_rollover(
}
}
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return;
}
@@ -324,7 +319,7 @@ int PINT_perf_set_info(
return 0;
}
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
switch(option)
{
case PINT_PERF_HISTORY_SIZE:
@@ -360,11 +355,11 @@ int PINT_perf_set_info(
}
break;
default:
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(-PVFS_EINVAL);
}
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(0);
}
@@ -383,7 +378,7 @@ int PINT_perf_get_info(
return (0);
}
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
switch(option)
{
case PINT_PERF_HISTORY_SIZE:
@@ -393,11 +388,11 @@ int PINT_perf_get_info(
*arg = pc->key_count;
break;
default:
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(-PVFS_EINVAL);
}
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(0);
}
@@ -424,7 +419,7 @@ void PINT_perf_retrieve(
return;
}
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
/* it isn't very safe to allow the caller to ask for more keys than are
* available, because they will probably overrun key array bounds when
@@ -462,7 +457,7 @@ void PINT_perf_retrieve(
memcpy(interval_array_ms, pc->interval_array_ms,
(tmp_max_history*sizeof(uint64_t)));
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
/* fill in interval length for newest interval */
gettimeofday(&tv, NULL);
@@ -491,7 +486,7 @@ char* PINT_perf_generate_text(
struct tm tmp_tm;
int ret;
- gen_mutex_lock(pc->mutex);
+ gen_mutex_lock(&pc->mutex);
line_size = 26 + (24*pc->history_size);
total_size = (pc->key_count+2)*line_size + 1;
@@ -509,7 +504,7 @@ char* PINT_perf_generate_text(
tmp_str = (char*)malloc(actual_size*sizeof(char));
if(!tmp_str)
{
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(NULL);
}
position = tmp_str;
@@ -599,7 +594,7 @@ char* PINT_perf_generate_text(
position++;
}
- gen_mutex_unlock(pc->mutex);
+ gen_mutex_unlock(&pc->mutex);
return(tmp_str);
}
Index: pint-perf-counter.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-perf-counter.h,v
diff -p -u -r1.11 -r1.11.22.1
--- pint-perf-counter.h 1 Aug 2006 00:37:37 -0000 1.11
+++ pint-perf-counter.h 21 Jul 2008 18:19:54 -0000 1.11.22.1
@@ -61,7 +61,7 @@ struct PINT_perf_key
/** struct representing a perf counter instance */
struct PINT_perf_counter
{
- gen_mutex_t* mutex;
+ gen_mutex_t mutex;
struct PINT_perf_key* key_array; /**< keys (provided by initialize()) */
int key_count; /**< number of keys */
int history_size; /**< number of history intervals */
Index: pint-util.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-util.c,v
diff -p -u -r1.13 -r1.13.12.1
--- pint-util.c 18 Aug 2006 15:03:47 -0000 1.13
+++ pint-util.c 21 Jul 2008 18:19:54 -0000 1.13.12.1
@@ -10,32 +10,15 @@
*/
/* This file includes definitions of common internal utility functions */
-
#include <string.h>
+#include <assert.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
-#include <assert.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include "pvfs2-types.h"
-#include "pint-util.h"
#include "gen-locks.h"
+#include "pint-util.h"
#include "gossip.h"
-#include "pvfs2-debug.h"
-#include "bmi-byteswap.h"
-
-static int current_tag = 1;
-static gen_mutex_t current_tag_lock = GEN_MUTEX_INITIALIZER;
-
-static gen_mutex_t check_group_mutex = GEN_MUTEX_INITIALIZER;
-static char* check_group_pw_buffer = NULL;
-static long check_group_pw_buffer_size = 0;
-static char* check_group_gr_buffer = NULL;
-static long check_group_gr_buffer_size = 0;
-static int PINT_check_group(uid_t uid, gid_t gid);
void PINT_time_mark(PINT_time_marker *out_marker)
{
@@ -72,6 +55,9 @@ void PINT_time_diff(PINT_time_marker mar
(double)(mark1.utime.tv_usec) / 1000000);
}
+static int current_tag = 1;
+static gen_mutex_t current_tag_lock = GEN_MUTEX_INITIALIZER;
+
PVFS_msg_tag_t PINT_util_get_next_tag(void)
{
PVFS_msg_tag_t ret;
@@ -199,6 +185,7 @@ int PINT_copy_object_attr(PVFS_object_at
if (dest->u.meta.dfile_array)
{
free(dest->u.meta.dfile_array);
+ dest->u.meta.dfile_array = NULL;
}
}
dest->u.meta.dfile_array = malloc(df_array_size);
@@ -220,7 +207,7 @@ int PINT_copy_object_attr(PVFS_object_at
{
assert(src->u.meta.dist_size > 0);
- if ((dest->mask & PVFS_ATTR_META_DIST))
+ if ((dest->mask & PVFS_ATTR_META_DIST) && dest->u.meta.dist)
{
PINT_dist_free(dest->u.meta.dist);
}
@@ -231,6 +218,7 @@ int PINT_copy_object_attr(PVFS_object_at
}
dest->u.meta.dist_size = src->u.meta.dist_size;
}
+ memcpy(&dest->u.meta.hint, &src->u.meta.hint, sizeof(dest->u.meta.hint));
}
if (src->mask & PVFS_ATTR_SYMLNK_TARGET)
@@ -260,6 +248,7 @@ void PINT_free_object_attr(PVFS_object_a
if (attr->u.meta.dfile_array)
{
free(attr->u.meta.dfile_array);
+ attr->u.meta.dfile_array = NULL;
}
}
if (attr->mask & PVFS_ATTR_META_DIST)
@@ -267,6 +256,7 @@ void PINT_free_object_attr(PVFS_object_a
if (attr->u.meta.dist)
{
PINT_dist_free(attr->u.meta.dist);
+ attr->u.meta.dist = NULL;
}
}
}
@@ -278,6 +268,7 @@ void PINT_free_object_attr(PVFS_object_a
attr->u.sym.target_path)
{
free(attr->u.sym.target_path);
+ attr->u.sym.target_path = NULL;
}
}
}
@@ -288,413 +279,94 @@ void PINT_free_object_attr(PVFS_object_a
if (attr->u.dir.hint.dist_name)
{
free(attr->u.dir.hint.dist_name);
+ attr->u.dir.hint.dist_name = NULL;
}
if (attr->u.dir.hint.dist_params)
{
free(attr->u.dir.hint.dist_params);
+ attr->u.dir.hint.dist_params = NULL;
}
}
}
}
}
-/* PINT_check_mode()
- *
- * checks to see if the type of access described by "access_type" is permitted
- * for user "uid" of group "gid" on the object with attributes "attr"
- *
- * returns 0 on success, -PVFS_EACCES if permission is not granted
- */
-int PINT_check_mode(
- PVFS_object_attr *attr,
- PVFS_uid uid, PVFS_gid gid,
- enum PINT_access_type access_type)
+char *PINT_util_get_object_type(int objtype)
{
- int in_group_flag = 0;
- int ret = 0;
- uint32_t perm_mask = (PVFS_ATTR_COMMON_UID |
- PVFS_ATTR_COMMON_GID |
- PVFS_ATTR_COMMON_PERM);
-
- /* if we don't have masks for the permission information that we
- * need, then the system is broken
- */
- assert((attr->mask & perm_mask) == perm_mask);
-
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - check_mode called --- "
- "(uid=%d,gid=%d,access_type=%d)\n", uid, gid, access_type);
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - object attributes --- "
- "(uid=%d,gid=%d,mode=%d)\n", attr->owner, attr->group,
- attr->perms);
-
- /* give root permission, no matter what */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG,
- " - checking if uid (%d) is root ...\n", uid);
- if (uid == 0)
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return 0;
- }
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
-
- /* see if uid matches object owner */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking if owner (%d) "
- "matches uid (%d)...\n", attr->owner, uid);
- if(attr->owner == uid)
- {
- /* see if object user permissions match access type */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking if permissions "
- "(%d) allows access type (%d) for user...\n", attr->perms, access_type);
- if(access_type == PINT_ACCESS_READABLE && (attr->perms &
- PVFS_U_READ))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_WRITABLE && (attr->perms &
- PVFS_U_WRITE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_EXECUTABLE && (attr->perms &
- PVFS_U_EXECUTE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
- }
- else
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
- }
-
- /* see if other bits allow access */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking if permissions "
- "(%d) allows access type (%d) by others...\n", attr->perms, access_type);
- if(access_type == PINT_ACCESS_READABLE && (attr->perms &
- PVFS_O_READ))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_WRITABLE && (attr->perms &
- PVFS_O_WRITE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_EXECUTABLE && (attr->perms &
- PVFS_O_EXECUTE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
-
- /* see if gid matches object group */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking if group (%d) "
- "matches gid (%d)...\n", attr->group, gid);
- if(attr->group == gid)
- {
- /* default group match */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- in_group_flag = 1;
- }
- else
- {
- /* no default group match, check supplementary groups */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking for"
- " supplementary group match...\n");
- ret = PINT_check_group(uid, attr->group);
- if(ret == 0)
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- in_group_flag = 1;
- }
- else
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
- if(ret != -PVFS_ENOENT)
- {
- /* system error; not just failed match */
- return(ret);
- }
- }
- }
-
- if(in_group_flag)
+ static char *obj_types[] =
{
- /* see if object group permissions match access type */
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - checking if permissions "
- "(%d) allows access type (%d) for group...\n", attr->perms, access_type);
- if(access_type == PINT_ACCESS_READABLE && (attr->perms &
- PVFS_G_READ))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_WRITABLE && (attr->perms &
- PVFS_G_WRITE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- if(access_type == PINT_ACCESS_EXECUTABLE && (attr->perms &
- PVFS_G_EXECUTE))
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - yes\n");
- return(0);
- }
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, " - no\n");
+ "NONE", "METAFILE", "DATAFILE",
+ "DIRECTORY", "SYMLINK", "DIRDATA", "UNKNOWN"
+ };
+ switch(objtype)
+ {
+ case PVFS_TYPE_NONE:
+ return obj_types[0];
+ case PVFS_TYPE_METAFILE:
+ return obj_types[1];
+ case PVFS_TYPE_DATAFILE:
+ return obj_types[2];
+ case PVFS_TYPE_DIRECTORY:
+ return obj_types[3];
+ case PVFS_TYPE_SYMLINK:
+ return obj_types[4];
+ case PVFS_TYPE_DIRDATA:
+ return obj_types[5];
}
-
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "******PINT_check_mode: denying access\n");
- /* default case: access denied */
- return -PVFS_EACCES;
+ return obj_types[6];
}
-/* PINT_check_group()
- *
- * checks to see if uid is a member of gid
- *
- * returns 0 on success, -PVFS_ENOENT if not a member, other PVFS error codes
- * on system failure
- */
-static int PINT_check_group(uid_t uid, gid_t gid)
+PVFS_time PINT_util_get_current_time(void)
{
- struct passwd pwd;
- struct passwd* pwd_p = NULL;
- struct group grp;
- struct group* grp_p = NULL;
- int i = 0;
- int ret = -1;
-
- /* Explanation:
- *
- * We use the _r variants of getpwuid and getgrgid in order to insure
- * thread safety; particularly if this function ever gets called in a
- * client side situation in which we can't prevent the application from
- * making conflicting calls.
- *
- * These _r functions require that a buffer be supplied for the user and
- * group information, however. These buffers may be unconfortably large
- * for the stack, so we malloc them on a static pointer and then mutex
- * lock this function so that it can still be reentrant.
- */
-
- gen_mutex_lock(&check_group_mutex);
-
- if(!check_group_pw_buffer)
- {
- /* need to create a buffer for pw and grp entries */
-#if defined(_SC_GETGR_R_SIZE_MAX) && defined(_SC_GETPW_R_SIZE_MAX)
- /* newish posix systems can tell us what the max buffer size is */
- check_group_gr_buffer_size = sysconf(_SC_GETGR_R_SIZE_MAX);
- check_group_pw_buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX);
-#else
- /* fall back for older systems */
- check_group_pw_buffer_size = 1024;
- check_group_gr_buffer_size = 1024;
-#endif
- check_group_pw_buffer = (char*)malloc(check_group_pw_buffer_size);
- check_group_gr_buffer = (char*)malloc(check_group_gr_buffer_size);
- if(!check_group_pw_buffer || !check_group_gr_buffer)
- {
- if(check_group_pw_buffer)
- {
- free(check_group_pw_buffer);
- check_group_pw_buffer = NULL;
- }
- if(check_group_gr_buffer)
- {
- free(check_group_gr_buffer);
- check_group_gr_buffer = NULL;
- }
- gen_mutex_unlock(&check_group_mutex);
- return(-PVFS_ENOMEM);
- }
- }
-
- /* get user information */
- ret = getpwuid_r(uid, &pwd, check_group_pw_buffer,
- check_group_pw_buffer_size,
- &pwd_p);
- if(ret != 0)
- {
- gen_mutex_unlock(&check_group_mutex);
- return(-PVFS_ENOENT);
- }
-
- /* check primary group */
- if(pwd.pw_gid == gid) return 0;
-
- /* get other group information */
- ret = getgrgid_r(gid, &grp, check_group_gr_buffer,
- check_group_gr_buffer_size,
- &grp_p);
- if(ret != 0)
- {
- gen_mutex_unlock(&check_group_mutex);
- return(-PVFS_ENOENT);
- }
-
- gen_mutex_unlock(&check_group_mutex);
+ struct timeval t = {0,0};
+ PVFS_time current_time = 0;
+ gettimeofday(&t, NULL);
+ current_time = (PVFS_time)t.tv_sec;
+ return current_time;
+}
- for(i = 0; grp.gr_mem[i] != NULL; i++)
- {
- if(0 == strcmp(pwd.pw_name, grp.gr_mem[i]) )
- {
- gen_mutex_unlock(&check_group_mutex);
- return 0;
- }
- }
+PVFS_time PINT_util_mktime_version(PVFS_time time)
+{
+ struct timeval t = {0,0};
+ PVFS_time version = (time << 32);
- gen_mutex_unlock(&check_group_mutex);
- return(-PVFS_ENOENT);
+ gettimeofday(&t, NULL);
+ version |= (PVFS_time)t.tv_usec;
+ return version;
}
-/* Checks if a given user is part of any groups that matches the file gid */
-static int in_group_p(PVFS_uid uid, PVFS_gid gid, PVFS_gid attr_group)
+PVFS_time PINT_util_mkversion_time(PVFS_time version)
{
- if (attr_group == gid)
- return 1;
- if (PINT_check_group(uid, attr_group) == 0)
- return 1;
- return 0;
+ return (PVFS_time)(version >> 32);
}
-/*
- * Return 0 if requesting clients is granted want access to the object
- * by the acl. Returns -PVFS_E... otherwise.
- */
-int PINT_check_acls(void *acl_buf, size_t acl_size,
- PVFS_object_attr *attr,
- PVFS_uid uid, PVFS_gid gid, int want)
+char *PINT_util_guess_alias(void)
{
- pvfs2_acl_entry pe, *pa;
- int i = 0, found = 0, count = 0;
- uint32_t perm_mask = (PVFS_ATTR_COMMON_UID |
- PVFS_ATTR_COMMON_GID |
- PVFS_ATTR_COMMON_PERM);
+ char tmp_alias[1024];
+ char *tmpstr;
+ char *alias;
+ int ret;
- if (acl_size == 0)
+ /* hmm...failed to find alias as part of the server config filename,
+ * use the hostname to guess
+ */
+ ret = gethostname(tmp_alias, 1024);
+ if(ret != 0)
{
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "no acl's present.. denying access\n");
- return -PVFS_EACCES;
+ gossip_err("Failed to get hostname while attempting to guess "
+ "alias. Use -a to specify the alias for this server "
+ "process directly\n");
+ return NULL;
}
+ alias = tmp_alias;
- /* keyval for ACLs includes a \0. so subtract the thingie */
- acl_size--;
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "PINT_check_acls: read keyval size "
- " %d (%d acl entries)\n",
- (int) acl_size,
- (int) (acl_size / sizeof(pvfs2_acl_entry)));
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "uid = %d, gid = %d, want = %d\n",
- uid, gid, want);
-
- assert((attr->mask & perm_mask) == perm_mask);
- assert(acl_buf);
- assert(acl_size % sizeof(pvfs2_acl_entry) == 0);
- count = acl_size / sizeof(pvfs2_acl_entry);
-
- for (i = 0; i < count; i++)
+ tmpstr = strstr(tmp_alias, ".");
+ if(tmpstr)
{
- pa = (pvfs2_acl_entry *) acl_buf + i;
- /*
- NOTE: Remember that keyval is encoded as lebf, so convert it
- to host representation
- */
- pe.p_tag = bmitoh32(pa->p_tag);
- pe.p_perm = bmitoh32(pa->p_perm);
- pe.p_id = bmitoh32(pa->p_id);
- pa = &pe;
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "Decoded ACL entry %d "
- "(p_tag %d, p_perm %d, p_id %d)\n",
- i, pa->p_tag, pa->p_perm, pa->p_id);
- switch(pa->p_tag)
- {
- case PVFS2_ACL_USER_OBJ:
- /* (May have been checked already) */
- if (attr->owner == uid)
- goto check_perm;
- break;
- case PVFS2_ACL_USER:
- if (pa->p_id == uid)
- goto mask;
- break;
- case PVFS2_ACL_GROUP_OBJ:
- if (in_group_p(uid, gid, attr->group))
- {
- found = 1;
- if ((pa->p_perm & want) == want)
- goto mask;
- }
- break;
- case PVFS2_ACL_GROUP:
- if (in_group_p(uid, gid, pa->p_id)) {
- found = 1;
- if ((pa->p_perm & want) == want)
- goto mask;
- }
- break;
- case PVFS2_ACL_MASK:
- break;
- case PVFS2_ACL_OTHER:
- if (found)
- {
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "(1) PINT_check_acls:"
- "returning access denied\n");
- return -PVFS_EACCES;
- }
- else
- goto check_perm;
- default:
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "(2) PINT_check_acls: "
- "returning EIO\n");
- return -PVFS_EIO;
- }
+ *tmpstr = 0;
}
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "(3) PINT_check_acls: returning EIO\n");
- return -PVFS_EIO;
-mask:
- /* search the remaining entries */
- i = i + 1;
- for (; i < count; i++)
- {
- pvfs2_acl_entry me, *mask_obj = (pvfs2_acl_entry *) acl_buf + i;
-
- /*
- NOTE: Again, since pvfs2_acl_entry is in lebf, we need to
- convert it to host endian format
- */
- me.p_tag = bmitoh32(mask_obj->p_tag);
- me.p_perm = bmitoh32(mask_obj->p_perm);
- me.p_id = bmitoh32(mask_obj->p_id);
- mask_obj = &me;
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "Decoded (mask) ACL entry %d "
- "(p_tag %d, p_perm %d, p_id %d)\n",
- i, mask_obj->p_tag, mask_obj->p_perm, mask_obj->p_id);
- if (mask_obj->p_tag == PVFS2_ACL_MASK)
- {
- if ((pa->p_perm & mask_obj->p_perm & want) == want)
- return 0;
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "(4) PINT_check_acls:"
- "returning access denied (mask)\n");
- return -PVFS_EACCES;
- }
- }
-
-check_perm:
- if ((pa->p_perm & want) == want)
- return 0;
- gossip_debug(GOSSIP_PERMISSIONS_DEBUG, "(5) PINT_check_acls: returning"
- "access denied\n");
- return -PVFS_EACCES;
+ return strdup(tmp_alias);
}
/*
Index: pint-util.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pint-util.h,v
diff -p -u -r1.11 -r1.11.12.1
--- pint-util.h 17 Aug 2006 08:11:50 -0000 1.11
+++ pint-util.h 21 Jul 2008 18:19:55 -0000 1.11.12.1
@@ -75,9 +75,6 @@ typedef struct PINT_time_marker_s PINT_t
PVFS_msg_tag_t PINT_util_get_next_tag(void);
-int PINT_check_acls(void *acl_buf, size_t acl_size,
- PVFS_object_attr *attr,
- PVFS_uid uid, PVFS_gid gid, int want);
int PINT_copy_object_attr(PVFS_object_attr *dest, PVFS_object_attr *src);
void PINT_free_object_attr(PVFS_object_attr *attr);
void PINT_time_mark(PINT_time_marker* out_marker);
@@ -87,18 +84,6 @@ void PINT_time_diff(PINT_time_marker mar
double* out_utime_sec,
double* out_stime_sec);
-enum PINT_access_type
-{
- PINT_ACCESS_EXECUTABLE = 1,
- PINT_ACCESS_WRITABLE = 2,
- PINT_ACCESS_READABLE = 4,
-};
-
-int PINT_check_mode(
- PVFS_object_attr *attr,
- PVFS_uid uid, PVFS_gid gid,
- enum PINT_access_type access_type);
-
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
@@ -131,6 +116,23 @@ int PINT_check_mode(
#error Cant stat mounted filesystems
#endif
+
+char *PINT_util_get_object_type(int objtype);
+PVFS_time PINT_util_get_current_time(void);
+
+PVFS_time PINT_util_mktime_version(PVFS_time time);
+PVFS_time PINT_util_mkversion_time(PVFS_time version);
+
+void PINT_util_digest_init(void);
+void PINT_util_digest_finalize(void);
+
+int PINT_util_digest_sha1(const void *input_message, size_t input_length,
+ char **output, size_t *output_length);
+
+int PINT_util_digest_md5(const void *input_message, size_t input_length,
+ char **output, size_t *output_length);
+
+char *PINT_util_guess_alias(void);
#endif /* __PINT_UTIL_H */
Index: pvfs2-debug.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pvfs2-debug.c,v
diff -p -u -r1.43.8.1 -r1.43.8.1.2.1
--- pvfs2-debug.c 27 Sep 2006 21:02:26 -0000 1.43.8.1
+++ pvfs2-debug.c 21 Jul 2008 18:19:55 -0000 1.43.8.1.2.1
@@ -18,22 +18,7 @@ typedef struct
uint64_t mask_val;
} __keyword_mask_t;
-#define __DEBUG_ALL \
-(GOSSIP_TROVE_DEBUG | GOSSIP_BMI_DEBUG_ALL | GOSSIP_SERVER_DEBUG |\
-GOSSIP_CLIENT_DEBUG | GOSSIP_JOB_DEBUG | GOSSIP_REQUEST_DEBUG | \
-GOSSIP_REQ_SCHED_DEBUG | GOSSIP_FLOW_PROTO_DEBUG | \
-GOSSIP_FLOW_DEBUG | GOSSIP_NCACHE_DEBUG | GOSSIP_ACACHE_DEBUG | \
-GOSSIP_DIST_DEBUG | GOSSIP_DBPF_ATTRCACHE_DEBUG | \
-GOSSIP_MMAP_RCACHE_DEBUG | GOSSIP_LOOKUP_DEBUG | \
-GOSSIP_REMOVE_DEBUG | GOSSIP_GETATTR_DEBUG | GOSSIP_READDIR_DEBUG|\
-GOSSIP_IO_DEBUG | GOSSIP_DBPF_OPEN_CACHE_DEBUG | \
-GOSSIP_PERMISSIONS_DEBUG | GOSSIP_CANCEL_DEBUG | \
-GOSSIP_MSGPAIR_DEBUG | GOSSIP_CLIENTCORE_DEBUG | \
-GOSSIP_SETATTR_DEBUG | GOSSIP_MKDIR_DEBUG | \
-GOSSIP_SETEATTR_DEBUG | GOSSIP_GETEATTR_DEBUG | \
-GOSSIP_LISTEATTR_DEBUG | GOSSIP_DBPF_KEYVAL_DEBUG | \
-GOSSIP_ACCESS_DEBUG | GOSSIP_ACCESS_DETAIL_DEBUG | \
-GOSSIP_PERFCOUNTER_DEBUG | GOSSIP_LOCK_DEBUG)
+#define __DEBUG_ALL ((uint64_t) -1)
/* map all config keywords to pvfs2 debug masks here */
static __keyword_mask_t s_keyword_mask_map[] =
@@ -80,6 +65,8 @@ static __keyword_mask_t s_keyword_mask_m
{ "getattr", GOSSIP_GETATTR_DEBUG },
/* Debug the server setattr state machine. */
{ "setattr", GOSSIP_SETATTR_DEBUG },
+ /* vectored getattr server state machine */
+ { "listattr", GOSSIP_LISTATTR_DEBUG },
/* Debug the client and server get ext attributes SM. */
{ "geteattr", GOSSIP_GETEATTR_DEBUG },
/* Debug the client and server set ext attributes SM. */
@@ -103,6 +90,8 @@ static __keyword_mask_t s_keyword_mask_m
{ "clientcore", GOSSIP_CLIENTCORE_DEBUG },
/* Debug the client timing state machines (job timeout, etc.) */
{ "clientcore_timing", GOSSIP_CLIENTCORE_TIMING_DEBUG },
+ /* network encoding */
+ { "endecode", GOSSIP_ENDECODE_DEBUG },
/* Show server file (metadata) accesses (both modify and read-only). */
{ "access", GOSSIP_ACCESS_DEBUG },
/* Show more detailed server file accesses */
@@ -117,8 +106,18 @@ static __keyword_mask_t s_keyword_mask_m
{ "coalesce", GOSSIP_DBPF_COALESCE_DEBUG },
/* Debug the lock syscall */
{ "lock", GOSSIP_LOCK_DEBUG},
- /* Everything except the perf counter. Useful for debugging */
- { "verbose", (__DEBUG_ALL & ~GOSSIP_PERFCOUNTER_DEBUG)},
+ /* Display the hostnames instead of IP addrs in debug output */
+ { "access_hostnames", GOSSIP_ACCESS_HOSTNAMES },
+ /* Show the client device events */
+ { "user_dev", GOSSIP_USER_DEV_DEBUG },
+ /* Debug the fsck tool */
+ { "fsck", GOSSIP_FSCK_DEBUG },
+ { "bstream", GOSSIP_BSTREAM_DEBUG },
+ /* Everything except the periodic events. Useful for debugging */
+ { "verbose",
+ (__DEBUG_ALL & ~(GOSSIP_PERFCOUNTER_DEBUG | GOSSIP_STATE_MACHINE_DEBUG |
+ GOSSIP_ENDECODE_DEBUG | GOSSIP_USER_DEV_DEBUG))
+ },
/* No debug output */
{ "none", GOSSIP_NO_DEBUG },
/* Everything */
Index: pvfs2-internal.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pvfs2-internal.h,v
diff -p -u -r1.4 -r1.4.12.1
--- pvfs2-internal.h 17 Aug 2006 08:14:37 -0000 1.4
+++ pvfs2-internal.h 21 Jul 2008 18:19:55 -0000 1.4.12.1
@@ -25,6 +25,27 @@
* specifier and a parameter are mismatched, that machine will issue
* a warning, while 64-bit machines will silently perform the cast.
*/
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#endif
+
+#ifdef BITS_PER_LONG
+/* don't use SIZEOF_* fields generated at configure */
+#if BITS_PER_LONG == 32
+# define llu(x) (x)
+# define lld(x) (x)
+# define SCANF_lld "%lld"
+#elif BITS_PER_LONG == 64
+# define llu(x) (unsigned long long)(x)
+# define lld(x) (long long)(x)
+#define SCANF_lld "%ld"
+#else
+# error Unexpected BITS_PER_LONG
+#endif
+
+#else
+
#if SIZEOF_LONG_INT == 4
# define llu(x) (x)
# define lld(x) (x)
@@ -37,14 +58,35 @@
# error Unexpected sizeof(long int)
#endif
+#endif /* BITS_PER_LONG */
+
/* key string definition macros. These are used by the server and
* by the client (in the case of xattrs with viewdist, etc).
*/
-#define ROOT_HANDLE_KEYSTR "rh"
-#define DIRECTORY_ENTRY_KEYSTR "de"
-#define DATAFILE_HANDLES_KEYSTR "dh"
-#define METAFILE_DIST_KEYSTR "md"
-#define SYMLINK_TARGET_KEYSTR "st"
+#define ROOT_HANDLE_KEYSTR "rh\0"
+#define ROOT_HANDLE_KEYLEN 3
+
+#define DIRECTORY_ENTRY_KEYSTR "de\0"
+#define DIRECTORY_ENTRY_KEYLEN 3
+
+#define DATAFILE_HANDLES_KEYSTR "dh\0"
+#define DATAFILE_HANDLES_KEYLEN 3
+
+#define METAFILE_DIST_KEYSTR "md\0"
+#define METAFILE_DIST_KEYLEN 3
+
+#define SYMLINK_TARGET_KEYSTR "st\0"
+#define SYMLINK_TARGET_KEYLEN 3
+
+/* Optional xattrs have "user.pvfs2." as a prefix */
+#define SPECIAL_DIST_NAME_KEYSTR "dist_name\0"
+#define SPECIAL_DIST_NAME_KEYLEN 21
+#define SPECIAL_DIST_PARAMS_KEYSTR "dist_params\0"
+#define SPECIAL_DIST_PARAMS_KEYLEN 23
+#define SPECIAL_NUM_DFILES_KEYSTR "num_dfiles\0"
+#define SPECIAL_NUM_DFILES_KEYLEN 22
+#define SPECIAL_METAFILE_HINT_KEYSTR "meta_hint\0"
+#define SPECIAL_METAFILE_HINT_KEYLEN 21
#define IO_MAX_REGIONS 64
Index: pvfs2-util.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/pvfs2-util.c,v
diff -p -u -r1.90 -r1.90.16.1
--- pvfs2-util.c 16 Jun 2006 21:01:12 -0000 1.90
+++ pvfs2-util.c 21 Jul 2008 18:19:55 -0000 1.90.16.1
@@ -100,6 +100,60 @@ static int PINT_util_resolve_absolute(
char* out_fs_path,
int out_fs_path_max);
+struct PVFS_sys_mntent* PVFS_util_gen_mntent(
+ char* config_server,
+ char* fs_name)
+{
+ struct PVFS_sys_mntent* tmp_ent = NULL;
+
+ tmp_ent = (struct PVFS_sys_mntent*)malloc(sizeof(struct
+ PVFS_sys_mntent));
+ if(!tmp_ent)
+ {
+ return(NULL);
+ }
+ memset(tmp_ent, 0, sizeof(struct PVFS_sys_mntent));
+
+ tmp_ent->num_pvfs_config_servers = 1;
+ tmp_ent->pvfs_config_servers = (char**)malloc(sizeof(char*));
+ if(!tmp_ent->pvfs_config_servers)
+ {
+ free(tmp_ent);
+ return(NULL);
+ }
+
+ tmp_ent->pvfs_config_servers[0] = strdup(config_server);
+ if(!tmp_ent->pvfs_config_servers[0])
+ {
+ free(tmp_ent->pvfs_config_servers);
+ free(tmp_ent);
+ return(NULL);
+ }
+
+ tmp_ent->pvfs_fs_name = strdup(fs_name);
+ if(!tmp_ent->pvfs_fs_name)
+ {
+ free(tmp_ent->pvfs_config_servers[0]);
+ free(tmp_ent->pvfs_config_servers);
+ free(tmp_ent);
+ return(NULL);
+ }
+
+ tmp_ent->flowproto = FLOWPROTO_DEFAULT;
+ tmp_ent->encoding = ENCODING_DEFAULT;
+
+ return(tmp_ent);
+}
+
+void PVFS_util_gen_mntent_release(struct PVFS_sys_mntent* mntent)
+{
+ free(mntent->pvfs_config_servers[0]);
+ free(mntent->pvfs_config_servers);
+ free(mntent->pvfs_fs_name);
+ free(mntent);
+ return;
+}
+
void PVFS_util_gen_credentials(
PVFS_credentials *credentials)
{
@@ -124,13 +178,13 @@ int PVFS_util_get_umask(void)
}
PVFS_credentials *PVFS_util_dup_credentials(
- PVFS_credentials *credentials)
+ const PVFS_credentials *credentials)
{
PVFS_credentials *ret = NULL;
if (credentials)
{
- ret = (PVFS_credentials *)malloc(sizeof(PVFS_credentials));
+ ret = malloc(sizeof(PVFS_credentials));
if (ret)
{
memcpy(ret, credentials, sizeof(PVFS_credentials));
@@ -164,6 +218,12 @@ int PVFS_util_copy_sys_attr(
dest_attr->dfile_count = src_attr->dfile_count;
dest_attr->objtype = src_attr->objtype;
dest_attr->mask = src_attr->mask;
+ dest_attr->flags = src_attr->flags;
+
+ if (src_attr->mask & PVFS_ATTR_SYS_SIZE)
+ {
+ dest_attr->size = src_attr->size;
+ }
if((src_attr->mask & PVFS_ATTR_SYS_LNK_TARGET) &&
src_attr->link_target)
@@ -255,6 +315,30 @@ const PVFS_util_tab *PVFS_util_parse_pvf
int ret = -1;
int tmp_mntent_count = 0;
PVFS_util_tab *current_tab = NULL;
+ char *epenv, *tmp;
+
+ if((epenv = getenv("PVFS2EP")) != NULL)
+ {
+ struct PVFS_sys_mntent *mntent;
+ current_tab = &s_stat_tab_array[0];
+ current_tab->mntent_array = malloc(sizeof(struct PVFS_sys_mntent));
+ mntent = ¤t_tab->mntent_array[0];
+ strcpy(current_tab->tabfile_name, "PVFSEP");
+ current_tab->mntent_count = 1;
+ mntent->pvfs_config_servers = malloc(sizeof(char *));
+ mntent->pvfs_config_servers[0] = strdup(index(epenv, '=') + 1);
+ mntent->num_pvfs_config_servers = 1;
+ mntent->the_pvfs_config_server = mntent->pvfs_config_servers[0];
+ mntent->pvfs_fs_name = strdup(rindex(mntent->the_pvfs_config_server, '/'));
+ mntent->pvfs_fs_name++;
+ mntent->flowproto = FLOWPROTO_DEFAULT;
+ mntent->encoding = ENCODING_DEFAULT;
+ mntent->mnt_dir = strdup(epenv);
+ tmp = index(mntent->mnt_dir, '=');
+ *tmp = 0;
+ mntent->mnt_opts = strdup("rw");
+ return &s_stat_tab_array[0];
+ }
if (tabfile != NULL)
{
@@ -370,6 +454,8 @@ const PVFS_util_tab *PVFS_util_parse_pvf
char *cp;
int cur_server;
+ /* Enable integrity checks by default */
+ me->integrity_check = 1;
/* comma-separated list of ways to contact a config server */
me->num_pvfs_config_servers = 1;
for (cp=PINT_FSTAB_NAME(tmp_ent); *cp; cp++)
@@ -528,6 +614,7 @@ const PVFS_util_tab *PVFS_util_parse_pvf
}
s_stat_tab_count++;
strcpy(s_stat_tab_array[s_stat_tab_count-1].tabfile_name, targetfile);
+ PINT_fstab_close(mnt_fp);
gen_mutex_unlock(&s_stat_tab_mutex);
return (&s_stat_tab_array[s_stat_tab_count - 1]);
@@ -843,6 +930,7 @@ int PVFS_util_remove_internal_mntent(
}
PVFS_util_copy_mntent(
&tmp_mnt_array[new_count++], current_mnt);
+ PVFS_util_free_mntent(current_mnt);
}
/* finally, swap the mntent arrays */
@@ -924,6 +1012,12 @@ int PVFS_util_resolve(
char* parent_path = NULL;
int base_len = 0;
+ if(strlen(local_path) > (PVFS_NAME_MAX-1))
+ {
+ gossip_err("Error: PVFS_util_resolve() input path too long.\n");
+ return(-PVFS_ENAMETOOLONG);
+ }
+
/* the most common case first; just try to resolve the path that we
* were given
*/
@@ -1084,43 +1178,55 @@ int PVFS_util_init_defaults(void)
#define KILOBYTE 1024
#define MEGABYTE (1024 * KILOBYTE)
#define GIGABYTE (1024 * MEGABYTE)
-/*
-#define TERABYTE (1024 * GIGABYTE)
-#define PETABYTE (1024 * TERABYTE)
-#define EXABYTE (1024 * PETABYTE)
-#define ZETTABYTE (1024 * EXABYTE)
-#define YOTTABYTE (1024 * ZETTABYTE)
-*/
+#define TERABYTE (1024llu * GIGABYTE)
+#define PETABYTE (1024llu * TERABYTE)
+#define EXABYTE (1024llu * PETABYTE)
+#define ZETTABYTE (1024llu * EXABYTE)
+#define YOTTABYTE (1024llu * ZETTABYTE)
+
/*****************/
/* si size units */
/*****************/
#define SI_KILOBYTE 1000
#define SI_MEGABYTE (1000 * SI_KILOBYTE)
#define SI_GIGABYTE (1000 * SI_MEGABYTE)
-/*
-#define SI_TERABYTE (1000 * SI_GIGABYTE)
-#define SI_PETABYTE (1000 * SI_TERABYTE)
-#define SI_EXABYTE (1000 * SI_PETABYTE)
-#define SI_ZETTABYTE (1000 * SI_EXABYTE)
-#define SI_YOTTABYTE (1000 * SI_ZETTABYTE)
-*/
-#define NUM_SIZES 3
+#define SI_TERABYTE (1000llu * SI_GIGABYTE)
+#define SI_PETABYTE (1000llu * SI_TERABYTE)
+#define SI_EXABYTE (1000llu * SI_PETABYTE)
+#define SI_ZETTABYTE (1000llu * SI_EXABYTE)
+#define SI_YOTTABYTE (1000llu * SI_ZETTABYTE)
+
+#if SIZEOF_LONG_INT == 8
+#define NUM_SIZES 5
+#else
+#define NUM_SIZES 4
+#endif
static PVFS_size PINT_s_size_table[NUM_SIZES] =
{
- /*YOTTABYTE, ZETTABYTE, EXABYTE, PETABYTE, TERABYTE, */
+ /*YOTTABYTE, ZETTABYTE, EXABYTE, */
+#if SIZEOF_LONG_INT == 8
+ PETABYTE,
+ TERABYTE,
+#endif
GIGABYTE, MEGABYTE, KILOBYTE
};
static PVFS_size PINT_s_si_size_table[NUM_SIZES] =
{
- /*SI_YOTTABYTE, SI_ZETTABYTE, SI_EXABYTE, SI_PETABYTE, SI_TERABYTE, */
+ /*SI_YOTTABYTE, SI_ZETTABYTE, SI_EXABYTE, */
+#if SIZEOF_LONG_INT == 8
+ SI_PETABYTE, SI_TERABYTE,
+#endif
SI_GIGABYTE, SI_MEGABYTE, SI_KILOBYTE
};
static const char *PINT_s_str_size_table[NUM_SIZES] =
{
- /*"Y", "Z", "E", "P","T", */
+ /*"Y", "Z", "E", */
+#if SIZEOF_LONG_INT == 8
+ "P","T",
+#endif
"G", "M", "K"
};
@@ -1513,6 +1619,25 @@ uint32_t PVFS_util_sys_to_object_attr_ma
attrmask |= PVFS_ATTR_SYMLNK_TARGET;
}
+ if(sys_attrmask & PVFS_ATTR_SYS_UID)
+ attrmask |= PVFS_ATTR_COMMON_UID;
+ if(sys_attrmask & PVFS_ATTR_SYS_GID)
+ attrmask |= PVFS_ATTR_COMMON_GID;
+ if(sys_attrmask & PVFS_ATTR_SYS_PERM)
+ attrmask |= PVFS_ATTR_COMMON_PERM;
+ if(sys_attrmask & PVFS_ATTR_SYS_ATIME)
+ attrmask |= PVFS_ATTR_COMMON_ATIME;
+ if(sys_attrmask & PVFS_ATTR_SYS_CTIME)
+ attrmask |= PVFS_ATTR_COMMON_CTIME;
+ if(sys_attrmask & PVFS_ATTR_SYS_MTIME)
+ attrmask |= PVFS_ATTR_COMMON_MTIME;
+ if(sys_attrmask & PVFS_ATTR_SYS_TYPE)
+ attrmask |= PVFS_ATTR_COMMON_TYPE;
+ if(sys_attrmask & PVFS_ATTR_SYS_ATIME_SET)
+ attrmask |= PVFS_ATTR_COMMON_ATIME_SET;
+ if(sys_attrmask & PVFS_ATTR_SYS_MTIME_SET)
+ attrmask |= PVFS_ATTR_COMMON_MTIME_SET;
+
gossip_debug(GOSSIP_GETATTR_DEBUG,
"attrmask being passed to server: ");
PINT_attrmask_print(GOSSIP_GETATTR_DEBUG, attrmask);
@@ -1797,6 +1922,40 @@ static void PINT_util_fsent_destroy(PINT
}
}
#endif /* DEFINE_MY_GET_NEXT_FSENT */
+
+int32_t PVFS_util_translate_mode(int mode, int suid)
+{
+ int ret = 0, i = 0;
+#define NUM_MODES 11
+ static int modes[NUM_MODES] =
+ {
+ S_IXOTH, S_IWOTH, S_IROTH,
+ S_IXGRP, S_IWGRP, S_IRGRP,
+ S_IXUSR, S_IWUSR, S_IRUSR,
+ S_ISGID, S_ISUID
+ };
+ static int pvfs2_modes[NUM_MODES] =
+ {
+ PVFS_O_EXECUTE, PVFS_O_WRITE, PVFS_O_READ,
+ PVFS_G_EXECUTE, PVFS_G_WRITE, PVFS_G_READ,
+ PVFS_U_EXECUTE, PVFS_U_WRITE, PVFS_U_READ,
+ PVFS_G_SGID, PVFS_U_SUID
+ };
+
+ for(i = 0; i < NUM_MODES; i++)
+ {
+ if (mode & modes[i])
+ {
+ ret |= pvfs2_modes[i];
+ }
+ }
+ if (suid == 0 && (ret & PVFS_U_SUID))
+ {
+ ret &= ~PVFS_U_SUID;
+ }
+ return ret;
+#undef NUM_MODES
+}
/*
* Local variables:
Index: server-config-mgr.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/server-config-mgr.c,v
diff -p -u -r1.15 -r1.15.22.1
--- server-config-mgr.c 18 Aug 2006 21:23:46 -0000 1.15
+++ server-config-mgr.c 21 Jul 2008 18:19:55 -0000 1.15.22.1
@@ -31,13 +31,12 @@ typedef struct
PVFS_fs_id fs_id;
- gen_mutex_t *server_config_mutex;
struct server_configuration_s *server_config;
int ref_count; /* allows same config to be added multiple times */
} server_config_t;
static struct qhash_table *s_fsid_to_config_table = NULL;
-static gen_mutex_t *s_server_config_mgr_mutex = NULL;
+static gen_mutex_t s_server_config_mgr_mutex = GEN_MUTEX_INITIALIZER;
/*
while loading configuration settings for all known file systems
(across all configured servers), we keep track of the minimum handle
@@ -50,7 +49,7 @@ static int hash_fsid(void *key, int tabl
static int hash_fsid_compare(void *key, struct qlist_head *link);
#define SC_MGR_INITIALIZED() \
-(s_fsid_to_config_table && s_server_config_mgr_mutex)
+(s_fsid_to_config_table)
/*
this is a check that needs to be made each time the
@@ -75,17 +74,8 @@ int PINT_server_config_mgr_initialize(vo
qhash_init(hash_fsid_compare, hash_fsid, 17);
if (s_fsid_to_config_table)
{
- s_server_config_mgr_mutex = gen_mutex_build();
- if (s_server_config_mgr_mutex)
- {
- s_min_handle_recycle_timeout_in_sec = -1;
- ret = 0;
- }
- else
- {
- qhash_finalize(s_fsid_to_config_table);
- ret = -PVFS_ENOMEM;
- }
+ s_min_handle_recycle_timeout_in_sec = -1;
+ ret = 0;
}
else
{
@@ -103,7 +93,7 @@ int PINT_server_config_mgr_finalize(void
if (SC_MGR_INITIALIZED())
{
- gen_mutex_lock(s_server_config_mgr_mutex);
+ gen_mutex_lock(&s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK(ret);
for (i = 0; i < s_fsid_to_config_table->table_size; i++)
@@ -121,7 +111,6 @@ int PINT_server_config_mgr_finalize(void
PINT_config_release(config->server_config);
free(config->server_config);
- gen_mutex_destroy(config->server_config_mutex);
free(config);
}
} while(hash_link);
@@ -129,9 +118,8 @@ int PINT_server_config_mgr_finalize(void
qhash_finalize(s_fsid_to_config_table);
s_fsid_to_config_table = NULL;
- gen_mutex_unlock(s_server_config_mgr_mutex);
- gen_mutex_destroy(s_server_config_mgr_mutex);
- s_server_config_mgr_mutex = NULL;
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
+ gen_mutex_destroy(&s_server_config_mgr_mutex);
s_min_handle_recycle_timeout_in_sec = -1;
ret = 0;
@@ -149,7 +137,7 @@ int PINT_server_config_mgr_reload_cached
if (SC_MGR_INITIALIZED())
{
- gen_mutex_lock(s_server_config_mgr_mutex);
+ gen_mutex_lock(&s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK(ret);
PINT_cached_config_finalize();
@@ -157,7 +145,7 @@ int PINT_server_config_mgr_reload_cached
if (ret)
{
PVFS_perror("PINT_cached_config_initialize failed", ret);
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
return ret;
}
@@ -203,17 +191,17 @@ int PINT_server_config_mgr_reload_cached
"Reloading handle mappings for fs_id %d\n",
cur_fs->coll_id);
- ret = PINT_handle_load_mapping(
- config->server_config, cur_fs);
+ ret = PINT_cached_config_handle_load_mapping(cur_fs);
if (ret)
{
- PVFS_perror("PINT_handle_load_mapping failed", ret);
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ PVFS_perror(
+ "PINT_cached_config_handle_load_mapping failed", ret);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
return ret;
}
}
}
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
ret = 0;
}
return ret;
@@ -221,18 +209,21 @@ int PINT_server_config_mgr_reload_cached
int PINT_server_config_mgr_add_config(
struct server_configuration_s *config_s,
- PVFS_fs_id fs_id)
+ PVFS_fs_id fs_id,
+ int* free_config_flag)
{
int ret = -PVFS_EINVAL;
server_config_t *config = NULL;
struct qlist_head *hash_link = NULL;
+ *free_config_flag = 0;
+
gossip_debug(GOSSIP_CLIENT_DEBUG, "PINT_server_config_mgr_add_"
"config: adding config %p\n", config_s);
if (SC_MGR_INITIALIZED() && config_s)
{
- gen_mutex_lock(s_server_config_mgr_mutex);
+ gen_mutex_lock(&s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK(ret);
hash_link = qhash_search(s_fsid_to_config_table, &fs_id);
@@ -245,7 +236,11 @@ int PINT_server_config_mgr_add_config(
assert(config);
assert(config->server_config);
config->ref_count++;
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ /* set a flag to inform caller that we aren't using the config
+ * structure
+ */
+ *free_config_flag = 1;
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
return(0);
}
@@ -257,13 +252,6 @@ int PINT_server_config_mgr_add_config(
}
memset(config, 0, sizeof(server_config_t));
- config->server_config_mutex = gen_mutex_build();
- if (!config->server_config_mutex)
- {
- ret = -PVFS_ENOMEM;
- goto add_failure;
- }
-
config->server_config = config_s;
config->fs_id = fs_id;
config->ref_count = 1;
@@ -274,7 +262,7 @@ int PINT_server_config_mgr_add_config(
gossip_debug(GOSSIP_CLIENT_DEBUG, "\tmapped fs_id %d => "
"config %p\n", fs_id, config_s);
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
ret = 0;
}
@@ -287,14 +275,9 @@ int PINT_server_config_mgr_add_config(
if (config)
{
qhash_search_and_remove(s_fsid_to_config_table, &fs_id);
- if (config->server_config_mutex)
- {
- gen_mutex_destroy(config->server_config_mutex);
- config->server_config_mutex = NULL;
- }
free(config);
}
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
return ret;
}
@@ -310,7 +293,7 @@ int PINT_server_config_mgr_remove_config
if (SC_MGR_INITIALIZED())
{
- gen_mutex_lock(s_server_config_mgr_mutex);
+ gen_mutex_lock(&s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK(ret);
hash_link = qhash_search(
@@ -338,13 +321,6 @@ int PINT_server_config_mgr_remove_config
PINT_config_release(config->server_config);
free(config->server_config);
- if(gen_mutex_trylock(config->server_config_mutex) == EBUSY)
- {
- gossip_err("FIXME: Destroying mutex that is in use!\n");
- }
- gen_mutex_unlock(config->server_config_mutex);
- gen_mutex_destroy(config->server_config_mutex);
-
free(config);
config = NULL;
}
@@ -357,7 +333,7 @@ int PINT_server_config_mgr_remove_config
ret = 0;
}
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
}
return ret;
}
@@ -371,7 +347,7 @@ struct server_configuration_s *__PINT_se
if (SC_MGR_INITIALIZED())
{
- gen_mutex_lock(s_server_config_mgr_mutex);
+ gen_mutex_lock(&s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK(ret);
hash_link = qhash_search(s_fsid_to_config_table, &fs_id);
@@ -385,10 +361,15 @@ struct server_configuration_s *__PINT_se
GOSSIP_CLIENT_DEBUG, "server_config_mgr: LOCKING config "
"object %p with fs_id %d\n", config, fs_id);
#endif
- gen_mutex_lock(config->server_config_mutex);
ret = config->server_config;
}
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ /* if we find a match, then old onto the mutex and let the caller
+ * release it in a put_config call
+ */
+ if(!ret)
+ {
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
+ }
}
return ret;
}
@@ -403,7 +384,6 @@ void __PINT_server_config_mgr_put_config
if (SC_MGR_INITIALIZED() && config_s)
{
- gen_mutex_lock(s_server_config_mgr_mutex);
SC_MGR_ASSERT_OK( );
cur = config_s->file_systems;
@@ -424,9 +404,8 @@ void __PINT_server_config_mgr_put_config
GOSSIP_CLIENT_DEBUG, "server_config_mgr: "
"UNLOCKING config object %p\n", config);
#endif
- gen_mutex_unlock(config->server_config_mutex);
}
- gen_mutex_unlock(s_server_config_mgr_mutex);
+ gen_mutex_unlock(&s_server_config_mgr_mutex);
}
}
Index: server-config-mgr.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/server-config-mgr.h,v
diff -p -u -r1.7 -r1.7.28.1
--- server-config-mgr.h 15 May 2006 22:25:05 -0000 1.7
+++ server-config-mgr.h 21 Jul 2008 18:19:55 -0000 1.7.28.1
@@ -17,7 +17,8 @@ int PINT_server_config_mgr_reload_cached
int PINT_server_config_mgr_add_config(
struct server_configuration_s *config_s,
- PVFS_fs_id fs_id);
+ PVFS_fs_id fs_id,
+ int* free_config_flag);
int PINT_server_config_mgr_remove_config(
PVFS_fs_id fs_id);
@@ -35,6 +36,7 @@ int PINT_server_config_mgr_get_abs_min_h
#define PINT_server_config_mgr_get_config __PINT_server_config_mgr_get_config
#define PINT_server_config_mgr_put_config __PINT_server_config_mgr_put_config
#elif defined(__PVFS2_SERVER__)
+#include "src/server/pvfs2-server.h"
#define PINT_server_config_mgr_get_config(__fsid) get_server_config_struct()
static inline void PINT_server_config_mgr_put_config(
struct server_configuration_s *config_s) { return; }
Index: server-config.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/server-config.c,v
diff -p -u -r1.92 -r1.92.4.1
--- server-config.c 11 Sep 2006 20:22:01 -0000 1.92
+++ server-config.c 21 Jul 2008 18:19:55 -0000 1.92.4.1
@@ -18,6 +18,7 @@
#include "server-config.h"
#include "pvfs2.h"
#include "job.h"
+#include "trove.h"
#include "gossip.h"
#include "extent-utils.h"
#include "mkspace.h"
@@ -26,9 +27,12 @@
#include "pvfs2-server.h"
#include "pvfs2-internal.h"
+#ifdef WITH_OPENSSL
+#include "openssl/evp.h"
+#endif
+
static const char * replace_old_keystring(const char * oldkey);
-static DOTCONF_CB(get_pvfs_server_id);
static DOTCONF_CB(get_logstamp);
static DOTCONF_CB(get_storage_space);
static DOTCONF_CB(enter_defaults_context);
@@ -45,6 +49,8 @@ static DOTCONF_CB(enter_storage_hints_co
static DOTCONF_CB(exit_storage_hints_context);
static DOTCONF_CB(enter_export_options_context);
static DOTCONF_CB(exit_export_options_context);
+static DOTCONF_CB(enter_server_options_context);
+static DOTCONF_CB(exit_server_options_context);
static DOTCONF_CB(enter_mhranges_context);
static DOTCONF_CB(exit_mhranges_context);
static DOTCONF_CB(enter_dhranges_context);
@@ -59,9 +65,11 @@ static DOTCONF_CB(get_perf_update_interv
static DOTCONF_CB(get_root_handle);
static DOTCONF_CB(get_name);
static DOTCONF_CB(get_logfile);
+static DOTCONF_CB(get_logtype);
static DOTCONF_CB(get_event_logging_list);
static DOTCONF_CB(get_filesystem_collid);
static DOTCONF_CB(get_alias_list);
+static DOTCONF_CB(check_this_server);
#ifdef USE_TRUSTED
static DOTCONF_CB(get_trusted_portlist);
static DOTCONF_CB(get_trusted_network);
@@ -71,6 +79,7 @@ static DOTCONF_CB(get_bmi_module_list);
static DOTCONF_CB(get_flow_module_list);
static DOTCONF_CB(get_root_squash);
+static DOTCONF_CB(get_root_squash_exceptions);
static DOTCONF_CB(get_read_only);
static DOTCONF_CB(get_all_squash);
static DOTCONF_CB(get_anon_gid);
@@ -83,7 +92,6 @@ static DOTCONF_CB(get_attr_cache_keyword
static DOTCONF_CB(get_attr_cache_size);
static DOTCONF_CB(get_attr_cache_max_num_elems);
static DOTCONF_CB(get_trove_sync_meta);
-static DOTCONF_CB(get_trove_alt_aio);
static DOTCONF_CB(get_trove_sync_data);
static DOTCONF_CB(get_db_cache_size_bytes);
static DOTCONF_CB(get_trove_max_concurrent_io);
@@ -98,8 +106,10 @@ static DOTCONF_CB(get_client_job_bmi_tim
static DOTCONF_CB(get_client_job_flow_timeout);
static DOTCONF_CB(get_client_retry_limit);
static DOTCONF_CB(get_client_retry_delay);
+static DOTCONF_CB(get_secret_key);
static DOTCONF_CB(get_coalescing_high_watermark);
static DOTCONF_CB(get_coalescing_low_watermark);
+static DOTCONF_CB(get_trove_method);
static FUNC_ERRORHANDLER(errorhandler);
const char *contextchecker(command_t *cmd, unsigned long mask);
@@ -115,8 +125,7 @@ static void copy_filesystem(
struct filesystem_configuration_s *src_fs);
static int cache_config_files(
struct server_configuration_s *config_s,
- char *global_config_filename,
- char *server_config_filename);
+ char *global_config_filename);
static int is_populated_filesystem_configuration(
struct filesystem_configuration_s *fs);
static int is_root_handle_in_a_meta_range(
@@ -147,11 +156,12 @@ static int is_root_handle_in_my_range(
/* PVFS2 servers are deployed using configuration files that provide information
* about the file systems, storage locations and endpoints that each server
- * manages. For every pvfs2 deployment, there is a global config file
- * (<i>fs.conf</i>) shared between all of the pvfs2 servers, as well as
- * per-server config files (<i>server.conf</i>) that contain config options
- * unique to that server (such as host/port endpoint). Configuration options
- * in both the global and server specific config files have the following format:
+ * manages. For every pvfs2 deployment, there should be a global config file
+ * (<i>fs.conf</i>) shared across all of the pvfs2 servers. When the servers
+ * are started up, a command line parameter (server-alias) indicates what options
+ * are relevant and applicable for a particular server.
+ * This parameter will be used by the server to parse relevant options.
+ * Configuration options in the global config files have the following format:
*
* <pre>
* OptionName OptionValue
@@ -190,8 +200,8 @@ static int is_root_handle_in_my_range(
*
* Options and contexts that appear in the top-level (not defined within
* another context) are considered to be defined in a special <i>Global</i>
- * context. Many options are only specified to appear within either the
- * <i>Global</i> context or the <a name="Default">Default</a> context,
+ * context. Many options are only specified to appear within
+ * the <a name="Default">Default</a> context,
* which is a context that allows a default value to be specified for certain
* options.
*
@@ -203,29 +213,6 @@ static int is_root_handle_in_my_range(
*/
static const configoption_t options[] =
{
- /*
- * Specifies a string identifier for the pvfs2 server that is to be
- * run on this host. This option is required for each per-server config
- * file. The format of this string is:
- *
- * {transport}://{hostname}:{port}
- *
- * Where {transport} is one of the possible BMI transport modules
- * (tcp, ib, gm). Example:
- *
- * tcp://myhost.mydn:12345
- *
- */
- {"HostID",ARG_STR, get_pvfs_server_id,NULL,CTX_GLOBAL,NULL},
-
- /* Specifies the local path for the pvfs2 server to use as storage space.
- * This option is required for each per-server config file.
- * Example:
- *
- * /tmp/pvfs.storage
- */
- {"StorageSpace",ARG_STR, get_storage_space,NULL,CTX_GLOBAL,NULL},
-
/* Options specified within the Defaults context are used as
* default values over all the pvfs2 server specific config files.
*/
@@ -299,6 +286,47 @@ static const configoption_t options[] =
*/
{"Alias",ARG_LIST, get_alias_list,NULL,CTX_ALIASES,NULL},
+ /* Defines the server alias for the server specific options that
+ * are to be set within the ServerOptions context.
+ */
+ {"Server", ARG_STR, check_this_server, NULL, CTX_SERVER_OPTIONS, NULL},
+
+ /* This groups the Server specific options.
+ *
+ * The ServerOptions context should be defined after the Alias mappings
+ * have been defined. The reason is that the ServerOptions context is
+ * defined in terms of the aliases defined in that context.
+ *
+ * Default options applicable to all servers can be overridden on
+ * a per-server basis in the ServerOptions context.
+ * To illustrate:
+ * Suppose the Option name is X, its default value is Y,
+ * and one wishes to override the option for a server to Y'.
+ *
+ * <Defaults>
+ * ..
+ * X Y
+ * ..
+ * </Defaults>
+ *
+ * <ServerOptions>
+ * Server {server alias}
+ * ..
+ * X Y'
+ * ..
+ * </ServerOptions>
+ *
+ * The ServerOptions context REQUIRES the Server option specify
+ * the server alias, which sets the remaining options specified
+ * in the context for that server.
+ */
+ {"<ServerOptions>",ARG_NONE,enter_server_options_context,NULL,
+ CTX_GLOBAL, NULL},
+ /* Specifies the end-tag of the ServerOptions context.
+ */
+ {"</ServerOptions>",ARG_NONE,exit_server_options_context,NULL,
+ CTX_SERVER_OPTIONS,NULL},
+
/* This groups options specific to a filesystem. A pvfs2 server may manage
* more than one filesystem, so a config file may have more than
* one Filesystem context, each defining the parameters of a different
@@ -454,7 +482,7 @@ static const configoption_t options[] =
* concurrently
*/
{"TroveMaxConcurrentIO", ARG_INT, get_trove_max_concurrent_io, NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"16"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"16"},
/* The gossip interface in pvfs allows users to specify different
* levels of logging for the pvfs server. The output of these
@@ -465,7 +493,16 @@ static const configoption_t options[] =
* a particular server in the Global context.
*/
{"LogFile",ARG_STR, get_logfile,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"/tmp/pvfs2-server.log"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"/tmp/pvfs2-server.log"},
+
+ /* The LogType option can be used to control the destination of log
+ * messages from PVFS2 server. The default value is "file", which causes
+ * all log messages to be written to the file specified by the LogFile
+ * parameter. Another option is "syslog", which causes all log messages
+ * to be written to syslog.
+ */
+ {"LogType",ARG_STR, get_logtype,NULL,
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"file"},
/* The gossip interface in pvfs allows users to specify different
* levels of logging for the pvfs server. This option sets that level for
@@ -486,19 +523,33 @@ static const configoption_t options[] =
* EventLogging -flow,-flowproto
*/
{"EventLogging",ARG_LIST, get_event_logging_list,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"none,"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"none,"},
/* At startup each pvfs server allocates space for a set number
* of incoming requests to prevent the allocation delay at the beginning
* of each unexpected request. This parameter specifies the number
* of requests for which to allocate space.
*
- * If set in the Defaults context, its value will be used for all servers.
- * The default value can also be overwritten by setting a separate value
- * in the Global context.
+ * A default value is set in the Defaults context which will be be used
+ * for all servers.
+ * However, the default value can also be overwritten by setting a separate value
+ * in the ServerOptions context using the Option tag.
*/
{"UnexpectedRequests",ARG_INT, get_unexp_req,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"50"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"50"},
+
+ /* Specifies the local path for the pvfs2 server to use as storage space.
+ * This option specifies the default path for all servers and will appear
+ * in the Defaults context.
+ *
+ * NOTE: This can be overridden in the <ServerOptions> tag on a per-server
+ * basis. Look at the "Option" tag for more details
+ * Example:
+ *
+ * StorageSpace /tmp/pvfs.storage
+ */
+ {"StorageSpace",ARG_STR, get_storage_space,NULL,
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,NULL},
/* Current implementations of TCP on most systems use a window
* size that is too small for almost all uses of pvfs.
@@ -520,57 +571,57 @@ static const configoption_t options[] =
* PSC networking options</a> for details.
*/
{"TCPBufferSend",ARG_INT, get_tcp_buffer_send,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"0"},
+ CTX_DEFAULTS,"0"},
/* See the <a href="#TCPBufferSend">TCPBufferSend</a> option.
*/
{"TCPBufferReceive",ARG_INT, get_tcp_buffer_receive,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"0"},
+ CTX_DEFAULTS,"0"},
/* If enabled, specifies that the server should bind its port only on
* the specified address (rather than INADDR_ANY)
*/
{"TCPBindSpecific",ARG_STR, get_tcp_bind_specific,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"no"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"no"},
/* Specifies the timeout value in seconds for BMI jobs on the server.
*/
{"ServerJobBMITimeoutSecs",ARG_INT, get_server_job_bmi_timeout,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "30"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS, "300"},
/* Specifies the timeout value in seconds for TROVE jobs on the server.
*/
{"ServerJobFlowTimeoutSecs",ARG_INT, get_server_job_flow_timeout,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "30"},
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS, "300"},
/* Specifies the timeout value in seconds for BMI jobs on the client.
*/
{"ClientJobBMITimeoutSecs",ARG_INT, get_client_job_bmi_timeout,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "300"},
+ CTX_DEFAULTS, "300"},
/* Specifies the timeout value in seconds for FLOW jobs on the client.
*/
{"ClientJobFlowTimeoutSecs",ARG_INT, get_client_job_flow_timeout,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "300"},
+ CTX_DEFAULTS, "300"},
/* Specifies the number of retry attempts for operations (when possible)
*/
{"ClientRetryLimit",ARG_INT, get_client_retry_limit,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "5"},
+ CTX_DEFAULTS, "5"},
/* Specifies the delay in milliseconds to wait between retries.
*/
{"ClientRetryDelayMilliSecs",ARG_INT, get_client_retry_delay,NULL,
- CTX_DEFAULTS|CTX_GLOBAL, "2000"},
+ CTX_DEFAULTS, "2000"},
/* This specifies the frequency (in milliseconds)
* that performance monitor should be updated
* when the pvfs server is running in admin mode.
*
- * Can be set in either Default or Global contexts.
+ * Can be set in either Default or ServerOptions contexts.
*/
{"PerfUpdateInterval",ARG_INT, get_perf_update_interval,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"1000"},
+ CTX_DEFAULTS,"1000"},
/* List the BMI modules to load when the server is started. At present,
* only tcp, infiniband, and myrinet are valid BMI modules.
@@ -586,11 +637,10 @@ static const configoption_t options[] =
*
* Note that only the bmi modules compiled into pvfs should be
* specified in this list. The BMIModules option can be specified
- * in either the Defaults or Global contexts.
+ * in either the Defaults or ServerOptions contexts.
*/
- {"BMIModules",ARG_LIST, get_bmi_module_list,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,NULL},
-
+ {"BMIModules",ARG_LIST, get_bmi_module_list,NULL, CTX_DEFAULTS,NULL},
+
/* List the flow modules to load when the server is started. The modules
* available for loading currently are:
*
@@ -610,7 +660,28 @@ static const configoption_t options[] =
*
*/
{"FlowModules",ARG_LIST, get_flow_module_list,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"flowproto_multiqueue,"},
+ CTX_DEFAULTS,"flowproto_multiqueue,"},
+
+ /* Specifies the format of the date/timestamp that events will have
+ * in the event log. Possible values are:
+ *
+ * usec: [%H:%M:%S.%U]
+ *
+ * datetime: [%m/%d %H:%M]
+ *
+ * thread: [%H:%M:%S.%U (%lu)]
+ *
+ * none
+ *
+ * The format of the option is one of the above values. For example,
+ *
+ * LogStamp datetime
+ */
+ {"LogStamp",ARG_STR, get_logstamp,NULL,
+ CTX_DEFAULTS|CTX_SERVER_OPTIONS,"usec"},
+
+ /* --- end default options for all servers */
+
/* buffer size to use for bulk data transfers */
{"FlowBufferSizeBytes", ARG_INT,
@@ -620,44 +691,70 @@ static const configoption_t options[] =
{"FlowBuffersPerFlow", ARG_INT,
get_flow_buffers_per_flow, NULL, CTX_FILESYSTEM,"8"},
- /* Define options that will influence the way a file-system gets exported
+ /*
+ * File-system export options
+ *
+ * Define options that will influence the way a file-system gets exported
* to the rest of the world.
*/
- /* RootSquash option specifies whether the exported file-system needs to squash accesses
- * by root. This is an optional parameter that needs to be specified as part of the ExportOptions
- * context and is a list of BMI URL specification of client addresses for which RootSquash
- * has to be enforced.
+ /* RootSquash option specifies whether the exported file-system needs to
+ * squash accesses by root. This is an optional parameter that needs
+ * to be specified as part of the ExportOptions
+ * context and is a list of BMI URL specification of client addresses
+ * for which RootSquash has to be enforced.
+ *
* RootSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
*/
{"RootSquash", ARG_LIST, get_root_squash, NULL,
CTX_EXPORT, ""},
+
+ /* RootSquashExceptions option specifies exceoptions to the RootSquash
+ * list. This is an optional parameter that needs to be specified as
+ * part of the ExportOptions context and is a list of BMI URL
+ * specification of client addresses for which RootSquash
+ * has to be enforced.
+ * RootSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
+ */
+ {"RootSquashExceptions", ARG_LIST, get_root_squash_exceptions, NULL,
+ CTX_EXPORT, ""},
- /* ReadOnly option specifies whether the exported file-system needs to disallow write accesses
- * from clients or anything that modifies the state of the file-system.
- * This is an optional parameter that needs to be specified as part of the ExportOptions
- * context and is a list of BMI URL specification of client addresses for which ReadOnly
- * has to be enforced.
+ /* ReadOnly option specifies whether the exported file-system needs to
+ * disallow write accesses from clients or anything that modifies the
+ * state of the file-system.
+ * This is an optional parameter that needs to be specified as part of
+ * the ExportOptions context and is a list of BMI URL specification of
+ * client addresses for which ReadOnly has to be enforced.
+ * An example:
+ *
* ReadOnly tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
*/
{"ReadOnly", ARG_LIST, get_read_only, NULL,
CTX_EXPORT, ""},
- /* AllSquash option specifies whether the exported file-system needs to squash all accesses
- * to the file-system to a specified uid/gid!
- * This is an optional parameter that needs to be specified as part of the ExportOptions
- * context and is a list of BMI URL specification of client addresses for which AllSquash
- * has to be enforced.
+ /* AllSquash option specifies whether the exported file-system needs to
+ * squash all accesses to the file-system to a specified uid/gid!
+ * This is an optional parameter that needs to be specified as part of
+ * the ExportOptions context and is a list of BMI URL specification of client
+ * addresses for which AllSquash has to be enforced.
+ * An example:
+ *
* AllSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
*/
{"AllSquash", ARG_LIST, get_all_squash, NULL,
CTX_EXPORT, ""},
- /* AnonUID and AnonGID are 2 integers that tell the servers to translate the requesting clients'
- * uid/gid to the specified ones whenever AllSquash is specified!
- * If these are not specified and AllSquash is specified then the uid used will be
- * that of nobody and gid that of nobody
+ /* AnonUID and AnonGID are 2 integers that tell the servers to translate
+ * the requesting clients' uid/gid to the specified ones whenever AllSquash
+ * is specified!
+ * If these are not specified and AllSquash is specified then the uid used
+ * will be that of nobody and gid that of nobody.
+ * An example:
+ *
+ * AnonUID 3454
+ * AnonGID 3454
*/
+
{"AnonUID", ARG_STR, get_anon_uid, NULL,
CTX_EXPORT, "65534"},
{"AnonGID", ARG_STR, get_anon_gid, NULL,
@@ -675,8 +772,9 @@ static const configoption_t options[] =
get_handle_recycle_timeout_seconds, NULL,
CTX_STORAGEHINTS,"360"},
- /* The TROVE layer has an attribute caching component that handles
- * caching of stored attributes. This is used to improve the performance of
+ /* The TROVE layer (server side storage layer)
+ * has an attribute caching component that
+ * caches stored attributes. This is used to improve the performance of
* metadata accesses. The AttrCacheKeywords option is a list of the
* object types that should get cached in the attribute cache.
* The possible values for this option are:
@@ -746,28 +844,6 @@ static const configoption_t options[] =
{"DBCacheType", ARG_STR, get_db_cache_type, NULL,
CTX_STORAGEHINTS, "sys"},
- /* enable alternate AIO implementation for certain types of I/O
- * operations (experimental
- */
- {"TroveAltAIOMode",ARG_STR, get_trove_alt_aio, NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"no"},
-
- /* Specifies the format of the date/timestamp that events will have
- * in the event log. Possible values are:
- *
- * usec: [%H:%M:%S
- *
- * datetime: [%m/%d %H:%M]
- *
- * none
- *
- * The format of the option is one of the above values. For example,
- *
- * LogStamp datetime
- */
- {"LogStamp",ARG_STR, get_logstamp,NULL,
- CTX_DEFAULTS|CTX_GLOBAL,"usec"},
-
/* This option specifies a parameter name to be passed to the
* distribution to be used. This option should be immediately
* followed by a Value option.
@@ -797,6 +873,33 @@ static const configoption_t options[] =
{"CoalescingLowWatermark", ARG_INT, get_coalescing_low_watermark, NULL,
CTX_STORAGEHINTS, "1"},
+ /* This option specifies the method used for trove. Currently the
+ * dbpf method is the default. Other methods include 'alt-aio'.
+ *
+ * The null-aio method is an implementation that does no disk I/O at all
+ * and is only useful for development or debugging purposes.
+ *
+ * Note that this option can be specified in either the <a href="#Defaults">
+ * Defaults</a> context of the main fs.conf, or in a filesystem specific
+ * <a href="#StorageHints">StorageHints</a>
+ * context, but the semantics of TroveMethod in the
+ * <a href="#Defaults">Defaults</a>
+ * context is different from other options. The TroveMethod in the
+ * <a href="#Defaults">Defaults</a> context only specifies which
+ * method is used at
+ * server initialization. It does not specify the default TroveMethod
+ * for all the filesystems the server supports. To set the TroveMethod
+ * for a filesystem, the TroveMethod must be placed in the
+ * <a href="#StorageHints">StorageHints</a> context for that filesystem.
+ */
+ {"TroveMethod", ARG_STR, get_trove_method, NULL,
+ CTX_DEFAULTS|CTX_STORAGEHINTS, "dbpf"},
+
+ /* Specifies the file system's key for use in HMAC-based digests of
+ * client operations.
+ */
+ {"SecretKey",ARG_STR, get_secret_key,NULL,CTX_FILESYSTEM,NULL},
+
LAST_OPTION
};
@@ -806,7 +909,7 @@ static const configoption_t options[] =
* Params: struct server_configuration_s*,
* global_config_filename - common config file for all servers
* and clients
- * server_config_filename - config file specific to one server
+ * server_alias_name - alias (if any) provided for this server
* (ignored on client side)
*
* Returns: 0 on success; 1 on failure
@@ -815,7 +918,7 @@ static const configoption_t options[] =
int PINT_parse_config(
struct server_configuration_s *config_obj,
char *global_config_filename,
- char *server_config_filename)
+ char *server_alias_name)
{
struct server_configuration_s *config_s;
configfile_t *configfile = (configfile_t *)0;
@@ -830,6 +933,7 @@ int PINT_parse_config(
config_s = config_obj;
memset(config_s, 0, sizeof(struct server_configuration_s));
+ config_s->server_alias = server_alias_name;
/* set some global defaults for optional parameters */
config_s->logstamp_type = GOSSIP_LOGSTAMP_DEFAULT;
config_s->server_job_bmi_timeout = PVFS2_SERVER_JOB_BMI_TIMEOUT_DEFAULT;
@@ -840,15 +944,13 @@ int PINT_parse_config(
config_s->client_retry_delay_ms = PVFS2_CLIENT_RETRY_DELAY_MS_DEFAULT;
config_s->trove_max_concurrent_io = 16;
- if (cache_config_files(
- config_s, global_config_filename, server_config_filename))
+ if (cache_config_files(config_s, global_config_filename))
{
return 1;
}
assert(config_s->fs_config_buflen && config_s->fs_config_buf);
- assert(config_s->server_config_buflen && config_s->server_config_buf);
- /* first read in the fs.conf defaults config file */
+ /* read in the fs.conf defaults config file */
config_s->configuration_context = CTX_GLOBAL;
configfile = PINT_dotconf_create(config_s->fs_config_filename,
options, (void *)config_s,
@@ -859,6 +961,7 @@ int PINT_parse_config(
config_s->fs_config_filename);
return 1;
}
+ config_s->private_data = configfile;
configfile->errorhandler = (dotconf_errorhandler_t)errorhandler;
configfile->contextchecker = (dotconf_contextchecker_t)contextchecker;
@@ -869,37 +972,24 @@ int PINT_parse_config(
}
PINT_dotconf_cleanup(configfile);
- /* then read in the server.conf (host specific) config file */
- config_s->configuration_context = CTX_GLOBAL;
- configfile = PINT_dotconf_create(config_s->server_config_filename,
- options, (void *)config_s, CASE_INSENSITIVE);
- if (!configfile)
- {
- gossip_err("Error opening config file: %s\n",
- config_s->server_config_filename);
- return 1;
- }
- configfile->errorhandler = (dotconf_errorhandler_t)errorhandler;
- configfile->contextchecker = (dotconf_contextchecker_t)contextchecker;
-
- if (PINT_dotconf_command_loop(configfile) == 0)
- {
- /* NOTE: dotconf error handler will log message */
- return 1;
- }
- PINT_dotconf_cleanup(configfile);
-
- if (!config_s->host_id)
+ if (server_alias_name)
{
- gossip_err("Configuration file error. "
- "No host ID specified.\n");
- return 1;
+ struct host_alias_s *halias;
+ halias = find_host_alias_ptr_by_alias(
+ config_s, server_alias_name);
+ if (!halias || !halias->bmi_address)
+ {
+ gossip_err("Configuration file error. "
+ "No host ID specified for alias %s.\n", server_alias_name);
+ return 1;
+ }
+ config_s->host_id = strdup(halias->bmi_address);
}
- if (!config_s->storage_path)
+ if (server_alias_name && !config_s->storage_path)
{
gossip_err("Configuration file error. "
- "No storage path specified.\n");
+ "No storage path specified for alias %s.\n", server_alias_name);
return 1;
}
@@ -948,25 +1038,16 @@ FUNC_ERRORHANDLER(errorhandler)
return(1);
}
-DOTCONF_CB(get_pvfs_server_id)
-{
- struct server_configuration_s *config_s =
- (struct server_configuration_s *)cmd->context;
- if (config_s->host_id)
- {
- gossip_err("WARNING: HostID value being overwritten (from "
- "%s to %s).\n",config_s->host_id,cmd->data.str);
- free(config_s->host_id);
- }
- config_s->host_id = (cmd->data.str ? strdup(cmd->data.str) : NULL);
- return NULL;
-}
-
DOTCONF_CB(get_logstamp)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
if(!strcmp(cmd->data.str, "none"))
{
config_s->logstamp_type = GOSSIP_LOGSTAMP_NONE;
@@ -979,6 +1060,10 @@ DOTCONF_CB(get_logstamp)
{
config_s->logstamp_type = GOSSIP_LOGSTAMP_DATETIME;
}
+ else if(!strcmp(cmd->data.str, "thread"))
+ {
+ config_s->logstamp_type = GOSSIP_LOGSTAMP_THREAD;
+ }
else
{
return("LogStamp tag (if specified) must have one of the following values: none, usec, or datetime.\n");
@@ -992,9 +1077,13 @@ DOTCONF_CB(get_storage_space)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
if (config_s->storage_path)
{
- gossip_err("WARNING: StorageSpace value being overwritten.\n");
free(config_s->storage_path);
}
config_s->storage_path =
@@ -1153,6 +1242,48 @@ DOTCONF_CB(exit_export_options_context)
return NULL;
}
+DOTCONF_CB(enter_server_options_context)
+{
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+ config_s->configuration_context = CTX_SERVER_OPTIONS;
+
+ return PINT_dotconf_set_defaults(
+ cmd->configfile, CTX_SERVER_OPTIONS);
+}
+
+DOTCONF_CB(exit_server_options_context)
+{
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+ config_s->configuration_context = CTX_GLOBAL;
+ config_s->my_server_options = 0;
+ return NULL;
+}
+
+DOTCONF_CB(check_this_server)
+{
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+
+ if(is_valid_alias(config_s->host_aliases, cmd->data.str))
+ {
+ /* if the Server option specifies our alias, enable setting
+ * of server specific options
+ */
+ if(config_s->server_alias &&
+ strcmp(config_s->server_alias, cmd->data.str) == 0)
+ {
+ config_s->my_server_options = 1;
+ }
+ }
+ else
+ {
+ return "Unrecognized alias specified.\n";
+ }
+ return NULL;
+}
+
DOTCONF_CB(enter_mhranges_context)
{
struct server_configuration_s *config_s =
@@ -1217,7 +1348,7 @@ DOTCONF_CB(exit_distribution_context)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
- config_s->configuration_context = CTX_GLOBAL;
+ config_s->configuration_context = CTX_FILESYSTEM;
return NULL;
}
@@ -1225,6 +1356,11 @@ DOTCONF_CB(get_unexp_req)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
config_s->initial_unexpected_requests = cmd->data.value;
return NULL;
}
@@ -1250,6 +1386,11 @@ DOTCONF_CB(get_tcp_bind_specific)
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
if(strcasecmp(cmd->data.str, "yes") == 0)
{
config_s->tcp_bind_specific = 1;
@@ -1266,12 +1407,15 @@ DOTCONF_CB(get_tcp_bind_specific)
return NULL;
}
-
-
DOTCONF_CB(get_server_job_bmi_timeout)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
config_s->server_job_bmi_timeout = cmd->data.value;
return NULL;
}
@@ -1280,6 +1424,11 @@ DOTCONF_CB(get_server_job_flow_timeout)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
config_s->server_job_flow_timeout = cmd->data.value;
return NULL;
}
@@ -1329,12 +1478,34 @@ DOTCONF_CB(get_logfile)
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
/* free whatever was added in set_defaults phase */
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
if (config_s->logfile)
free(config_s->logfile);
config_s->logfile = (cmd->data.str ? strdup(cmd->data.str) : NULL);
return NULL;
}
+DOTCONF_CB(get_logtype)
+{
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+ /* free whatever was added in set_defaults phase */
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
+ if (config_s->logtype)
+ free(config_s->logtype);
+ config_s->logtype = (cmd->data.str ? strdup(cmd->data.str) : NULL);
+ return NULL;
+}
+
+
DOTCONF_CB(get_event_logging_list)
{
struct server_configuration_s *config_s =
@@ -1343,12 +1514,15 @@ DOTCONF_CB(get_event_logging_list)
char buf[512] = {0};
char *ptr = buf;
- if (config_s->event_logging != NULL)
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
+ if (config_s->event_logging != NULL)
{
- len = strlen(config_s->event_logging);
- strncpy(ptr,config_s->event_logging,len);
- ptr += (len * sizeof(char));
free(config_s->event_logging);
+ config_s->event_logging = NULL;
}
for(i = 0; i < cmd->arg_count; i++)
{
@@ -1370,10 +1544,8 @@ DOTCONF_CB(get_flow_module_list)
if (config_s->flow_modules != NULL)
{
- len = strlen(config_s->flow_modules);
- strncpy(ptr,config_s->flow_modules,len);
- ptr += (len * sizeof(char));
free(config_s->flow_modules);
+ config_s->flow_modules = NULL;
}
for(i = 0; i < cmd->arg_count; i++)
{
@@ -1532,6 +1704,50 @@ DOTCONF_CB(get_root_squash)
return NULL;
}
+DOTCONF_CB(get_root_squash_exceptions)
+{
+ struct filesystem_configuration_s *fs_conf = NULL;
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+
+ fs_conf = (struct filesystem_configuration_s *)
+ PINT_llist_head(config_s->file_systems);
+ assert(fs_conf);
+
+ if (cmd->arg_count != 0)
+ {
+ fs_conf->root_squash_exceptions_netmasks = (int *) calloc(cmd->arg_count, sizeof(int));
+ if (fs_conf->root_squash_exceptions_netmasks == NULL)
+ {
+ fs_conf->root_squash_exceptions_count = 0;
+ return("Could not allocate memory for root_squash_exceptions_netmasks\n");
+ }
+ if (get_list_of_strings(cmd->arg_count, cmd->data.list,
+ &fs_conf->root_squash_exceptions_hosts) < 0)
+ {
+ free(fs_conf->root_squash_exceptions_netmasks);
+ fs_conf->root_squash_exceptions_netmasks = NULL;
+ fs_conf->root_squash_exceptions_count = 0;
+ return("Could not allocate memory for root_squash_exceptions_hosts\n");
+ }
+ fs_conf->root_squash_exceptions_count = cmd->arg_count;
+ /* Setup the netmasks */
+ if (setup_netmasks(fs_conf->root_squash_exceptions_count, fs_conf->root_squash_exceptions_hosts,
+ fs_conf->root_squash_exceptions_netmasks) < 0)
+ {
+ free(fs_conf->root_squash_exceptions_netmasks);
+ fs_conf->root_squash_exceptions_netmasks = NULL;
+ free_list_of_strings(fs_conf->root_squash_exceptions_count, &fs_conf->root_squash_exceptions_hosts);
+ fs_conf->root_squash_exceptions_count = 0;
+ return("Could not setup netmasks for root_squash_exceptions_hosts\n");
+ }
+ gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %d RootSquashExceptions wildcard entries\n",
+ cmd->arg_count);
+ }
+ return NULL;
+}
+
+
DOTCONF_CB(get_read_only)
{
struct filesystem_configuration_s *fs_conf = NULL;
@@ -1676,10 +1892,8 @@ DOTCONF_CB(get_bmi_module_list)
if (config_s->bmi_modules != NULL)
{
- len = strlen(config_s->bmi_modules);
- strncpy(ptr,config_s->bmi_modules,len);
- ptr += (len * sizeof(char));
free(config_s->bmi_modules);
+ config_s->bmi_modules = NULL;
}
for(i = 0; i < cmd->arg_count; i++)
{
@@ -1934,28 +2148,6 @@ DOTCONF_CB(get_attr_cache_max_num_elems)
return NULL;
}
-DOTCONF_CB(get_trove_alt_aio)
-{
- struct server_configuration_s *config_s =
- (struct server_configuration_s *)cmd->context;
-
- if(strcasecmp(cmd->data.str, "yes") == 0)
- {
- config_s->trove_alt_aio_mode = 1;
- }
- else if(strcasecmp(cmd->data.str, "no") == 0)
- {
- config_s->trove_alt_aio_mode = 0;
- }
- else
- {
- return("TroveAltAIOMode value must be 'yes' or 'no'.\n");
- }
-
- return NULL;
-}
-
-
DOTCONF_CB(get_trove_sync_meta)
{
struct filesystem_configuration_s *fs_conf = NULL;
@@ -2030,6 +2222,12 @@ DOTCONF_CB(get_trove_max_concurrent_io)
{
struct server_configuration_s *config_s =
(struct server_configuration_s *)cmd->context;
+
+ if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
+ config_s->my_server_options == 0)
+ {
+ return NULL;
+ }
config_s->trove_max_concurrent_io = cmd->data.value;
return NULL;
}
@@ -2310,6 +2508,19 @@ DOTCONF_CB(get_default_num_dfiles)
return NULL;
}
+DOTCONF_CB(get_secret_key)
+{
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+ struct filesystem_configuration_s *fs_conf = NULL;
+
+ fs_conf = (struct filesystem_configuration_s *)
+ PINT_llist_head(config_s->file_systems);
+
+ fs_conf->secret_key = strdup(cmd->data.str);
+ return NULL;
+}
+
DOTCONF_CB(get_immediate_completion)
{
struct server_configuration_s *config_s =
@@ -2364,6 +2575,42 @@ DOTCONF_CB(get_coalescing_low_watermark)
return NULL;
}
+DOTCONF_CB(get_trove_method)
+{
+ int * method;
+ struct server_configuration_s *config_s =
+ (struct server_configuration_s *)cmd->context;
+
+ method = &config_s->trove_method;
+ if(config_s->configuration_context == CTX_STORAGEHINTS)
+ {
+ /* we must be in a storagehints inside a filesystem context */
+ struct filesystem_configuration_s *fs_conf =
+ (struct filesystem_configuration_s *)
+ PINT_llist_head(config_s->file_systems);
+
+ method = &fs_conf->trove_method;
+ }
+
+ if(!strcmp(cmd->data.str, "dbpf"))
+ {
+ *method = TROVE_METHOD_DBPF;
+ }
+ else if(!strcmp(cmd->data.str, "alt-aio"))
+ {
+ *method = TROVE_METHOD_DBPF_ALTAIO;
+ }
+ else if(!strcmp(cmd->data.str, "null-aio"))
+ {
+ *method = TROVE_METHOD_DBPF_NULLAIO;
+ }
+ else
+ {
+ return "Error unknown TroveMethod option\n";
+ }
+ return NULL;
+}
+
/*
* Function: PINT_config_release
*
@@ -2397,30 +2644,24 @@ void PINT_config_release(struct server_c
config_s->fs_config_filename = NULL;
}
- if (config_s->server_config_filename)
- {
- free(config_s->server_config_filename);
- config_s->server_config_filename = NULL;
- }
-
if (config_s->fs_config_buf)
{
free(config_s->fs_config_buf);
config_s->fs_config_buf = NULL;
}
- if (config_s->server_config_buf)
- {
- free(config_s->server_config_buf);
- config_s->server_config_buf = NULL;
- }
-
if (config_s->logfile)
{
free(config_s->logfile);
config_s->logfile = NULL;
}
+ if (config_s->logtype)
+ {
+ free(config_s->logtype);
+ config_s->logtype = NULL;
+ }
+
if (config_s->event_logging)
{
free(config_s->event_logging);
@@ -2683,6 +2924,10 @@ static void free_filesystem(void *ptr)
free(fs->attr_cache_keywords);
fs->attr_cache_keywords = NULL;
}
+ if(fs->secret_key)
+ {
+ free(fs->secret_key);
+ }
/* free all ro_hosts specifications */
if (fs->ro_hosts)
{
@@ -2744,6 +2989,11 @@ static void copy_filesystem(
dest_fs->meta_handle_ranges = PINT_llist_new();
dest_fs->data_handle_ranges = PINT_llist_new();
+ if(src_fs->secret_key)
+ {
+ dest_fs->secret_key = strdup(src_fs->secret_key);
+ }
+
assert(dest_fs->meta_handle_ranges);
assert(dest_fs->data_handle_ranges);
@@ -3316,7 +3566,7 @@ char *PINT_config_get_merged_handle_rang
}
/*
- verify that both config files exist. if so, cache them in RAM so
+ verify that the config file exists. if so, cache it in RAM so
that getconfig will not have to re-read the file contents each time.
returns 0 on success; 1 on failure.
@@ -3325,14 +3575,12 @@ char *PINT_config_get_merged_handle_rang
*/
static int cache_config_files(
struct server_configuration_s *config_s,
- char *global_config_filename,
- char *server_config_filename)
+ char *global_config_filename)
{
int fd = 0, nread = 0;
struct stat statbuf;
char *working_dir = NULL;
char *my_global_fn = NULL;
- char *my_server_fn = NULL;
char buf[512] = {0};
assert(config_s);
@@ -3342,16 +3590,14 @@ static int cache_config_files(
/* pick some filenames if not provided */
my_global_fn = ((global_config_filename != NULL) ?
global_config_filename : "fs.conf");
- my_server_fn = ((server_config_filename != NULL) ?
- server_config_filename : "server.conf");
- open_global_config:
+open_global_config:
memset(&statbuf, 0, sizeof(struct stat));
if (stat(my_global_fn, &statbuf) == 0)
{
if (statbuf.st_size == 0)
{
- gossip_err("Invalid global config file %s. This "
+ gossip_err("Invalid config file %s. This "
"file is 0 bytes in length!\n", my_global_fn);
goto error_exit;
}
@@ -3382,40 +3628,6 @@ static int cache_config_files(
goto error_exit;
}
- open_server_config:
- memset(&statbuf,0,sizeof(struct stat));
- if (stat(my_server_fn, &statbuf) == 0)
- {
- if (statbuf.st_size == 0)
- {
- gossip_err("Invalid server config file %s. This "
- "file is 0 bytes in length!\n", my_server_fn);
- goto error_exit;
- }
- config_s->server_config_filename = strdup(my_server_fn);
- config_s->server_config_buflen = statbuf.st_size + 1;
- }
- else if (errno == ENOENT)
- {
- gossip_err("Failed to find server config file %s. This "
- "file does not exist!\n", my_server_fn);
- goto error_exit;
- }
- else
- {
- assert(working_dir);
- snprintf(buf, 512, "%s/%s", working_dir, my_server_fn);
- my_server_fn = buf;
- goto open_server_config;
- }
-
- if (!config_s->server_config_filename ||
- (config_s->server_config_buflen == 0))
- {
- gossip_err("Failed to stat server config file. (0 file size?)\n");
- goto error_exit;
- }
-
if ((fd = open(my_global_fn, O_RDONLY)) == -1)
{
gossip_err("Failed to open fs config file %s.\n",
@@ -3443,34 +3655,6 @@ static int cache_config_files(
}
close(fd);
- if ((fd = open(my_server_fn,O_RDONLY)) == -1)
- {
- gossip_err("Failed to open fs config file %s.\n", my_server_fn);
- goto error_exit;
- }
-
- config_s->server_config_buf = (char *)
- malloc(config_s->server_config_buflen);
- if (!config_s->server_config_buf)
- {
- gossip_err("Failed to allocate %d bytes for caching the server "
- "config file\n", (int) config_s->server_config_buflen);
- goto close_fd_fail;
- }
-
- memset(config_s->server_config_buf, 0, config_s->server_config_buflen);
- nread = read(fd, config_s->server_config_buf,
- (config_s->server_config_buflen - 1));
- if (nread != (config_s->server_config_buflen - 1))
- {
- gossip_err("Failed to read server config file %s "
- "(nread is %d | config_buflen is %d)\n",
- my_server_fn, nread,
- (int)(config_s->server_config_buflen - 1));
- goto close_fd_fail;
- }
-
- close(fd);
return 0;
close_fd_fail:
@@ -3739,6 +3923,74 @@ int PINT_config_trim_filesystems_except(
return ret;
}
+int PINT_config_get_fs_key(
+ struct server_configuration_s *config,
+ PVFS_fs_id fs_id,
+ char ** key,
+ int * length)
+{
+#ifndef WITH_OPENSSL
+ *key = NULL;
+ *length = 0;
+ return -PVFS_ENOSYS;
+#else
+ int len, b64len;
+ char *b64buf;
+ struct filesystem_configuration_s *fs_conf = NULL;
+ BIO *b64 = NULL;
+ BIO *mem = NULL;
+ BIO *bio = NULL;
+
+ if (config)
+ {
+ fs_conf = PINT_config_find_fs_id(config, fs_id);
+ }
+
+ if(!fs_conf)
+ {
+ gossip_err("Could not locate fs_conf for fs_id %d\n", fs_id);
+ return -PVFS_EINVAL;
+ }
+ /* This is actually ok since an FS may not have secret key */
+ if (!fs_conf->secret_key)
+ {
+ *length = 0;
+ *key = NULL;
+ return 0;
+ }
+
+ b64len = strlen(fs_conf->secret_key);
+ b64buf = malloc(b64len+1);
+ if(!b64buf)
+ {
+ return -PVFS_ENOMEM;
+ }
+ memcpy(b64buf, fs_conf->secret_key, b64len);
+
+ /* for some reason openssl's base64 decoding needs a newline at the end */
+ b64buf[b64len] = '\n';
+
+ b64 = BIO_new(BIO_f_base64());
+ mem = BIO_new_mem_buf(b64buf, b64len+1);
+ bio = BIO_push(b64, mem);
+
+ len = BIO_pending(bio);
+ *key = malloc(len);
+ if(!*key)
+ {
+ BIO_free_all(bio);
+ return -PVFS_ENOMEM;
+ }
+
+ *length = BIO_read(bio, *key, len);
+
+ free(b64buf);
+
+ BIO_free_all(bio);
+ return 0;
+#endif /* WITH_OPENSSL */
+}
+
#ifdef __PVFS2_TROVE_SUPPORT__
static int is_root_handle_in_my_range(
struct server_configuration_s *config,
@@ -3843,9 +4095,8 @@ int PINT_config_pvfs2_mkspace(
gossip_err("Could not find handle range for host %s\n",
config->host_id);
gossip_err("Please make sure that the host names in "
- "%s and %s are consistent\n",
- config->fs_config_filename,
- config->server_config_filename);
+ "%s are consistent\n",
+ config->fs_config_filename);
break;
}
Index: server-config.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/server-config.h,v
diff -p -u -r1.55 -r1.55.4.1
--- server-config.h 11 Sep 2006 20:22:01 -0000 1.55
+++ server-config.h 21 Jul 2008 18:19:55 -0000 1.55.4.1
@@ -27,6 +27,7 @@ enum
CTX_DISTRIBUTION = (1 << 8),
CTX_SECURITY = (1 << 9),
CTX_EXPORT = (1 << 10),
+ CTX_SERVER_OPTIONS = (1 << 11),
};
typedef struct phys_server_desc
@@ -86,9 +87,13 @@ typedef struct filesystem_configuration_
int coalescing_high_watermark;
int coalescing_low_watermark;
+ char *secret_key;
+
int fp_buffer_size;
int fp_buffers_per_flow;
+ int trove_method;
+
/* Export flags bitwise OR of flags specified */
int exp_flags;
@@ -100,6 +105,10 @@ typedef struct filesystem_configuration_
char **root_squash_hosts;
int *root_squash_netmasks;
+ int root_squash_exceptions_count;
+ char **root_squash_exceptions_hosts;
+ int *root_squash_exceptions_netmasks;
+
int all_squash_count;
char **all_squash_hosts;
int *all_squash_netmasks;
@@ -126,13 +135,12 @@ typedef struct distribution_configuratio
typedef struct server_configuration_s
{
char *host_id;
+ char *server_alias; /* the command line server-alias parameter */
+ int my_server_options;
char *storage_path;
char *fs_config_filename; /* the fs.conf file name */
size_t fs_config_buflen; /* the fs.conf file length */
char *fs_config_buf; /* the fs.conf file contents */
- char *server_config_filename; /* the server.conf file name */
- size_t server_config_buflen; /* the server.conf file length */
- char *server_config_buf; /* the server.conf file contents */
int initial_unexpected_requests;
int server_job_bmi_timeout; /* job timeout values in seconds */
int server_job_flow_timeout;
@@ -142,7 +150,8 @@ typedef struct server_configuration_s
int client_retry_delay_ms; /* delay between retries */
int perf_update_interval; /* how quickly (in msecs) to
update perf monitor */
- char *logfile;
+ char *logfile; /* what log file to write to */
+ char *logtype; /* "file" or "syslog" destination */
enum gossip_logstamp logstamp_type; /* how to timestamp logs */
char *event_logging;
char *bmi_modules; /* BMI modules */
@@ -179,12 +188,14 @@ typedef struct server_configuration_s
int trove_max_concurrent_io; /* allow the number of aio operations to
* be configurable.
*/
+ int trove_method;
+ void *private_data;
} server_configuration_s;
int PINT_parse_config(
struct server_configuration_s *config_s,
char *global_config_filename,
- char *server_config_filename);
+ char *server_alias_name);
void PINT_config_release(
struct server_configuration_s *config_s);
@@ -255,6 +266,12 @@ PINT_llist *PINT_config_get_filesystems(
int PINT_config_trim_filesystems_except(
struct server_configuration_s *config_s,
PVFS_fs_id fs_id);
+
+int PINT_config_get_fs_key(
+ struct server_configuration_s *config,
+ PVFS_fs_id fs_id,
+ char ** key,
+ int * length);
struct server_configuration_s *PINT_get_server_config(void);
Index: state-machine.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/state-machine.h,v
diff -p -u -r1.12 -r1.12.28.1
--- state-machine.h 30 May 2006 19:16:29 -0000 1.12
+++ state-machine.h 21 Jul 2008 18:19:55 -0000 1.12.28.1
@@ -7,7 +7,8 @@
#ifndef __STATE_MACHINE_H
#define __STATE_MACHINE_H
-#include <state-machine-values.h>
+#include "job.h"
+#include "quicklist.h"
/* STATE-MACHINE.H
*
@@ -37,29 +38,120 @@
* function. See src/server/server-state-machine.c for examples.
*/
-#include "job.h"
+enum PINT_state_code {
+ SM_NONE = 0,
+ SM_NEXT = 1,
+ SM_RETURN = 2,
+ SM_EXTERN = 3,
+ SM_NESTED = 5,
+ SM_JUMP = 6,
+ SM_TERM = 7,
+ SM_PJMP = 8,
+ SM_RUN = 9
+};
+
+/* these define things like stack size and so forth for the common
+ * state machine code.
+ * The state stack size limits the number of nested state machines that
+ * can exist. 8 seems reasonable.
+ */
+#define PINT_STATE_STACK_SIZE 8
+
+struct PINT_state_stack_s
+{
+ struct PINT_state_s *state;
+ int prev_base_frame;
+};
+
+/* State machine control block - one per running instance of a state
+ * machine
+ */
+typedef struct PINT_smcb
+{
+ /* state machine execution variables */
+ int stackptr;
+ struct PINT_state_s *current_state;
+ struct PINT_state_stack_s state_stack[PINT_STATE_STACK_SIZE];
+
+ struct qlist_head frames; /* circular list of frames */
+ int base_frame; /* index of current base frame */
+ int frame_count; /* number of frames in list */
+
+ /* usage specific routinet to look up SM from OP */
+ struct PINT_state_machine_s *(*op_get_state_machine)(int);
+ /* state machine context and control variables */
+ int op; /* this field externally indicates type of state machine */
+ PVFS_id_gen_t op_id; /* unique ID for this operation */
+ struct PINT_smcb *parent_smcb; /* points to parent smcb or NULL */
+ int op_terminate; /* indicates SM is ready to terminate */
+ int op_cancelled; /* indicates SM operation was cancelled */
+ int children_running; /* the number of child SMs running */
+ int op_completed; /* indicates SM operation was added to completion Q */
+ /* add a lock here */
+ job_context_id context; /* job context when waiting for children */
+ int (*terminate_fn)(struct PINT_smcb *, job_status_s *);
+ void *user_ptr; /* external user pointer */
+ int immediate; /* specifies immediate completion of the state machine */
+} PINT_smcb;
-#ifndef PINT_OP_STATE
-#error "PINT_OP_STATE must be defined before state-machine.h is included."
-#endif
+#define PINT_SET_OP_COMPLETE do{PINT_smcb_set_complete(smcb);} while (0)
+
+struct PINT_state_machine_s
+{
+ const char *name;
+ struct PINT_state_s *first_state;
+};
-union PINT_state_array_values
+struct PINT_state_s
{
const char *state_name;
struct PINT_state_machine_s *parent_machine;
- int (*state_action)(struct PINT_OP_STATE *, job_status_s *);
+ enum PINT_state_code flag;
+ union
+ {
+ int (*func)(struct PINT_smcb *, job_status_s *);
+ struct PINT_state_machine_s *nested;
+ } action;
+ struct PINT_pjmp_tbl_s *pjtbl;
+ struct PINT_tran_tbl_s *trtbl;
+};
+
+struct PINT_pjmp_tbl_s
+{
int return_value;
- int flag;
- struct PINT_state_machine_s *nested_machine;
- union PINT_state_array_values *next_state;
+ enum PINT_state_code flag;
+ struct PINT_state_machine_s *state_machine;
};
-struct PINT_state_machine_s
+struct PINT_tran_tbl_s
{
- const char *name;
- union PINT_state_array_values *state_machine;
+ int return_value;
+ enum PINT_state_code flag;
+ struct PINT_state_s *next_state;
};
+/* All state action functions return this type which controls state
+ * machine action
+ */
+typedef enum {
+ SM_ACTION_DEFERRED = 0,
+ SM_ACTION_COMPLETE = 1,
+ SM_ACTION_TERMINATE = 2,
+ SM_ERROR = -1 /* this is a catastrophic error */
+} PINT_sm_action;
+
+extern char * PINT_sm_action_string[];
+#define SM_ACTION_STRING(action) \
+ (action == SM_ERROR ? "ERROR" : PINT_sm_action_string[action])
+
+#define SM_ACTION_ISERR(ret) ((ret)<0)
+#define SM_ACTION_ISVALID(ret) \
+ (ret == SM_ACTION_DEFERRED || \
+ ret == SM_ACTION_COMPLETE || \
+ ret == SM_ACTION_TERMINATE || \
+ ret == SM_ERROR)
+
+/* what is this type? */
enum {
JMP_NOT_READY = 99,
DEFAULT_ERROR = -1,
@@ -70,10 +162,51 @@ enum {
#define SM_NESTED_STATE 1
/* Prototypes for functions provided by user */
-int PINT_state_machine_start(struct PINT_OP_STATE *, job_status_s *ret);
-int PINT_state_machine_complete(struct PINT_OP_STATE *);
+int PINT_state_machine_complete(void *);
+
+/* This macro returns the state machine string of the current machine.
+ * We assume the first 6 characters of every state machine name are "pvfs2_".
+ */
+#define PINT_state_machine_current_machine_name(smcb) \
+ ((smcb)->current_state ? (((smcb)->current_state->parent_machine->name) + 6) : "UNKNOWN")
+
+/* This macro returns the current state invoked */
+#define PINT_state_machine_current_state_name(smcb) \
+ ((smcb)->current_state ? ((smcb)->current_state->state_name) : "UNKNOWN")
+
+/* Prototypes for functions defined in by state machine code */
+int PINT_state_machine_halt(void);
+int PINT_state_machine_terminate(struct PINT_smcb *, job_status_s *);
+PINT_sm_action PINT_state_machine_next(struct PINT_smcb *,job_status_s *);
+PINT_sm_action PINT_state_machine_invoke(struct PINT_smcb *, job_status_s *);
+PINT_sm_action PINT_state_machine_start(struct PINT_smcb *, job_status_s *);
+PINT_sm_action PINT_state_machine_continue(
+ struct PINT_smcb *smcb, job_status_s *r);
+int PINT_state_machine_locate(struct PINT_smcb *) __attribute__((used));
+int PINT_smcb_set_op(struct PINT_smcb *smcb, int op);
+int PINT_smcb_op(struct PINT_smcb *smcb);
+int PINT_smcb_immediate_completion(struct PINT_smcb *smcb);
+void PINT_smcb_set_complete(struct PINT_smcb *smcb);
+int PINT_smcb_invalid_op(struct PINT_smcb *smcb);
+int PINT_smcb_complete(struct PINT_smcb *smcb);
+void PINT_smcb_set_cancelled(struct PINT_smcb *smcb);
+int PINT_smcb_cancelled(struct PINT_smcb *smcb);
+int PINT_smcb_alloc(struct PINT_smcb **, int, int,
+ struct PINT_state_machine_s *(*getmach)(int),
+ int (*term_fn)(struct PINT_smcb *, job_status_s *),
+ job_context_id context_id);
+void PINT_smcb_free(struct PINT_smcb *);
+void *PINT_sm_frame(struct PINT_smcb *, int);
+int PINT_sm_push_frame(struct PINT_smcb *smcb, int task_id, void *frame_p);
+void *PINT_sm_pop_frame(struct PINT_smcb *smcb,
+ int *task_id,
+ int *error_code,
+ int *remaining);
+
+/* This macro is used in calls to PINT_sm_fram() */
+#define PINT_FRAME_CURRENT 0
-/* NOTE: All other function prototypes are defined in state-machine-fns.h */
+struct PINT_state_machine_s pvfs2_void_sm;
/*
* Local variables:
Index: str-utils.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/str-utils.c,v
diff -p -u -r1.18 -r1.18.16.1
--- str-utils.c 16 Jun 2006 21:01:12 -0000 1.18
+++ str-utils.c 21 Jul 2008 18:19:55 -0000 1.18.16.1
@@ -9,6 +9,7 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#include <assert.h>
#include "str-utils.h"
@@ -277,7 +278,7 @@ int PINT_get_path_element(
{
int count = -1;
char *segp = (char *)0;
- void *segstate;
+ void *segstate = NULL;
char local_pathname[PVFS_NAME_MAX] = {0};
strncpy(local_pathname,pathname,PVFS_NAME_MAX);
@@ -349,7 +350,7 @@ int PINT_split_string_list(char ***token
const char *holder = NULL;
const char *holder2 = NULL;
const char *end = NULL;
- int tokencount = 1;
+ int tokencount = 1, retval;
int i = -1;
if (!comma_list || !tokens)
@@ -365,6 +366,15 @@ int PINT_split_string_list(char ***token
holder++;
}
+ /* if we don't find any commas, just set the entire string to the first
+ * token and return
+ */
+ if(0 == tokencount)
+ {
+ tokencount = 1;
+ }
+
+ retval = tokencount;
/* allocate pointers for each */
*tokens = (char **) malloc(sizeof(char *) * tokencount);
if (!(*tokens))
@@ -372,6 +382,17 @@ int PINT_split_string_list(char ***token
return 0;
}
+ if(1 == tokencount)
+ {
+ (*tokens)[0] = strdup(comma_list);
+ if(!(*tokens)[0])
+ {
+ tokencount = 0;
+ goto failure;
+ }
+ return tokencount;
+ }
+
/* copy out all of the tokenized strings */
holder = comma_list;
end = comma_list + strlen(comma_list);
@@ -382,6 +403,10 @@ int PINT_split_string_list(char ***token
{
holder2 = end;
}
+ if (holder2 - holder == 0) {
+ retval--;
+ goto out;
+ }
(*tokens)[i] = (char *) malloc((holder2 - holder) + 1);
if (!(*tokens)[i])
{
@@ -389,11 +414,12 @@ int PINT_split_string_list(char ***token
}
strncpy((*tokens)[i], holder, (holder2 - holder));
(*tokens)[i][(holder2 - holder)] = '\0';
+ assert(strlen((*tokens)[i]) != 0);
holder = holder2 + 1;
-
}
- return (tokencount);
+out:
+ return (retval);
failure:
@@ -459,12 +485,12 @@ void PINT_free_string_list(char ** list,
*
*/
int PINT_remove_base_dir(
- char *pathname,
+ const char *pathname,
char *out_dir,
int out_max_len)
{
int ret = -1, len = 0;
- char *start, *end, *end_ref;
+ const char *start, *end, *end_ref;
if (pathname && out_dir && out_max_len)
{
@@ -474,7 +500,7 @@ int PINT_remove_base_dir(
}
start = pathname;
- end = (char *) (pathname + strlen(pathname));
+ end = pathname + strlen(pathname);
end_ref = end;
while (end && (end > start) && (*(--end) != '/'));
Index: str-utils.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/str-utils.h,v
diff -p -u -r1.16 -r1.16.16.1
--- str-utils.h 16 Jun 2006 21:01:13 -0000 1.16
+++ str-utils.h 21 Jul 2008 18:19:55 -0000 1.16.16.1
@@ -40,7 +40,7 @@ void PINT_free_string_list(
char ** list,
int len);
int PINT_remove_base_dir(
- char *pathname,
+ const char *pathname,
char *out_dir,
int out_max_len);
int PINT_remove_dir_prefix(
Index: xattr-utils.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/xattr-utils.c,v
diff -p -u -r1.2 -r1.2.36.1
--- xattr-utils.c 23 Feb 2006 23:29:25 -0000 1.2
+++ xattr-utils.c 21 Jul 2008 18:19:55 -0000 1.2.36.1
@@ -13,7 +13,11 @@
#include "xattr-utils.h"
#ifndef HAVE_FGETXATTR
+#ifndef HAVE_FGETXATTR_EXTRA_ARGS
ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size)
+#else
+ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, int pos, int opts )
+#endif
{
errno = ENOSYS;
return -1;
Index: xattr-utils.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/common/misc/xattr-utils.h,v
diff -p -u -r1.2 -r1.2.32.1
--- xattr-utils.h 7 Mar 2006 21:35:08 -0000 1.2
+++ xattr-utils.h 21 Jul 2008 18:19:55 -0000 1.2.32.1
@@ -9,9 +9,21 @@
#include "pvfs2-config.h"
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#endif
+
#ifndef HAVE_FGETXATTR_PROTOTYPE
+#ifndef HAVE_FGETXATTR_EXTRA_ARGS
/* prototype taken from fgetxattr(2) on Fedora FC4 */
ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size);
+#else
+ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, int pos, int opts);
+#endif
#endif
#endif
--- state-machine-fns.h 2008-07-21 14:19:56.000000000 -0400
+++ /dev/null 2004-06-24 14:04:38.000000000 -0400
@@ -1,269 +0,0 @@
-/*
- * (C) 2001 Clemson University and The University of Chicago
- *
- * See COPYING in top-level directory.
- */
-
-#ifndef __STATE_MACHINE_FNS_H
-#define __STATE_MACHINE_FNS_H
-
-#include <assert.h>
-
-#include "gossip.h"
-#include "pvfs2-debug.h"
-
-/* STATE-MACHINE-FNS.H
- *
- * This file implements a small collection of functions used when
- * interacting with the state machine system implemented in
- * state-machine.h. Probably you'll only need these functions in one
- * file per instance of a state machine implementation.
- *
- * Note that state-machine.h must be included before this is included.
- * This is usually accomplished through including some *other* file that
- * includes state-machine.h, because state-machine.h needs a key #define
- * before it can be included.
- *
- * The PINT_OP_STATE_TABLE has been replaced with a macro that must be #defined
- * instead: PINT_OP_STATE_GET_MACHINE.
- * This allows the _locate function to be used in the client as well.
- *
- * A good example of this is the pvfs2-server.h in the src/server directory,
- * which includes state-machine.h at the bottom, and server-state-machine.c,
- * which includes first pvfs2-server.h and then state-machine-fns.h.
- */
-
-#ifndef __STATE_MACHINE_H
-#error "state-machine.h must be included before state-machine-fns.h is included."
-#endif
-
-/* This macro returns the state machine string of the current machine.
- * We assume the first 6 characters of every state machine name are "pvfs2_".
- */
-#define PINT_state_machine_current_machine_name(s) \
- ((s->current_state - 2)->parent_machine->name + 6)
-
-/* This macro returns the current state invoked */
-#define PINT_state_machine_current_state_name(s) \
- ((s->current_state - 3)->state_name)
-
-/* Prototypes for functions defined in here */
-static inline int PINT_state_machine_halt(void);
-static inline int PINT_state_machine_next(struct PINT_OP_STATE *,job_status_s *r);
-static union PINT_state_array_values *PINT_state_machine_locate(struct PINT_OP_STATE *) __attribute__((used));
-static inline union PINT_state_array_values *PINT_pop_state(struct PINT_OP_STATE *s);
-static inline void PINT_push_state(struct PINT_OP_STATE *s, union PINT_state_array_values *p);
-
-/* Function: PINT_state_machine_halt(void)
- Params: None
- Returns: True
- Synopsis: This function is used to shutdown the state machine
- */
-static inline int PINT_state_machine_halt(void)
-{
- return 0;
-}
-
-/* Function: PINT_state_machine_next()
- Params:
- Returns: return value of state action
-
- Synopsis: Runs through a list of return values to find the next function to
- call. Calls that function. Once that function is called, this one exits
- and we go back to pvfs2-server.c's while loop.
- */
-static inline int PINT_state_machine_next(struct PINT_OP_STATE *s,
- job_status_s *r)
-{
- int code_val = r->error_code; /* temp to hold the return code */
- int retval; /* temp to hold return value of state action */
- union PINT_state_array_values *loc; /* temp pointer into state memory */
- const char * state_name;
- const char * machine_name;
-
- do {
- /* skip over the current state action to get to the return code list */
- loc = s->current_state + 1;
-
- /* for each entry in the state machine table there is a return
- * code followed by a next state pointer to the new state.
- * This loops through each entry, checking for a match on the
- * return address, and then sets the new current_state and calls
- * the new state action function */
- while (loc->return_value != code_val &&
- loc->return_value != DEFAULT_ERROR)
- {
- /* each entry has a return value followed by a next state
- * pointer, so we increment by two.
- */
- loc += 2;
- }
-
- /* skip over the return code to get to the pointer for the
- * next state
- */
- loc += 1;
-
- /* its not legal to actually reach a termination point; preceding
- * function should have completed state machine.
- */
- if(loc->flag == SM_TERMINATE)
- {
- gossip_err("Error: state machine using an invalid termination path.\n");
- return(-PVFS_EINVAL);
- }
-
- /* Update the server_op struct to reflect the new location
- * see if the selected return value is a STATE_RETURN */
- if (loc->flag == SM_RETURN)
- {
- s->current_state = PINT_pop_state(s);
- s->current_state += 1; /* skip state flags */
- }
- } while (loc->flag == SM_RETURN);
-
- s->current_state = loc->next_state;
- s->current_state += 2;
-
-
- /* To do nested states, we check to see if the next state is
- * a nested state machine, and if so we push the return state
- * onto a stack */
- while (s->current_state->flag == SM_JUMP)
- {
- PINT_push_state(s, s->current_state);
- s->current_state += 1; /* skip state flag; now we point to the state
- * machine */
-
- s->current_state = s->current_state->nested_machine->state_machine;
- s->current_state += 2;
- }
-
- /* skip over the flag so that we point to the function for the next
- * state. then call it.
- */
- s->current_state += 1;
-
- state_name = PINT_state_machine_current_state_name(s);
- machine_name = PINT_state_machine_current_machine_name(s);
-
- gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
- "[SM Entering]: (%p) %s:%s (status: %d)\n",
- s,
- /* skip pvfs2_ */
- machine_name,
- state_name,
- (int32_t)r->status_user_tag);
-
- retval = (s->current_state->state_action)(s,r);
-
- gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
- "[SM Exiting]: (%p) %s:%s (error code: %d)\n",
- s,
- /* skip pvfs2_ */
- machine_name,
- state_name,
- r->error_code);
-
- /* return to the while loop in pvfs2-server.c */
- return retval;
-}
-
-static inline int PINT_state_machine_invoke(
- struct PINT_OP_STATE *s, job_status_s *r)
-{
- int retval;
- const char * state_name;
- const char * machine_name;
-
- state_name = PINT_state_machine_current_state_name(s);
- machine_name = PINT_state_machine_current_machine_name(s);
-
- gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
- "[SM Entering]: (%p) %s:%s (status: %d)\n",
- s,
- /* skip pvfs2_ */
- machine_name,
- state_name,
- (int32_t)r->status_user_tag);
-
- retval = (s->current_state->state_action)(s,r);
-
- gossip_debug(GOSSIP_STATE_MACHINE_DEBUG,
- "[SM Exiting]: (%p) %s:%s (error code: %d)\n",
- s,
- /* skip pvfs2_ */
- machine_name,
- state_name,
- r->error_code);
- return retval;
-}
-
-/* Function: PINT_state_machine_locate(void)
- Params:
- Returns: Pointer to the start of the state machine indicated by
- s_op->op
- Synopsis: This function is used to start a state machines execution.
- */
-
-static union PINT_state_array_values *PINT_state_machine_locate(struct PINT_OP_STATE *s_op)
-{
- union PINT_state_array_values *current_tmp;
-
- /* check for valid inputs */
- if (!s_op || s_op->op < 0)
- {
- gossip_err("State machine requested not valid\n");
- return NULL;
- }
- if (PINT_OP_STATE_GET_MACHINE(s_op->op) != NULL)
- {
- current_tmp = PINT_OP_STATE_GET_MACHINE(s_op->op)->state_machine;
- current_tmp += 2;
- /* handle the case in which the first state points to a nested
- * machine, rather than a simple function
- */
- while(current_tmp->flag == SM_JUMP)
- {
- PINT_push_state(s_op, current_tmp);
- current_tmp += 1;
- current_tmp = ((struct PINT_state_machine_s *)
- current_tmp->nested_machine)->state_machine;
- current_tmp += 2;
- }
-
- /* this returns a pointer to a "PINT_state_array_values"
- * structure, whose state_action member is the function to call.
- */
- return current_tmp + 1;
- }
-
- gossip_err("State machine not found for operation %d\n",s_op->op);
- return NULL;
-}
-
-static inline union PINT_state_array_values *PINT_pop_state(struct PINT_OP_STATE *s)
-{
- assert(s->stackptr > 0);
-
- return s->state_stack[--s->stackptr];
-}
-
-static inline void PINT_push_state(struct PINT_OP_STATE *s,
- union PINT_state_array_values *p)
-{
- assert(s->stackptr < PINT_STATE_STACK_SIZE);
-
- s->state_stack[s->stackptr++] = p;
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * End:
- *
- * vim: ts=8 sts=4 sw=4 expandtab
- */
-
-#endif
--- state-machine-values.h 2008-07-21 14:19:56.000000000 -0400
+++ /dev/null 2004-06-24 14:04:38.000000000 -0400
@@ -1,33 +0,0 @@
-/*
- * (C) 2001 Clemson University and The University of Chicago
- *
- * See COPYING in top-level directory.
- */
-
-#ifndef __STATE_MACHINE_VALUES_H
-#define __STATE_MACHINE_VALUES_H
-
-/* these values are used both in statecomp (to generate the state machine
- * code), and in the state machine processing.
- *
- * they are kept separate from the rest of the code to keep the number of
- * includes for the statecomp code down.
- */
-#define SM_NONE 0
-#define SM_NEXT 1
-#define SM_RETURN 2
-#define SM_EXTERN 3
-#define SM_NESTED 5
-#define SM_JUMP 6
-#define SM_TERMINATE 7
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * End:
- *
- * vim: ts=8 sts=4 sw=4 expandtab
- */
-
-#endif
More information about the Pvfs2-cvs
mailing list