From: Trond Myklebust <trond.myklebust@fys.uio.no>

NFSv2: Fix up NFSv2 reads so that they correctly report when the server
returned a short read due to EOF.


---

 fs/nfs/proc.c |   16 ++++++++++++++--
 fs/nfs/read.c |    5 ++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff -puN fs/nfs/proc.c~nfs-short-read-fix fs/nfs/proc.c
--- 25/fs/nfs/proc.c~nfs-short-read-fix	2004-02-29 15:04:24.000000000 -0800
+++ 25-akpm/fs/nfs/proc.c	2004-02-29 15:04:24.000000000 -0800
@@ -186,8 +186,14 @@ nfs_proc_read(struct nfs_read_data *rdat
 	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 
-	if (status >= 0)
+	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
+		/* Emulate the eof flag, which isn't normally needed in NFSv2
+		 * as it is guaranteed to always return the file attributes
+		 */
+		if (rdata->args.offset + rdata->args.count >= fattr->size)
+			rdata->res.eof = 1;
+	}
 	dprintk("NFS reply read: %d\n", status);
 	return status;
 }
@@ -541,8 +547,14 @@ nfs_read_done(struct rpc_task *task)
 {
 	struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 
-	if (task->tk_status >= 0)
+	if (task->tk_status >= 0) {
 		nfs_refresh_inode(data->inode, data->res.fattr);
+		/* Emulate the eof flag, which isn't normally needed in NFSv2
+		 * as it is guaranteed to always return the file attributes
+		 */
+		if (data->args.offset + data->args.count >= data->res.fattr->size)
+			data->res.eof = 1;
+	}
 	nfs_readpage_result(task);
 }
 
diff -puN fs/nfs/read.c~nfs-short-read-fix fs/nfs/read.c
--- 25/fs/nfs/read.c~nfs-short-read-fix	2004-02-29 15:04:24.000000000 -0800
+++ 25-akpm/fs/nfs/read.c	2004-02-29 15:04:24.000000000 -0800
@@ -121,7 +121,10 @@ nfs_readpage_sync(struct file *file, str
 		}
 		count -= result;
 		rdata.args.pgbase += result;
-		if (result < rdata.args.count)	/* NFSv2ism */
+		/* Note: result == 0 should only happen if we're caching
+		 * a write that extends the file and punches a hole.
+		 */
+		if (rdata.res.eof != 0 || result == 0)
 			break;
 	} while (count);
 	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;

_