Skip to content

Commit bd80d8a

Browse files
committed
afs: Use ITER_XARRAY for writing
Use a single ITER_XARRAY iterator to describe the portion of a file to be transmitted to the server rather than generating a series of small ITER_BVEC iterators on the fly. This will make it easier to implement AIO in afs. In theory we could maybe use one giant ITER_BVEC, but that means potentially allocating a huge array of bio_vec structs (max 256 per page) when in fact the pagecache already has a structure listing all the relevant pages (radix_tree/xarray) that can be walked over. Signed-off-by: David Howells <[email protected]> Tested-By: Marc Dionne <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected] Link: https://lore.kernel.org/r/153685395197.14766.16289516750731233933.stgit@warthog.procyon.org.uk/ Link: https://lore.kernel.org/r/158861251312.340223.17924900795425422532.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/159465828607.1377938.6903132788463419368.stgit@warthog.procyon.org.uk/ Link: https://lore.kernel.org/r/160588535018.3465195.14509994354240338307.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/161118152415.1232039.6452879415814850025.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/161161048194.2537118.13763612220937637316.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/161340411602.1303470.4661108879482218408.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/161539555629.286939.5241869986617154517.stgit@warthog.procyon.org.uk/ # v4 Link: https://lore.kernel.org/r/161653811456.2770958.7017388543246759245.stgit@warthog.procyon.org.uk/ # v5 Link: https://lore.kernel.org/r/161789095005.6155.6789055030327407928.stgit@warthog.procyon.org.uk/ # v6
1 parent c450846 commit bd80d8a

File tree

6 files changed

+126
-218
lines changed

6 files changed

+126
-218
lines changed

