Commit 43f0f081 authored by Anna Schumaker's avatar Anna Schumaker
Browse files

SUNRPC: Split out _shift_data_right_tail()



xdr_shrink_pagelen() is very similar to what we need for hole expansion,
so split out the common code into its own function that can be used by
both functions.

Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 06216ecb
Loading
Loading
Loading
Loading
+41 −27
Original line number Diff line number Diff line
@@ -266,6 +266,46 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base,
	} while ((len -= copy) != 0);
}

static unsigned int
_shift_data_right_tail(struct xdr_buf *buf, unsigned int pgfrom, size_t len)
{
	struct kvec *tail = buf->tail;
	unsigned int tailbuf_len;
	unsigned int result = 0;
	size_t copy;

	tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;

	/* Shift the tail first */
	if (tailbuf_len != 0) {
		unsigned int free_space = tailbuf_len - tail->iov_len;

		if (len < free_space)
			free_space = len;
		if (len > free_space)
			len = free_space;

		tail->iov_len += free_space;
		copy = len;

		if (tail->iov_len > len) {
			char *p = (char *)tail->iov_base + len;
			memmove(p, tail->iov_base, tail->iov_len - free_space);
			result += tail->iov_len - free_space;
		} else
			copy = tail->iov_len;

		/* Copy from the inlined pages into the tail */
		_copy_from_pages((char *)tail->iov_base,
					 buf->pages,
					 buf->page_base + pgfrom,
					 copy);
		result += copy;
	}

	return result;
}

/**
 * _copy_to_pages
 * @pages: array of pages
@@ -446,39 +486,13 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len)
static unsigned int
xdr_shrink_pagelen(struct xdr_buf *buf, size_t len)
{
	struct kvec *tail;
	size_t copy;
	unsigned int pglen = buf->page_len;
	unsigned int tailbuf_len;
	unsigned int result;

	result = 0;
	tail = buf->tail;
	if (len > buf->page_len)
		len = buf-> page_len;
	tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;

	/* Shift the tail first */
	if (tailbuf_len != 0) {
		unsigned int free_space = tailbuf_len - tail->iov_len;

		if (len < free_space)
			free_space = len;
		tail->iov_len += free_space;

		copy = len;
		if (tail->iov_len > len) {
			char *p = (char *)tail->iov_base + len;
			memmove(p, tail->iov_base, tail->iov_len - len);
			result += tail->iov_len - len;
		} else
			copy = tail->iov_len;
		/* Copy from the inlined pages into the tail */
		_copy_from_pages((char *)tail->iov_base,
				buf->pages, buf->page_base + pglen - len,
				copy);
		result += copy;
	}
	result = _shift_data_right_tail(buf, pglen - len, len);
	buf->page_len -= len;
	buf->buflen -= len;
	/* Have we truncated the message? */