Commit 0bce91be authored by Chuck Lever's avatar Chuck Lever Committed by Linus Torvalds

[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.
parent 2fbace60
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment