diff options
| author | Chuck Lever <cel@citi.umich.edu> | 2002-11-07 00:43:38 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-11-07 00:43:38 -0800 |
| commit | 0bce91be4b67ba6aab55d889b7d4c23ba28ada53 (patch) | |
| tree | 9ac5047dd16d4191eb5ccbd20f420831e266c0e5 | |
| parent | 2fbace6096db970a2e5c1e5a25570135394f494c (diff) | |
[PATCH] bug in NFSv2 end-of-file read handling
NFSv2 doesn't pass connectathon 2002, at least on some Linux kernels.
Trond deemed the following modification necessary in all kernels to
address the problem.
| -rw-r--r-- | fs/nfs/nfs2xdr.c | 7 | ||||
| -rw-r--r-- | fs/nfs/read.c | 18 |
2 files changed, 13 insertions, 12 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 8e652afdfea4..4673cca4d3b3 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -233,7 +233,6 @@ nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) static int nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) { - struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct iovec *iov = req->rq_rvec; int status, count, recvd, hdrlen; @@ -243,11 +242,6 @@ nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) count = ntohl(*p++); res->eof = 0; - if (rcvbuf->page_len) { - u32 end = page_offset(rcvbuf->pages[0]) + rcvbuf->page_base + count; - if (end >= res->fattr->size) - res->eof = 1; - } hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len < hdrlen) { printk(KERN_WARNING "NFS: READ reply header overflowed:" @@ -263,7 +257,6 @@ nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) printk(KERN_WARNING "NFS: server cheating in read reply: " "count %d > recvd %d\n", count, recvd); count = recvd; - res->eof = 0; } dprintk("RPC: readres OK count %d\n", count); diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 01d2447b737c..647ea4898a0d 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -256,11 +256,12 @@ nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof) { struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct inode *inode = data->inode; + struct nfs_fattr *fattr = &data->fattr; dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", task->tk_pid, task->tk_status); - nfs_refresh_inode(inode, &data->fattr); + nfs_refresh_inode(inode, fattr); while (!list_empty(&data->pages)) { struct nfs_page *req = nfs_list_entry(data->pages.next); struct page *page = req->wb_page; @@ -269,13 +270,20 @@ nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof) if (task->tk_status >= 0) { if (count < PAGE_CACHE_SIZE) { char *p = kmap(page); - memset(p + count, 0, PAGE_CACHE_SIZE - count); + + if (count < req->wb_bytes) + memset(p + req->wb_offset + count, 0, + req->wb_bytes - count); kunmap(page); - count = 0; - if (eof) + + if (eof || + ((fattr->valid & NFS_ATTR_FATTR) && + ((req_offset(req) + req->wb_offset + count) >= fattr->size))) SetPageUptodate(page); else - SetPageError(page); + if (count < req->wb_bytes) + SetPageError(page); + count = 0; } else { count -= PAGE_CACHE_SIZE; SetPageUptodate(page); |
