25-akpm/fs/nfs/nfs3proc.c       |   42 ++++++-----------------
 25-akpm/fs/nfs/nfs4proc.c       |   48 ++++++++++-----------------
 25-akpm/fs/nfs/proc.c           |   48 ++++++++++-----------------
 25-akpm/fs/nfs/write.c          |   71 +++++++++++++++++++++-------------------
 25-akpm/include/linux/nfs_xdr.h |    6 +--
 5 files changed, 90 insertions(+), 125 deletions(-)

diff -puN fs/nfs/nfs3proc.c~23-write_proc fs/nfs/nfs3proc.c
--- 25/fs/nfs/nfs3proc.c~23-write_proc	Mon Jul  7 14:19:44 2003
+++ 25-akpm/fs/nfs/nfs3proc.c	Mon Jul  7 14:19:44 2003
@@ -249,45 +249,27 @@ nfs3_proc_read(struct nfs_read_data *rda
 }
 
 static int
-nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
-		struct nfs_fattr *fattr, int flags,
-		unsigned int base, unsigned int count,
-		struct page *page, struct nfs_writeverf *verf)
+nfs3_proc_write(struct nfs_write_data *wdata)
 {
-	u64			offset = page_offset(page) + base;
-	struct nfs_writeargs	arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.stable		= NFS_FILE_SYNC,
-		.pgbase		= base,
-		.pages		= &page
-	};
-	struct nfs_writeres	res = {
-		.fattr		= fattr,
-		.verf		= verf,
-	};
+	int			rpcflags = wdata->flags;
+	struct inode *		inode = wdata->inode;
+	struct nfs_fattr *	fattr = wdata->res.fattr;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_argp	= &wdata->args,
+		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
-	int			status, rpcflags = 0;
+	int			status;
 
-	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
+			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	if (flags & NFS_RW_SWAP)
-		rpcflags |= NFS_RPC_SWAPFLAGS;
-	arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
-
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
-
 	if (status >= 0)
 		nfs3_write_refresh_inode(inode, fattr);
-
-	dprintk("NFS reply read: %d\n", status);
-	return status < 0? status : res.count;
+	dprintk("NFS reply write: %d\n", status);
+	return status < 0? status : wdata->res.count;
 }
 
 /*
diff -puN fs/nfs/nfs4proc.c~23-write_proc fs/nfs/nfs4proc.c
--- 25/fs/nfs/nfs4proc.c~23-write_proc	Mon Jul  7 14:19:44 2003
+++ 25-akpm/fs/nfs/nfs4proc.c	Mon Jul  7 14:19:44 2003
@@ -1056,51 +1056,41 @@ nfs4_proc_read(struct nfs_read_data *rda
 }
 
 static int
-nfs4_proc_write(struct inode *inode, struct rpc_cred *cred,
-		struct nfs_fattr *fattr, int flags,
-		unsigned int base, unsigned int count,
-		struct page *page, struct nfs_writeverf *verf)
+nfs4_proc_write(struct nfs_write_data *wdata)
 {
+	int rpcflags = wdata->flags;
+	struct inode *inode = wdata->inode;
+	struct nfs_fattr *fattr = wdata->res.fattr;
+	nfs4_stateid *stateid = &wdata->args.stateid;
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs4_shareowner	*sp;
-	uint64_t offset = page_offset(page) + base;
-	struct nfs_writeargs arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.stable		= (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE,
-		.pgbase		= base,
-		.pages		= &page,
-	};
-	struct nfs_writeres res = {
-		.fattr		= fattr,
-		.count		= count,
-		.verf		= verf,
-	};
+	struct nfs4_shareowner *sp;
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_WRITE],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred,
+		.rpc_argp	= &wdata->args,
+		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
-	int			rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0;
+	int status;
 
-	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
+			(long long) wdata->args.offset);
 
 	/*
-	* Try first to use O_WRONLY, then O_RDWR stateid.
-	*/
+	 * Try first to use O_WRONLY, then O_RDWR stateid.
+	 */
 	sp = nfs4_get_inode_share(inode, O_WRONLY);
 	if (!sp)
 		sp = nfs4_get_inode_share(inode, O_RDWR);
 
 	if (sp)
-		memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid));
+		memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
 	else
-		memcpy(arg.stateid, zero_stateid, sizeof(nfs4_stateid));
+		memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
 
 	fattr->valid = 0;
-	return rpc_call_sync(server->client, &msg, rpcflags);
+	status = rpc_call_sync(server->client, &msg, rpcflags);
+	dprintk("NFS reply write: %d\n", status);
+	return status;
 }
 
 /*
diff -puN fs/nfs/proc.c~23-write_proc fs/nfs/proc.c
--- 25/fs/nfs/proc.c~23-write_proc	Mon Jul  7 14:19:44 2003
+++ 25-akpm/fs/nfs/proc.c	Mon Jul  7 14:19:44 2003
@@ -178,45 +178,33 @@ nfs_proc_read(struct nfs_read_data *rdat
 }
 
 static int
-nfs_proc_write(struct inode *inode, struct rpc_cred *cred,
-	       struct nfs_fattr *fattr, int how,
-	       unsigned int base, unsigned int count,
-	       struct page *page, struct nfs_writeverf *verf)
+nfs_proc_write(struct nfs_write_data *wdata)
 {
-	u64			offset = page_offset(page) + base;
-	struct nfs_writeargs	arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.stable		= NFS_FILE_SYNC,
-		.pgbase		= base,
-		.pages		= &page
-	};
-	struct nfs_writeres     res = {
-		.fattr		= fattr,
-		.verf		= verf,
-		.count		= count
-	};
+	int			flags = wdata->flags;
+	struct inode *		inode = wdata->inode;
+	struct nfs_fattr *	fattr = wdata->res.fattr;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_argp	= &wdata->args,
+		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred
 	};
-	int			status, flags = 0;
+	int			status;
 
-	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
+			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	if (how & NFS_RW_SWAP)
-		flags |= NFS_RPC_SWAPFLAGS;
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-
-	if (status >= 0)
+	if (status >= 0) {
 		nfs_write_refresh_inode(inode, fattr);
-
+		/* NFSv2 writes don't return a byte count or write
+		 * verifier, so we make up values here.  Note that
+		 * v2 writes are always NFS_FILE_SYNC writes. */
+		wdata->res.count = wdata->args.count;
+		wdata->verf.committed = NFS_FILE_SYNC;
+	}
 	dprintk("NFS reply write: %d\n", status);
-	verf->committed = NFS_FILE_SYNC;      /* NFSv2 always syncs data */
-	return status < 0? status : count;
+	return status < 0? status : wdata->res.count;
 }
 
 static int
diff -puN fs/nfs/write.c~23-write_proc fs/nfs/write.c
--- 25/fs/nfs/write.c~23-write_proc	Mon Jul  7 14:19:44 2003
+++ 25-akpm/fs/nfs/write.c	Mon Jul  7 14:19:44 2003
@@ -132,66 +132,73 @@ static int
 nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
 		   unsigned int offset, unsigned int count)
 {
-	struct rpc_cred	*cred = NULL;
-	loff_t		base;
 	unsigned int	wsize = NFS_SERVER(inode)->wsize;
-	int		result, refresh = 0, written = 0, flags;
-	u8		*buffer;
-	struct nfs_fattr fattr;
-	struct nfs_writeverf verf;
-
+	int		result, written = 0;
+	int		swapfile = IS_SWAPFILE(inode);
+	struct nfs_write_data	wdata = {
+		.flags		= swapfile ? NFS_RPC_SWAPFLAGS : 0,
+		.cred		= NULL,
+		.inode		= inode,
+		.args		= {
+			.fh		= NFS_FH(inode),
+			.pages		= &page,
+			.stable		= NFS_FILE_SYNC,
+			.pgbase		= offset,
+			.count		= wsize,
+		},
+		.res		= {
+			.fattr		= &wdata.fattr,
+			.verf		= &wdata.verf,
+		},
+	};
 
 	if (file)
-		cred = get_rpccred(nfs_file_cred(file));
-	if (!cred)
-		cred = get_rpccred(NFS_I(inode)->mm_cred);
+		wdata.cred = get_rpccred(nfs_file_cred(file));
+	if (!wdata.cred)
+		wdata.cred = get_rpccred(NFS_I(inode)->mm_cred);
 
 	dprintk("NFS:      nfs_writepage_sync(%s/%Ld %d@%Ld)\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode),
 		count, (long long)(page_offset(page) + offset));
 
-	base = page_offset(page) + offset;
-
-	flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
-
 	do {
-		if (count < wsize && !IS_SWAPFILE(inode))
-			wsize = count;
+		if (count < wsize && !swapfile)
+			wdata.args.count = count;
+		wdata.args.offset = page_offset(page) + wdata.args.pgbase;
 
-		result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
-						 offset, wsize, page, &verf);
+		result = NFS_PROTO(inode)->write(&wdata);
 
 		if (result < 0) {
 			/* Must mark the page invalid after I/O error */
 			ClearPageUptodate(page);
 			goto io_error;
 		}
-		if (result != wsize)
-			printk("NFS: short write, wsize=%u, result=%d\n",
-			wsize, result);
-		refresh = 1;
-		buffer  += wsize;
-		base    += wsize;
-	        offset  += wsize;
-		written += wsize;
-		count   -= wsize;
+		if (result < wdata.args.count)
+			printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n",
+					wdata.args.count, result);
+
+		wdata.args.offset += result;
+	        wdata.args.pgbase += result;
+		written += result;
+		count -= result;
+
 		/*
 		 * If we've extended the file, update the inode
 		 * now so we don't invalidate the cache.
 		 */
-		if (base > i_size_read(inode))
-			i_size_write(inode, base);
+		if (wdata.args.offset > i_size_read(inode))
+			i_size_write(inode, wdata.args.offset);
 	} while (count);
 
 	if (PageError(page))
 		ClearPageError(page);
 
 io_error:
-	if (cred)
-		put_rpccred(cred);
+	if (wdata.cred)
+		put_rpccred(wdata.cred);
 
-	return written? written : result;
+	return written ? written : result;
 }
 
 static int
diff -puN include/linux/nfs_xdr.h~23-write_proc include/linux/nfs_xdr.h
--- 25/include/linux/nfs_xdr.h~23-write_proc	Mon Jul  7 14:19:44 2003
+++ 25-akpm/include/linux/nfs_xdr.h	Mon Jul  7 14:19:44 2003
@@ -606,6 +606,7 @@ struct nfs_read_data {
 };
 
 struct nfs_write_data {
+	int			flags;
 	struct rpc_task		task;
 	struct inode		*inode;
 	struct rpc_cred		*cred;
@@ -636,10 +637,7 @@ struct nfs_rpc_ops {
 	int	(*access)  (struct inode *, struct rpc_cred *, int);
 	int	(*readlink)(struct inode *, struct page *);
 	int	(*read)    (struct nfs_read_data *);
-	int	(*write)   (struct inode *, struct rpc_cred *,
-			    struct nfs_fattr *,
-			    int, unsigned int, unsigned int,
-			    struct page *, struct nfs_writeverf *verfp);
+	int	(*write)   (struct nfs_write_data *);
 	int	(*commit)  (struct inode *, struct nfs_fattr *,
 			    unsigned long, unsigned int);
 	int	(*create)  (struct inode *, struct qstr *, struct iattr *,

_