These patches address the issues brought up in this earlier post:
http://www.beowulf-underground.org/pipermail/pvfs2-developers/2006-March/001830.html

sys-statfs-async.patch:
-------------
adds a nonblocking version of the statfs function and updates pvfs2-client-core to use it

sys-mount-async.patch:
-------------
adds a nonblocking version of the fs_add function (this is the code path that triggers the getconfig request) and updates pvfs2-client-core to use it

Each of these patches includes an extra nested state machine to help organize the work that needs to happen. These patches shouldn't make any noticeable difference in normal circumstances for most people, but they let pvfs2-client handle other operations while a mount or statfs request is stalled.

-Phil
diff -Naur pvfs2-old/include/pvfs2-sysint.h pvfs2/include/pvfs2-sysint.h
--- pvfs2-old/include/pvfs2-sysint.h	2006-03-26 20:00:29.000000000 +0200
+++ pvfs2/include/pvfs2-sysint.h	2006-03-26 22:55:47.000000000 +0200
@@ -199,6 +199,10 @@
     uint64_t default_debug_mask);
 int PVFS_sys_fs_add(
     struct PVFS_sys_mntent* mntent);
+int PVFS_isys_fs_add(
+    struct PVFS_sys_mntent* mntent,
+    PVFS_sys_op_id *op_id,
+    void *user_ptr);
 int PVFS_sys_fs_remove(
     struct PVFS_sys_mntent* mntent);
 int PVFS_sys_finalize(
diff -Naur pvfs2-old/src/apps/kernel/linux/pvfs2-client-core.c pvfs2/src/apps/kernel/linux/pvfs2-client-core.c
--- pvfs2-old/src/apps/kernel/linux/pvfs2-client-core.c	2006-03-26 20:00:29.000000000 +0200
+++ pvfs2/src/apps/kernel/linux/pvfs2-client-core.c	2006-03-26 22:55:47.000000000 +0200
@@ -135,6 +135,8 @@
     PVFS_ds_keyval  val;
     void *io_kernel_mapped_buf;
 
+    struct PVFS_sys_mntent* mntent; /* used only by mount */
+
     int was_handled_inline;
     int was_cancelled_io;
 
@@ -981,11 +983,9 @@
     ret = 0;                                                          \
 } while(0)
 
-static PVFS_error service_fs_mount_request(vfs_request_t *vfs_request)
+static PVFS_error post_fs_mount_request(vfs_request_t *vfs_request)
 {
     PVFS_error ret = -PVFS_ENODEV;
-    struct PVFS_sys_mntent mntent;
-    PVFS_handle root_handle;
     char *ptr = NULL, *ptrcomma = NULL;
     char buf[PATH_MAX] = {0};
 
@@ -994,76 +994,30 @@
       mntent entries are not filled in, so add some defaults here
       if they weren't passed in the options.
     */
-    memset(&mntent, 0, sizeof(struct PVFS_sys_mntent));
+    vfs_request->mntent = (struct PVFS_sys_mntent*)malloc(sizeof(struct
+        PVFS_sys_mntent));
+    if(!vfs_request->mntent)
+    {
+        return -PVFS_ENOMEM;
+    }
+    memset(vfs_request->mntent, 0, sizeof(struct PVFS_sys_mntent));
         
     gossip_debug(
         GOSSIP_CLIENTCORE_DEBUG,
         "Got an fs mount request for host:\n  %s\n",
         vfs_request->in_upcall.req.fs_mount.pvfs2_config_server);
 
-    generate_upcall_mntent(mntent, vfs_request->in_upcall, 1);
+    generate_upcall_mntent((*vfs_request->mntent), vfs_request->in_upcall, 1);
 
-    ret = PVFS_sys_fs_add(&mntent);
-    if (ret < 0)
-    {
-      fail_downcall:
-        gossip_err(
-            "Failed to mount via host %s\n",
-            vfs_request->in_upcall.req.fs_mount.pvfs2_config_server);
-
-        PVFS_perror_gossip("Mount failed", ret);
+    ret = PVFS_isys_fs_add(vfs_request->mntent, &vfs_request->op_id, (void*)vfs_request);
 
-        vfs_request->out_downcall.type = PVFS2_VFS_OP_FS_MOUNT;
-        vfs_request->out_downcall.status = ret;
-    }
-    else
+fail_downcall:
+    if(ret < 0)
     {
-        /*
-          ungracefully ask bmi to drop connections on cancellation so
-          that the server will immediately know that a cancellation
-          occurred
-        */
-        PVFS_BMI_addr_t tmp_addr;
-
-        if (BMI_addr_lookup(&tmp_addr, mntent.the_pvfs_config_server) == 0)
-        {
-            if (BMI_set_info(
-                    tmp_addr, BMI_FORCEFUL_CANCEL_MODE, NULL) == 0)
-            {
-                gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "BMI forceful "
-                             "cancel mode enabled\n");
-            }
-        }
-        reset_acache_timeout();
-
-        /*
-          before sending success response we need to resolve the root
-          handle, given the previously resolved fs_id
-        */
-        ret = PINT_cached_config_get_root_handle(mntent.fs_id, &root_handle);
-        if (ret)
-        {
-            gossip_err("Failed to retrieve root handle for "
-                       "resolved fs_id %d\n", mntent.fs_id);
-            goto fail_downcall;
-        }
-            
-        gossip_debug(GOSSIP_CLIENTCORE_DEBUG,
-                     "FS mount got root handle %llu on fs id %d\n",
-                     llu(root_handle), mntent.fs_id);
-
-        vfs_request->out_downcall.type = PVFS2_VFS_OP_FS_MOUNT;
-        vfs_request->out_downcall.status = 0;
-        vfs_request->out_downcall.resp.fs_mount.fs_id = mntent.fs_id;
-        vfs_request->out_downcall.resp.fs_mount.root_handle =
-            root_handle;
-        vfs_request->out_downcall.resp.fs_mount.id = dynamic_mount_id++;
+        PVFS_perror_gossip("Posting fs_add failed", ret);
     }
 
-    PVFS_util_free_mntent(&mntent);
-
-    write_inlined_device_response(vfs_request);
-    return 0;
+    return ret;
 }
 
 static PVFS_error service_fs_umount_request(vfs_request_t *vfs_request)
@@ -1685,6 +1639,7 @@
 static inline void package_downcall_members(
     vfs_request_t *vfs_request, int *error_code)
 {
+    int ret = -PVFS_EINVAL;
     assert(vfs_request);
     assert(error_code);
 
@@ -1886,6 +1841,72 @@
             vfs_request->out_downcall.resp.statfs.files_avail = (long)
                 vfs_request->response.statfs.statfs_buf.handles_available_count;
             break;
+        case PVFS2_VFS_OP_FS_MOUNT:
+            if (*error_code)
+            {
+                gossip_err(
+                    "Failed to mount via host %s\n",
+                    vfs_request->in_upcall.req.fs_mount.pvfs2_config_server);
+
+                PVFS_perror_gossip("Mount failed", *error_code);
+            }
+            else
+            {
+                PVFS_handle root_handle;
+                /*
+                  ungracefully ask bmi to drop connections on cancellation so
+                  that the server will immediately know that a cancellation
+                  occurred
+                */
+                PVFS_BMI_addr_t tmp_addr;
+
+                if (BMI_addr_lookup(&tmp_addr, 
+                    vfs_request->mntent->the_pvfs_config_server) == 0)
+                {
+                    if (BMI_set_info(
+                            tmp_addr, BMI_FORCEFUL_CANCEL_MODE, NULL) == 0)
+                    {
+                        gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "BMI forceful "
+                                     "cancel mode enabled\n");
+                    }
+                }
+                reset_acache_timeout();
+
+                /*
+                  before sending success response we need to resolve the root
+                  handle, given the previously resolved fs_id
+                */
+                ret = PINT_cached_config_get_root_handle(
+                    vfs_request->mntent->fs_id, &root_handle);
+                if (ret)
+                {
+                    gossip_err("Failed to retrieve root handle for "
+                               "resolved fs_id %d\n", vfs_request->mntent->fs_id);
+                    gossip_err(
+                        "Failed to mount via host %s\n",
+                        vfs_request->in_upcall.req.fs_mount.pvfs2_config_server);
+                    PVFS_perror_gossip("Mount failed", ret);
+                    PVFS_util_free_mntent(vfs_request->mntent);
+                    *error_code = ret;
+                    break;
+                }
+                    
+                gossip_debug(GOSSIP_CLIENTCORE_DEBUG,
+                             "FS mount got root handle %llu on fs id %d\n",
+                             llu(root_handle), vfs_request->mntent->fs_id);
+
+                vfs_request->out_downcall.type = PVFS2_VFS_OP_FS_MOUNT;
+                vfs_request->out_downcall.status = 0;
+                vfs_request->out_downcall.resp.fs_mount.fs_id = 
+                    vfs_request->mntent->fs_id;
+                vfs_request->out_downcall.resp.fs_mount.root_handle =
+                    root_handle;
+                vfs_request->out_downcall.resp.fs_mount.id = dynamic_mount_id++;
+            }
+
+            PVFS_util_free_mntent(vfs_request->mntent);
+
+            break;
         case PVFS2_VFS_OP_RENAME:
             break;
         case PVFS2_VFS_OP_TRUNCATE:
@@ -2237,13 +2258,14 @@
             posted_op = 1;
             ret = post_statfs_request(vfs_request);
             break;
+        case PVFS2_VFS_OP_FS_MOUNT:
+            posted_op = 1;
+            ret = post_fs_mount_request(vfs_request);
+            break;
             /*
-              NOTE: mount, and umount are blocking
+              NOTE: following operations are blocking
               calls that are serviced inline.
             */
-        case PVFS2_VFS_OP_FS_MOUNT:
-            ret = service_fs_mount_request(vfs_request);
-            break;
         case PVFS2_VFS_OP_FS_UMOUNT:
             ret = service_fs_umount_request(vfs_request);
             break;
diff -Naur pvfs2-old/src/client/sysint/client-state-machine.c pvfs2/src/client/sysint/client-state-machine.c
--- pvfs2-old/src/client/sysint/client-state-machine.c	2006-03-26 20:00:29.000000000 +0200
+++ pvfs2/src/client/sysint/client-state-machine.c	2006-03-26 22:55:41.000000000 +0200
@@ -194,7 +194,8 @@
     {&pvfs2_client_del_eattr_sm},
     {&pvfs2_client_list_eattr_sm},
     {&pvfs2_client_small_io_sm},
-    {&pvfs2_client_statfs_sm}
+    {&pvfs2_client_statfs_sm},
+    {&pvfs2_fs_add_sm}
 };
 
 struct PINT_client_op_entry_s PINT_client_sm_mgmt_table[] =
@@ -794,6 +795,7 @@
         { PVFS_SERVER_GET_CONFIG, "PVFS_SERVER_GET_CONFIG" },
         { PVFS_CLIENT_JOB_TIMER, "PVFS_CLIENT_JOB_TIMER" },
         { PVFS_DEV_UNEXPECTED, "PVFS_DEV_UNEXPECTED" },
+        { PVFS_SYS_FS_ADD, "PVFS_SYS_FS_ADD" },
         { 0, "UNKNOWN" }
     };
 
