From: Trond Myklebust 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; _