Commit 8d86e373 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Clean up helpers xdr_set_iov() and xdr_set_page_base()



Allow xdr_set_iov() to set a base so that we can use it to set the
cursor to a specific position in the kvec buffer.

If the new base overflows the kvec/pages buffer in either xdr_set_iov()
or xdr_set_page_base(), then truncate it so that we point to the end of
the buffer.

Finally, change both function to return the number of bytes remaining to
read in their buffers.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 2b1f83d1
Loading
Loading
Loading
Loading
+19 −17
Original line number Original line Diff line number Diff line
@@ -970,18 +970,21 @@ void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int b
}
}
EXPORT_SYMBOL_GPL(xdr_write_pages);
EXPORT_SYMBOL_GPL(xdr_write_pages);


static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov,
static unsigned int xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov,
		unsigned int len)
				unsigned int base, unsigned int len)
{
{
	if (len > iov->iov_len)
	if (len > iov->iov_len)
		len = iov->iov_len;
		len = iov->iov_len;
	xdr->p = (__be32*)iov->iov_base;
	if (unlikely(base > len))
		base = len;
	xdr->p = (__be32*)(iov->iov_base + base);
	xdr->end = (__be32*)(iov->iov_base + len);
	xdr->end = (__be32*)(iov->iov_base + len);
	xdr->iov = iov;
	xdr->iov = iov;
	xdr->page_ptr = NULL;
	xdr->page_ptr = NULL;
	return len - base;
}
}


static int xdr_set_page_base(struct xdr_stream *xdr,
static unsigned int xdr_set_page_base(struct xdr_stream *xdr,
				      unsigned int base, unsigned int len)
				      unsigned int base, unsigned int len)
{
{
	unsigned int pgnr;
	unsigned int pgnr;
@@ -991,8 +994,10 @@ static int xdr_set_page_base(struct xdr_stream *xdr,
	void *kaddr;
	void *kaddr;


	maxlen = xdr->buf->page_len;
	maxlen = xdr->buf->page_len;
	if (base >= maxlen)
	if (base >= maxlen) {
		return -EINVAL;
		base = maxlen;
		maxlen = 0;
	} else
		maxlen -= base;
		maxlen -= base;
	if (len > maxlen)
	if (len > maxlen)
		len = maxlen;
		len = maxlen;
@@ -1011,14 +1016,14 @@ static int xdr_set_page_base(struct xdr_stream *xdr,
		pgend = PAGE_SIZE;
		pgend = PAGE_SIZE;
	xdr->end = (__be32*)(kaddr + pgend);
	xdr->end = (__be32*)(kaddr + pgend);
	xdr->iov = NULL;
	xdr->iov = NULL;
	return 0;
	return len;
}
}


static void xdr_set_page(struct xdr_stream *xdr, unsigned int base,
static void xdr_set_page(struct xdr_stream *xdr, unsigned int base,
			 unsigned int len)
			 unsigned int len)
{
{
	if (xdr_set_page_base(xdr, base, len) < 0)
	if (xdr_set_page_base(xdr, base, len) == 0)
		xdr_set_iov(xdr, xdr->buf->tail, xdr->nwords << 2);
		xdr_set_iov(xdr, xdr->buf->tail, 0, xdr_stream_remaining(xdr));
}
}


static void xdr_set_next_page(struct xdr_stream *xdr)
static void xdr_set_next_page(struct xdr_stream *xdr)
@@ -1055,12 +1060,9 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p,
	xdr->scratch.iov_base = NULL;
	xdr->scratch.iov_base = NULL;
	xdr->scratch.iov_len = 0;
	xdr->scratch.iov_len = 0;
	xdr->nwords = XDR_QUADLEN(buf->len);
	xdr->nwords = XDR_QUADLEN(buf->len);
	if (buf->head[0].iov_len != 0)
	if (xdr_set_iov(xdr, buf->head, 0, buf->len) == 0 &&
		xdr_set_iov(xdr, buf->head, buf->len);
	    xdr_set_page_base(xdr, 0, buf->len) == 0)
	else if (buf->page_len != 0)
		xdr_set_iov(xdr, buf->tail, 0, buf->len);
		xdr_set_page_base(xdr, 0, buf->len);
	else
		xdr_set_iov(xdr, buf->tail, buf->len);
	if (p != NULL && p > xdr->p && xdr->end >= p) {
	if (p != NULL && p > xdr->p && xdr->end >= p) {
		xdr->nwords -= p - xdr->p;
		xdr->nwords -= p - xdr->p;
		xdr->p = p;
		xdr->p = p;