Index: include/pvfs2-sysint.h
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/include/pvfs2-sysint.h,v
retrieving revision 1.71
diff -u -a -p -r1.71 pvfs2-sysint.h
--- include/pvfs2-sysint.h	26 Sep 2006 03:44:14 -0000	1.71
+++ include/pvfs2-sysint.h	25 May 2007 02:58:13 -0000
@@ -349,6 +349,7 @@ PVFS_error PVFS_isys_create(
     PVFS_sys_attr attr,
     const PVFS_credentials *credentials,
     PVFS_sys_dist *dist,
+    PVFS_sys_layout *layout,
     PVFS_sysresp_create *resp,
     PVFS_sys_op_id *op_id,
     void *user_ptr);
@@ -359,6 +360,7 @@ PVFS_error PVFS_sys_create(
     PVFS_sys_attr attr,
     const PVFS_credentials *credentials,
     PVFS_sys_dist *dist,
+    PVFS_sys_layout *layout,
     PVFS_sysresp_create *resp);
 
 PVFS_error PVFS_isys_remove(
Index: include/pvfs2-types.h
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/include/pvfs2-types.h,v
retrieving revision 1.137.6.1
diff -u -a -p -r1.137.6.1 pvfs2-types.h
--- include/pvfs2-types.h	5 Apr 2007 15:49:35 -0000	1.137.6.1
+++ include/pvfs2-types.h	25 May 2007 02:56:26 -0000
@@ -171,6 +171,50 @@ endecode_fields_1a(
     uint32_t, extent_count,
     PVFS_handle_extent, extent_array);
 
+/* Layout algorithm for converting from server lists in the config
+ * to a list of servers to use to store datafiles for a file.
+ */
+enum PVFS_sys_layout_algorithm
+{
+    /* order the datafiles according to the server list */
+    PVFS_SYS_LAYOUT_NONE = 1,
+
+    /* choose the first datafile randomly, and then round-robin in-order */
+    PVFS_SYS_LAYOUT_ROUND_ROBIN = 2,
+
+    /* choose each datafile randomly */
+    PVFS_SYS_LAYOUT_RANDOM = 3,
+
+    /* order the datafiles based on the list specified */
+    PVFS_SYS_LAYOUT_LIST = 4
+};
+
+/* The list of datafile servers that can be passed into PVFS_sys_create
+ * to specify the exact layout of a file.  The count parameter will override
+ * the num_dfiles field in the attribute.
+ */
+struct PVFS_sys_server_list
+{
+    int32_t count;
+    PVFS_BMI_addr_t *servers;
+};
+
+/* The server laout struct passed to PVFS_sys_create.  The algorithm
+ * specifies how the servers are chosen to layout the file.  If the
+ * algorithm is set to PVFS_SYS_LAYOUT_LIST, the server_list parameter
+ * is used to determine the layout.
+ */
+typedef struct PVFS_sys_layout_s
+{
+    /* The algorithm to use to layout the file */
+    enum PVFS_sys_layout_algorithm algorithm;
+
+    /* The server list specified if the
+     * PVFS_SYS_LAYOUT_LIST algorithm is chosen.
+     */
+    struct PVFS_sys_server_list server_list;
+} PVFS_sys_layout;
+
 /* predefined special values for types */
 #define PVFS_HANDLE_NULL     ((PVFS_handle)0)
 #define PVFS_FS_ID_NULL       ((PVFS_fs_id)0)
Index: src/apps/admin/pvfs2-cp.c
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/apps/admin/pvfs2-cp.c,v
retrieving revision 1.23.10.2
diff -u -a -p -r1.23.10.2 pvfs2-cp.c
--- src/apps/admin/pvfs2-cp.c	13 Jan 2007 01:22:11 -0000	1.23.10.2
+++ src/apps/admin/pvfs2-cp.c	25 May 2007 05:06:37 -0000
@@ -628,7 +628,7 @@ static int generic_open(file_object *obj
             
 		ret = PVFS_sys_create(entry_name, parent_ref, 
                                       obj->u.pvfs2.attr, credentials,
-                                      new_dist, &resp_create);
+                                      new_dist, NULL, &resp_create);
 		if (ret < 0)
 		{
 		    PVFS_perror("PVFS_sys_create", ret); 
Index: src/apps/admin/pvfs2-touch.c
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/apps/admin/pvfs2-touch.c,v
retrieving revision 1.3
diff -u -a -p -r1.3 pvfs2-touch.c
--- src/apps/admin/pvfs2-touch.c	1 Aug 2006 00:27:11 -0000	1.3
+++ src/apps/admin/pvfs2-touch.c	25 May 2007 15:54:37 -0000
@@ -17,6 +17,7 @@
 #include <getopt.h>
 
 #include "pvfs2.h"
+#include "pvfs2-mgmt.h"
 #include "str-utils.h"
 
 #ifndef PVFS2_VERSION
@@ -37,6 +38,9 @@ int main(int argc, char **argv)
 {
     int ret = -1, i = 0;
     struct options *user_opts = NULL;
+    PVFS_BMI_addr_t *io_servers;
+    int io_server_count;
+    PVFS_sys_layout layout;
 
     /* look at command line arguments */
     user_opts = parse_args(argc, argv);
@@ -117,11 +121,67 @@ int main(int argc, char **argv)
 
         parent_ref = resp_lookup.ref;
 
+        rc = PVFS_mgmt_count_servers(parent_ref.fs_id,
+                                     &credentials,
+                                     PVFS_MGMT_IO_SERVER,
+                                     &io_server_count);
+        if(rc)
+        {
+            fprintf(stderr,
+                    "Error: An error occurred while trying to get "
+                    "the server count\n");
+            PVFS_perror("PVFS_mgmt_count_servers", rc);
+            ret = -1;
+            break;
+        }
+
+        io_servers = malloc(sizeof(PVFS_BMI_addr_t) * io_server_count);
+        if(!io_servers)
+        {
+            PVFS_perror("Failed to allocate io server array", -PVFS_ENOMEM);
+            ret = -1;
+            break;
+        }
+
+        rc = PVFS_mgmt_get_server_array(parent_ref.fs_id,
+                                        &credentials,
+                                        PVFS_MGMT_IO_SERVER,
+                                        io_servers,
+                                        &io_server_count);
+        if(rc)
+        {
+            fprintf(stderr,
+                    "Error: An error occurred while trying to get "
+                    "the server array\n");
+            PVFS_perror("PVFS_mgmt_get_server_array", rc);
+            ret = -1;
+            break;
+        }
+
+        layout.algorithm = PVFS_SYS_LAYOUT_LIST;
+        /* set count to number of evens */
+        layout.server_list.count = (int)(io_server_count / 2);
+        layout.server_list.servers = malloc(sizeof(PVFS_BMI_addr_t) *
+                                            layout.server_list.count);
+        if(!layout.server_list.servers)
+        {
+            PVFS_perror("Failed to allocate server list", -PVFS_ENOMEM);
+            ret = -1;
+            break;
+        }
+
+        for(i = 0; i < layout.server_list.count; ++i)
+        {
+            layout.server_list.servers[i] = 
+                io_servers[(io_server_count - 1 - i * 2)];
+        }
+
         rc = PVFS_sys_create(filename,
                              parent_ref,
                              attr,
                              &credentials,
                              NULL,
+                             &layout,
                              &resp_create);
         if (rc)
         {
Index: src/apps/kernel/linux/pvfs2-client-core.c
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/apps/kernel/linux/pvfs2-client-core.c,v
retrieving revision 1.77.6.6
diff -u -a -p -r1.77.6.6 pvfs2-client-core.c
--- src/apps/kernel/linux/pvfs2-client-core.c	5 Apr 2007 15:49:35 -0000	1.77.6.6
+++ src/apps/kernel/linux/pvfs2-client-core.c	25 May 2007 05:08:07 -0000
@@ -504,7 +504,7 @@ static PVFS_error post_create_request(vf
         vfs_request->in_upcall.req.create.d_name,
         vfs_request->in_upcall.req.create.parent_refn,
         vfs_request->in_upcall.req.create.attributes,
-        &vfs_request->in_upcall.credentials, NULL,
+        &vfs_request->in_upcall.credentials, NULL, NULL,
         &vfs_request->response.create,
         &vfs_request->op_id, (void *)vfs_request);
 
Index: src/client/sysint/client-state-machine.h
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/client/sysint/client-state-machine.h,v
retrieving revision 1.165.10.1
diff -u -a -p -r1.165.10.1 client-state-machine.h
--- src/client/sysint/client-state-machine.h	5 Apr 2007 15:49:37 -0000	1.165.10.1
+++ src/client/sysint/client-state-machine.h	25 May 2007 03:14:22 -0000
@@ -83,6 +83,7 @@ struct PINT_client_create_sm
     int stored_error_code;
 
     PINT_dist *dist;
+    PVFS_sys_layout layout;
     PVFS_handle metafile_handle;
     PVFS_handle *datafile_handles;
     PVFS_BMI_addr_t *data_server_addrs;
Index: src/client/sysint/sys-create.sm
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/client/sysint/sys-create.sm,v
retrieving revision 1.99.6.1
diff -u -a -p -r1.99.6.1 sys-create.sm
--- src/client/sysint/sys-create.sm	13 Dec 2006 19:53:34 -0000	1.99.6.1
+++ src/client/sysint/sys-create.sm	25 May 2007 06:44:41 -0000
@@ -228,11 +228,11 @@ PVFS_error PVFS_isys_create(
     PVFS_sys_attr attr,
     const PVFS_credentials *credentials,
     PVFS_sys_dist *dist,
+    PVFS_sys_layout *layout,
     PVFS_sysresp_create *resp,
     PVFS_sys_op_id *op_id,
     void *user_ptr)
 {
-    int num_dfiles_req = 0;
     PVFS_error ret = -PVFS_EINVAL;
     PINT_client_sm *sm_p = NULL;
 
@@ -284,6 +284,29 @@ PVFS_error PVFS_isys_create(
     sm_p->u.create.stored_error_code = 0;
     sm_p->u.create.retry_count = 0;
 
+    /* copy layout to sm struct */
+    if(layout)
+    {
+        sm_p->u.create.layout.algorithm = layout->algorithm;
+        if(layout->algorithm == PVFS_SYS_LAYOUT_LIST)
+        {
+            sm_p->u.create.layout.server_list.count = layout->server_list.count;
+            sm_p->u.create.layout.server_list.servers =
+                malloc(layout->server_list.count * sizeof(PVFS_BMI_addr_t));
+            if(!sm_p->u.create.layout.server_list.servers)
+            {
+                return -PVFS_ENOMEM;
+            }
+            memcpy(sm_p->u.create.layout.server_list.servers,
+                   layout->server_list.servers,
+                   layout->server_list.count * sizeof(PVFS_BMI_addr_t));
+        }
+    }
+    else
+    {
+        sm_p->u.create.layout.algorithm = PVFS_SYS_LAYOUT_ROUND_ROBIN;
+    }
+
     sm_p->object_ref = parent_ref;
 
     /* If the user specifies a distribution use that
@@ -304,51 +327,6 @@ PVFS_error PVFS_isys_create(
         }
         sm_p->u.create.dist->params = dist->params;
     }
-    else
-    {
-        /* Get the default distribution */
-        sm_p->u.create.dist = get_default_distribution(sm_p->parent_ref.fs_id);
-        if (!sm_p->u.create.dist)
-        {
-            free(sm_p);
-            return -PVFS_ENOMEM;
-        }
-    }
-    
-    /* If an application hint has been provided, use that to request dfile
-       else, if a tabfile hint has been provided, use that instead*/
-    num_dfiles_req = 0;
-    if (attr.mask & PVFS_ATTR_SYS_DFILE_COUNT)
-    {
-        num_dfiles_req = attr.dfile_count;
-    }
-    else
-    {
-        /* Check the mount options */
-        int rc;
-        struct PVFS_sys_mntent mntent;
-
-        rc = PVFS_util_get_mntent_copy(sm_p->object_ref.fs_id, &mntent);
-        if (0 == rc)
-        {
-            num_dfiles_req = mntent.default_num_dfiles;
-        }
-    }
-
-    /* Determine the number of dfiles, passing in client hints to
-       override any server hints */
-    ret = PINT_cached_config_get_num_dfiles(sm_p->object_ref.fs_id,
-                                            sm_p->u.create.dist,
-                                            num_dfiles_req,
-                                            &sm_p->u.create.num_data_files);
-
-    if (ret < 0)
-    {
-        gossip_err("Failed to get number of data servers\n");
-        free(sm_p);
-        return ret;
-    }
-
     gossip_debug(
         GOSSIP_CLIENT_DEBUG, "Creating file %s under %llu, %d\n",
         object_name, llu(parent_ref.handle), parent_ref.fs_id);
@@ -365,6 +343,7 @@ PVFS_error PVFS_sys_create(
     PVFS_sys_attr attr,
     const PVFS_credentials *credentials,
     PVFS_sys_dist *dist,
+    PVFS_sys_layout *layout,
     PVFS_sysresp_create *resp)
 {
     PVFS_error ret = -PVFS_EINVAL, error = 0;
@@ -373,7 +352,7 @@ PVFS_error PVFS_sys_create(
     gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_sys_create entered\n");
 
     ret = PVFS_isys_create(object_name, parent_ref, attr, credentials,
-                           dist, resp, &op_id, NULL);
+                           dist, layout, resp, &op_id, NULL);
     if (ret)
     {
         PVFS_perror_gossip("PVFS_isys_create call", ret);
@@ -627,24 +606,6 @@ static int create_datafiles_setup_msgpai
 
     js_p->error_code = 0;
 
-    memset(&sm_p->msgpair, 0, sizeof(PINT_sm_msgpair_state));
-
-    /* allocate msgarray and set msgarray_count */
-    if (sm_p->msgarray && (sm_p->msgarray != &(sm_p->msgpair)))
-    {
-        free(sm_p->msgarray);
-    }
-    sm_p->msgarray = (PINT_sm_msgpair_state *)malloc(
-        (sm_p->u.create.num_data_files *
-         sizeof(PINT_sm_msgpair_state)));
-    if (sm_p->msgarray == NULL)
-    {
-        gossip_err("create: failed to allocate msgarray\n");
-        js_p->error_code = -PVFS_ENOMEM;
-        return 1;
-    }
-    sm_p->msgarray_count = sm_p->u.create.num_data_files;
-
     /* allocate handle extent array objects */
     if (sm_p->u.create.io_handle_extent_array == NULL)
     {
@@ -675,12 +636,19 @@ static int create_datafiles_setup_msgpai
     server_config = PINT_get_server_config_struct(
         sm_p->object_ref.fs_id);
 
-    ret = PINT_cached_config_get_next_io(
+    ret = PINT_cached_config_map_servers(
         server_config,
         sm_p->object_ref.fs_id,
-        sm_p->u.create.num_data_files,
+        &sm_p->u.create.num_data_files,
+        &sm_p->u.create.layout,
         sm_p->u.create.data_server_addrs,
         sm_p->u.create.io_handle_extent_array);
+    if(ret < 0)
+    {
+        gossip_err("create: failed to map the layout to a set of IO servers\n");
+        js_p->error_code = ret;
+        return 1;
+    }
 
     PINT_put_server_config_struct(server_config);
 
@@ -690,7 +658,24 @@ static int create_datafiles_setup_msgpai
         js_p->error_code = ret;
         return 1;
     }
-    
+
+    memset(&sm_p->msgpair, 0, sizeof(PINT_sm_msgpair_state));
+
+    /* allocate msgarray and set msgarray_count */
+    if (sm_p->msgarray && (sm_p->msgarray != &(sm_p->msgpair)))
+    {
+        free(sm_p->msgarray);
+    }
+    sm_p->msgarray = (PINT_sm_msgpair_state *)malloc(
+        (sm_p->u.create.num_data_files * sizeof(PINT_sm_msgpair_state)));
+    if (sm_p->msgarray == NULL)
+    {
+        gossip_err("create: failed to allocate msgarray\n");
+        js_p->error_code = -PVFS_ENOMEM;
+        return 1;
+    }
+    sm_p->msgarray_count = sm_p->u.create.num_data_files;
+
     /* for each datafile, prepare to post a create send/recv pair */
     for(i = 0; i < sm_p->u.create.num_data_files; i++)
     {
@@ -716,11 +701,6 @@ static int create_datafiles_setup_msgpai
         msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
         msg_p->comp_fn = create_datafiles_comp_fn;
         msg_p->svr_addr = sm_p->u.create.data_server_addrs[i];
-
-        gossip_debug(GOSSIP_VARSTRIP_DEBUG, 
-                     "Data file number: %d - Server name: %s\n",
-                     i, PVFS_mgmt_map_addr(msg_p->fs_id, sm_p->cred_p,
-                                           msg_p->svr_addr, NULL));
     }
     return 1;
 }
@@ -1042,8 +1022,8 @@ static int create_cleanup(PINT_client_sm
 static int create_parent_getattr_inspect(
     PINT_client_sm *sm_p, job_status_s *js_p)
 {
+    int num_dfiles_req = 0;
     PVFS_object_attr *attr = NULL;
-    int num_dfiles_requested_override = 0;
     PINT_dist *current_dist; 
     int ret = 0;
 
@@ -1073,99 +1053,133 @@ static int create_parent_getattr_inspect
         attr->u.dir.hint.dist_name_len,
         attr->u.dir.hint.dist_params_len);
 
-    num_dfiles_requested_override = attr->u.dir.hint.dfile_count;
-    /* override the # of data files for this create */
-    if (num_dfiles_requested_override > 0)
-    {
-        /* Determine the number of dfiles */
-        PINT_cached_config_get_num_dfiles(sm_p->object_ref.fs_id,
-                sm_p->u.create.dist,
-                num_dfiles_requested_override,
-                &sm_p->u.create.num_data_files);
-    }
-    gossip_debug(GOSSIP_CLIENT_DEBUG, "Setting number of datafiles to %d [requested %d]\n", 
-        sm_p->u.create.num_data_files, num_dfiles_requested_override);
-    current_dist = sm_p->u.create.dist;
     /* We have an overriding distribution name for this directory.. honor that */
-    if (attr->u.dir.hint.dist_name_len > 0)
+    if (!sm_p->u.create.dist && attr->u.dir.hint.dist_name_len > 0)
     {
         /* switch it only if it is different! */
-        if (strcmp(attr->u.dir.hint.dist_name, current_dist->dist_name))
+        sm_p->u.create.dist = PINT_dist_create(attr->u.dir.hint.dist_name);
+        if (!sm_p->u.create.dist)
         {
-            PINT_dist *new_dist = NULL;
-            new_dist = PINT_dist_create(attr->u.dir.hint.dist_name);
-            if (new_dist)
-            {
-                gossip_debug(GOSSIP_CLIENT_DEBUG, "Overridding distribution name to %s instead of %s\n",
-                    attr->u.dir.hint.dist_name,
-                    current_dist->dist_name);
-                PINT_dist_free(current_dist);
-                sm_p->u.create.dist = new_dist;
-                current_dist = new_dist;
-            }
-            else
-            {
-                gossip_debug(GOSSIP_CLIENT_DEBUG, "Could not override distribution name with %s instead of %s\n",
-                    attr->u.dir.hint.dist_name,
-                    current_dist->dist_name);
-            }
-        }
-        else {
-            gossip_debug(GOSSIP_CLIENT_DEBUG, "retaining current distribution name %s\n",
-                current_dist->dist_name);
+            js_p->error_code = -PVFS_ENOMEM;
+            return 1;
         }
-    }
+        gossip_debug(GOSSIP_CLIENT_DEBUG, 
+                     "Using dir hint distribution %s\n",
+                     attr->u.dir.hint.dist_name);
 
-    /* okay, we might need to override some dist params as well */
-    if (attr->u.dir.hint.dist_params_len > 0)
-    {
-        /* We have a series of comma separated key:val strings */
-        char **key, **val;
-        int64_t tmp_val;
-        int nparams = 0;
-
-        /* ignore parse errors! */
-        if (PINT_split_keyvals(attr->u.dir.hint.dist_params,
-            &nparams, &key, &val) == 0)
+        /* We might need to override some dist params as well */
+        if (attr->u.dir.hint.dist_params_len > 0)
         {
-            int i;
-            for (i = 0; i < nparams; i++)
+            /* We have a series of comma separated key:val strings */
+            char **key, **val;
+            int64_t tmp_val;
+            int nparams = 0;
+
+            /* ignore parse errors! */
+            if (PINT_split_keyvals(attr->u.dir.hint.dist_params,
+                                   &nparams, &key, &val) == 0)
             {
-                gossip_debug(GOSSIP_CLIENT_DEBUG, "distribution parameter %s, value %s\n",
-                    key[i], val[i]);
-                /* NOTE: just as in server-config.c when parsing "Param" and
-                 * "Value" fields, we will assume that all values are 64 bit
-                 * integers.  The only difference here is that we scan
-                 * directly into a 64 bit integer, rather than converting
-                 * from the int format that dotconf supports.
-                 */
-                ret = sscanf(val[i], SCANF_lld, &tmp_val);
-                if(ret != 1)
-                {
-                    gossip_err("Error: unsupported type for distribution parameter %s, value %s found in directory hints.\n", 
-                        key[i], val[i]);
-                    gossip_err("Error: continuing anyway.\n");
-                }
-                else
+                int i;
+                for (i = 0; i < nparams; i++)
                 {
-                    if(current_dist->methods->set_param(current_dist->dist_name,
-                        current_dist->params,
-                        key[i],
-                        &tmp_val))
+                    gossip_debug(GOSSIP_CLIENT_DEBUG, 
+                                 "distribution parameter %s, value %s\n",
+                                 key[i], val[i]);
+                    /* NOTE: just as in server-config.c when parsing "Param" and
+                     * "Value" fields, we will assume that all values are 64 bit
+                     * integers.  The only difference here is that we scan
+                     * directly into a 64 bit integer, rather than converting
+                     * from the int format that dotconf supports.
+                     */
+                    ret = sscanf(val[i], SCANF_lld, &tmp_val);
+                    if(ret != 1)
                     {
-
-                        gossip_err("Error: could not override hinted distribution parameter %s, value %s found in directory hints\n",
-                            key[i],
-                            val[i]);
+                        gossip_err(
+                            "Error: unsupported type for distribution "
+                            "parameter %s, value %s found in directory hints.\n",
+                            key[i], val[i]);
+                        gossip_err("Error: continuing anyway.\n");
+                    }
+                    else
+                    {
+                        if(current_dist->methods->set_param(
+                                current_dist->dist_name,
+                                current_dist->params,
+                                key[i],
+                                &tmp_val))
+                        {
+
+                            gossip_err("Error: could not override hinted "
+                                       "distribution parameter %s, value %s "
+                                       "found in directory hints\n",
+                                       key[i], val[i]);
+                        }
                     }
-                 }
-                 free(key[i]);
-                 free(val[i]);
+                    free(key[i]);
+                    free(val[i]);
+                }
+                free(key);
+                free(val);
             }
-            free(key);
-            free(val);
         }
     }
+
+    /* If the dir hint doesn't have a dist set, use 
+     * the default for the filesystem
+     */
+    if(!sm_p->u.create.dist)
+    {
+        /* Get the default distribution */
+        sm_p->u.create.dist = get_default_distribution(sm_p->parent_ref.fs_id);
+        if (!sm_p->u.create.dist)
+        {
+            free(sm_p);
+            return -PVFS_ENOMEM;
+        }
+    }
+
+    /* If an application hint has been provided, use that to request dfile
+       else, if a tabfile hint has been provided, use that instead*/
+    num_dfiles_req = 0;
+    if (sm_p->u.create.sys_attr.mask & PVFS_ATTR_SYS_DFILE_COUNT)
+    {
+        num_dfiles_req = sm_p->u.create.sys_attr.dfile_count;
+    }
+
+    else if(attr->u.dir.hint.dfile_count > 0)
+    {
+        num_dfiles_req = attr->u.dir.hint.dfile_count;
+    }
+    else
+    {
+        /* Check the mount options */
+        int rc;
+        struct PVFS_sys_mntent mntent;
+
+        rc = PVFS_util_get_mntent_copy(sm_p->object_ref.fs_id, &mntent);
+        if (0 == rc)
+        {
+            num_dfiles_req = mntent.default_num_dfiles;
+        }
+    }
+
+    /* Determine the number of dfiles, passing in client hints to
+       override any server hints */
+    ret = PINT_cached_config_get_num_dfiles(sm_p->object_ref.fs_id,
+                                            sm_p->u.create.dist,
+                                            num_dfiles_req,
+                                            &sm_p->u.create.num_data_files);
+
+    if (ret < 0)
+    {
+        gossip_err("Failed to get number of data servers\n");
+        js_p->error_code = ret;
+        return 1;
+    }
+    gossip_debug(GOSSIP_CLIENT_DEBUG, 
+                 "Setting number of datafiles to %d [requested %d]\n", 
+                 sm_p->u.create.num_data_files, num_dfiles_req);
+
     return(1);
 }
 
Index: src/common/misc/pint-cached-config.c
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/common/misc/pint-cached-config.c,v
retrieving revision 1.19.20.1
diff -u -a -p -r1.19.20.1 pint-cached-config.c
--- src/common/misc/pint-cached-config.c	13 Dec 2006 19:54:00 -0000	1.19.20.1
+++ src/common/misc/pint-cached-config.c	25 May 2007 15:41:52 -0000
@@ -388,6 +388,214 @@ int PINT_cached_config_get_next_meta(
     return ret;
 }
 
+int PINT_cached_config_get_extents(
+    struct server_configuration_s *config,
+    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, PINT_config_get_host_addr_ptr(
+                config, cur_mapping->alias_mapping->host_alias));
+        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(
+    struct server_configuration_s *config,
+    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, j, ret;
+    int start_index = -1;
+    int index;
+
+    assert(config);
+    assert(inout_num_datafiles);
+    assert(handle_extent_array);
+
+    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)
+            {
+                ret = PINT_cached_config_get_extents(
+                    config, 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], PINT_config_get_host_addr_ptr(
+                        config, cur_mapping->alias_mapping->host_alias));
+                if (ret)
+                {
+                    return ret;
+                }
+
+                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:
+
+            /* all random */
+            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
+             */
+            for(i = 0; i < *inout_num_datafiles; ++i)
+            {
+                index = rand() % *inout_num_datafiles;
+                for(j = 0; j < i; ++j)
+                {
+                    if(addr_array[index] == 0)
+                    {
+                        cur_mapping = PINT_llist_head(server_list);
+                        assert(cur_mapping);
+                        server_list = PINT_llist_next(server_list);
+
+                        /* found an unused index */
+                        ret = BMI_addr_lookup(
+                            &addr_array[index],
+                            PINT_config_get_host_addr_ptr(
+                                config,
+                                cur_mapping->alias_mapping->host_alias));
+                        if (ret)
+                        {
+                            return ret;
+                        }
+
+                        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
Index: src/common/misc/pint-cached-config.h
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/common/misc/pint-cached-config.h,v
retrieving revision 1.9
diff -u -a -p -r1.9 pint-cached-config.h
--- src/common/misc/pint-cached-config.h	18 Aug 2006 15:32:39 -0000	1.9
+++ src/common/misc/pint-cached-config.h	25 May 2007 03:03:53 -0000
@@ -32,6 +32,11 @@ int PINT_handle_load_mapping(
     struct server_configuration_s *config,
     struct filesystem_configuration_s *fs);
 
+int PINT_cached_config_map_alias(
+    struct server_configuration_s *config,
+    const char *alias,
+    PVFS_BMI_addr_t *addr);
+
 int PINT_cached_config_get_next_meta(
     struct server_configuration_s *config,
     PVFS_fs_id fsid,
@@ -67,7 +72,21 @@ 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(
+    struct server_configuration_s *config,
+    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_extents(
+    struct server_configuration_s *config,
+    PVFS_fs_id fsid,
+    PVFS_BMI_addr_t *addr,
+    PVFS_handle_extent_array *handle_extents);
 
 int PINT_cached_config_get_num_dfiles(
     PVFS_fs_id fsid,
Index: src/proto/PINT-le-bytefield.c
===================================================================
RCS file: /home/slang/mirror-pvfs-cvs/projects/cvsroot/pvfs2/src/proto/PINT-le-bytefield.c,v
retrieving revision 1.47.10.1
diff -u -a -p -r1.47.10.1 PINT-le-bytefield.c
--- src/proto/PINT-le-bytefield.c	5 Apr 2007 15:49:48 -0000	1.47.10.1
+++ src/proto/PINT-le-bytefield.c	24 May 2007 19:23:06 -0000
@@ -505,6 +505,8 @@ static int lebf_encode_resp(
     return ret;
 }
 
+const char * PINT_map_server_op_to_string(enum PVFS_server_op op);
+
 /* lebf_decode_req()
  *
  * decodes a request message
