diff -u --recursive --new-file linux-2.4.19-02-fix_kmap2/fs/nfs/nfs2xdr.c linux-2.4.19-03-fix_kmap3/fs/nfs/nfs2xdr.c --- linux-2.4.19-02-fix_kmap2/fs/nfs/nfs2xdr.c Sat Oct 5 03:10:49 2002 +++ linux-2.4.19-03-fix_kmap3/fs/nfs/nfs2xdr.c Sat Oct 5 03:45:06 2002 @@ -87,17 +87,6 @@ return p + XDR_QUADLEN(NFS2_FHSIZE); } -static inline u32 * -xdr_decode_string2(u32 *p, char **string, unsigned int *len, - unsigned int maxlen) -{ - *len = ntohl(*p++); - if (*len > maxlen) - return NULL; - *string = (char *) p; - return p + XDR_QUADLEN(*len); -} - static inline u32* xdr_decode_time(u32 *p, u64 *timep) { @@ -106,7 +95,7 @@ return p; } -static inline u32 * +static u32 * xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) { fattr->type = (enum nfs_ftype) ntohl(*p++); @@ -257,7 +246,7 @@ 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); @@ -394,7 +383,7 @@ struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct iovec *iov = rcvbuf->head; struct page **page; - int hdrlen; + int hdrlen, recvd; int status, nr; unsigned int len, pglen; u32 *end, *entry; @@ -409,11 +398,14 @@ } pglen = rcvbuf->page_len; + recvd = req->rq_received - hdrlen; + if (pglen > recvd) + pglen = recvd; page = rcvbuf->pages; p = kmap(*page); end = (u32 *)((char *)p + pglen); + entry = p; for (nr = 0; *p++; nr++) { - entry = p - 1; if (p + 2 > end) goto short_pkt; p++; /* fileid */ @@ -426,14 +418,21 @@ } if (p + 2 > end) goto short_pkt; + entry = p; } + if (!nr && (entry[0] != 0 || entry[1] == 0)) + goto short_pkt; + out: kunmap(*page); return nr; short_pkt: - printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); entry[0] = entry[1] = 0; - kunmap(*page); - return nr; + /* truncate listing? */ + if (!nr) { + printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); + entry[1] = 1; + } + goto out; err_unmap: kunmap(*page); return -errno_NFSERR_IO; diff -u --recursive --new-file linux-2.4.19-02-fix_kmap2/fs/nfs/nfs3xdr.c linux-2.4.19-03-fix_kmap3/fs/nfs/nfs3xdr.c --- linux-2.4.19-02-fix_kmap2/fs/nfs/nfs3xdr.c Sat Oct 5 03:10:49 2002 +++ linux-2.4.19-03-fix_kmap3/fs/nfs/nfs3xdr.c Sat Oct 5 03:45:44 2002 @@ -153,18 +153,7 @@ return p; } -static inline u32 * -xdr_decode_string2(u32 *p, char **string, unsigned int *len, - unsigned int maxlen) -{ - *len = ntohl(*p++); - if (*len > maxlen) - return NULL; - *string = (char *) p; - return p + XDR_QUADLEN(*len); -} - -static inline u32 * +static u32 * xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) { unsigned int type; @@ -514,7 +503,7 @@ struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct iovec *iov = rcvbuf->head; struct page **page; - int hdrlen; + int hdrlen, recvd; int status, nr; unsigned int len, pglen; u32 *entry, *end; @@ -539,11 +528,14 @@ } pglen = rcvbuf->page_len; + recvd = req->rq_received - hdrlen; + if (pglen > recvd) + pglen = recvd; page = rcvbuf->pages; p = kmap(*page); + entry = p; end = (u32 *)((char *)p + pglen); for (nr = 0; *p++; nr++) { - entry = p - 1; if (p + 3 > end) goto short_pkt; p += 2; /* inode # */ @@ -580,15 +572,21 @@ if (p + 2 > end) goto short_pkt; + entry = p; } + if (!nr && (entry[0] != 0 || entry[1] == 0)) + goto short_pkt; + out: kunmap(*page); return nr; short_pkt: - printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); - /* truncate listing */ entry[0] = entry[1] = 0; - kunmap(*page); - return nr; + /* truncate listing? */ + if (!nr) { + printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); + entry[1] = 1; + } + goto out; err_unmap: kunmap(*page); return -errno_NFSERR_IO; @@ -810,7 +808,7 @@ 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); diff -u --recursive --new-file linux-2.4.19-02-fix_kmap2/include/linux/sunrpc/xprt.h linux-2.4.19-03-fix_kmap3/include/linux/sunrpc/xprt.h --- linux-2.4.19-02-fix_kmap2/include/linux/sunrpc/xprt.h Sat Oct 5 03:10:50 2002 +++ linux-2.4.19-03-fix_kmap3/include/linux/sunrpc/xprt.h Sat Oct 5 03:11:10 2002 @@ -66,15 +66,6 @@ }; /* - * This is the RPC buffer - */ -struct rpc_iov { - struct iovec io_vec[MAX_IOVEC]; - unsigned int io_nr; - unsigned int io_len; -}; - -/* * This describes a complete RPC request */ struct rpc_rqst { diff -u --recursive --new-file linux-2.4.19-02-fix_kmap2/net/sunrpc/xdr.c linux-2.4.19-03-fix_kmap3/net/sunrpc/xdr.c --- linux-2.4.19-02-fix_kmap2/net/sunrpc/xdr.c Sat Oct 5 03:10:51 2002 +++ linux-2.4.19-03-fix_kmap3/net/sunrpc/xdr.c Sat Oct 5 03:11:11 2002 @@ -174,24 +174,6 @@ } /* - * Zero the last n bytes in an iovec array of 'nr' elements - */ -void xdr_zero_iovec(struct iovec *iov, int nr, size_t n) -{ - struct iovec *pvec; - - for (pvec = iov + nr - 1; n && nr > 0; nr--, pvec--) { - if (n < pvec->iov_len) { - memset((char *)pvec->iov_base + pvec->iov_len - n, 0, n); - n = 0; - } else { - memset(pvec->iov_base, 0, pvec->iov_len); - n -= pvec->iov_len; - } - } -} - -/* * Map a struct xdr_buf into an iovec array. */ int xdr_kmap(struct iovec *iov_base, struct xdr_buf *xdr, unsigned int base) diff -u --recursive --new-file linux-2.4.19-02-fix_kmap2/net/sunrpc/xprt.c linux-2.4.19-03-fix_kmap3/net/sunrpc/xprt.c --- linux-2.4.19-02-fix_kmap2/net/sunrpc/xprt.c Sat Oct 5 03:10:51 2002 +++ linux-2.4.19-03-fix_kmap3/net/sunrpc/xprt.c Sat Oct 5 03:11:11 2002 @@ -130,41 +130,6 @@ } /* - * Adjust the iovec to move on 'n' bytes - */ - -extern inline void -xprt_move_iov(struct msghdr *msg, struct iovec *niv, unsigned amount) -{ - struct iovec *iv=msg->msg_iov; - int i; - - /* - * Eat any sent iovecs - */ - while (iv->iov_len <= amount) { - amount -= iv->iov_len; - iv++; - msg->msg_iovlen--; - } - - /* - * And chew down the partial one - */ - niv[0].iov_len = iv->iov_len-amount; - niv[0].iov_base =((unsigned char *)iv->iov_base)+amount; - iv++; - - /* - * And copy any others - */ - for(i = 1; i < msg->msg_iovlen; i++) - niv[i]=*iv++; - - msg->msg_iov=niv; -} - -/* * Serialize write access to sockets, in order to prevent different * requests from interfering with each other. * Also prevents TCP socket reconnections from colliding with writes.