Cheers,
Trond
diff -u --recursive --new-file linux-2.5.31/fs/nfs/nfs2xdr.c linux-2.5.31-fix_read/fs/nfs/nfs2xdr.c
--- linux-2.5.31/fs/nfs/nfs2xdr.c Wed Jul 31 17:35:17 2002
+++ linux-2.5.31-fix_read/fs/nfs/nfs2xdr.c Tue Aug 20 17:10:08 2002
@@ -233,6 +233,7 @@
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;
@@ -241,25 +242,33 @@
p = xdr_decode_fattr(p, res->fattr);
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) {
+ if (iov->iov_len < hdrlen) {
+ printk(KERN_WARNING "NFS: READ reply header overflowed:"
+ "length %d > %d\n", hdrlen, iov->iov_len);
+ return -errno_NFSERR_IO;
+ } else if (iov->iov_len != hdrlen) {
dprintk("NFS: READ header is short. iovec will be shifted.\n");
xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
}
- recvd = req->rq_rlen - hdrlen;
+ recvd = req->rq_received - hdrlen;
if (count > recvd) {
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);
- if (count < res->count) {
+ if (count < res->count)
res->count = count;
- res->eof = 1; /* Silly NFSv3ism which can't be helped */
- } else
- res->eof = 0;
return count;
}
diff -u --recursive --new-file linux-2.5.31/fs/nfs/nfs3xdr.c linux-2.5.31-fix_read/fs/nfs/nfs3xdr.c
--- linux-2.5.31/fs/nfs/nfs3xdr.c Wed Jul 31 17:31:30 2002
+++ linux-2.5.31-fix_read/fs/nfs/nfs3xdr.c Tue Aug 20 17:10:08 2002
@@ -793,16 +793,21 @@
}
hdrlen = (u8 *) p - (u8 *) iov->iov_base;
- if (iov->iov_len > hdrlen) {
+ if (iov->iov_len < hdrlen) {
+ printk(KERN_WARNING "NFS: READ reply header overflowed:"
+ "length %d > %d\n", hdrlen, iov->iov_len);
+ return -errno_NFSERR_IO;
+ } else if (iov->iov_len != hdrlen) {
dprintk("NFS: READ header is short. iovec will be shifted.\n");
xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
}
- recvd = req->rq_rlen - hdrlen;
+ recvd = req->rq_received - hdrlen;
if (count > recvd) {
printk(KERN_WARNING "NFS: server cheating in read reply: "
"count %d > recvd %d\n", count, recvd);
count = recvd;
+ res->eof = 0;
}
if (count < res->count)
diff -u --recursive --new-file linux-2.5.31/fs/nfs/read.c linux-2.5.31-fix_read/fs/nfs/read.c
--- linux-2.5.31/fs/nfs/read.c Thu May 23 17:10:17 2002
+++ linux-2.5.31-fix_read/fs/nfs/read.c Tue Aug 20 17:10:08 2002
@@ -424,9 +424,14 @@
memset(p + count, 0, PAGE_CACHE_SIZE - count);
kunmap(page);
count = 0;
- } else
+ if (data->res.eof)
+ SetPageUptodate(page);
+ else
+ SetPageError(page);
+ } else {
count -= PAGE_CACHE_SIZE;
- SetPageUptodate(page);
+ SetPageUptodate(page);
+ }
} else
SetPageError(page);
flush_dcache_page(page);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/