fs/nfs/nfs3proc.c       |   30 +++++++++---------------------
 fs/nfs/nfs4proc.c       |   40 +++++++++++++++-------------------------
 fs/nfs/proc.c           |   38 +++++++++++++++-----------------------
 fs/nfs/read.c           |   40 ++++++++++++++++++++++++++--------------
 include/linux/nfs_xdr.h |    6 ++----
 5 files changed, 67 insertions(+), 87 deletions(-)

diff -puN fs/nfs/nfs3proc.c~22-read_proc fs/nfs/nfs3proc.c
--- 25/fs/nfs/nfs3proc.c~22-read_proc	2003-06-26 18:38:23.000000000 -0700
+++ 25-akpm/fs/nfs/nfs3proc.c	2003-06-26 18:38:23.000000000 -0700
@@ -225,38 +225,26 @@ nfs3_proc_readlink(struct inode *inode, 
 }
 
 static int
-nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
-	       struct nfs_fattr *fattr, int flags,
-	       unsigned int base, unsigned int count, struct page *page,
-	       int *eofp)
+nfs3_proc_read(struct nfs_read_data *rdata)
 {
-	u64			offset = page_offset(page) + base;
-	struct nfs_readargs	arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.pgbase		= base,
-		.pages		= &page
-	};
-	struct nfs_readres	res = {
-		.fattr		= fattr,
-		.count		= count,
-	};
+	int			flags = rdata->flags;
+	struct inode *		inode = rdata->inode;
+	struct nfs_fattr *	fattr = rdata->res.fattr;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_argp	= &rdata->args,
+		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
-	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
+			(long long) rdata->args.offset);
 	fattr->valid = 0;
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
 	dprintk("NFS reply read: %d\n", status);
-	*eofp = res.eof;
 	return status;
 }
 
diff -puN fs/nfs/nfs4proc.c~22-read_proc fs/nfs/nfs4proc.c
--- 25/fs/nfs/nfs4proc.c~22-read_proc	2003-06-26 18:38:23.000000000 -0700
+++ 25-akpm/fs/nfs/nfs4proc.c	2003-06-26 18:38:23.000000000 -0700
@@ -1012,45 +1012,36 @@ nfs4_proc_readlink(struct inode *inode, 
 }
 
 static int
-nfs4_proc_read(struct inode *inode, struct rpc_cred *cred,
-	       struct nfs_fattr *fattr, int flags,
-	       unsigned int base, unsigned int count,
-	       struct page *page, int *eofp)
+nfs4_proc_read(struct nfs_read_data *rdata)
 {
+	int flags = rdata->flags;
+	struct inode *inode = rdata->inode;
+	struct nfs_fattr *fattr = rdata->res.fattr;
+	nfs4_stateid *stateid = &rdata->args.stateid;
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_shareowner	*sp;
-	uint64_t offset = page_offset(page) + base;
-	struct nfs_readargs arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.pgbase		= base,
-		.pages		= &page,
-	};
-	struct nfs_readres res = {
-		.fattr		= fattr,
-		.count		= count,
-	};
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_READ],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred,
+		.rpc_argp	= &rdata->args,
+		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	unsigned long timestamp = jiffies;
 	int status;
 
-	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
+			(long long) rdata->args.offset);
+
 	/*
-	* Try first to use O_RDONLY, then O_RDWR stateid.
-	*/
+	 * Try first to use O_RDONLY, then O_RDWR stateid.
+	 */
 	sp = nfs4_get_inode_share(inode, O_RDONLY);
 	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;
 	status = rpc_call_sync(server->client, &msg, flags);
@@ -1061,7 +1052,6 @@ nfs4_proc_read(struct inode *inode, stru
 			nfs_zap_caches(inode);
 	}
 	dprintk("NFS reply read: %d\n", status);
-	*eofp = res.eof;
 	return status;
 }
 
diff -puN fs/nfs/proc.c~22-read_proc fs/nfs/proc.c
--- 25/fs/nfs/proc.c~22-read_proc	2003-06-26 18:38:23.000000000 -0700
+++ 25-akpm/fs/nfs/proc.c	2003-06-26 18:38:23.000000000 -0700
@@ -149,39 +149,31 @@ nfs_proc_readlink(struct inode *inode, s
 }
 
 static int