diff -Naur pvfs2-old/src/client/sysint/client-state-machine.h pvfs2/src/client/sysint/client-state-machine.h
--- pvfs2-old/src/client/sysint/client-state-machine.h	2006-03-26 20:00:29.000000000 +0200
+++ pvfs2/src/client/sysint/client-state-machine.h	2006-03-26 22:55:41.000000000 +0200
@@ -337,6 +337,7 @@
 
 struct PINT_server_get_config_sm
 {
+    struct server_configuration_s *config;
     struct PVFS_sys_mntent *mntent;
     char *fs_config_buf;
     char *server_config_buf;
@@ -604,6 +605,7 @@
     PVFS_SYS_LISTEATTR             = 16,
     PVFS_SYS_SMALL_IO              = 17,
     PVFS_SYS_STATFS                = 18,
+    PVFS_SYS_FS_ADD                = 19,
     PVFS_MGMT_SETPARAM_LIST        = 70,
     PVFS_MGMT_NOOP                 = 71,
     PVFS_MGMT_STATFS_LIST          = 72,
@@ -762,11 +764,13 @@
 extern struct PINT_state_machine_s pvfs2_client_del_eattr_sm;
 extern struct PINT_state_machine_s pvfs2_client_list_eattr_sm;
 extern struct PINT_state_machine_s pvfs2_client_statfs_sm;
+extern struct PINT_state_machine_s pvfs2_fs_add_sm;
 
 /* nested state machines (helpers) */
 extern struct PINT_state_machine_s pvfs2_client_lookup_ncache_sm;
 extern struct PINT_state_machine_s pvfs2_client_remove_helper_sm;
 extern struct PINT_state_machine_s pvfs2_client_mgmt_statfs_list_nested_sm;
+extern struct PINT_state_machine_s pvfs2_server_get_config_nested_sm;
 
 #include "state-machine.h"
 
diff -Naur pvfs2-old/src/client/sysint/fs-add.c pvfs2/src/client/sysint/fs-add.c
--- pvfs2-old/src/client/sysint/fs-add.c	2005-11-10 02:26:58.000000000 +0100
+++ pvfs2/src/client/sysint/fs-add.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,208 +0,0 @@
-/*
- * (C) 2001 Clemson University and The University of Chicago
- *
- * See COPYING in top-level directory.
- */
-
-/** \file
- *  \ingroup sysint
- *
- *  PVFS2 system interface bootstrapping routine to tell the interface
- *  about available file systems.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "acache.h"
-#include "ncache.h"
-#include "pint-cached-config.h"
-#include "pvfs2-sysint.h"
-#include "pvfs2-util.h"
-#include "pint-sysint-utils.h"
-#include "gen-locks.h"
-#include "pint-servreq.h"
-#include "PINT-reqproto-encode.h"
-#include "dotconf.h"
-#include "trove.h"
-#include "server-config-mgr.h"
-#include "client-state-machine.h"
-
-gen_mutex_t mt_config = GEN_MUTEX_INITIALIZER;
-
-/** Tell the system interface about the location of a PVFS2 file system.
- *
- * \return 0 on success, -PVFS_error on failure.
- */
-int PVFS_sys_fs_add(struct PVFS_sys_mntent *mntent)
-{
-    int ret = -PVFS_EINVAL;
-    int i;
-    struct server_configuration_s *new_server_config = NULL;
-    PVFS_BMI_addr_t test_addr;
-
-    gen_mutex_lock(&mt_config);
-
-    /* Normally the fs_id value has not been resolved yet at this point, and
-     * will be zero.  If it is a non-zero value (and this get_config call
-     * succeeds) then it indicates someone has already added this mntent
-     * instance.  It is ok to add the same _file system_ twice, but not the
-     * same mntent instance.
-     */
-    new_server_config = PINT_server_config_mgr_get_config(mntent->fs_id);
-    if (new_server_config)
-    {
-        PINT_server_config_mgr_put_config(new_server_config);
-        PVFS_perror_gossip("Configuration for fs already exists", ret);
-        return -PVFS_EEXIST;
-    }
-
-    /* make sure BMI knows how to handle this method, else fail quietly */
-    for(i = 0; i < mntent->num_pvfs_config_servers; i++)
-    {
-        ret = BMI_addr_lookup(&test_addr, mntent->pvfs_config_servers[i]);
-        if (ret == 0)
-        {
-            break;
-        }
-    }
-
-    if (i == mntent->num_pvfs_config_servers)
-    {
-        gossip_err("%s: Failed to initialize any appropriate "
-                   "BMI methods.\n", __func__);
-        goto error_exit;
-    }
-    mntent->the_pvfs_config_server = mntent->pvfs_config_servers[i];
-
-    new_server_config = (struct server_configuration_s *)malloc(
-        sizeof(struct server_configuration_s));
-    if (!new_server_config)
-    {
-        ret = -PVFS_ENOMEM;
-        PVFS_perror_gossip("Failed to allocate configuration object", ret);
-        goto error_exit;
-    }
-    memset(new_server_config, 0, sizeof(struct server_configuration_s));
-
-    /* get configuration parameters from server */
-    ret = PINT_server_get_config(new_server_config, mntent);
-    if (ret < 0)
-    {
-        PVFS_perror_gossip("PINT_server_get_config failed", ret);
-        goto error_exit;
-    }
-
-#ifdef USE_TRUSTED
-    /* once we know about the server configuration, we need to tell BMI */
-    BMI_set_info(0, BMI_TRUSTED_CONNECTION, (void *) new_server_config);
-    gossip_debug(GOSSIP_SERVER_DEBUG, "Enabling trusted connections!\n");
-#endif
-
-    /*
-      clear out all configuration information about file systems that
-      aren't matching the one being added now.  this ensures no
-      erroneous handle mappings are added next
-    */
-    ret = PINT_config_trim_filesystems_except(
-        new_server_config, mntent->fs_id);
-    if (ret < 0)
-    {
-        PVFS_perror_gossip(
-            "PINT_config_trim_filesystems_except failed", ret);
-        goto error_exit;
-    }
-
-    /*
-      add the mntent to the internal mount tables; it's okay if it's
-      already there, as the return value will tell us and we can
-      ignore it.  in short, if the mntent was from a pvfstab file, it
-      should already exist in the tables.  in any other case, it needs
-      to be added properly.
-    */
-    ret = PVFS_util_add_dynamic_mntent(mntent);
-    if (ret < 0)
-    {
-        PVFS_perror_gossip("PVFS_util_add_mnt failed", ret);
-        goto error_exit;
-    }
-
-    /* finally, try to add the new config to the server config manager */
-    ret = PINT_server_config_mgr_add_config(
-        new_server_config, mntent->fs_id);
-    if (ret < 0)
-    {
-        PVFS_perror_gossip("PINT_server_config_mgr_add_config failed", ret);
-        goto error_exit;
-    }
-
-    /*
-      reload all handle mappings as well as the interface with the new
-      configuration information
-    */
-    PINT_server_config_mgr_reload_cached_config_interface();
-
-    gen_mutex_unlock(&mt_config);
-    return 0;
-
-  error_exit:
-    gen_mutex_unlock(&mt_config);
-    if (new_server_config)
-    {
-        PINT_config_release(new_server_config);
-        free(new_server_config);
-    }
-    return ret;
-}
-
-/* PVFS_sys_fs_remove()
- *
- * tells the system interface to dynamically "unmount" a mounted file
- * system by removing the configuration info and reloading the cached
- * configuration interface
- *
- * returns 0 on success, -PVFS_error on failure
- */
-int PVFS_sys_fs_remove(struct PVFS_sys_mntent *mntent)
-{
-    int ret = -PVFS_EINVAL;
-
-    if (mntent)
-    {
-        gen_mutex_lock(&mt_config);
-        ret = PVFS_util_remove_internal_mntent(mntent);
-        if (ret == 0)
-        {
-            ret = PINT_server_config_mgr_remove_config(mntent->fs_id);
-            if (ret < 0)
-            {
-                PVFS_perror_gossip("PINT_server_config_mgr_remove_config "
-                            "failed", ret);
-            }
-
-            /*
-              reload all handle mappings as well as the interface with
-              the new configuration information
-            */
-            PINT_server_config_mgr_reload_cached_config_interface();
-        }
-        gen_mutex_unlock(&mt_config);
-    }
-    return ret;
-}
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- * End:
- *
- * vim: ts=8 sts=4 sw=4 expandtab
- */
diff -Naur pvfs2-old/src/client/sysint/fs-add.sm pvfs2/src/client/sysint/fs-add.sm
--- pvfs2-old/src/client/sysint/fs-add.sm	1970-01-01 01:00:00.000000000 +0100
+++ pvfs2/src/client/sysint/fs-add.sm	2006-03-26 22:55:47.000000000 +0200
@@ -0,0 +1,315 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * Changes by Acxiom Corporation to add support for nonblocking fs addition
+ * Copyright © Acxiom Corporation, 2006.
+ *
+ * See COPYING in top-level directory.
+ */
+
+/** \file
+ *  \ingroup sysint
+ *
+ *  PVFS2 system interface bootstrapping routine to tell the interface
+ *  about available file systems.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "acache.h"
+#include "ncache.h"
+#include "pint-cached-config.h"
+#include "pvfs2-sysint.h"
+#include "pvfs2-util.h"
+#include "pint-sysint-utils.h"
+#include "gen-locks.h"
+#include "pint-servreq.h"
+#include "PINT-reqproto-encode.h"
+#include "dotconf.h"
+#include "trove.h"
+#include "server-config-mgr.h"
+#include "client-state-machine.h"
+
+gen_mutex_t mt_config = GEN_MUTEX_INITIALIZER;
+extern job_context_id pint_client_sm_context;
+
+static int fs_add_parent_cleanup(
+    PINT_client_sm *sm_p, job_status_s *js_p);
+
+%%
+
+machine pvfs2_fs_add_sm(
+    run_nested,
+    parent_cleanup)
+{
+    state run_nested 
+    {
+        jump pvfs2_server_get_config_nested_sm;
+        default => parent_cleanup;
+    }
+
+    state parent_cleanup
+    {
+        run fs_add_parent_cleanup;
+        default => terminate;
+    }
+}
+
+%%
+
+/** Tell the system interface about the location of a PVFS2 file system.
+ *
+ * \return 0 on success, -PVFS_error on failure.
+ */
+PVFS_error PVFS_isys_fs_add(
+    struct PVFS_sys_mntent *mntent,
+    PVFS_sys_op_id *op_id,
+    void* user_ptr)
+{
+    int ret = -PVFS_EINVAL;
+    int i;
+    struct server_configuration_s *new_server_config = NULL;
+    PVFS_BMI_addr_t test_addr;
+    PINT_client_sm *sm_p = NULL;
+    PVFS_credentials creds;
+
+    PVFS_util_gen_credentials(&creds);
+
+    gen_mutex_lock(&mt_config);
+
+    /* Normally the fs_id value has not been resolved yet at this point, and
+     * will be zero.  If it is a non-zero value (and this get_config call
+     * succeeds) then it indicates someone has already added this mntent
+     * instance.  It is ok to add the same _file system_ twice, but not the
+     * same mntent instance.
+     */
+    new_server_config = PINT_server_config_mgr_get_config(mntent->fs_id);
+    if (new_server_config)
+    {
+        PINT_server_config_mgr_put_config(new_server_config);
+        PVFS_perror_gossip("Attempted duplicate mntent addition", ret);
+        gen_mutex_unlock(&mt_config);
+        return -PVFS_EEXIST;
+    }
+
+    /* make sure BMI knows how to handle this method, else fail quietly */
+    for(i = 0; i < mntent->num_pvfs_config_servers; i++)
+    {
+        ret = BMI_addr_lookup(&test_addr, mntent->pvfs_config_servers[i]);
+        if (ret == 0)
+        {
+            break;
+        }
+    }
+
+    if (i == mntent->num_pvfs_config_servers)
+    {
+        gossip_err("%s: Failed to initialize any appropriate "
+                   "BMI methods.\n", __func__);
+        gen_mutex_unlock(&mt_config);
+        return(ret);
+    }
+    mntent->the_pvfs_config_server = mntent->pvfs_config_servers[i];
+
+    sm_p = (PINT_client_sm *)malloc(sizeof(*sm_p));
+    if (sm_p == NULL)
+    {
+        return -PVFS_ENOMEM;
+    }
+    memset(sm_p, 0, sizeof(*sm_p));
+
+    sm_p->u.get_config.mntent = mntent;
+    sm_p->u.get_config.config = 
+        (struct server_configuration_s *)malloc(
+        sizeof(struct server_configuration_s));
+    if (!sm_p->u.get_config.config)
+    {
+        ret = -PVFS_ENOMEM;
+        PVFS_perror_gossip("Failed to allocate configuration object", ret);
+        gen_mutex_unlock(&mt_config);
+        return(ret);
+    }
+    memset(sm_p->u.get_config.config, 0, sizeof(struct server_configuration_s));
+
+    /* NOTE: we set these fields manually here rather than use
+     * PINT_init_msgarray_params(), because we don't yet have a server
+     * configuration file to override default parameters.
+     */
+    sm_p->msgarray_params.job_context = pint_client_sm_context;
+    sm_p->msgarray_params.job_timeout = 30;   /* 30 second job timeout */
+    sm_p->msgarray_params.retry_delay = 2000; /* 2 second retry delay */
+    sm_p->msgarray_params.retry_limit = 5;    /* retry up to 5 times */
+
+    sm_p->msgarray_count = 1;
+    sm_p->msgarray = &(sm_p->msgpair);
+
+    PINT_init_sysint_credentials(sm_p->cred_p, &creds);
+
+    return PINT_client_state_machine_post(
+        sm_p, PVFS_SYS_FS_ADD, op_id, user_ptr);
+}
+
+int PVFS_sys_fs_add(struct PVFS_sys_mntent *mntent)
+{
+    int ret = -PVFS_EINVAL, error = 0;
+    PVFS_sys_op_id op_id;
+
+    ret = PVFS_isys_fs_add(mntent, &op_id, NULL);
+    if (ret)
+    {
+        PVFS_perror_gossip("PVFS_isys_fs_add call", ret);
+        error = ret;
+    }
+    else
+    {
+        ret = PINT_sys_wait(op_id, "fs_add", &error);
+        if (ret)
+        {
+            PVFS_perror_gossip("PVFS_sys_wait call", ret);
+            error = ret;
+        }
+    }
+
+    PINT_sys_release(op_id);
+    return error;
+}
+
+/* PVFS_sys_fs_remove()
+ *
+ * tells the system interface to dynamically "unmount" a mounted file
+ * system by removing the configuration info and reloading the cached
+ * configuration interface
+ *
+ * returns 0 on success, -PVFS_error on failure
+ */
+int PVFS_sys_fs_remove(struct PVFS_sys_mntent *mntent)
+{
+    int ret = -PVFS_EINVAL;
+
+    if (mntent)
+    {
+        gen_mutex_lock(&mt_config);
+        ret = PVFS_util_remove_internal_mntent(mntent);
+        if (ret == 0)
+        {
+            ret = PINT_server_config_mgr_remove_config(mntent->fs_id);
+            if (ret < 0)
+            {
+                PVFS_perror_gossip("PINT_server_config_mgr_remove_config "
+                            "failed", ret);
+            }
+
+            /*
+              reload all handle mappings as well as the interface with
+              the new configuration information
+            */
+            PINT_server_config_mgr_reload_cached_config_interface();
+        }
+        gen_mutex_unlock(&mt_config);
+    }
+    return ret;
+}
+
+static int fs_add_parent_cleanup(
+    PINT_client_sm *sm_p, job_status_s *js_p)
+{
+    int ret = -PVFS_EINVAL;
+
+    if(js_p->error_code != 0)
+    {
+        gen_mutex_unlock(&mt_config);
+        PINT_config_release(sm_p->u.get_config.config);
+        free(sm_p->u.get_config.config);
+        sm_p->error_code  = js_p->error_code;
+        sm_p->op_complete = 1;
+        return(0);
+    }
+
+#ifdef USE_TRUSTED
+    /* once we know about the server configuration, we need to tell BMI */
+    BMI_set_info(0, BMI_TRUSTED_CONNECTION, (void *)sm_p->u.get_config.config);
+    gossip_debug(GOSSIP_SERVER_DEBUG, "Enabling trusted connections!\n");
+#endif
+
+    /*
+      clear out all configuration information about file systems that
+      aren't matching the one being added now.  this ensures no
+      erroneous handle mappings are added next
+    */
+    ret = PINT_config_trim_filesystems_except(
+        sm_p->u.get_config.config, sm_p->u.get_config.mntent->fs_id);
+    if (ret < 0)
+    {
+        PVFS_perror_gossip(
+            "PINT_config_trim_filesystems_except failed", ret);
+        gen_mutex_unlock(&mt_config);
+        PINT_config_release(sm_p->u.get_config.config);
+        free(sm_p->u.get_config.config);
+        sm_p->error_code  = ret;
+        sm_p->op_complete = 1;
+        return(0);
+    }
+
+    /*
+      add the mntent to the internal mount tables; it's okay if it's
+      already there, as the return value will tell us and we can
+      ignore it.  in short, if the mntent was from a pvfstab file, it
+      should already exist in the tables.  in any other case, it needs
+      to be added properly.
+    */
+    ret = PVFS_util_add_dynamic_mntent(sm_p->u.get_config.mntent);
+    if (ret < 0)
+    {
+        PVFS_perror_gossip("PVFS_util_add_mnt failed", ret);
+        gen_mutex_unlock(&mt_config);
+        PINT_config_release(sm_p->u.get_config.config);
+        free(sm_p->u.get_config.config);
+        sm_p->error_code  = ret;
+        sm_p->op_complete = 1;
+        return(0);
+    }
+
+    /* finally, try to add the new config to the server config manager */
+    ret = PINT_server_config_mgr_add_config(
+        sm_p->u.get_config.config, sm_p->u.get_config.mntent->fs_id);
+    if (ret < 0)
+    {
+        PVFS_perror_gossip("PINT_server_config_mgr_add_config failed", ret);
+        gen_mutex_unlock(&mt_config);
+        PINT_config_release(sm_p->u.get_config.config);
+        free(sm_p->u.get_config.config);
+        sm_p->error_code  = ret;
+        sm_p->op_complete = 1;
+        return(0);
+    }
+
+    /*
+      reload all handle mappings as well as the interface with the new
+      configuration information
+    */
+    PINT_server_config_mgr_reload_cached_config_interface();
+
+    gen_mutex_unlock(&mt_config);
+
+    sm_p->error_code  = 0;
+    sm_p->op_complete = 1;
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff -Naur pvfs2-old/src/client/sysint/module.mk.in pvfs2/src/client/sysint/module.mk.in
--- pvfs2-old/src/client/sysint/module.mk.in	2006-03-26 20:00:29.000000000 +0200
+++ pvfs2/src/client/sysint/module.mk.in	2006-03-26 22:55:47.000000000 +0200
@@ -10,8 +10,7 @@
 	$(DIR)/client-state-machine.c \
 	$(DIR)/mgmt-misc.c \
 	$(DIR)/sys-dist.c \
-	$(DIR)/error-details.c \
-	$(DIR)/fs-add.c
+	$(DIR)/error-details.c
 
 CLIENT_SMCGEN := \
 	$(DIR)/remove.c \
@@ -37,6 +36,7 @@
 	$(DIR)/client-job-timer.c \
 	$(DIR)/perf-count-timer.c \
 	$(DIR)/server-get-config.c \
+	$(DIR)/fs-add.c \
 	$(DIR)/mgmt-noop.c \
 	$(DIR)/mgmt-setparam-list.c \
 	$(DIR)/mgmt-statfs-list.c \
diff -Naur pvfs2-old/src/client/sysint/server-get-config.sm pvfs2/src/client/sysint/server-get-config.sm
--- pvfs2-old/src/client/sysint/server-get-config.sm	2005-08-26 21:10:55.000000000 +0200
+++ pvfs2/src/client/sysint/server-get-config.sm	2006-03-26 22:55:47.000000000 +0200
@@ -30,18 +30,21 @@
 /* state function prototypes */
 static int server_get_config_setup_msgpair(
     PINT_client_sm *sm_p, job_status_s *js_p);
-static int server_get_config_cleanup(
+static int server_get_config_parent_cleanup(
     PINT_client_sm *sm_p, job_status_s *js_p);
 static int server_get_config_cleanup(
     PINT_client_sm *sm_p, job_status_s *js_p);
+static int server_get_config_parse(
+    PINT_client_sm *sm_p, job_status_s *js_p);
 static int server_get_config_comp_fn(
     void *v_p, struct PVFS_server_resp *resp_p, int i);
 
 %%
 
-machine pvfs2_server_get_config_sm(
+nested machine pvfs2_server_get_config_nested_sm(
     setup_msgpair,
     xfer_msgpair,
+    parse,
     cleanup)
 {
     state setup_msgpair
@@ -54,12 +57,36 @@
     state xfer_msgpair
     {
         jump pvfs2_msgpairarray_sm;
+        success => parse;
+        default => cleanup;
+    }
+
+    state parse
+    {
+        run server_get_config_parse;
         default => cleanup;
     }
 
     state cleanup
     {
         run server_get_config_cleanup;
+        default => return;
+    }
+}
+
+machine pvfs2_server_get_config_sm(
+    run_nested,
+    parent_cleanup)
+{
+    state run_nested 
+    {
+        jump pvfs2_server_get_config_nested_sm;
+        default => parent_cleanup;
+    }
+
+    state parent_cleanup
+    {
+        run server_get_config_parent_cleanup;
         default => terminate;
     }
 }
@@ -81,7 +108,6 @@
     PINT_client_sm *sm_p = NULL;
     PVFS_error error = 0;
     PVFS_credentials creds;
-    struct filesystem_configuration_s* cur_fs = NULL;
     PVFS_sys_op_id op_id;
 
     gossip_debug(GOSSIP_CLIENT_DEBUG,
@@ -112,20 +138,16 @@
     sm_p->msgarray_params.job_timeout = 30;   /* 30 second job timeout */
     sm_p->msgarray_params.retry_delay = 2000; /* 2 second retry delay */
     sm_p->msgarray_params.retry_limit = 5;    /* retry up to 5 times */
-    PINT_init_sysint_credentials(sm_p->cred_p, &creds);
-    sm_p->u.get_config.mntent = mntent_p;
-
-    if (ENCODING_IS_VALID(mntent_p->encoding))
-    {
-        sm_p->msgpair.enc_type = mntent_p->encoding;
-    }
 
     sm_p->msgarray_count = 1;
     sm_p->msgarray = &(sm_p->msgpair);
 
+    PINT_init_sysint_credentials(sm_p->cred_p, &creds);
+    sm_p->u.get_config.mntent = mntent_p;
+    sm_p->u.get_config.config = config;
+
     ret = PINT_client_state_machine_post(
         sm_p, PVFS_SERVER_GET_CONFIG, &op_id, NULL);
-
     if (ret)
     {
         PVFS_perror_gossip("PINT_client_state_machine_post call", ret);
@@ -141,67 +163,8 @@
         }
     }
 
-    if (error)
-    {
-	goto exit_path;
-    }
-
-    gossip_debug(GOSSIP_CLIENT_DEBUG,
-                 "PINT_server_get_config completed\n");
-
-    ret = server_parse_config(
-        config,  sm_p->u.get_config.fs_config_buf,
-        sm_p->u.get_config.fs_config_buf_size,
-        sm_p->u.get_config.server_config_buf,
-        sm_p->u.get_config.server_config_buf_size);
-
-    if (ret)
-    {
-	gossip_err("Failed to get_config from host %s\n",
-                   mntent_p->the_pvfs_config_server); 
-	error = -PVFS_ENODEV;
-        goto exit_path;
-    }
-
-    cur_fs = PINT_config_find_fs_name(config, mntent_p->pvfs_fs_name);
-    if (!cur_fs)
-    {
-	gossip_err("Warning:\n Cannot retrieve information about "
-		"pvfstab entry %s\n",
-		mntent_p->the_pvfs_config_server);
-
-	/*
-          if the device has no space left on it, we can't save
-          the config file for parsing and get a failure; make
-          a note of that possibility here
-        */ 
-	gossip_err("\nHINTS: If you're sure that your pvfstab file "
-                   "contains valid information,\n please make sure "
-                   "that you are not out of disk space and that you "
-                   "have\n write permissions in the current "
-                   "directory or in the /tmp directory\n\n");
-
-	error = -PVFS_ENODEV;
-        goto exit_path;
-    }
-
-    mntent_p->fs_id = cur_fs->coll_id;
-    cur_fs->flowproto = mntent_p->flowproto;
-    cur_fs->encoding = mntent_p->encoding;
-
-  exit_path:
-
-    if (sm_p && !sm_p->u.get_config.persist_config_buffers)
-    {
-	free(sm_p->u.get_config.fs_config_buf);
-	free(sm_p->u.get_config.server_config_buf);
-
-        sm_p->u.get_config.fs_config_buf = NULL;
-        sm_p->u.get_config.server_config_buf = NULL;
-    }
-
     PINT_sys_release(op_id);
-    return error;
+    return(error);
 }
 
 static int server_parse_config(
@@ -292,6 +255,11 @@
     gossip_debug(GOSSIP_CLIENT_DEBUG,
 		"get_config state: server_get_config_setup_msgpair\n");
 
+    if (ENCODING_IS_VALID(sm_p->u.get_config.mntent->encoding))
+    {
+        sm_p->msgpair.enc_type = sm_p->u.get_config.mntent->encoding;
+    }
+
     msg_p = &sm_p->msgarray[0];
 
     ret = BMI_addr_lookup(&serv_addr,
@@ -318,12 +286,81 @@
 static int server_get_config_cleanup(PINT_client_sm *sm_p,
                                     job_status_s *js_p)
 {
+    if (sm_p && !sm_p->u.get_config.persist_config_buffers)
+    {
+	free(sm_p->u.get_config.fs_config_buf);
+	free(sm_p->u.get_config.server_config_buf);
+
+        sm_p->u.get_config.fs_config_buf = NULL;
+        sm_p->u.get_config.server_config_buf = NULL;
+    }
+
+    /* preserve js_p->error_code */
+
+    return 1;
+}
+
+static int server_get_config_parse(PINT_client_sm *sm_p,
+                                    job_status_s *js_p)
+{
+    int ret = -1;
+    struct filesystem_configuration_s* cur_fs = NULL;
+
+    ret = server_parse_config(
+        sm_p->u.get_config.config,  sm_p->u.get_config.fs_config_buf,
+        sm_p->u.get_config.fs_config_buf_size,
+        sm_p->u.get_config.server_config_buf,
+        sm_p->u.get_config.server_config_buf_size);
+    if (ret)
+    {
+	gossip_err("Failed to get_config from host %s\n",
+                   sm_p->u.get_config.mntent->the_pvfs_config_server); 
+	js_p->error_code = ret;
+        return 1;
+    }
+    
+    cur_fs = PINT_config_find_fs_name(sm_p->u.get_config.config, 
+        sm_p->u.get_config.mntent->pvfs_fs_name);
+    if (!cur_fs)
+    {
+	gossip_err("Warning:\n Cannot retrieve information about "
+		"pvfstab entry %s\n",
+		sm_p->u.get_config.mntent->the_pvfs_config_server);
+
+	/*
+          if the device has no space left on it, we can't save
+          the config file for parsing and get a failure; make
+          a note of that possibility here
+        */ 
+	gossip_err("\nHINTS: If you're sure that your pvfstab file "
+                   "contains valid information,\n please make sure "
+                   "that you are not out of disk space and that you "
+                   "have\n write permissions in the current "
+                   "directory or in the /tmp directory\n\n");
+
+	js_p->error_code = -PVFS_ENODEV;
+        return(1);
+    }
+
+    sm_p->u.get_config.mntent->fs_id = cur_fs->coll_id;
+    cur_fs->flowproto = sm_p->u.get_config.mntent->flowproto;
+    cur_fs->encoding = sm_p->u.get_config.mntent->encoding;
+
+    js_p->error_code = 0;
+    return 1;
+}
+
+
+static int server_get_config_parent_cleanup(PINT_client_sm *sm_p,
+                                    job_status_s *js_p)
+{
     sm_p->error_code  = js_p->error_code;
     sm_p->op_complete = 1;
 
     return 0;
 }
 
+
 static int server_get_config_comp_fn(
     void *v_p,
     struct PVFS_server_resp *resp_p,
diff -Naur pvfs2-old/include/pvfs2-sysint.h pvfs2-new/include/pvfs2-sysint.h
--- pvfs2-old/include/pvfs2-sysint.h	2005-11-02 14:46:08.000000000 +0100
+++ pvfs2-new/include/pvfs2-sysint.h	2006-03-02 23:20:52.000000000 +0100
@@ -424,6 +424,13 @@
     PVFS_object_ref ref,
     PVFS_credentials *credentials);
 
+PVFS_error PVFS_isys_statfs(
+    PVFS_fs_id fs_id,
+    PVFS_credentials *credentials,
+    PVFS_sysresp_statfs *statfs,
+    PVFS_sys_op_id *op_id,
+    void *user_ptr);
+
 PVFS_error PVFS_sys_statfs(
     PVFS_fs_id fs_id,
     PVFS_credentials *credentials,
diff -Naur pvfs2-old/src/apps/kernel/linux/pvfs2-client-core.c pvfs2-new/src/apps/kernel/linux/pvfs2-client-core.c
--- pvfs2-old/src/apps/kernel/linux/pvfs2-client-core.c	2006-01-18 17:19:03.000000000 +0100
+++ pvfs2-new/src/apps/kernel/linux/pvfs2-client-core.c	2006-03-02 23:20:53.000000000 +0100
@@ -1273,7 +1273,7 @@
 }
 
 
-static PVFS_error service_statfs_request(vfs_request_t *vfs_request)
+static PVFS_error post_statfs_request(vfs_request_t *vfs_request)
 {
     PVFS_error ret = -PVFS_EINVAL;
 
@@ -1281,42 +1281,17 @@
         GOSSIP_CLIENTCORE_DEBUG, "Got a statfs request for fsid %d\n",
         vfs_request->in_upcall.req.statfs.fs_id);
 
-    ret = PVFS_sys_statfs(
+    ret = PVFS_isys_statfs(
         vfs_request->in_upcall.req.statfs.fs_id,
         &vfs_request->in_upcall.credentials,
-        &vfs_request->response.statfs);
-
-    vfs_request->out_downcall.status = ret;
-    vfs_request->out_downcall.type = vfs_request->in_upcall.type;
+        &vfs_request->response.statfs,
+        &vfs_request->op_id, (void *)vfs_request);
 
     if (ret < 0)
     {
-        PVFS_perror_gossip("Statfs failed", ret);
-    }
-    else
-    {
-        PVFS_sysresp_statfs *resp = &vfs_request->response.statfs;
-
-        vfs_request->out_downcall.resp.statfs.block_size =
-            STATFS_DEFAULT_BLOCKSIZE;
-        vfs_request->out_downcall.resp.statfs.blocks_total = (long)
-            (resp->statfs_buf.bytes_total /
-             vfs_request->out_downcall.resp.statfs.block_size);
-        vfs_request->out_downcall.resp.statfs.blocks_avail = (long)
-            (resp->statfs_buf.bytes_available /
-             vfs_request->out_downcall.resp.statfs.block_size);
-        /*
-          these values really represent handle/inode counts
-          rather than an accurate number of files
-        */
-        vfs_request->out_downcall.resp.statfs.files_total = (long)
-            resp->statfs_buf.handles_total_count;
-        vfs_request->out_downcall.resp.statfs.files_avail = (long)
-            resp->statfs_buf.handles_available_count;
+        PVFS_perror_gossip("Posting statfs failed", ret);
     }
-
-    write_inlined_device_response(vfs_request);
-    return 0;
+    return ret;
 }
 
 #ifdef USE_MMAP_RA_CACHE
@@ -1905,6 +1880,24 @@
                 copy_dirents_to_downcall(vfs_request);
             }
             break;
+        case PVFS2_VFS_OP_STATFS:
+            vfs_request->out_downcall.resp.statfs.block_size =
+                STATFS_DEFAULT_BLOCKSIZE;
+            vfs_request->out_downcall.resp.statfs.blocks_total = (long)
+                (vfs_request->response.statfs.statfs_buf.bytes_total /
+                 vfs_request->out_downcall.resp.statfs.block_size);
+            vfs_request->out_downcall.resp.statfs.blocks_avail = (long)
+                (vfs_request->response.statfs.statfs_buf.bytes_available /
+                 vfs_request->out_downcall.resp.statfs.block_size);
+            /*
+              these values really represent handle/inode counts
+              rather than an accurate number of files
+            */
+            vfs_request->out_downcall.resp.statfs.files_total = (long)
+                vfs_request->response.statfs.statfs_buf.handles_total_count;
+            vfs_request->out_downcall.resp.statfs.files_avail = (long)
+                vfs_request->response.statfs.statfs_buf.handles_available_count;
+            break;
         case PVFS2_VFS_OP_RENAME:
             break;
         case PVFS2_VFS_OP_TRUNCATE:
@@ -2252,8 +2245,12 @@
             posted_op = 1;
             ret = post_listxattr_request(vfs_request);
             break;
+        case PVFS2_VFS_OP_STATFS:
+            posted_op = 1;
+            ret = post_statfs_request(vfs_request);
+            break;
             /*
-              NOTE: mount, umount and statfs are blocking
+              NOTE: mount, and umount are blocking
               calls that are serviced inline.
             */
         case PVFS2_VFS_OP_FS_MOUNT:
@@ -2262,9 +2259,6 @@
         case PVFS2_VFS_OP_FS_UMOUNT:
             ret = service_fs_umount_request(vfs_request);
             break;
-        case PVFS2_VFS_OP_STATFS:
-            ret = service_statfs_request(vfs_request);
-            break;
         case PVFS2_VFS_OP_PERF_COUNT:
             ret = service_perf_count_request(vfs_request);
             break;
diff -Naur pvfs2-old/src/client/sysint/client-state-machine.c pvfs2-new/src/client/sysint/client-state-machine.c
--- pvfs2-old/src/client/sysint/client-state-machine.c	2006-01-04 14:48:05.000000000 +0100
+++ pvfs2-new/src/client/sysint/client-state-machine.c	2006-03-02 23:20:53.000000000 +0100
@@ -193,7 +193,8 @@
     {&pvfs2_client_set_eattr_sm},
     {&pvfs2_client_del_eattr_sm},
     {&pvfs2_client_list_eattr_sm},
-    {&pvfs2_client_small_io_sm}
+    {&pvfs2_client_small_io_sm},
+    {&pvfs2_client_statfs_sm}
 };
 
 struct PINT_client_op_entry_s PINT_client_sm_mgmt_table[] =
diff -Naur pvfs2-old/src/client/sysint/client-state-machine.h pvfs2-new/src/client/sysint/client-state-machine.h
--- pvfs2-old/src/client/sysint/client-state-machine.h	2006-01-16 18:06:44.000000000 +0100
+++ pvfs2-new/src/client/sysint/client-state-machine.h	2006-03-02 23:20:53.000000000 +0100
@@ -288,6 +288,7 @@
     int count; 
     PVFS_id_gen_t *addr_array;
     PVFS_error_details *details;
+    PVFS_sysresp_statfs* resp; /* ignored by mgmt functions */
 };
 
 struct PINT_client_mgmt_perf_mon_list_sm
@@ -602,6 +603,7 @@
     PVFS_SYS_DELEATTR              = 15,
     PVFS_SYS_LISTEATTR             = 16,
     PVFS_SYS_SMALL_IO              = 17,
+    PVFS_SYS_STATFS                = 18,
     PVFS_MGMT_SETPARAM_LIST        = 70,
     PVFS_MGMT_NOOP                 = 71,
     PVFS_MGMT_STATFS_LIST          = 72,
@@ -759,10 +761,12 @@
 extern struct PINT_state_machine_s pvfs2_client_set_eattr_sm;
 extern struct PINT_state_machine_s pvfs2_client_del_eattr_sm;
 extern struct PINT_state_machine_s pvfs2_client_list_eattr_sm;
+extern struct PINT_state_machine_s pvfs2_client_statfs_sm;
 
 /* nested state machines (helpers) */
 extern struct PINT_state_machine_s pvfs2_client_lookup_ncache_sm;
 extern struct PINT_state_machine_s pvfs2_client_remove_helper_sm;
+extern struct PINT_state_machine_s pvfs2_client_mgmt_statfs_list_nested_sm;
 
 #include "state-machine.h"
 
diff -Naur pvfs2-old/src/client/sysint/mgmt-statfs-list.sm pvfs2-new/src/client/sysint/mgmt-statfs-list.sm
--- pvfs2-old/src/client/sysint/mgmt-statfs-list.sm	2005-10-06 17:54:12.000000000 +0200
+++ pvfs2-new/src/client/sysint/mgmt-statfs-list.sm	2006-03-26 19:55:59.000000000 +0200
@@ -1,6 +1,9 @@
 /* 
  * (C) 2003 Clemson University and The University of Chicago 
  *
+ * Changes by Acxiom Corporation to add support for nonblocking statfs
+ * Copyright © Acxiom Corporation, 2006.
+ *
  * See COPYING in top-level directory.
  */
 
@@ -31,13 +34,15 @@
     PINT_client_sm *sm_p, job_status_s *js_p);
 static int mgmt_statfs_list_cleanup(
     PINT_client_sm *sm_p, job_status_s *js_p);
