diff -urpN linux-2.6.1-patched/fs/nfs/inode.c linux-2.6.1-client/fs/nfs/inode.c
--- linux-2.6.1-patched/fs/nfs/inode.c	2004-02-06 16:15:00.628256000 -0500
+++ linux-2.6.1-client/fs/nfs/inode.c	2004-02-24 10:51:17.560256000 -0500
@@ -107,6 +107,8 @@ struct rpc_program		nfs_program = {
 	.pipe_dir_name		= "/nfs",
 };
 
+struct list_head ds_conn_pool[DS_POOL_HASH_SIZE]; /* rpc connections to data servers */
+
 static inline unsigned long
 nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
 {
@@ -759,7 +761,10 @@ nfs_fhget(struct super_block *sb, struct
 		inode->i_mtime = fattr->mtime;
 		inode->i_ctime = fattr->ctime;
 		if (fattr->valid & NFS_ATTR_FATTR_V4)
+		{
+		  dprintk("Setting change attr to %Ld\n",fattr->change_attr);
 			nfsi->change_attr = fattr->change_attr;
+		}
 		inode->i_size = nfs_size_to_loff_t(fattr->size);
 		inode->i_nlink = fattr->nlink;
 		inode->i_uid = fattr->uid;
@@ -1291,6 +1296,7 @@ static int nfs_update_inode(struct inode
 	 * lookup validation will know that the inode is bad.
 	 * (But we fall through to invalidate the caches.)
 	 */
+	dprintk("__nfs_refresh_inode: nfs_invaliate_inode\n");
 	nfs_invalidate_inode(inode);
  out_err:
 	return -EIO;
@@ -1828,6 +1834,7 @@ static struct inode *nfs_alloc_inode(str
 		return NULL;
 	nfsi->flags = 0;
 	nfsi->mm_cred = NULL;
+	nfsi->file_locations = NULL;
 #ifdef CONFIG_NFS_V4_ACL
 	nfsi->acl = NFS4_ACL_NOT_CACHED;
 	nfsi->default_acl = NFS4_ACL_NOT_CACHED;
@@ -1877,12 +1884,38 @@ void nfs_destroy_inodecache(void)
 		printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
 }
 
+/* Shutdown connection to data servers in connection pool
+ */
+static void
+nfs4_shutdown_data_server_conns(void)
+{
+	struct list_head *pos, *next;
+	struct nfs4_data_server *local = NULL;
+	int i;
+	dprintk("nfs4_shutdown_data_server_conns: Begin\n");
+
+	for (i=0; i < DS_POOL_HASH_SIZE;i++)
+	{
+		list_for_each_safe(pos, next, &ds_conn_pool[i]) 
+		{
+			local = list_entry(pos, struct nfs4_data_server,ds_ip_num);
+			if (local->ds_data_client != NULL)
+			{
+				dprintk("nfs4_shutdown_data_server_conns: About to shutdown data server\n");
+				rpc_shutdown_client(local->ds_data_client);
+				dprintk("nfs4_shutdown_data_server_conns: Finished shutdown data server connection\n");
+			}
+		}
+	}
+	dprintk("nfs4_shutdown_data_server_conns: End\n");
+}
+
 /*
  * Initialize NFS
  */
 static int __init init_nfs_fs(void)
 {
-	int err;
+	int err,i;
 
 	err = nfs_init_nfspagecache();
 	if (err)
@@ -1900,6 +1933,10 @@ static int __init init_nfs_fs(void)
 	if (err)
 		goto out1;
 
+	/* Initialize the data server connection pool */
+	for (i = 0; i < DS_POOL_HASH_SIZE; i++)
+	  INIT_LIST_HEAD(&(ds_conn_pool[i]));
+
 #ifdef CONFIG_PROC_FS
 	rpc_proc_register(&nfs_rpcstat);
 #endif
@@ -1928,6 +1965,7 @@ static void __exit exit_nfs_fs(void)
 	nfs_destroy_readpagecache();
 	nfs_destroy_inodecache();
 	nfs_destroy_nfspagecache();
+	nfs4_shutdown_data_server_conns();
 #ifdef CONFIG_PROC_FS
 	rpc_proc_unregister("nfs");
 #endif
Binary files linux-2.6.1-patched/fs/nfs/.inode.c.swp and linux-2.6.1-client/fs/nfs/.inode.c.swp differ
diff -urpN linux-2.6.1-patched/fs/nfs/nfs4proc.c linux-2.6.1-client/fs/nfs/nfs4proc.c
--- linux-2.6.1-patched/fs/nfs/nfs4proc.c	2004-02-06 16:15:00.684257000 -0500
+++ linux-2.6.1-client/fs/nfs/nfs4proc.c	2004-03-09 18:43:04.356256000 -0500
@@ -39,6 +39,7 @@
 #include <linux/utsname.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/inet.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs.h>
 #include <linux/nfs4.h>
@@ -56,8 +57,31 @@
 static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
+extern struct rpc_program nfs_program;
+
 
 extern nfs4_stateid zero_stateid;
+extern struct list_head ds_conn_pool[];
+
+/* search for dataserver in ds_conn_pool */
+static struct rpc_clnt*
+find_dataserver_client(unsigned int hashval, int ip)
+{
+       struct list_head *pos, *next;
+       struct nfs4_data_server *local = NULL;
+       dprintk("find_dataserver_client: Begin\n");
+       list_for_each_safe(pos, next, &ds_conn_pool[hashval])
+       {
+               local = list_entry(pos, struct nfs4_data_server,ds_ip_num);
+               dprintk("find_dataserver_client: Current entry %d\n",local->ds_ip);
+               if (local->ds_ip != ip)
+                       continue;
+               dprintk("find_dataserver_client: Found Client End\n");
+               return local->ds_data_client;
+       }
+       dprintk("find_dataserver_client: Returning Null End\n");
+       return NULL;
+}
 
 /*
  * This is our standard bitmap for GETATTR requests.
@@ -202,10 +226,224 @@ nfs4_open_reclaim(struct nfs4_state_owne
 	nfs_refresh_inode(inode, &fattr);
 	return status;
 }
+/* Selects a server to read/write from. If a file location has been 
+ * returned to the client from the server then it reads the data 
+ * from a returned data server.  The current algorithm for choosing
+ * from a list of data servers is Round Robin.  If the file_locations
+ * list is empty, then it reads from the server in the super_block
+ * (the server that was mounted)
+ */
+static struct rpc_clnt* 
+get_data_server(struct inode* inode)
+{
+	struct nfs_inode* nfsi = NFS_I(inode);
+	struct nfs4_file_locations* fileLocList = nfsi->file_locations;
+	u32 last_server,index;
+	dprintk("get_data_server: Begin\n");
+
+	if (fileLocList != NULL && fileLocList->locationslen > 0)
+	{
+/*
+		last_server = fileLocList->last_location;
+		index = last_server + 1;
+		index = index % fileLocList->locationslen;
+		fileLocList->last_location = index;
+	        dprintk("get_data_server:Returning index %d server %s\n",index,fileLocList->locations[index]->data_client->cl_server);
+		dprintk("get_data_server: End\n");
+		return fileLocList->locations[index]->data_client; 
+*/
+
+		return fileLocList->locations[0]->data_client; 
+	}
+	else
+	{
+	        dprintk("get_data_server: Returning metaserver\n");
+		dprintk("get_data_server: End\n");
+		return NFS_CLIENT(inode);
+	}
+}
+
+/* free memory for the file_locations structures created in do_open decode function */
+void
+nfs4_free_file_locations(struct nfs4_file_locations*  file_locations)
+{
+	int locationslen=0,i=0;
+	dprintk("nfs4_free_file_locations: Begin\n");
+	if (file_locations != NULL && file_locations->locationslen != 0)
+	{
+		dprintk("nfs4_free_file_locations Freeing Memory %d\n",file_locations->locationslen);
+		locationslen = file_locations->locationslen;
+		for (i=0; i < locationslen;i++)
+	        {
+			kfree(file_locations->locations[i]->server);
+			kfree(file_locations->locations[i]);
+		}
+		kfree(file_locations->locations);
+		kfree(file_locations);
+	}
+        else
+	{
+		kfree(file_locations);
+	}
+	dprintk("nfs4_free_file_locations: End\n");
+}
+
+/*
+  This method sets the current set of read/write servers for this 
+  client to access in the inode.  The close method should clear the list of 
+  fs_locations in the inode.  The close method might not be best as
+  it seems that close is not always the last command called on a file.  
+  Need to look into this more....
+*/
+static struct rpc_clnt*
+nfs4_create_data_server_conn(struct nfs_server *sb, char* server)
+{
+	rpc_authflavor_t authflavour;
+	struct rpc_xprt *xprt = NULL;
+	struct rpc_clnt *clnt = NULL;
+	static struct rpc_timeout timeparms;
+	int proto;
+        struct sockaddr_in server_addr;
+	u32 ipbinary;
+	u32 version;
+	unsigned int	cl_softrtry = 1;/* soft timeouts */
+	unsigned int	cl_intr     = 1;/* interruptible */
+        unsigned int    cl_chatty = 1;/* be verbose */
+	dprintk("nfs4_create_data_server_conn: Begin\n");
+
+	/* Assume the hostname is a ip address */
+	ipbinary = in_aton(server);
+	if (sb->addr.sin_addr.s_addr == ipbinary)
+	{
+		/* The data server is the state server.  
+		 * Return the client in the sb and return
+		 */
+		dprintk("nfs4_create_data_server_conn: State server %s equals data server.  Returning rpc client in superblock\n",sb->hostname);		
+		clnt = sb->client;
+		goto out;
+	}
+
+	/* store data about original client to create a copy */
+	proto = sb->client->cl_xprt->prot;
+	memcpy(&timeparms,&sb->client->cl_xprt->timeout,sizeof(struct rpc_timeout));
+	authflavour = RPC_AUTH_UNIX;
+	version = sb->rpc_ops->version;
+	cl_intr     = sb->client->cl_intr;
+	cl_softrtry = sb->client->cl_softrtry;
+	cl_chatty   = sb->client->cl_chatty;
+
+	server_addr.sin_family = AF_INET;
+	memcpy(&server_addr.sin_addr.s_addr,&ipbinary ,4);
+	server_addr.sin_port = htons(NFS_PORT);
+
+	/* Now create transport and client */
+	dprintk("nfs4_create_data_server_conn: About to try and create proto to server %s\n",server);
+	xprt = xprt_create_proto(proto,&server_addr, &timeparms);
+	if (xprt == NULL) {
+		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+		goto out_fail;
+	}
+
+	dprintk("nfs4_create_data_server_conn: About to try and create rpc client\n");
+	dprintk("nfs4_create_data_server_conn: flav: %d ver: %d name: %s\n",authflavour,version,nfs_program.name);
+	clnt = rpc_create_client(xprt,server , &nfs_program,version, authflavour);
+
+	if (clnt == NULL) {
+		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
+		xprt_destroy(xprt);
+		goto out_fail;
+	}
+
+	clnt->cl_intr     = cl_intr;
+	clnt->cl_softrtry = cl_softrtry;
+	clnt->cl_chatty   = cl_chatty;
+
+out:
+	dprintk("nfs4_create_data_server_conn: End\n");
+	return clnt;
+
+out_fail:
+	return NULL;
+}
+
+/*
+  This method sets the current set of read/write servers for this 
+  client to access.  
+  The close method should clear the list of fs_locations on destruction
+  of the inode.
+*/
+static int
+nfs4_refresh_file_locations(struct inode* inode, struct nfs4_file_locations* floc)
+{
+	struct rpc_clnt*        clnt = NULL;
+	int i,ll;
+	struct nfs4_file_location* loc = NULL;
+	u32 ip;
+	unsigned int ip_hash;
+	struct nfs4_data_server* ds = NULL;
+	dprintk("nfs4_refresh_file_locations: Begin\n");
+
+	/* this means we do not need to set the file location */
+	if (inode == NULL || floc == NULL)
+		return 0; /* no action needed */
+
+	if (NFS_I(inode)->file_locations != NULL)
+	{
+		nfs4_free_file_locations(NFS_I(inode)->file_locations);
+	}
+	NFS_I(inode)->file_locations = floc;
+	
+	ll = floc->locationslen;
+	/* Create a connection to the data server if one does not allready exist */
+	if (ll <= 0)
+		goto no_exist;
+	for (i=0;i < ll;i++)
+	{
+		loc = floc->locations[i];
+		
+		/* Search current data server pool for an existing connection */
+		ip = in_aton(loc->server);
+		ip_hash = dataserver_hashval(ip);
+		dprintk("nfs4_refresh_file_locations: server: %s ipnum %d ip_hash %d\n",loc->server,ip,ip_hash);
+		if ((clnt = find_dataserver_client(ip_hash, ip))) 
+		{
+			dprintk("nfs4_refresh_file_locations: Updating data client from data server pool at index %d\n",i);
+			loc->data_client = clnt;
+		}
+		else
+		{
+			dprintk("nfs4_refresh_file_locations: Updating data client index %d\n",i);
+			if (!(clnt = nfs4_create_data_server_conn(NFS_SERVER(inode),loc->server)))
+				goto cleanup_err;
+			loc->data_client = clnt;
+			ds = kmalloc(sizeof(struct nfs4_data_server),GFP_KERNEL);
+			if (!ds)
+				goto cleanup_client_err;
+			ds->ds_ip = ip;
+			ds->ds_data_client = clnt;
+			list_add_tail(&ds->ds_ip_num, &ds_conn_pool[ip_hash]);
+		}
+	}
+	dprintk("nfs4_refresh_file_locations: End\n");
+	return 0;
+cleanup_client_err:
+	rpc_shutdown_client(clnt);
+cleanup_err:
+	nfs4_free_file_locations(floc);
+	return 1; /* fail */
+no_exist:
+	printk("nfs4_refresh_file_locations: No File Locations Exist!!");
+	return 1;/* fail */
+}
+
 
 /*
  * Returns an nfs4_state + an referenced inode
  */
+/* Modified getattr part of compound to ask for the file_locations data.  A
+   new connection is then created to this server (should this be done now or
+   on the read/write command? and the data is set in the inode.
+*/
 struct nfs4_state *
 nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred)
 {
@@ -220,6 +458,7 @@ nfs4_do_open(struct inode *dir, struct q
 	};
 	struct nfs_fattr        f_attr = {
 		.valid          = 0,
+		.file_locations = (struct nfs4_file_locations*)kmalloc(sizeof(struct nfs4_file_locations),GFP_KERNEL),
 	};
 	struct nfs_openargs o_arg = {
 		.fh             = NFS_FH(dir),
@@ -241,7 +480,7 @@ nfs4_do_open(struct inode *dir, struct q
 		.rpc_resp       = &o_res,
 		.rpc_cred	= cred,
 	};
-
+	dprintk("%s: Start\n",__FUNCTION__);
 retry:
 	status = -ENOMEM;
 	if (!(sp = nfs4_get_state_owner(NFS_SERVER(dir), cred))) {
@@ -261,10 +500,19 @@ retry:
 	o_arg.id = sp->so_id;
 	o_arg.clientid = NFS_SERVER(dir)->nfs4_state->cl_clientid,
 
+	/* Initialize file locations data to know whether 
+	 * we receceived the attribute 
+	 */
+	f_attr.file_locations->locationslen = 0;
+
+	dprintk("nfs4_do_open: call sync Begin\n");
 	status = rpc_call_sync(server->client, &msg, 0);
 	nfs4_increment_seqid(status, sp);
 	if (status)
+	{
+		nfs4_free_file_locations(f_attr.file_locations);
 		goto out_up;
+	}
 	process_cinfo(&d_cinfo, &d_attr);
 	nfs_refresh_inode(dir, &d_attr);
 
@@ -276,6 +524,16 @@ retry:
 	if (!state)
 		goto out_up;
 
+	/* This means the server does not support this attribute */
+	if (f_attr.file_locations->locationslen == 0)
+	{
+		kfree(f_attr.file_locations);
+	}
+	/* Reset the new Read Write server 
+	*/
+	else if ((status = nfs4_refresh_file_locations(inode,f_attr.file_locations)))
+		goto out_up;
+
 	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
 		struct nfs_open_confirmargs oc_arg = {
 			.fh             = &o_res.fh,
@@ -325,6 +583,7 @@ out_up:
 		goto retry;
 	BUG_ON(status < -1000 || status > 0);
 out:
+	dprintk("%s: End\n",__FUNCTION__);
 	return ERR_PTR(status);
 }
 
@@ -392,11 +651,16 @@ nfs4_do_close(struct inode *inode, struc
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 	};
+	struct nfs_inode* nfsi = NFS_I(inode);
+	struct nfs4_file_locations* fileLocList = nfsi->file_locations;
+ 
 
 	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));
 	/* Serialization for the sequence id */
 	arg.seqid = sp->so_seqid,
 	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	nfs4_free_file_locations(fileLocList);
+	nfsi->file_locations = NULL;
 
         /* hmm. we are done with the inode, and in the process of freeing
 	 * the state_owner. we keep this around to process errors
@@ -558,9 +822,7 @@ nfs4_proc_getattr(struct inode *inode, s
 		.rpc_argp = NFS_FH(inode),
 		.rpc_resp = &res,
 	};
-	
 	fattr->valid = 0;
-
 	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 }
 
@@ -954,6 +1216,7 @@ nfs4_proc_read(struct nfs_read_data *rda
 	};
 	unsigned long timestamp = jiffies;
 	int status;
+	struct rpc_clnt*        data_server;
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
@@ -961,7 +1224,7 @@ nfs4_proc_read(struct nfs_read_data *rda
 	/*
 	 * Try first to use O_RDONLY, then O_RDWR stateid.
 	 */
-	if (filp) {
+if (filp) {
 		struct nfs4_state *state;
 		state = (struct nfs4_state *)filp->private_data;
 		nfs4_copy_stateid(&rdata->args.stateid, state, rdata->lockowner);
@@ -972,7 +1235,8 @@ nfs4_proc_read(struct nfs_read_data *rda
 	}
 
 	fattr->valid = 0;
-	status = rpc_call_sync(server->client, &msg, flags);
+	data_server = get_data_server(inode);
+	status = rpc_call_sync(data_server, &msg, flags);
 	if (!status)
 		renew_lease(server, timestamp);
 	dprintk("NFS reply read: %d\n", status);
@@ -985,13 +1249,13 @@ nfs4_proc_write(struct nfs_write_data *w
 	int rpcflags = wdata->flags;
 	struct inode *inode = wdata->inode;
 	struct nfs_fattr *fattr = wdata->res.fattr;
-	struct nfs_server *server = NFS_SERVER(inode);
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
 	};
 	int status;
+	struct rpc_clnt*        data_server;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
@@ -1010,7 +1274,12 @@ nfs4_proc_write(struct nfs_write_data *w
 	}
 
 	fattr->valid = 0;
-	status = rpc_call_sync(server->client, &msg, rpcflags);
+ 	/* This function is the initial point for all write requests.
+ 	 * If a file location has been returned to the client from the server,
+ 	 * then it writes the data to the returned data server 
+ 	 */
+	data_server = get_data_server(inode);
+	status = rpc_call_sync(data_server, &msg, rpcflags);
 	dprintk("NFS reply write: %d\n", status);
 	return status;
 }
@@ -1462,15 +1731,21 @@ nfs4_read_done(struct rpc_task *task)
 {
 	struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 	struct inode *inode = data->inode;
+	dprintk("%s: Begin\n",__FUNCTION__);
 
 	if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
 		task->tk_action = nfs4_restart_read;
 		return;
 	}
+	/* DH-TODO: Disable updating piggybacked ack since read commands 
+	 * no longer being sent to state server
+ 	 * Need to handle non-file_loc scenario
 	if (task->tk_status > 0)
 		renew_lease(NFS_SERVER(inode), data->timestamp);
+	*/
 	/* Call back common NFS readpage processing */
 	nfs_readpage_result(task);
+	dprintk("%s: End\n",__FUNCTION__);
 }
 
 static void
@@ -1486,7 +1761,8 @@ nfs4_proc_read_setup(struct nfs_read_dat
 	struct inode *inode = data->inode;
 	struct nfs_page *req = nfs_list_entry(data->pages.next);
 	int flags;
-
+	struct rpc_clnt*        data_server;
+ 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req);
 	data->args.pgbase = req->wb_pgbase;
@@ -1506,9 +1782,11 @@ nfs4_proc_read_setup(struct nfs_read_dat
 	/* N.B. Do we need to test? Never called for swapfile inode */
 	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 
-	/* Finalize the task. */
-	rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags);
+	/* Determine which server to send request to */
+	data_server = get_data_server(inode);
+	rpc_init_task(task, data_server, nfs4_read_done, flags);
 	task->tk_calldata = data;
+
 	/* Release requests */
 	task->tk_release = nfs_readdata_release;
 
@@ -1534,17 +1812,24 @@ nfs4_write_done(struct rpc_task *task)
 {
 	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
 	struct inode *inode = data->inode;
-	
+	dprintk("%s: Begin\n",__FUNCTION__);
 	if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
 		task->tk_action = nfs4_restart_write;
 		return;
 	}
+	/* DH-TODO: Disable updating piggybacked ack since read commands 
+	 * no longer being sent to state server
+ 	 * Need to handle non-file_loc scenario
 	if (task->tk_status >= 0)
 		renew_lease(NFS_SERVER(inode), data->timestamp);
+	*/
+
 	/* Call back common NFS writeback processing */
 	nfs_writeback_done(task);
+	dprintk("%s: End\n",__FUNCTION__);
 }
 
+
 static void
 nfs4_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
 {
@@ -1559,7 +1844,8 @@ nfs4_proc_write_setup(struct nfs_write_d
 	struct nfs_page *req = nfs_list_entry(data->pages.next);
 	int stable;
 	int flags;
-	
+	struct rpc_clnt*        data_server;
+
 	if (how & FLUSH_STABLE) {
 		if (!NFS_I(inode)->ncommit)
 			stable = NFS_FILE_SYNC;
@@ -1588,8 +1874,13 @@ nfs4_proc_write_setup(struct nfs_write_d
 	/* Set the initial flags for the task.  */
 	flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
-	/* Finalize the task. */
-	rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags);
+	/* This function is the initial point for all write requests.
+	 * If a file location has been returned to the client from the server,
+	 * then it writes the data to the returned data server 
+	 */
+	/* Determine which server to send request to */
+	data_server = get_data_server(inode);
+	rpc_init_task(task, data_server, nfs4_write_done, flags);
 	task->tk_calldata = data;
 	/* Release requests */
 	task->tk_release = nfs_writedata_release;
@@ -1623,7 +1914,9 @@ nfs4_proc_commit_setup(struct nfs_write_
 	};	
 	struct inode *inode = data->inode;
 	int flags;
-	
+	struct nfs_inode* nfsi = NFS_I(inode);
+	struct nfs4_file_locations* fileLocList = nfsi->file_locations;
+
 	data->args.fh     = NFS_FH(data->inode);
 	data->args.offset = start;
 	data->args.count  = len;
@@ -1635,7 +1928,16 @@ nfs4_proc_commit_setup(struct nfs_write_
 	flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
 	/* Finalize the task. */
-	rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
+	if (fileLocList!= NULL && fileLocList->locationslen > 0)
+	{
+	        dprintk("nfs4_proc_commit_setup: Comitting to server %s\n",fileLocList->locations[0]->data_client->cl_server);
+		rpc_init_task(task, fileLocList->locations[0]->data_client, nfs4_commit_done, flags);
+	}
+	else
+	{
+	        dprintk("nfs4_proc_commit_setup: Committing to metaserver\n");
+		rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
+	}
 	task->tk_calldata = data;
 	/* Release requests */
 	task->tk_release = nfs_commit_release;
@@ -2135,9 +2437,8 @@ nfs4_proc_setlk(struct nfs4_state *state
 	lsp = nfs4_find_lock_state(state, request->fl_owner);
 	if (lsp == NULL) {
 		struct nfs4_state_owner *owner = state->owner;
-		struct nfs_open_to_lock otl = {
-			.lock_owner.clientid = server->nfs4_state->cl_clientid,
-		};
+		struct nfs_open_to_lock otl;
+		otl.lock_owner.clientid = server->nfs4_state->cl_clientid,
 		status = -ENOMEM;
 		lsp = nfs4_alloc_lock_state(state, request->fl_owner);
 		if (!lsp)
diff -urpN linux-2.6.1-patched/fs/nfs/nfs4xdr.c linux-2.6.1-client/fs/nfs/nfs4xdr.c
--- linux-2.6.1-patched/fs/nfs/nfs4xdr.c	2004-02-17 15:41:38.579260000 -0500
+++ linux-2.6.1-client/fs/nfs/nfs4xdr.c	2004-03-12 17:33:37.740256000 -0500
@@ -724,6 +724,13 @@ encode_getfattr(struct xdr_stream *xdr)
 				       nfs4_fattr_bitmap[1]);
 }
 
+static inline int
+encode_open_getfattr(struct xdr_stream *xdr)
+{
+	return encode_getattr_two(xdr, nfs4_fattr_bitmap[0],
+				       nfs4_fattr_bitmap[1] | FATTR4_WORD1_FILE_LOCATIONS);
+}
+
 /*
  * Request the change attribute in order to check attribute+cache consistency
  */
@@ -1601,7 +1608,7 @@ nfs4_xdr_enc_open(struct rpc_rqst *req, 
 	status = encode_open(&xdr, args);
 	if (status)
 		goto out;
-	status = encode_getfattr(&xdr);
+	status = encode_open_getfattr(&xdr);
 	if (status)
 		goto out;
 	status = encode_getfh(&xdr);
@@ -2392,7 +2399,7 @@ decode_getfattr(struct xdr_stream *xdr, 
 	unsigned int type;
 	int fmode = 0;
 	int status;
-	
+	struct nfs4_file_locations *file_locations = NULL;
 	status = decode_op_hdr(xdr, OP_GETATTR);
 	if (status)
 		return status;
@@ -2410,7 +2417,7 @@ decode_getfattr(struct xdr_stream *xdr, 
         READ32(attrlen);
 
 	if ((bmval0 & ~nfs4_fattr_bitmap[0]) ||
-	    (bmval1 & ~nfs4_fattr_bitmap[1])) {
+	    (bmval1 & ~(nfs4_fattr_bitmap[1] | FATTR4_WORD1_FILE_LOCATIONS))) {
 		dprintk("read_attrs: server returned bad attributes!\n");
 		goto xdr_error;
 	}
@@ -2554,9 +2561,56 @@ decode_getfattr(struct xdr_stream *xdr, 
                 READTIME(nfp->mtime);
                 dprintk("read_attrs: mtime=%ld\n", (long)nfp->mtime.tv_sec);
         }
+        if (bmval1 & FATTR4_WORD1_FILE_LOCATIONS) {
+		int i = 0;
+		uint32_t file_locations_serverlen=0;
+		file_locations = nfp->file_locations;
+		dprintk("Starting decoding file_locations\n");
+
+		/* For now there is always 1 data server */
+		READ_BUF(4);
+		len += 4;
+		READ32(file_locations->locationslen); 
+                dprintk("read_attrs: file_locations locationslen= %d\n",file_locations->locationslen);
+		if (file_locations->locationslen <= 0)
+		{
+			printk("read_attrs: Server does either not support or have any available data locations.\n");
+			goto xdr_error;
+		}
+		file_locations->last_location = 0; /* init value */
+		file_locations->locations = (struct nfs4_file_location**)kmalloc(file_locations->locationslen*sizeof(struct nfs4_file_location*),GFP_KERNEL);
+		if (!file_locations->locations)
+			goto xdr_error;
+		for (i=0; i < file_locations->locationslen;i++)
+	        {
+			file_locations->locations[i] = (struct nfs4_file_location*)kmalloc(sizeof(struct nfs4_file_location),GFP_KERNEL);
+			if (!file_locations->locations[i])
+				goto xdr_error;
+
+			READ_BUF(4);
+			len += 4;
+			READ32(file_locations->locations[i]->serverlen);
+			file_locations_serverlen = file_locations->locations[i]->serverlen;
+			dprintk("read_attrs file_location server name length: %d\n",file_locations_serverlen);
+			if (file_locations_serverlen > XDR_MAX_NETOBJ) {
+				printk("read_attrs: serverlen too long!\n");
+				return 1;
+			}
+			READ_BUF(file_locations_serverlen);
+			len += (XDR_QUADLEN(file_locations_serverlen) << 2);
+			file_locations->locations[i]->server = (char*)kmalloc((file_locations_serverlen + 1) * sizeof(char),GFP_KERNEL);
+			if (!file_locations->locations[i]->server)
+				goto xdr_error;
+
+			strncpy(file_locations->locations[i]->server, (char*)p,file_locations_serverlen);
+			file_locations->locations[i]->server[file_locations_serverlen] = '\0';
+			dprintk("read_attrs file_locations server= %s\n",file_locations->locations[i]->server);
+
+			file_locations->locations[i]->data_client = NULL; /* initialize */
+		}
+        }
         if (len != attrlen)
                 goto xdr_error;
-	
         DECODE_TAIL;
 }
 
diff -urpN linux-2.6.1-patched/include/linux/nfs4.h linux-2.6.1-client/include/linux/nfs4.h
--- linux-2.6.1-patched/include/linux/nfs4.h	2004-03-05 14:54:33.043261000 -0500
+++ linux-2.6.1-client/include/linux/nfs4.h	2004-03-05 14:56:00.929256000 -0500
@@ -326,6 +326,7 @@ enum lock_type4 {
 #define FATTR4_WORD1_TIME_METADATA      (1 << 20)
 #define FATTR4_WORD1_TIME_MODIFY        (1 << 21)
 #define FATTR4_WORD1_TIME_MODIFY_SET    (1 << 22)
+#define FATTR4_WORD1_FILE_LOCATIONS     (1 << 23)
 
 #define NFSPROC4_NULL 0
 #define NFSPROC4_COMPOUND 1
diff -urpN linux-2.6.1-patched/include/linux/nfs_fs.h linux-2.6.1-client/include/linux/nfs_fs.h
--- linux-2.6.1-patched/include/linux/nfs_fs.h	2004-02-06 16:15:00.905257000 -0500
+++ linux-2.6.1-client/include/linux/nfs_fs.h	2004-02-24 10:51:17.589259000 -0500
@@ -172,8 +172,21 @@ struct nfs_inode {
 	struct posix_acl	*default_acl;
 #endif /* CONFIG_NFS_V4_ACL */
 	struct inode		vfs_inode;
+  struct nfs4_file_locations*         file_locations;
 };
 
+struct nfs4_data_server {
+  struct list_head        ds_ip_num;   /* hash by ip addr num */
+  u32                     ds_ip;
+  struct rpc_clnt*        ds_data_client;
+};
+
+#define DS_POOL_HASH_BITS                 4
+#define DS_POOL_HASH_SIZE                (1 << DS_POOL_HASH_BITS)
+#define DS_POOL_HASH_MASK                (DS_POOL_HASH_SIZE - 1)
+ 
+#define dataserver_hashval(id) ((id) & DS_POOL_HASH_MASK)
+
 /*
  * Legal inode flag values
  */
diff -urpN linux-2.6.1-patched/include/linux/nfs_xdr.h linux-2.6.1-client/include/linux/nfs_xdr.h
--- linux-2.6.1-patched/include/linux/nfs_xdr.h	2004-02-06 16:15:00.973256000 -0500
+++ linux-2.6.1-client/include/linux/nfs_xdr.h	2004-02-24 10:51:17.593257000 -0500
@@ -3,6 +3,19 @@
 
 #include <linux/sunrpc/xprt.h>
 
+struct nfs4_file_location {
+  u32                     serverlen;
+  char*                   server;
+  struct rpc_clnt*        data_client;
+};
+
+struct nfs4_file_locations {
+  u32                         algorithm_id; /* Indicate load balancing algorithm for this file */
+  u32                         last_location; /* The last read/write request used the last_location index in locations */
+  u32                         locationslen;
+  struct nfs4_file_location** locations;
+};
+
 struct nfs_fattr {
 	unsigned short		valid;		/* which fields are valid */
 	__u64			pre_size;	/* pre_op_attr.size	  */
@@ -41,6 +54,7 @@ struct nfs_fattr {
 	unsigned long		timestamp;
 #ifdef CONFIG_NFS_V4
 	struct nfs4_acl        *acl;            /* NFSv4 ACL */
+  struct nfs4_file_locations *      file_locations;   /* response */
 #endif /* CONFIG_NFS_V4 */
 };
 
