afs: Set up the iov_iter before calling afs_extract_data()
afs_extract_data sets up a temporary iov_iter and passes it to AF_RXRPC each time it is called to describe the remaining buffer to be filled. Instead: (1) Put an iterator in the afs_call struct. (2) Set the iterator for each marshalling stage to load data into the appropriate places. A number of convenience functions are provided to this end (eg. afs_extract_to_buf()). This iterator is then passed to afs_extract_data(). (3) Use the new ITER_DISCARD iterator to discard any excess data provided by FetchData. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
@@ -143,6 +143,7 @@ static struct afs_call *afs_alloc_call(struct afs_net *net,
|
||||
INIT_WORK(&call->async_work, afs_process_async_call);
|
||||
init_waitqueue_head(&call->waitq);
|
||||
spin_lock_init(&call->state_lock);
|
||||
call->_iter = &call->iter;
|
||||
|
||||
o = atomic_inc_return(&net->nr_outstanding_calls);
|
||||
trace_afs_call(call, afs_call_trace_alloc, 1, o,
|
||||
@@ -233,6 +234,7 @@ struct afs_call *afs_alloc_flat_call(struct afs_net *net,
|
||||
goto nomem_free;
|
||||
}
|
||||
|
||||
afs_extract_to_buf(call, call->reply_max);
|
||||
call->operation_ID = type->op;
|
||||
init_waitqueue_head(&call->waitq);
|
||||
return call;
|
||||
@@ -465,14 +467,12 @@ static void afs_deliver_to_call(struct afs_call *call)
|
||||
state == AFS_CALL_SV_AWAIT_ACK
|
||||
) {
|
||||
if (state == AFS_CALL_SV_AWAIT_ACK) {
|
||||
struct iov_iter iter;
|
||||
|
||||
iov_iter_kvec(&iter, READ, NULL, 0, 0);
|
||||
iov_iter_kvec(&call->iter, READ, NULL, 0, 0);
|
||||
ret = rxrpc_kernel_recv_data(call->net->socket,
|
||||
call->rxcall, &iter, false,
|
||||
&remote_abort,
|
||||
call->rxcall, &call->iter,
|
||||
false, &remote_abort,
|
||||
&call->service_id);
|
||||
trace_afs_recv_data(call, 0, 0, false, ret);
|
||||
trace_afs_receive_data(call, &call->iter, false, ret);
|
||||
|
||||
if (ret == -EINPROGRESS || ret == -EAGAIN)
|
||||
return;
|
||||
@@ -516,7 +516,7 @@ static void afs_deliver_to_call(struct afs_call *call)
|
||||
if (state != AFS_CALL_CL_AWAIT_REPLY)
|
||||
abort_code = RXGEN_SS_UNMARSHAL;
|
||||
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
|
||||
abort_code, -EBADMSG, "KUM");
|
||||
abort_code, ret, "KUM");
|
||||
goto local_abort;
|
||||
}
|
||||
}
|
||||
@@ -727,6 +727,7 @@ void afs_charge_preallocation(struct work_struct *work)
|
||||
call->async = true;
|
||||
call->state = AFS_CALL_SV_AWAIT_OP_ID;
|
||||
init_waitqueue_head(&call->waitq);
|
||||
afs_extract_to_tmp(call);
|
||||
}
|
||||
|
||||
if (rxrpc_kernel_charge_accept(net->socket,
|
||||
@@ -772,18 +773,15 @@ static int afs_deliver_cm_op_id(struct afs_call *call)
|
||||
{
|
||||
int ret;
|
||||
|
||||
_enter("{%zu}", call->offset);
|
||||
|
||||
ASSERTCMP(call->offset, <, 4);
|
||||
_enter("{%zu}", iov_iter_count(call->_iter));
|
||||
|
||||
/* the operation ID forms the first four bytes of the request data */
|
||||
ret = afs_extract_data(call, &call->tmp, 4, true);
|
||||
ret = afs_extract_data(call, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
call->operation_ID = ntohl(call->tmp);
|
||||
afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
|
||||
call->offset = 0;
|
||||
|
||||
/* ask the cache manager to route the call (it'll change the call type
|
||||
* if successful) */
|
||||
@@ -887,30 +885,19 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
|
||||
/*
|
||||
* Extract a piece of data from the received data socket buffers.
|
||||
*/
|
||||
int afs_extract_data(struct afs_call *call, void *buf, size_t count,
|
||||
bool want_more)
|
||||
int afs_extract_data(struct afs_call *call, bool want_more)
|
||||
{
|
||||
struct afs_net *net = call->net;
|
||||
struct iov_iter iter;
|
||||
struct kvec iov;
|
||||
struct iov_iter *iter = call->_iter;
|
||||
enum afs_call_state state;
|
||||
u32 remote_abort = 0;
|
||||
int ret;
|
||||
|
||||
_enter("{%s,%zu},,%zu,%d",
|
||||
call->type->name, call->offset, count, want_more);
|
||||
_enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more);
|
||||
|
||||
ASSERTCMP(call->offset, <=, count);
|
||||
|
||||
iov.iov_base = buf + call->offset;
|
||||
iov.iov_len = count - call->offset;
|
||||
iov_iter_kvec(&iter, READ, &iov, 1, count - call->offset);
|
||||
|
||||
ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, &iter,
|
||||
ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
|
||||
want_more, &remote_abort,
|
||||
&call->service_id);
|
||||
call->offset += (count - call->offset) - iov_iter_count(&iter);
|
||||
trace_afs_recv_data(call, count, call->offset, want_more, ret);
|
||||
if (ret == 0 || ret == -EAGAIN)
|
||||
return ret;
|
||||
|
||||
|
Reference in New Issue
Block a user