fs/afs/fsclient.c

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,8 +1055,7 @@ static const struct afs_call_type afs_RXFSStoreData64 = {
10551055
/*
10561056
* store a set of pages to a very large file
10571057
*/
1058-
static void afs_fs_store_data64(struct afs_operation *op,
1059-
loff_t pos, loff_t size, loff_t i_size)
1058+
static void afs_fs_store_data64(struct afs_operation *op)
10601059
{
10611060
struct afs_vnode_param *vp = &op->file[0];
10621061
struct afs_call *call;
@@ -1071,7 +1070,7 @@ static void afs_fs_store_data64(struct afs_operation *op,
10711070
if (!call)
10721071
return afs_op_nomem(op);
10731072

1074-
call->send_pages = true;
1073+
call->write_iter = op->store.write_iter;
10751074

10761075
/* marshall the parameters */
10771076
bp = call->request;
@@ -1087,55 +1086,46 @@ static void afs_fs_store_data64(struct afs_operation *op,
10871086
*bp++ = 0; /* unix mode */
10881087
*bp++ = 0; /* segment size */
10891088

1090-
*bp++ = htonl(upper_32_bits(pos));
1091-
*bp++ = htonl(lower_32_bits(pos));
1092-
*bp++ = htonl(upper_32_bits(size));
1093-
*bp++ = htonl(lower_32_bits(size));
1094-
*bp++ = htonl(upper_32_bits(i_size));
1095-
*bp++ = htonl(lower_32_bits(i_size));
1089+
*bp++ = htonl(upper_32_bits(op->store.pos));
1090+
*bp++ = htonl(lower_32_bits(op->store.pos));
1091+
*bp++ = htonl(upper_32_bits(op->store.size));
1092+
*bp++ = htonl(lower_32_bits(op->store.size));
1093+
*bp++ = htonl(upper_32_bits(op->store.i_size));
1094+
*bp++ = htonl(lower_32_bits(op->store.i_size));
10961095

10971096
trace_afs_make_fs_call(call, &vp->fid);
10981097
afs_make_op_call(op, call, GFP_NOFS);
10991098
}
11001099

11011100
/*
1102-
* store a set of pages
1101+
* Write data to a file on the server.
11031102
*/
11041103
void afs_fs_store_data(struct afs_operation *op)
11051104
{
11061105
struct afs_vnode_param *vp = &op->file[0];
11071106
struct afs_call *call;
1108-
loff_t size, pos, i_size;
11091107
__be32 *bp;
11101108

11111109
_enter(",%x,{%llx:%llu},,",
11121110
key_serial(op->key), vp->fid.vid, vp->fid.vnode);
11131111

1114-
size = (loff_t)op->store.last_to - (loff_t)op->store.first_offset;
1115-
if (op->store.first != op->store.last)
1116-
size += (loff_t)(op->store.last - op->store.first) << PAGE_SHIFT;
1117-
pos = (loff_t)op->store.first << PAGE_SHIFT;
1118-
pos += op->store.first_offset;
1119-
1120-
i_size = i_size_read(&vp->vnode->vfs_inode);
1121-
if (pos + size > i_size)
1122-
i_size = size + pos;
1123-
11241112
_debug("size %llx, at %llx, i_size %llx",
1125-
(unsigned long long) size, (unsigned long long) pos,
1126-
(unsigned long long) i_size);
1113+
(unsigned long long)op->store.size,
1114+
(unsigned long long)op->store.pos,
1115+
(unsigned long long)op->store.i_size);
11271116

1128-
if (upper_32_bits(pos) || upper_32_bits(i_size) || upper_32_bits(size) ||
1129-
upper_32_bits(pos + size))
1130-
return afs_fs_store_data64(op, pos, size, i_size);
1117+
if (upper_32_bits(op->store.pos) ||
1118+
upper_32_bits(op->store.size) ||
1119+
upper_32_bits(op->store.i_size))
1120+
return afs_fs_store_data64(op);
11311121

11321122
call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
11331123
(4 + 6 + 3) * 4,
11341124
(21 + 6) * 4);
11351125
if (!call)
11361126
return afs_op_nomem(op);
11371127

1138-
call->send_pages = true;
1128+
call->write_iter = op->store.write_iter;
11391129

11401130
/* marshall the parameters */
11411131
bp = call->request;
@@ -1151,9 +1141,9 @@ void afs_fs_store_data(struct afs_operation *op)
11511141
*bp++ = 0; /* unix mode */
11521142
*bp++ = 0; /* segment size */
11531143

1154-
*bp++ = htonl(lower_32_bits(pos));
1155-
*bp++ = htonl(lower_32_bits(size));
1156-
*bp++ = htonl(lower_32_bits(i_size));
1144+
*bp++ = htonl(lower_32_bits(op->store.pos));
1145+
*bp++ = htonl(lower_32_bits(op->store.size));
1146+
*bp++ = htonl(lower_32_bits(op->store.i_size));
11571147

11581148
trace_afs_make_fs_call(call, &vp->fid);
11591149
afs_make_op_call(op, call, GFP_NOFS);

fs/afs/internal.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct afs_call {
107107
void *request; /* request data (first part) */
108108
size_t iov_len; /* Size of *iter to be used */
109109
struct iov_iter def_iter; /* Default buffer/data iterator */
110+
struct iov_iter *write_iter; /* Iterator defining write to be made */
110111
struct iov_iter *iter; /* Iterator currently in use */
111112
union { /* Convenience for ->def_iter */
112113
struct kvec kvec[1];
@@ -133,7 +134,6 @@ struct afs_call {
133134
unsigned char unmarshall; /* unmarshalling phase */
134135
unsigned char addr_ix; /* Address in ->alist */
135136
bool drop_ref; /* T if need to drop ref for incoming call */
136-
bool send_pages; /* T if data from mapping should be sent */
137137
bool need_attention; /* T if RxRPC poked us */
138138
bool async; /* T if asynchronous */
139139
bool upgrade; /* T to request service upgrade */
@@ -811,12 +811,13 @@ struct afs_operation {
811811
afs_lock_type_t type;
812812
} lock;
813813
struct {
814-
struct address_space *mapping; /* Pages being written from */
815-
pgoff_t first; /* first page in mapping to deal with */
816-
pgoff_t last; /* last page in mapping to deal with */
817-
unsigned first_offset; /* offset into mapping[first] */
818-
unsigned last_to; /* amount of mapping[last] */
819-
bool laundering; /* Laundering page, PG_writeback not set */
814+
struct iov_iter *write_iter;
815+
loff_t pos;
816+
loff_t size;
817+
loff_t i_size;
818+
pgoff_t first; /* first page in mapping to deal with */
819+
pgoff_t last; /* last page in mapping to deal with */
820+
bool laundering; /* Laundering page, PG_writeback not set */
820821
} store;
821822
struct {
822823
struct iattr *attr;

fs/afs/rxrpc.c

Lines changed: 15 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -271,40 +271,6 @@ void afs_flat_call_destructor(struct afs_call *call)
271271
call->buffer = NULL;
272272
}
273273

274-
#define AFS_BVEC_MAX 8
275-
276-
/*
277-
* Load the given bvec with the next few pages.
278-
*/
279-
static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
280-
struct bio_vec *bv, pgoff_t first, pgoff_t last,
281-
unsigned offset)
282-
{
283-
struct afs_operation *op = call->op;
284-
struct page *pages[AFS_BVEC_MAX];
285-
unsigned int nr, n, i, to, bytes = 0;
286-
287-
nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
288-
n = find_get_pages_contig(op->store.mapping, first, nr, pages);
289-
ASSERTCMP(n, ==, nr);
290-
291-
msg->msg_flags |= MSG_MORE;
292-
for (i = 0; i < nr; i++) {
293-
to = PAGE_SIZE;
294-
if (first + i >= last) {
295-
to = op->store.last_to;
296-
msg->msg_flags &= ~MSG_MORE;
297-
}
298-
bv[i].bv_page = pages[i];
299-
bv[i].bv_len = to - offset;
300-
bv[i].bv_offset = offset;
301-
bytes += to - offset;
302-
offset = 0;
303-
}
304-
305-
iov_iter_bvec(&msg->msg_iter, WRITE, bv, nr, bytes);
306-
}
307-
308274
/*
309275
* Advance the AFS call state when the RxRPC call ends the transmit phase.
310276
*/
@@ -317,42 +283,6 @@ static void afs_notify_end_request_tx(struct sock *sock,
317283
afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
318284
}
319285

320-
/*
321-
* attach the data from a bunch of pages on an inode to a call
322-
*/
323-
static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
324-
{
325-
struct afs_operation *op = call->op;
326-
struct bio_vec bv[AFS_BVEC_MAX];
327-
unsigned int bytes, nr, loop, offset;
328-
pgoff_t first = op->store.first, last = op->store.last;
329-
int ret;
330-
331-
offset = op->store.first_offset;
332-
op->store.first_offset = 0;
333-
334-
do {
335-
afs_load_bvec(call, msg, bv, first, last, offset);
336-
trace_afs_send_pages(call, msg, first, last, offset);
337-
338-
offset = 0;
339-
bytes = msg->msg_iter.count;
340-
nr = msg->msg_iter.nr_segs;
341-
342-
ret = rxrpc_kernel_send_data(op->net->socket, call->rxcall, msg,
343-
bytes, afs_notify_end_request_tx);
344-
for (loop = 0; loop < nr; loop++)
345-
put_page(bv[loop].bv_page);
346-
if (ret < 0)
347-
break;
348-
349-
first += nr;
350-
} while (first <= last);
351-
352-
trace_afs_sent_pages(call, op->store.first, last, first, ret);
353-
return ret;
354-
}
355-
356286
/*
357287
* Initiate a call and synchronously queue up the parameters for dispatch. Any
358288
* error is stored into the call struct, which the caller must check for.
@@ -384,21 +314,8 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
384314
* after the initial fixed part.
385315
*/
386316
tx_total_len = call->request_size;
387-
if (call->send_pages) {
388-
struct afs_operation *op = call->op;
389-
390-
if (op->store.last == op->store.first) {
391-
tx_total_len += op->store.last_to - op->store.first_offset;
392-
} else {
393-
/* It looks mathematically like you should be able to
394-
* combine the following lines with the ones above, but
395-
* unsigned arithmetic is fun when it wraps...
396-
*/
397-
tx_total_len += PAGE_SIZE - op->store.first_offset;
398-
tx_total_len += op->store.last_to;
399-
tx_total_len += (op->store.last - op->store.first - 1) * PAGE_SIZE;
400-
}
401-
}
317+
if (call->write_iter)
318+
tx_total_len += iov_iter_count(call->write_iter);
402319

403320
/* If the call is going to be asynchronous, we need an extra ref for
404321
* the call to hold itself so the caller need not hang on to its ref.
@@ -440,16 +357,26 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
440357
iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, call->request_size);
441358
msg.msg_control = NULL;
442359
msg.msg_controllen = 0;
443-
msg.msg_flags = MSG_WAITALL | (call->send_pages ? MSG_MORE : 0);
360+
msg.msg_flags = MSG_WAITALL | (call->write_iter ? MSG_MORE : 0);
444361

445362
ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
446363
&msg, call->request_size,
447364
afs_notify_end_request_tx);
448365
if (ret < 0)
449366
goto error_do_abort;
450367

451-
if (call->send_pages) {
452-
ret = afs_send_pages(call, &msg);
368+
if (call->write_iter) {
369+
msg.msg_iter = *call->write_iter;
370+
msg.msg_flags &= ~MSG_MORE;
371+
trace_afs_send_data(call, &msg);
372+
373+
ret = rxrpc_kernel_send_data(call->net->socket,
374+
call->rxcall, &msg,
375+
iov_iter_count(&msg.msg_iter),
376+
afs_notify_end_request_tx);
377+
*call->write_iter = msg.msg_iter;
378+
379+
trace_afs_sent_data(call, &msg, ret);
453380
if (ret < 0)
454381
goto error_do_abort;
455382
}

0 commit comments

Comments
 (0)