-nfs_proc_read(struct inode *inode, struct rpc_cred *cred,
-	      struct nfs_fattr *fattr, int flags,
-	      unsigned int base, unsigned int count, struct page *page,
-	      int *eofp)
+nfs_proc_read(struct nfs_read_data *rdata)
 {
-	u64			offset = page_offset(page) + base;
-	struct nfs_readargs	arg = {
-		.fh		= NFS_FH(inode),
-		.offset		= offset,
-		.count		= count,
-		.pgbase		= base,
-		.pages		= &page
-	};
-	struct nfs_readres	res = {
-		.fattr		= fattr,
-		.count		= count
-	};
+	int			flags = rdata->flags;
+	struct inode *		inode = rdata->inode;
+	struct nfs_fattr *	fattr = rdata->res.fattr;
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
-		.rpc_argp	= &arg,
-		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_argp	= &rdata->args,
+		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
-	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
+	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
+			(long long) rdata->args.offset);
 	fattr->valid = 0;
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-
-	if (status >= 0)
+	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
+		/* NFSv2 reads don't return an eof flag, so we make
+		 * up a value here.  XDR has already set eof to 0. */
+		if (status < rdata->args.count)
+			rdata->res.eof = 1;
+	}
 	dprintk("NFS reply read: %d\n", status);
-	*eofp = res.eof;
 	return status;
 }
 
diff -puN fs/nfs/read.c~22-read_proc fs/nfs/read.c
--- 25/fs/nfs/read.c~22-read_proc	2003-06-26 18:38:23.000000000 -0700
+++ 25-akpm/fs/nfs/read.c	2003-06-26 18:38:23.000000000 -0700
@@ -69,19 +69,28 @@ void nfs_readdata_release(struct rpc_tas
 static int
 nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
 {
-	struct rpc_cred	*cred = NULL;
-	struct nfs_fattr fattr;
-	unsigned int	offset = 0;
 	unsigned int	rsize = NFS_SERVER(inode)->rsize;
 	unsigned int	count = PAGE_CACHE_SIZE;
 	int		result;
-	int		flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
-	int		eof;
+	struct nfs_read_data	rdata = {
+		.flags		= (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0),
+		.cred		= NULL,
+		.inode		= inode,
+		.args		= {
+			.fh		= NFS_FH(inode),
+			.pages		= &page,
+			.pgbase		= 0UL,
+			.count		= rsize,
+		},
+		.res		= {
+			.fattr		= &rdata.fattr,
+		}
+	};
 
 	dprintk("NFS: nfs_readpage_sync(%p)\n", page);
 
 	if (file)
-		cred = nfs_file_cred(file);
+		rdata.cred = nfs_file_cred(file);
 
 	/*
 	 * This works now because the socket layer never tries to DMA
@@ -89,17 +98,19 @@ nfs_readpage_sync(struct file *file, str
 	 */
 	do {
 		if (count < rsize)
-			rsize = count;
+			rdata.args.count = count;
+		rdata.res.count = rdata.args.count;
+		rdata.args.offset = page_offset(page) + rdata.args.pgbase;
 
 		dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n",
 			NFS_SERVER(inode)->hostname,
 			inode->i_sb->s_id,
 			(long long)NFS_FILEID(inode),
-			(unsigned long long)offset, rsize);
+			(unsigned long long)rdata.args.pgbase,
+			rdata.args.count);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
-						offset, rsize, page, &eof);
+		result = NFS_PROTO(inode)->read(&rdata);
 		unlock_kernel();
 
 		/*
@@ -111,14 +122,15 @@ nfs_readpage_sync(struct file *file, str
 				result = -EINVAL;
 			goto io_error;
 		}
-		count  -= result;
-		offset += result;
-		if (result < rsize)	/* NFSv2ism */
+		count -= result;
+		rdata.args.pgbase += result;
+
+		if (rdata.res.eof)
 			break;
 	} while (count);
 
 	if (count)
-		memclear_highpage_flush(page, offset, count);
+		memclear_highpage_flush(page, rdata.args.pgbase, count);
 	SetPageUptodate(page);
 	if (PageError(page))
 		ClearPageError(page);
diff -puN include/linux/nfs_xdr.h~22-read_proc include/linux/nfs_xdr.h
--- 25/include/linux/nfs_xdr.h~22-read_proc	2003-06-26 18:38:23.000000000 -0700
+++ 25-akpm/include/linux/nfs_xdr.h	2003-06-26 18:38:23.000000000 -0700
@@ -591,6 +591,7 @@ struct nfs4_compound {
 #endif /* CONFIG_NFS_V4 */
 
 struct nfs_read_data {
+	int			flags;
 	struct rpc_task		task;
 	struct inode		*inode;
 	struct rpc_cred		*cred;
@@ -634,10 +635,7 @@ struct nfs_rpc_ops {
 			    struct nfs_fh *, struct nfs_fattr *);
 	int	(*access)  (struct inode *, struct rpc_cred *, int);
 	int	(*readlink)(struct inode *, struct page *);
-	int	(*read)    (struct inode *, struct rpc_cred *,
-			    struct nfs_fattr *,
-			    int, unsigned int, unsigned int,
-			    struct page *, int *eofp);
+	int	(*read)    (struct nfs_read_data *);
 	int	(*write)   (struct inode *, struct rpc_cred *,
 			    struct nfs_fattr *,
 			    int, unsigned int, unsigned int,

_