+static int mgmt_statfs_list_parent_cleanup(
+    PINT_client_sm *sm_p, job_status_s *js_p);
 
 static int statfs_list_comp_fn(
     void *v_p, struct PVFS_server_resp *resp_p, int index);
 
 %%
 
-machine pvfs2_client_mgmt_statfs_list_sm(
+nested machine pvfs2_client_mgmt_statfs_list_nested_sm(
     setup_msgpair,
     xfer_msgpair,
     cleanup)
@@ -58,6 +63,23 @@
     state cleanup
     {
         run mgmt_statfs_list_cleanup;
+        default => return;
+    }
+}
+
+machine pvfs2_client_mgmt_statfs_list_sm(
+    run_nested,
+    parent_cleanup)
+{
+    state run_nested
+    {
+        jump pvfs2_client_mgmt_statfs_list_nested_sm;
+        default => parent_cleanup;
+    }
+
+    state parent_cleanup
+    {
+        run mgmt_statfs_list_parent_cleanup;
         default => terminate;
     }
 }
@@ -227,10 +249,8 @@
         sm_p->msgarray = NULL;
     }
 
-    sm_p->error_code  = error;
-    sm_p->op_complete = 1;
-
-    return 0;
+    js_p->error_code = error;
+    return 1;
 }
 
 static int statfs_list_comp_fn(void *v_p,
@@ -288,6 +308,16 @@
     return 0;
 }
 
