SUNRPC: Cleanup xdr_shrink_bufhead()
Clean up xdr_shrink_bufhead() to use the new helpers instead of doing its own thing. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
c4f2f591f0
commit
6707fbd7d3
164
net/sunrpc/xdr.c
164
net/sunrpc/xdr.c
|
@ -550,6 +550,53 @@ static void xdr_buf_pages_copy_right(const struct xdr_buf *buf,
|
||||||
buf->page_base + base, pglen);
|
buf->page_base + base, pglen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xdr_buf_head_copy_right(const struct xdr_buf *buf,
|
||||||
|
unsigned int base, unsigned int len,
|
||||||
|
unsigned int shift)
|
||||||
|
{
|
||||||
|
const struct kvec *head = buf->head;
|
||||||
|
const struct kvec *tail = buf->tail;
|
||||||
|
unsigned int to = base + shift;
|
||||||
|
unsigned int pglen = 0, pgto = 0;
|
||||||
|
unsigned int talen = 0, tato = 0;
|
||||||
|
|
||||||
|
if (base >= head->iov_len)
|
||||||
|
return;
|
||||||
|
if (len > head->iov_len - base)
|
||||||
|
len = head->iov_len - base;
|
||||||
|
if (to >= buf->page_len + head->iov_len) {
|
||||||
|
tato = to - buf->page_len - head->iov_len;
|
||||||
|
talen = len;
|
||||||
|
} else if (to >= head->iov_len) {
|
||||||
|
pgto = to - head->iov_len;
|
||||||
|
pglen = len;
|
||||||
|
if (pgto + pglen > buf->page_len) {
|
||||||
|
talen = pgto + pglen - buf->page_len;
|
||||||
|
pglen -= talen;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pglen = len - to;
|
||||||
|
if (pglen > buf->page_len) {
|
||||||
|
talen = pglen - buf->page_len;
|
||||||
|
pglen = buf->page_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len -= talen;
|
||||||
|
base += len;
|
||||||
|
if (talen + tato > tail->iov_len)
|
||||||
|
talen = tail->iov_len > tato ? tail->iov_len - tato : 0;
|
||||||
|
memcpy(tail->iov_base + tato, head->iov_base + base, talen);
|
||||||
|
|
||||||
|
len -= pglen;
|
||||||
|
base -= pglen;
|
||||||
|
_copy_to_pages(buf->pages, buf->page_base + pgto, head->iov_base + base,
|
||||||
|
pglen);
|
||||||
|
|
||||||
|
base -= len;
|
||||||
|
memmove(head->iov_base + to, head->iov_base + base, len);
|
||||||
|
}
|
||||||
|
|
||||||
static void xdr_buf_tail_shift_right(const struct xdr_buf *buf,
|
static void xdr_buf_tail_shift_right(const struct xdr_buf *buf,
|
||||||
unsigned int base, unsigned int len,
|
unsigned int base, unsigned int len,
|
||||||
unsigned int shift)
|
unsigned int shift)
|
||||||
|
@ -577,6 +624,25 @@ static void xdr_buf_pages_shift_right(const struct xdr_buf *buf,
|
||||||
xdr_buf_pages_copy_right(buf, base, len, shift);
|
xdr_buf_pages_copy_right(buf, base, len, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xdr_buf_head_shift_right(const struct xdr_buf *buf,
|
||||||
|
unsigned int base, unsigned int len,
|
||||||
|
unsigned int shift)
|
||||||
|
{
|
||||||
|
const struct kvec *head = buf->head;
|
||||||
|
|
||||||
|
if (!shift)
|
||||||
|
return;
|
||||||
|
if (base >= head->iov_len) {
|
||||||
|
xdr_buf_pages_shift_right(buf, head->iov_len - base, len,
|
||||||
|
shift);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (base + len > head->iov_len)
|
||||||
|
xdr_buf_pages_shift_right(buf, 0, base + len - head->iov_len,
|
||||||
|
shift);
|
||||||
|
xdr_buf_head_copy_right(buf, base, len, shift);
|
||||||
|
}
|
||||||
|
|
||||||
static void xdr_buf_tail_copy_left(const struct xdr_buf *buf, unsigned int base,
|
static void xdr_buf_tail_copy_left(const struct xdr_buf *buf, unsigned int base,
|
||||||
unsigned int len, unsigned int shift)
|
unsigned int len, unsigned int shift)
|
||||||
{
|
{
|
||||||
|
@ -683,86 +749,31 @@ static void xdr_buf_pages_shift_left(const struct xdr_buf *buf,
|
||||||
/**
|
/**
|
||||||
* xdr_shrink_bufhead
|
* xdr_shrink_bufhead
|
||||||
* @buf: xdr_buf
|
* @buf: xdr_buf
|
||||||
* @len: bytes to remove from buf->head[0]
|
* @len: new length of buf->head[0]
|
||||||
*
|
*
|
||||||
* Shrinks XDR buffer's header kvec buf->head[0] by
|
* Shrinks XDR buffer's header kvec buf->head[0], setting it to
|
||||||
* 'len' bytes. The extra data is not lost, but is instead
|
* 'len' bytes. The extra data is not lost, but is instead
|
||||||
* moved into the inlined pages and/or the tail.
|
* moved into the inlined pages and/or the tail.
|
||||||
*/
|
*/
|
||||||
static unsigned int
|
static unsigned int xdr_shrink_bufhead(struct xdr_buf *buf, unsigned int len)
|
||||||
xdr_shrink_bufhead(struct xdr_buf *buf, size_t len)
|
|
||||||
{
|
{
|
||||||
struct kvec *head, *tail;
|
struct kvec *head = buf->head;
|
||||||
size_t copy, offs;
|
unsigned int shift, buflen = max(buf->len, len);
|
||||||
unsigned int pglen = buf->page_len;
|
|
||||||
unsigned int result;
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
tail = buf->tail;
|
|
||||||
head = buf->head;
|
|
||||||
|
|
||||||
WARN_ON_ONCE(len > head->iov_len);
|
WARN_ON_ONCE(len > head->iov_len);
|
||||||
if (len > head->iov_len)
|
if (head->iov_len > buflen) {
|
||||||
len = head->iov_len;
|
buf->buflen -= head->iov_len - buflen;
|
||||||
|
head->iov_len = buflen;
|
||||||
/* Shift the tail first */
|
|
||||||
if (tail->iov_len != 0) {
|
|
||||||
if (tail->iov_len > len) {
|
|
||||||
copy = tail->iov_len - len;
|
|
||||||
memmove((char *)tail->iov_base + len,
|
|
||||||
tail->iov_base, copy);
|
|
||||||
result += copy;
|
|
||||||
}
|
|
||||||
/* Copy from the inlined pages into the tail */
|
|
||||||
copy = len;
|
|
||||||
if (copy > pglen)
|
|
||||||
copy = pglen;
|
|
||||||
offs = len - copy;
|
|
||||||
if (offs >= tail->iov_len)
|
|
||||||
copy = 0;
|
|
||||||
else if (copy > tail->iov_len - offs)
|
|
||||||
copy = tail->iov_len - offs;
|
|
||||||
if (copy != 0) {
|
|
||||||
_copy_from_pages((char *)tail->iov_base + offs,
|
|
||||||
buf->pages,
|
|
||||||
buf->page_base + pglen + offs - len,
|
|
||||||
copy);
|
|
||||||
result += copy;
|
|
||||||
}
|
|
||||||
/* Do we also need to copy data from the head into the tail ? */
|
|
||||||
if (len > pglen) {
|
|
||||||
offs = copy = len - pglen;
|
|
||||||
if (copy > tail->iov_len)
|
|
||||||
copy = tail->iov_len;
|
|
||||||
memcpy(tail->iov_base,
|
|
||||||
(char *)head->iov_base +
|
|
||||||
head->iov_len - offs,
|
|
||||||
copy);
|
|
||||||
result += copy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Now handle pages */
|
if (len >= head->iov_len)
|
||||||
if (pglen != 0) {
|
return 0;
|
||||||
if (pglen > len)
|
shift = head->iov_len - len;
|
||||||
_shift_data_right_pages(buf->pages,
|
xdr_buf_try_expand(buf, shift);
|
||||||
buf->page_base + len,
|
xdr_buf_head_shift_right(buf, len, buflen - len, shift);
|
||||||
buf->page_base,
|
head->iov_len = len;
|
||||||
pglen - len);
|
buf->buflen -= shift;
|
||||||
copy = len;
|
buf->len -= shift;
|
||||||
if (len > pglen)
|
return shift;
|
||||||
copy = pglen;
|
|
||||||
_copy_to_pages(buf->pages, buf->page_base,
|
|
||||||
(char *)head->iov_base + head->iov_len - len,
|
|
||||||
copy);
|
|
||||||
result += copy;
|
|
||||||
}
|
|
||||||
head->iov_len -= len;
|
|
||||||
buf->buflen -= len;
|
|
||||||
/* Have we truncated the message? */
|
|
||||||
if (buf->len > buf->buflen)
|
|
||||||
buf->len = buf->buflen;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -798,7 +809,7 @@ static unsigned int xdr_shrink_pagelen(struct xdr_buf *buf, unsigned int len)
|
||||||
void
|
void
|
||||||
xdr_shift_buf(struct xdr_buf *buf, size_t len)
|
xdr_shift_buf(struct xdr_buf *buf, size_t len)
|
||||||
{
|
{
|
||||||
xdr_shrink_bufhead(buf, len);
|
xdr_shrink_bufhead(buf, buf->head->iov_len - len);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(xdr_shift_buf);
|
EXPORT_SYMBOL_GPL(xdr_shift_buf);
|
||||||
|
|
||||||
|
@ -1371,13 +1382,12 @@ static void xdr_realign_pages(struct xdr_stream *xdr)
|
||||||
struct xdr_buf *buf = xdr->buf;
|
struct xdr_buf *buf = xdr->buf;
|
||||||
struct kvec *iov = buf->head;
|
struct kvec *iov = buf->head;
|
||||||
unsigned int cur = xdr_stream_pos(xdr);
|
unsigned int cur = xdr_stream_pos(xdr);
|
||||||
unsigned int copied, offset;
|
unsigned int copied;
|
||||||
|
|
||||||
/* Realign pages to current pointer position */
|
/* Realign pages to current pointer position */
|
||||||
if (iov->iov_len > cur) {
|
if (iov->iov_len > cur) {
|
||||||
offset = iov->iov_len - cur;
|
copied = xdr_shrink_bufhead(buf, cur);
|
||||||
copied = xdr_shrink_bufhead(buf, offset);
|
trace_rpc_xdr_alignment(xdr, cur, copied);
|
||||||
trace_rpc_xdr_alignment(xdr, offset, copied);
|
|
||||||
xdr->nwords = XDR_QUADLEN(buf->len - cur);
|
xdr->nwords = XDR_QUADLEN(buf->len - cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue