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 [thread overview]
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 other threads:[~2020-12-09 14:49 UTC|newest]
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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).