+static int mgmt_statfs_list_parent_cleanup(
+    PINT_client_sm *sm_p, job_status_s *js_p)
+{
+
+    sm_p->error_code  = js_p->error_code;
+    sm_p->op_complete = 1;
+
+    return 0;
+}
+
 /*
  * Local variables:
  *  mode: c
diff -Naur pvfs2-old/src/client/sysint/module.mk.in pvfs2-new/src/client/sysint/module.mk.in
--- pvfs2-old/src/client/sysint/module.mk.in	2006-01-04 15:50:58.000000000 +0100
+++ pvfs2-new/src/client/sysint/module.mk.in	2006-03-02 23:20:53.000000000 +0100
@@ -10,7 +10,6 @@
 	$(DIR)/client-state-machine.c \
 	$(DIR)/mgmt-misc.c \
 	$(DIR)/sys-dist.c \
-	$(DIR)/sys-statfs.c \
 	$(DIR)/error-details.c \
 	$(DIR)/fs-add.c
 
@@ -34,6 +33,7 @@
 	$(DIR)/sys-symlink.c \
 	$(DIR)/sys-readdir.c \
 	$(DIR)/sys-rename.c \
+	$(DIR)/sys-statfs.c \
 	$(DIR)/client-job-timer.c \
 	$(DIR)/perf-count-timer.c \
 	$(DIR)/server-get-config.c \
diff -Naur pvfs2-old/src/client/sysint/sys-create.sm pvfs2-new/src/client/sysint/sys-create.sm
--- pvfs2-old/src/client/sysint/sys-create.sm	2006-02-17 15:09:43.000000000 +0100
+++ pvfs2-new/src/client/sysint/sys-create.sm	2006-03-02 23:20:53.000000000 +0100
@@ -1,8 +1,5 @@
 /* 
- * (C) 2003 Clemson University and The University of Chicago 
- *
- * Changes by Acxiom Corporation to add setgid support
- * Copyright © Acxiom Corporation, 2005.
+ * Copyright © Acxiom Corporation, 2006
  *
  * See COPYING in top-level directory.
  */
diff -Naur pvfs2-old/src/client/sysint/sys-statfs.c pvfs2-new/src/client/sysint/sys-statfs.c
--- pvfs2-old/src/client/sysint/sys-statfs.c	2005-02-07 19:57:36.000000000 +0100
+++ pvfs2-new/src/client/sysint/sys-statfs.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,96 +0,0 @@
-/* 
- * (C) 2003 Clemson University and The University of Chicago 
- *
- * See COPYING in top-level directory.
- */
-
-#include <string.h>
-#include <assert.h>
-
-#include "client-state-machine.h"
-#include "state-machine-fns.h"
-#include "pvfs2-debug.h"
-#include "gossip.h"
-#include "pvfs2-mgmt.h"
-
-
-int PVFS_sys_statfs(
-    PVFS_fs_id fs_id,
-    PVFS_credentials *credentials,
-    PVFS_sysresp_statfs* resp)
-{
-    int num_servers = 0;
-    int ret = -PVFS_EINVAL, i = 0;
-    struct PVFS_mgmt_server_stat* stat_array = NULL;
-    int num_io_servers = 0;
-    PVFS_size min_bytes_available = 0;
-    PVFS_size min_bytes_total = 0;
-
-    ret = PVFS_mgmt_count_servers(
-        fs_id, credentials, (PVFS_MGMT_IO_SERVER|PVFS_MGMT_META_SERVER),
-        &num_servers);
-    if (ret < 0)
-    {
-	return ret;
-    }
-
-    stat_array = (struct PVFS_mgmt_server_stat*)malloc(
-        num_servers*sizeof(struct PVFS_mgmt_server_stat));
-    if (!stat_array)
-    {
-	return(-PVFS_ENOMEM);
-    }
-
-    ret = PVFS_mgmt_statfs_all(fs_id, credentials,
-                               stat_array, &num_servers, NULL);
-    if (ret < 0)
-    {
-	free(stat_array);
-	return(ret);
-    }
-
-    /* aggregate statistics down into one statfs structure */
-    resp->statfs_buf.fs_id = fs_id;
-    resp->statfs_buf.bytes_available = 0;
-    resp->statfs_buf.bytes_total = 0;
-    resp->statfs_buf.handles_available_count = 0;
-    resp->statfs_buf.handles_total_count = 0;
-    for(i=0; i<num_servers; i++)
-    {
-	if(stat_array[i].server_type & PVFS_MGMT_IO_SERVER)
-	{
-	    num_io_servers++;
-	    if(min_bytes_available == 0 || 
-		min_bytes_available > stat_array[i].bytes_available)
-	    {
-		min_bytes_available = stat_array[i].bytes_available;
-	    }
-	    if(min_bytes_total == 0 || 
-		min_bytes_total > stat_array[i].bytes_total)
-	    {
-		min_bytes_total = stat_array[i].bytes_total;
-	    }
-	}
-	resp->statfs_buf.handles_available_count 
-	    += stat_array[i].handles_available_count;
-	resp->statfs_buf.handles_total_count 
-	    += stat_array[i].handles_total_count;
-    }
-    resp->statfs_buf.bytes_available = min_bytes_available*num_io_servers;
-    resp->statfs_buf.bytes_total = min_bytes_total*num_io_servers;
-    resp->server_count = num_servers;
-
-    free(stat_array);
-
-    return(0);
-}
-
-/*
- * Local variables:
- *  mode: c
- *  c-indent-level: 4
- *  c-basic-offset: 4
- * End:
- *
- * vim: ft=c ts=8 sts=4 sw=4 expandtab
- */
diff -Naur pvfs2-old/src/client/sysint/sys-statfs.sm pvfs2-new/src/client/sysint/sys-statfs.sm
--- pvfs2-old/src/client/sysint/sys-statfs.sm	1970-01-01 01:00:00.000000000 +0100
+++ pvfs2-new/src/client/sysint/sys-statfs.sm	2006-03-26 19:55:59.000000000 +0200
@@ -0,0 +1,254 @@
+/* 
+ * (C) 2003 Clemson University and The University of Chicago 
+ *
+ * Changes by Acxiom Corporation to add support for nonblocking statfs
+ * Copyright © Acxiom Corporation, 2006.
+ *
+ * See COPYING in top-level directory.
+ */
+
+/** \file
+ *  \ingroup sysint
+ *
+ *  PVFS2 system interface routines for statfs.
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include "client-state-machine.h"
+#include "pvfs2-debug.h"
+#include "job.h"
+#include "gossip.h"
+#include "str-utils.h"
+#include "pvfs2-mgmt.h"
+#include "pint-servreq.h"
+#include "pint-cached-config.h"
+#include "PINT-reqproto-encode.h"
+
+extern job_context_id pint_client_sm_context;
+
+/* state function prototypes */
+static int sys_statfs_cleanup(
+    PINT_client_sm *sm_p, job_status_s *js_p);
+
+
+%%
+
+machine pvfs2_client_statfs_sm(
+    run_nested,
+    cleanup)
+{
+    state run_nested
+    {
+        jump pvfs2_client_mgmt_statfs_list_nested_sm;
+        default => cleanup;
+    }
+
+    state cleanup
+    {
+        run sys_statfs_cleanup;
+        default => return;
+    }
+}
+
+%%
+
+/** Initiate retrieval of file system statistics.
+ */
+PVFS_error PVFS_isys_statfs(
+    PVFS_fs_id fs_id,
+    PVFS_credentials *credentials,
+    PVFS_sysresp_statfs *resp,
+    PVFS_sys_op_id *op_id,
+    void *user_ptr)
+{
+    PINT_client_sm *sm_p = NULL;
+    struct server_configuration_s *server_config = NULL;
+    int ret = -1;
+
+    gossip_debug(GOSSIP_CLIENT_DEBUG,
+                 "PVFS_isys_statfs entered\n");
+
+    sm_p = (PINT_client_sm *)malloc(sizeof(*sm_p));
+    if (sm_p == NULL)
+    {
+        return -PVFS_ENOMEM;
+    }
+    memset(sm_p, 0, sizeof(*sm_p));
+
+    /* count the number of servers */
+    server_config = PINT_get_server_config_struct(fs_id);
+    assert(server_config);
+    ret = PINT_cached_config_count_servers(
+        server_config, fs_id,  PVFS_MGMT_IO_SERVER|PVFS_MGMT_META_SERVER,
+        &sm_p->u.statfs_list.count);
+    PINT_put_server_config_struct(server_config);
+    if (ret < 0)
+    {
+        free(sm_p);
+	return ret;
+    }
+
+    /* allocate storage for addresses and statfs buffers */
+    sm_p->u.statfs_list.addr_array = (PVFS_BMI_addr_t *)malloc(
+        sm_p->u.statfs_list.count*sizeof(PVFS_BMI_addr_t));
+    if (sm_p->u.statfs_list.addr_array == NULL)
+    {
+        free(sm_p);
+        return -PVFS_ENOMEM;
+    }
+
+    sm_p->u.statfs_list.stat_array = (struct PVFS_mgmt_server_stat*)malloc(
+        sm_p->u.statfs_list.count*sizeof(struct PVFS_mgmt_server_stat));
+    if (!sm_p->u.statfs_list.stat_array)
+    {
+        free(sm_p->u.statfs_list.addr_array);
+        free(sm_p);
+	return(-PVFS_ENOMEM);
+    }
+
+    /* generate default list of servers */
+    server_config = PINT_get_server_config_struct(fs_id);
+    assert(server_config);
+    ret = PINT_cached_config_get_server_array(
+        server_config, fs_id, PVFS_MGMT_IO_SERVER|PVFS_MGMT_META_SERVER,
+        sm_p->u.statfs_list.addr_array, &sm_p->u.statfs_list.count);
+    PINT_put_server_config_struct(server_config);
+    if (ret < 0)
+    {
+        free(sm_p->u.statfs_list.addr_array);
+        free(sm_p->u.statfs_list.stat_array);
+        free(sm_p);
+	return ret;
+    }
+
+    PINT_init_msgarray_params(&sm_p->msgarray_params, fs_id);
+    PINT_init_sysint_credentials(sm_p->cred_p, credentials);
+    sm_p->u.statfs_list.fs_id = fs_id;
+    sm_p->u.statfs_list.details = NULL;
+    sm_p->u.statfs_list.resp = resp;
+
+    memset(sm_p->u.statfs_list.stat_array, 0,
+           (sm_p->u.statfs_list.count * sizeof(struct PVFS_mgmt_server_stat)));
+
+    sm_p->msgarray_count = sm_p->u.statfs_list.count;
+    sm_p->msgarray = (PINT_sm_msgpair_state *)malloc(
+        (sm_p->msgarray_count * sizeof(PINT_sm_msgpair_state)));
+    if (sm_p->msgarray == NULL)
+    {
+        PVFS_util_release_credentials(sm_p->cred_p);
+        free(sm_p->u.statfs_list.addr_array);
+        free(sm_p->u.statfs_list.stat_array);
+        free(sm_p);
+        return -PVFS_ENOMEM;
+    }
+
+    return PINT_client_state_machine_post(
+        sm_p, PVFS_SYS_STATFS, op_id, user_ptr);
+}
+
+/** Obtain file system statistics.
+ */
+PVFS_error PVFS_sys_statfs(
+    PVFS_fs_id fs_id,
+    PVFS_credentials *credentials,
+    PVFS_sysresp_statfs* resp)
+{
+    PVFS_error ret = -PVFS_EINVAL, error = 0;
+    PVFS_sys_op_id op_id;
+
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_sys_statfs entered\n");
+
+    ret = PVFS_isys_statfs(
+        fs_id, credentials, resp, &op_id, NULL);
+
+    if (ret)
+    {
+        PVFS_perror_gossip("PVFS_isys_statfs call", ret);
+        error = ret;
+    }
+    else
+    {
+        ret = PINT_sys_wait(op_id, "statfs", &error);
+        if (ret)
+        {
+            PVFS_perror_gossip("PVFS_sys_wait call", ret);
+            error = ret;
+        }
+    }
+
+    gossip_debug(GOSSIP_CLIENT_DEBUG,
+                 "PVFS_sys_statfs completed\n");
+
+    PINT_sys_release(op_id);
+    return error;
+}
+
+static int sys_statfs_cleanup(PINT_client_sm *sm_p,
+                                          job_status_s *js_p)
+{
+    int i;
+    int num_io_servers = 0;
+    PVFS_size min_bytes_available = 0;
+    PVFS_size min_bytes_total = 0;
+    
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "statfs state: cleanup\n");
+
+    sm_p->error_code = js_p->error_code;
+
+    /* aggregate statistics down into one statfs structure */
+    sm_p->u.statfs_list.resp->statfs_buf.fs_id = sm_p->u.statfs_list.fs_id;
+    sm_p->u.statfs_list.resp->statfs_buf.bytes_available = 0;
+    sm_p->u.statfs_list.resp->statfs_buf.bytes_total = 0;
+    sm_p->u.statfs_list.resp->statfs_buf.handles_available_count = 0;
+    sm_p->u.statfs_list.resp->statfs_buf.handles_total_count = 0;
+    for(i=0; i<sm_p->u.statfs_list.count; i++)
+    {
+	if(sm_p->u.statfs_list.stat_array[i].server_type & PVFS_MGMT_IO_SERVER)
+	{
+	    num_io_servers++;
+	    if(min_bytes_available == 0 || 
+		min_bytes_available > sm_p->u.statfs_list.stat_array[i].bytes_available)
+	    {
+		min_bytes_available = sm_p->u.statfs_list.stat_array[i].bytes_available;
+	    }
+	    if(min_bytes_total == 0 || 
+		min_bytes_total > sm_p->u.statfs_list.stat_array[i].bytes_total)
+	    {
+		min_bytes_total = sm_p->u.statfs_list.stat_array[i].bytes_total;
+	    }
+	}
+	sm_p->u.statfs_list.resp->statfs_buf.handles_available_count 
+	    += sm_p->u.statfs_list.stat_array[i].handles_available_count;
+	sm_p->u.statfs_list.resp->statfs_buf.handles_total_count 
+	    += sm_p->u.statfs_list.stat_array[i].handles_total_count;
+    }
+    sm_p->u.statfs_list.resp->statfs_buf.bytes_available = 
+        min_bytes_available*num_io_servers;
+    sm_p->u.statfs_list.resp->statfs_buf.bytes_total = 
+        min_bytes_total*num_io_servers;
+    sm_p->u.statfs_list.resp->server_count = sm_p->u.statfs_list.count;
+
+    if(sm_p->u.statfs_list.stat_array)
+    {
+        free(sm_p->u.statfs_list.stat_array);
+    }
+    if(sm_p->u.statfs_list.addr_array)
+    {
+        free(sm_p->u.statfs_list.addr_array);
+    }
+
+    sm_p->op_complete = 1;
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  mode: c
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
_______________________________________________
Pvfs2-developers mailing list
Pvfs2-developers@beowulf-underground.org
http://www.beowulf-underground.org/mailman/listinfo/pvfs2-developers

Reply via email to