Commit 2f5705a5 authored by David Howells's avatar David Howells

afs: Use a bvec rather than a kvec in afs_send_pages()

Use a bvec rather than a kvec in afs_send_pages() as we don't then have to
call kmap() in advance.  This allows us to pass the array of contiguous
pages that we extracted through to rxrpc in one go rather than passing a
single page at a time.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 6a0e3999
...@@ -259,67 +259,74 @@ void afs_flat_call_destructor(struct afs_call *call) ...@@ -259,67 +259,74 @@ void afs_flat_call_destructor(struct afs_call *call)
call->buffer = NULL; call->buffer = NULL;
} }
#define AFS_BVEC_MAX 8
/*
* Load the given bvec with the next few pages.
*/
static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
struct bio_vec *bv, pgoff_t first, pgoff_t last,
unsigned offset)
{
struct page *pages[AFS_BVEC_MAX];
unsigned int nr, n, i, to, bytes = 0;
nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
n = find_get_pages_contig(call->mapping, first, nr, pages);
ASSERTCMP(n, ==, nr);
msg->msg_flags |= MSG_MORE;
for (i = 0; i < nr; i++) {
to = PAGE_SIZE;
if (first + i >= last) {
to = call->last_to;
msg->msg_flags &= ~MSG_MORE;
}
bv[i].bv_page = pages[i];
bv[i].bv_len = to - offset;
bv[i].bv_offset = offset;
bytes += to - offset;
offset = 0;
}
iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC, bv, nr, bytes);
}
/* /*
* attach the data from a bunch of pages on an inode to a call * attach the data from a bunch of pages on an inode to a call
*/ */
static int afs_send_pages(struct afs_call *call, struct msghdr *msg) static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
{ {
struct page *pages[8]; struct bio_vec bv[AFS_BVEC_MAX];
unsigned count, n, loop, offset, to; unsigned int bytes, nr, loop, offset;
pgoff_t first = call->first, last = call->last; pgoff_t first = call->first, last = call->last;
int ret; int ret;
_enter("");
offset = call->first_offset; offset = call->first_offset;
call->first_offset = 0; call->first_offset = 0;
do { do {
_debug("attach %lx-%lx", first, last); afs_load_bvec(call, msg, bv, first, last, offset);
offset = 0;
count = last - first + 1; bytes = msg->msg_iter.count;
if (count > ARRAY_SIZE(pages)) nr = msg->msg_iter.nr_segs;
count = ARRAY_SIZE(pages);
n = find_get_pages_contig(call->mapping, first, count, pages); /* Have to change the state *before* sending the last
ASSERTCMP(n, ==, count); * packet as RxRPC might give us the reply before it
* returns from sending the request.
loop = 0; */
do { if (first + nr >= last)
struct bio_vec bvec = {.bv_page = pages[loop], call->state = AFS_CALL_AWAIT_REPLY;
.bv_offset = offset}; ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
msg->msg_flags = 0; msg, bytes);
to = PAGE_SIZE; for (loop = 0; loop < nr; loop++)
if (first + loop >= last) put_page(bv[loop].bv_page);
to = call->last_to;
else
msg->msg_flags = MSG_MORE;
bvec.bv_len = to - offset;
offset = 0;
_debug("- range %u-%u%s",
offset, to, msg->msg_flags ? " [more]" : "");
iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC,
&bvec, 1, to - offset);
/* have to change the state *before* sending the last
* packet as RxRPC might give us the reply before it
* returns from sending the request */
if (first + loop >= last)
call->state = AFS_CALL_AWAIT_REPLY;
ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
msg, to - offset);
if (ret < 0)
break;
} while (++loop < count);
first += count;
for (loop = 0; loop < count; loop++)
put_page(pages[loop]);
if (ret < 0) if (ret < 0)
break; break;
first += nr;
} while (first <= last); } while (first <= last);
_leave(" = %d", ret);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment