diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-06-22 19:16:19 +0200 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-06-22 22:07:02 +0200 |
commit | 334ccfd545bba9690515f2c5c167d5adb161989b (patch) | |
tree | 8a06af4d40c711c578adc36d9afd3200a88a2689 /net/sunrpc/xdr.c | |
parent | [PATCH] RPC: Fix a race with rpc_restart_call() (diff) | |
download | linux-334ccfd545bba9690515f2c5c167d5adb161989b.tar.xz linux-334ccfd545bba9690515f2c5c167d5adb161989b.zip |
[PATCH] RPC: Ensure XDR iovec length is initialized correctly in call_header
Fix up call_header() so that it calls xdr_adjust_iovec().
Fix calculation of the scratch buffer length in xdr_init_encode().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xdr.c')
-rw-r--r-- | net/sunrpc/xdr.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 67b9f035ba86..f86d1baa6302 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -616,12 +616,24 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len) void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p) { struct kvec *iov = buf->head; + int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; + BUG_ON(scratch_len < 0); xdr->buf = buf; xdr->iov = iov; - xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len); - buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base; - xdr->p = p; + xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len); + xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len); + BUG_ON(iov->iov_len > scratch_len); + + if (p != xdr->p && p != NULL) { + size_t len; + + BUG_ON(p < xdr->p || p > xdr->end); + len = (char *)p - (char *)xdr->p; + xdr->p = p; + buf->len += len; + iov->iov_len += len; + } } EXPORT_SYMBOL(xdr_init_encode); |