diff -X /home/cel/src/linux/dont-diff -Naurp old/net/sunrpc/xdr.c new/net/sunrpc/xdr.c --- old/net/sunrpc/xdr.c Tue Oct 28 18:33:02 2003 +++ new/net/sunrpc/xdr.c Tue Oct 28 18:35:41 2003 @@ -215,7 +215,8 @@ int xdr_kmap(struct iovec *iov_base, str { struct iovec *iov = iov_base; struct page **ppage = xdr->pages; - unsigned int len, pglen = xdr->page_len, first_kmap; + struct page **first_kmap = NULL; + unsigned int len, pglen = xdr->page_len; len = xdr->head[0].iov_len; if (base < len) { @@ -238,16 +239,15 @@ int xdr_kmap(struct iovec *iov_base, str ppage += base >> PAGE_CACHE_SHIFT; base &= ~PAGE_CACHE_MASK; } - first_kmap = 1; do { len = PAGE_CACHE_SIZE; - if (first_kmap) { - first_kmap = 0; + if (!first_kmap) { + first_kmap = ppage; iov->iov_base = kmap(*ppage); } else { iov->iov_base = kmap_nonblock(*ppage); if (!iov->iov_base) - goto out; + goto out_err; } if (base) { iov->iov_base += base; @@ -268,6 +268,10 @@ map_tail: } out: return (iov - iov_base); +out_err: + for (; first_kmap != ppage; first_kmap++) + kunmap(*first_kmap); + return 0; } void xdr_kunmap(struct xdr_buf *xdr, unsigned int base, int niov) diff -X /home/cel/src/linux/dont-diff -Naurp old/net/sunrpc/xprt.c new/net/sunrpc/xprt.c --- old/net/sunrpc/xprt.c Tue Oct 28 18:33:02 2003 +++ new/net/sunrpc/xprt.c Tue Oct 28 18:35:41 2003 @@ -174,6 +174,10 @@ xprt_sendmsg(struct rpc_xprt *xprt, stru unsigned int slen_part, n; niov = xdr_kmap(niv, xdr, skip); + if (!niov) { + result = -EAGAIN; + break; + } msg.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL; msg.msg_iov = niv;