From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 04/16] SUNRPC: Cleanup xdr_shrink_bufhead() Date: Wed, 9 Dec 2020 09:47:49 -0500 Message-ID: <20201209144801.700778-5-trondmy@kernel.org> (raw) In-Reply-To: <20201209144801.700778-4-trondmy@kernel.org> From: Trond Myklebust <trond.myklebust@hammerspace.com> 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> --- net/sunrpc/xdr.c | 160 +++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index e19e89cbb6eb..cbf1bccac4fc 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -544,6 +544,51 @@ static void xdr_buf_pages_copy_right(const struct xdr_buf *buf, buf->page_base + base, pglen); } +static void xdr_buf_head_copy_right(const struct xdr_buf *buf, + unsigned int base, unsigned int shift) +{ + const struct kvec *head = buf->head; + const struct kvec *tail = buf->tail; + unsigned int to = base + shift; + unsigned int len = head->iov_len - base; + unsigned int pglen = 0, pgto = 0; + unsigned int talen = 0, tato = 0; + + if (base >= head->iov_len) + return; + if (head->iov_len > to) { + pglen = shift; + if (pglen > buf->page_len) { + talen = pglen - buf->page_len; + pglen = buf->page_len; + } + } else if (buf->page_len + head->iov_len > to) { + pgto = to - head->iov_len; + pglen = len; + if (pgto + pglen > buf->page_len) { + talen = pgto + pglen - buf->page_len; + pglen -= talen; + } + } else { + tato = to - buf->page_len - head->iov_len; + talen = 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, unsigned int base, unsigned int shift) { @@ -567,6 +612,21 @@ static void xdr_buf_pages_shift_right(const struct xdr_buf *buf, xdr_buf_pages_copy_right(buf, base, shift); } +static void xdr_buf_head_shift_right(const struct xdr_buf *buf, + unsigned int base, 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, shift); + return; + } + xdr_buf_pages_shift_right(buf, 0, shift); + xdr_buf_head_copy_right(buf, base, shift); +} + static void xdr_buf_tail_copy_left(const struct xdr_buf *buf, unsigned int base, unsigned int shift) { @@ -665,86 +725,27 @@ static void xdr_buf_pages_shift_left(const struct xdr_buf *buf, /** * xdr_shrink_bufhead * @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 * moved into the inlined pages and/or the tail. */ -static unsigned int -xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) -{ - struct kvec *head, *tail; - size_t copy, offs; - unsigned int pglen = buf->page_len; - unsigned int result; - - result = 0; - tail = buf->tail; - head = buf->head; - - WARN_ON_ONCE(len > head->iov_len); - if (len > head->iov_len) - len = head->iov_len; - - /* 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 (pglen != 0) { - if (pglen > len) - _shift_data_right_pages(buf->pages, - buf->page_base + len, - buf->page_base, - pglen - len); - copy = len; - if (len > pglen) - 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; +static unsigned int xdr_shrink_bufhead(struct xdr_buf *buf, unsigned int len) +{ + struct kvec *head = buf->head; + unsigned int shift = head->iov_len - len; - return result; + WARN_ON_ONCE(shift > head->iov_len); + if (len >= head->iov_len) + return 0; + + xdr_buf_try_expand(buf, shift); + xdr_buf_head_shift_right(buf, len, shift); + head->iov_len = len; + buf->buflen -= shift; + buf->len -= shift; + return shift; } /** @@ -772,7 +773,7 @@ static unsigned int xdr_shrink_pagelen(struct xdr_buf *buf, unsigned int len) void 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); @@ -1345,13 +1346,12 @@ static void xdr_realign_pages(struct xdr_stream *xdr) struct xdr_buf *buf = xdr->buf; struct kvec *iov = buf->head; unsigned int cur = xdr_stream_pos(xdr); - unsigned int copied, offset; + unsigned int copied; /* Realign pages to current pointer position */ if (iov->iov_len > cur) { - offset = iov->iov_len - cur; - copied = xdr_shrink_bufhead(buf, offset); - trace_rpc_xdr_alignment(xdr, offset, copied); + copied = xdr_shrink_bufhead(buf, cur); + trace_rpc_xdr_alignment(xdr, cur, copied); xdr->nwords = XDR_QUADLEN(buf->len - cur); } } -- 2.29.2
next prev parent reply index Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-12-09 14:47 [PATCH 00/16] Fixes for the NFSv4.2 READ_PLUS operation trondmy 2020-12-09 14:47 ` [PATCH 01/16] SUNRPC: _shift_data_left/right_pages should check the shift length trondmy 2020-12-09 14:47 ` [PATCH 02/16] SUNRPC: Fixes for xdr_align_data() trondmy 2020-12-09 14:47 ` [PATCH 03/16] SUNRPC: Fix xdr_expand_hole() trondmy 2020-12-09 14:47 ` trondmy [this message] 2020-12-09 14:47 ` [PATCH 05/16] SUNRPC: _copy_to/from_pages() now check for zero length trondmy 2020-12-09 14:47 ` [PATCH 06/16] SUNRPC: Clean up open coded setting of the xdr_stream 'nwords' field trondmy 2020-12-09 14:47 ` [PATCH 07/16] SUNRPC: Cleanup - constify a number of xdr_buf helpers trondmy 2020-12-09 14:47 ` [PATCH 08/16] SUNRPC: Avoid unnecessary copies in xdr_buf_pages_copy_left/right() trondmy 2020-12-09 14:47 ` [PATCH 09/16] NFSv4.2: Ensure we always reset the result->count in decode_read_plus() trondmy 2020-12-09 14:47 ` [PATCH 10/16] NFSv4.2: decode_read_plus_data() must skip padding after data segment trondmy 2020-12-09 14:47 ` [PATCH 11/16] NFSv4.2: decode_read_plus_hole() needs to check the extent offset trondmy 2020-12-09 14:47 ` [PATCH 12/16] NFSv4.2: Handle hole lengths that exceed the READ_PLUS read buffer trondmy 2020-12-09 14:47 ` [PATCH 13/16] NFSv4.2: Don't error when exiting early on a READ_PLUS buffer overflow trondmy 2020-12-09 14:47 ` [PATCH 14/16] NFSv4.2: Deal with potential READ_PLUS data extent " trondmy 2020-12-09 14:48 ` [PATCH 15/16] nfsd: Fixes for nfsd4_encode_read_plus_data() trondmy 2020-12-09 14:48 ` [PATCH 16/16] nfsd: Don't set eof on a truncated READ_PLUS trondmy 2020-12-09 16:16 ` [PATCH 15/16] nfsd: Fixes for nfsd4_encode_read_plus_data() Chuck Lever 2020-12-09 16:39 ` Trond Myklebust 2020-12-09 16:57 ` Chuck Lever 2020-12-09 17:01 ` Trond Myklebust
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20201209144801.700778-5-trondmy@kernel.org \ --to=trondmy@kernel.org \ --cc=linux-nfs@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Linux-NFS Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/linux-nfs/0 linux-nfs/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 linux-nfs linux-nfs/ https://lore.kernel.org/linux-nfs \ linux-nfs@vger.kernel.org public-inbox-index linux-nfs Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.kernel.vger.linux-nfs AGPL code for this site: git clone https://public-inbox.org/public-inbox.git