[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 = &current_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