Commit 12bdcf33 authored by David Howells's avatar David Howells

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: default avatarDavid Howells <dhowells@redhat.com>
parent 160cb957
...@@ -176,13 +176,13 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -176,13 +176,13 @@ static int afs_deliver_cb_callback(struct afs_call *call)
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0; afs_extract_to_tmp(call);
call->unmarshall++; call->unmarshall++;
/* extract the FID array and its count in two steps */ /* extract the FID array and its count in two steps */
case 1: case 1:
_debug("extract FID count"); _debug("extract FID count");
ret = afs_extract_data(call, &call->tmp, 4, true); ret = afs_extract_data(call, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -196,13 +196,12 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -196,13 +196,12 @@ static int afs_deliver_cb_callback(struct afs_call *call)
GFP_KERNEL); GFP_KERNEL);
if (!call->buffer) if (!call->buffer)
return -ENOMEM; return -ENOMEM;
call->offset = 0; afs_extract_to_buf(call, call->count * 3 * 4);
call->unmarshall++; call->unmarshall++;
case 2: case 2:
_debug("extract FID array"); _debug("extract FID array");
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, true);
call->count * 3 * 4, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -222,13 +221,13 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -222,13 +221,13 @@ static int afs_deliver_cb_callback(struct afs_call *call)
cb->cb.type = AFSCM_CB_UNTYPED; cb->cb.type = AFSCM_CB_UNTYPED;
} }
call->offset = 0; afs_extract_to_tmp(call);
call->unmarshall++; call->unmarshall++;
/* extract the callback array and its count in two steps */ /* extract the callback array and its count in two steps */
case 3: case 3:
_debug("extract CB count"); _debug("extract CB count");
ret = afs_extract_data(call, &call->tmp, 4, true); ret = afs_extract_data(call, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -237,13 +236,12 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -237,13 +236,12 @@ static int afs_deliver_cb_callback(struct afs_call *call)
if (call->count2 != call->count && call->count2 != 0) if (call->count2 != call->count && call->count2 != 0)
return afs_protocol_error(call, -EBADMSG, return afs_protocol_error(call, -EBADMSG,
afs_eproto_cb_count); afs_eproto_cb_count);
call->offset = 0; afs_extract_to_buf(call, call->count2 * 3 * 4);
call->unmarshall++; call->unmarshall++;
case 4: case 4:
_debug("extract CB array"); _debug("extract CB array");
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, false);
call->count2 * 3 * 4, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -256,7 +254,6 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -256,7 +254,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
cb->cb.type = ntohl(*bp++); cb->cb.type = ntohl(*bp++);
} }
call->offset = 0;
call->unmarshall++; call->unmarshall++;
case 5: case 5:
break; break;
...@@ -303,7 +300,8 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call) ...@@ -303,7 +300,8 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
ret = afs_extract_data(call, NULL, 0, false); afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -332,16 +330,15 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) ...@@ -332,16 +330,15 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0;
call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer) if (!call->buffer)
return -ENOMEM; return -ENOMEM;
afs_extract_to_buf(call, 11 * sizeof(__be32));
call->unmarshall++; call->unmarshall++;
case 1: case 1:
_debug("extract UUID"); _debug("extract UUID");
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, false);
11 * sizeof(__be32), false);
switch (ret) { switch (ret) {
case 0: break; case 0: break;
case -EAGAIN: return 0; case -EAGAIN: return 0;
...@@ -364,7 +361,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) ...@@ -364,7 +361,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
for (loop = 0; loop < 6; loop++) for (loop = 0; loop < 6; loop++)
r->node[loop] = ntohl(b[loop + 5]); r->node[loop] = ntohl(b[loop + 5]);
call->offset = 0;
call->unmarshall++; call->unmarshall++;
case 2: case 2:
...@@ -407,7 +403,8 @@ static int afs_deliver_cb_probe(struct afs_call *call) ...@@ -407,7 +403,8 @@ static int afs_deliver_cb_probe(struct afs_call *call)
_enter(""); _enter("");
ret = afs_extract_data(call, NULL, 0, false); afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -455,16 +452,15 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) ...@@ -455,16 +452,15 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0;
call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL); call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer) if (!call->buffer)
return -ENOMEM; return -ENOMEM;
afs_extract_to_buf(call, 11 * sizeof(__be32));
call->unmarshall++; call->unmarshall++;
case 1: case 1:
_debug("extract UUID"); _debug("extract UUID");
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, false);
11 * sizeof(__be32), false);
switch (ret) { switch (ret) {
case 0: break; case 0: break;
case -EAGAIN: return 0; case -EAGAIN: return 0;
...@@ -487,7 +483,6 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) ...@@ -487,7 +483,6 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
for (loop = 0; loop < 6; loop++) for (loop = 0; loop < 6; loop++)
r->node[loop] = ntohl(b[loop + 5]); r->node[loop] = ntohl(b[loop + 5]);
call->offset = 0;
call->unmarshall++; call->unmarshall++;
case 2: case 2:
...@@ -572,7 +567,8 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call) ...@@ -572,7 +567,8 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
_enter(""); _enter("");
ret = afs_extract_data(call, NULL, 0, false); afs_extract_discard(call, 0);
ret = afs_extract_data(call, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
This diff is collapsed.
...@@ -98,11 +98,16 @@ struct afs_call { ...@@ -98,11 +98,16 @@ struct afs_call {
struct afs_cb_interest *cbi; /* Callback interest for server used */ struct afs_cb_interest *cbi; /* Callback interest for server used */
void *request; /* request data (first part) */ void *request; /* request data (first part) */
struct address_space *mapping; /* Pages being written from */ struct address_space *mapping; /* Pages being written from */
struct iov_iter iter; /* Buffer iterator */
struct iov_iter *_iter; /* Iterator currently in use */
union { /* Convenience for ->iter */
struct kvec kvec[1];
struct bio_vec bvec[1];
};
void *buffer; /* reply receive buffer */ void *buffer; /* reply receive buffer */
void *reply[4]; /* Where to put the reply */ void *reply[4]; /* Where to put the reply */
pgoff_t first; /* first page in mapping to deal with */ pgoff_t first; /* first page in mapping to deal with */
pgoff_t last; /* last page in mapping to deal with */ pgoff_t last; /* last page in mapping to deal with */
size_t offset; /* offset into received data store */
atomic_t usage; atomic_t usage;
enum afs_call_state state; enum afs_call_state state;
spinlock_t state_lock; spinlock_t state_lock;
...@@ -127,7 +132,13 @@ struct afs_call { ...@@ -127,7 +132,13 @@ struct afs_call {
unsigned int debug_id; /* Trace ID */ unsigned int debug_id; /* Trace ID */
u32 operation_ID; /* operation ID for an incoming call */ u32 operation_ID; /* operation ID for an incoming call */
u32 count; /* count for use in unmarshalling */ u32 count; /* count for use in unmarshalling */
__be32 tmp; /* place to extract temporary data */ union { /* place to extract temporary data */
struct {
__be32 tmp_u;
__be32 tmp;
} __attribute__((packed));
__be64 tmp64;
};
afs_dataversion_t expected_version; /* Updated version expected from store */ afs_dataversion_t expected_version; /* Updated version expected from store */
afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */ afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */
}; };
...@@ -185,6 +196,7 @@ struct afs_read { ...@@ -185,6 +196,7 @@ struct afs_read {
refcount_t usage; refcount_t usage;
unsigned int index; /* Which page we're reading into */ unsigned int index; /* Which page we're reading into */
unsigned int nr_pages; unsigned int nr_pages;
unsigned int offset; /* offset into current page */
void (*page_done)(struct afs_call *, struct afs_read *); void (*page_done)(struct afs_call *, struct afs_read *);
struct page **pages; struct page **pages;
struct page *array[]; struct page *array[];
...@@ -550,6 +562,15 @@ struct afs_vnode { ...@@ -550,6 +562,15 @@ struct afs_vnode {
afs_callback_type_t cb_type; /* type of callback */ afs_callback_type_t cb_type; /* type of callback */
}; };
static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode)
{
#ifdef CONFIG_AFS_FSCACHE
return vnode->cache;
#else
return NULL;
#endif
}
/* /*
* cached security record for one user's attempt to access a vnode * cached security record for one user's attempt to access a vnode
*/ */
...@@ -930,12 +951,39 @@ extern struct afs_call *afs_alloc_flat_call(struct afs_net *, ...@@ -930,12 +951,39 @@ extern struct afs_call *afs_alloc_flat_call(struct afs_net *,
extern void afs_flat_call_destructor(struct afs_call *); extern void afs_flat_call_destructor(struct afs_call *);
extern void afs_send_empty_reply(struct afs_call *); extern void afs_send_empty_reply(struct afs_call *);
extern void afs_send_simple_reply(struct afs_call *, const void *, size_t); extern void afs_send_simple_reply(struct afs_call *, const void *, size_t);
extern int afs_extract_data(struct afs_call *, void *, size_t, bool); extern int afs_extract_data(struct afs_call *, bool);
extern int afs_protocol_error(struct afs_call *, int, enum afs_eproto_cause); extern int afs_protocol_error(struct afs_call *, int, enum afs_eproto_cause);
static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size)
{
call->kvec[0].iov_base = buf;
call->kvec[0].iov_len = size;
iov_iter_kvec(&call->iter, READ, call->kvec, 1, size);
}
static inline void afs_extract_to_tmp(struct afs_call *call)
{
afs_extract_begin(call, &call->tmp, sizeof(call->tmp));
}
static inline void afs_extract_to_tmp64(struct afs_call *call)
{
afs_extract_begin(call, &call->tmp64, sizeof(call->tmp64));
}
static inline void afs_extract_discard(struct afs_call *call, size_t size)
{
iov_iter_discard(&call->iter, READ, size);
}
static inline void afs_extract_to_buf(struct afs_call *call, size_t size)
{
afs_extract_begin(call, call->buffer, size);
}
static inline int afs_transfer_reply(struct afs_call *call) static inline int afs_transfer_reply(struct afs_call *call)
{ {
return afs_extract_data(call, call->buffer, call->reply_max, false); return afs_extract_data(call, false);
} }
static inline bool afs_check_call_state(struct afs_call *call, static inline bool afs_check_call_state(struct afs_call *call,
......
...@@ -143,6 +143,7 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, ...@@ -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_WORK(&call->async_work, afs_process_async_call);
init_waitqueue_head(&call->waitq); init_waitqueue_head(&call->waitq);
spin_lock_init(&call->state_lock); spin_lock_init(&call->state_lock);
call->_iter = &call->iter;
o = atomic_inc_return(&net->nr_outstanding_calls); o = atomic_inc_return(&net->nr_outstanding_calls);
trace_afs_call(call, afs_call_trace_alloc, 1, o, 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, ...@@ -233,6 +234,7 @@ struct afs_call *afs_alloc_flat_call(struct afs_net *net,
goto nomem_free; goto nomem_free;
} }
afs_extract_to_buf(call, call->reply_max);
call->operation_ID = type->op; call->operation_ID = type->op;
init_waitqueue_head(&call->waitq); init_waitqueue_head(&call->waitq);
return call; return call;
...@@ -465,14 +467,12 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -465,14 +467,12 @@ static void afs_deliver_to_call(struct afs_call *call)
state == AFS_CALL_SV_AWAIT_ACK state == AFS_CALL_SV_AWAIT_ACK
) { ) {
if (state == AFS_CALL_SV_AWAIT_ACK) { if (state == AFS_CALL_SV_AWAIT_ACK) {
struct iov_iter iter; iov_iter_kvec(&call->iter, READ, NULL, 0, 0);
iov_iter_kvec(&iter, READ, NULL, 0, 0);
ret = rxrpc_kernel_recv_data(call->net->socket, ret = rxrpc_kernel_recv_data(call->net->socket,
call->rxcall, &iter, false, call->rxcall, &call->iter,
&remote_abort, false, &remote_abort,
&call->service_id); &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) if (ret == -EINPROGRESS || ret == -EAGAIN)
return; return;
...@@ -516,7 +516,7 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -516,7 +516,7 @@ static void afs_deliver_to_call(struct afs_call *call)
if (state != AFS_CALL_CL_AWAIT_REPLY) if (state != AFS_CALL_CL_AWAIT_REPLY)
abort_code = RXGEN_SS_UNMARSHAL; abort_code = RXGEN_SS_UNMARSHAL;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall, rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, -EBADMSG, "KUM"); abort_code, ret, "KUM");
goto local_abort; goto local_abort;
} }
} }
...@@ -727,6 +727,7 @@ void afs_charge_preallocation(struct work_struct *work) ...@@ -727,6 +727,7 @@ void afs_charge_preallocation(struct work_struct *work)
call->async = true; call->async = true;
call->state = AFS_CALL_SV_AWAIT_OP_ID; call->state = AFS_CALL_SV_AWAIT_OP_ID;
init_waitqueue_head(&call->waitq); init_waitqueue_head(&call->waitq);
afs_extract_to_tmp(call);
} }
if (rxrpc_kernel_charge_accept(net->socket, if (rxrpc_kernel_charge_accept(net->socket,
...@@ -772,18 +773,15 @@ static int afs_deliver_cm_op_id(struct afs_call *call) ...@@ -772,18 +773,15 @@ static int afs_deliver_cm_op_id(struct afs_call *call)
{ {
int ret; int ret;
_enter("{%zu}", call->offset); _enter("{%zu}", iov_iter_count(call->_iter));
ASSERTCMP(call->offset, <, 4);
/* the operation ID forms the first four bytes of the request data */ /* 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) if (ret < 0)
return ret; return ret;
call->operation_ID = ntohl(call->tmp); call->operation_ID = ntohl(call->tmp);
afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST); 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 /* ask the cache manager to route the call (it'll change the call type
* if successful) */ * if successful) */
...@@ -887,30 +885,19 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) ...@@ -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. * Extract a piece of data from the received data socket buffers.
*/ */
int afs_extract_data(struct afs_call *call, void *buf, size_t count, int afs_extract_data(struct afs_call *call, bool want_more)
bool want_more)
{ {
struct afs_net *net = call->net; struct afs_net *net = call->net;
struct iov_iter iter; struct iov_iter *iter = call->_iter;
struct kvec iov;
enum afs_call_state state; enum afs_call_state state;
u32 remote_abort = 0; u32 remote_abort = 0;
int ret; int ret;
_enter("{%s,%zu},,%zu,%d", _enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more);
call->type->name, call->offset, count, 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, want_more, &remote_abort,
&call->service_id); &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) if (ret == 0 || ret == -EAGAIN)
return ret; return ret;
......
...@@ -187,19 +187,18 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) ...@@ -187,19 +187,18 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
u32 uniquifier, nentries, count; u32 uniquifier, nentries, count;
int i, ret; int i, ret;
_enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); _enter("{%u,%zu/%u}",
call->unmarshall, iov_iter_count(call->_iter), call->count);
again:
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0; afs_extract_to_buf(call,
sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
call->unmarshall++; call->unmarshall++;
/* Extract the returned uuid, uniquifier, nentries and blkaddrs size */ /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */
case 1: case 1:
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, true);
sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32),
true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -216,28 +215,28 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) ...@@ -216,28 +215,28 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
call->reply[0] = alist; call->reply[0] = alist;
call->count = count; call->count = count;
call->count2 = nentries; call->count2 = nentries;
call->offset = 0;
call->unmarshall++; call->unmarshall++;
more_entries:
count = min(call->count, 4U);
afs_extract_to_buf(call, count * sizeof(__be32));
/* Extract entries */ /* Extract entries */
case 2: case 2:
count = min(call->count, 4U); ret = afs_extract_data(call, call->count > 4);
ret = afs_extract_data(call, call->buffer,
count * sizeof(__be32),
call->count > 4);
if (ret < 0) if (ret < 0)
return ret; return ret;
alist = call->reply[0]; alist = call->reply[0];
bp = call->buffer; bp = call->buffer;
count = min(call->count, 4U);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
if (alist->nr_addrs < call->count2) if (alist->nr_addrs < call->count2)
afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
call->count -= count; call->count -= count;
if (call->count > 0) if (call->count > 0)
goto again; goto more_entries;
call->offset = 0;
call->unmarshall++; call->unmarshall++;
break; break;
} }
...@@ -318,44 +317,35 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call) ...@@ -318,44 +317,35 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call)
u32 count; u32 count;
int ret; int ret;
_enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); _enter("{%u,%zu/%u}",
call->unmarshall, iov_iter_count(call->_iter), call->count);
again:
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0; afs_extract_to_tmp(call);
call->unmarshall++; call->unmarshall++;
/* Extract the capabilities word count */ /* Extract the capabilities word count */
case 1: case 1:
ret = afs_extract_data(call, &call->tmp, ret = afs_extract_data(call, true);
1 * sizeof(__be32),
true);
if (ret < 0) if (ret < 0)
return ret; return ret;
count = ntohl(call->tmp); count = ntohl(call->tmp);
call->count = count; call->count = count;
call->count2 = count; call->count2 = count;
call->offset = 0;
call->unmarshall++; call->unmarshall++;
afs_extract_discard(call, count * sizeof(__be32));
/* Extract capabilities words */ /* Extract capabilities words */
case 2: case 2:
count = min(call->count, 16U); ret = afs_extract_data(call, false);
ret = afs_extract_data(call, call->buffer,
count * sizeof(__be32),
call->count > 16);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* TODO: Examine capabilities */ /* TODO: Examine capabilities */
call->count -= count;
if (call->count > 0)
goto again;
call->offset = 0;
call->unmarshall++; call->unmarshall++;
break; break;
} }
...@@ -426,22 +416,19 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -426,22 +416,19 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
u32 uniquifier, size; u32 uniquifier, size;
int ret; int ret;
_enter("{%u,%zu/%u,%u}", call->unmarshall, call->offset, call->count, call->count2); _enter("{%u,%zu,%u}",
call->unmarshall, iov_iter_count(call->_iter), call->count2);
again:
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
call->offset = 0; afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
call->unmarshall = 1; call->unmarshall = 1;
/* Extract the returned uuid, uniquifier, fsEndpoints count and /* Extract the returned uuid, uniquifier, fsEndpoints count and
* either the first fsEndpoint type or the volEndpoints * either the first fsEndpoint type or the volEndpoints
* count if there are no fsEndpoints. */ * count if there are no fsEndpoints. */
case 1: case 1:
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, true);
sizeof(uuid_t) +
3 * sizeof(__be32),
true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -459,15 +446,11 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -459,15 +446,11 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
return -ENOMEM; return -ENOMEM;
alist->version = uniquifier; alist->version = uniquifier;
call->reply[0] = alist; call->reply[0] = alist;
call->offset = 0;
if (call->count == 0) if (call->count == 0)
goto extract_volendpoints; goto extract_volendpoints;
call->unmarshall = 2; next_fsendpoint:
/* Extract fsEndpoints[] entries */
case 2:
switch (call->count2) { switch (call->count2) {
case YFS_ENDPOINT_IPV4: case YFS_ENDPOINT_IPV4:
size = sizeof(__be32) * (1 + 1 + 1); size = sizeof(__be32) * (1 + 1 + 1);
...@@ -481,7 +464,12 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -481,7 +464,12 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
} }
size += sizeof(__be32); size += sizeof(__be32);
ret = afs_extract_data(call, call->buffer, size, true); afs_extract_to_buf(call, size);
call->unmarshall = 2;
/* Extract fsEndpoints[] entries */
case 2:
ret = afs_extract_data(call, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -512,10 +500,9 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -512,10 +500,9 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
*/ */
call->count2 = ntohl(*bp++); call->count2 = ntohl(*bp++);
call->offset = 0;
call->count--; call->count--;
if (call->count > 0) if (call->count > 0)
goto again; goto next_fsendpoint;
extract_volendpoints: extract_volendpoints:
/* Extract the list of volEndpoints. */ /* Extract the list of volEndpoints. */
...@@ -526,6 +513,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -526,6 +513,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
return afs_protocol_error(call, -EBADMSG, return afs_protocol_error(call, -EBADMSG,
afs_eproto_yvl_vlendpt_type); afs_eproto_yvl_vlendpt_type);
afs_extract_to_buf(call, 1 * sizeof(__be32));
call->unmarshall = 3; call->unmarshall = 3;
/* Extract the type of volEndpoints[0]. Normally we would /* Extract the type of volEndpoints[0]. Normally we would
...@@ -533,17 +521,14 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -533,17 +521,14 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
* data of the current one, but this is the first... * data of the current one, but this is the first...
*/ */
case 3: case 3:
ret = afs_extract_data(call, call->buffer, sizeof(__be32), true); ret = afs_extract_data(call, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
bp = call->buffer; bp = call->buffer;
call->count2 = ntohl(*bp++);
call->offset = 0;
call->unmarshall = 4;
/* Extract volEndpoints[] entries */ next_volendpoint:
case 4: call->count2 = ntohl(*bp++);
switch (call->count2) { switch (call->count2) {
case YFS_ENDPOINT_IPV4: case YFS_ENDPOINT_IPV4:
size = sizeof(__be32) * (1 + 1 + 1); size = sizeof(__be32) * (1 + 1 + 1);
...@@ -557,8 +542,13 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -557,8 +542,13 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
} }
if (call->count > 1) if (call->count > 1)
size += sizeof(__be32); size += sizeof(__be32); /* Get next type too */
ret = afs_extract_data(call, call->buffer, size, true); afs_extract_to_buf(call, size);
call->unmarshall = 4;
/* Extract volEndpoints[] entries */
case 4:
ret = afs_extract_data(call, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -584,19 +574,17 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) ...@@ -584,19 +574,17 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
/* Got either the type of the next entry or the count of /* Got either the type of the next entry or the count of
* volEndpoints if no more fsEndpoints. * volEndpoints if no more fsEndpoints.
*/ */
call->offset = 0;
call->count--; call->count--;
if (call->count > 0) { if (call->count > 0)
call->count2 = ntohl(*bp++); goto next_volendpoint;
goto again;
}
end: end:
afs_extract_discard(call, 0);
call->unmarshall = 5; call->unmarshall = 5;
/* Done */ /* Done */
case 5: case 5:
ret = afs_extract_data(call, call->buffer, 0, false); ret = afs_extract_data(call, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
call->unmarshall = 6; call->unmarshall = 6;
......
...@@ -207,17 +207,16 @@ afs_edit_dir_reasons; ...@@ -207,17 +207,16 @@ afs_edit_dir_reasons;
#define EM(a, b) { a, b }, #define EM(a, b) { a, b },
#define E_(a, b) { a, b } #define E_(a, b) { a, b }
TRACE_EVENT(afs_recv_data, TRACE_EVENT(afs_receive_data,
TP_PROTO(struct afs_call *call, unsigned count, unsigned offset, TP_PROTO(struct afs_call *call, struct iov_iter *iter,
bool want_more, int ret), bool want_more, int ret),
TP_ARGS(call, count, offset, want_more, ret), TP_ARGS(call, iter, want_more, ret),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(loff_t, remain )
__field(unsigned int, call ) __field(unsigned int, call )
__field(enum afs_call_state, state ) __field(enum afs_call_state, state )
__field(unsigned int, count )
__field(unsigned int, offset )
__field(unsigned short, unmarshall ) __field(unsigned short, unmarshall )
__field(bool, want_more ) __field(bool, want_more )
__field(int, ret ) __field(int, ret )
...@@ -227,17 +226,18 @@ TRACE_EVENT(afs_recv_data, ...@@ -227,17 +226,18 @@ TRACE_EVENT(afs_recv_data,
__entry->call = call->debug_id; __entry->call = call->debug_id;
__entry->state = call->state; __entry->state = call->state;
__entry->unmarshall = call->unmarshall; __entry->unmarshall = call->unmarshall;
__entry->count = count; __entry->remain = iov_iter_count(iter);
__entry->offset = offset;
__entry->want_more = want_more; __entry->want_more = want_more;
__entry->ret = ret; __entry->ret = ret;
), ),
TP_printk("c=%08x s=%u u=%u %u/%u wm=%u ret=%d", TP_printk("c=%08x r=%llu u=%u w=%u s=%u ret=%d",
__entry->call, __entry->call,
__entry->state, __entry->unmarshall, __entry->remain,
__entry->offset, __entry->count, __entry->unmarshall,
__entry->want_more, __entry->ret) __entry->want_more,
__entry->state,
__entry->ret)
); );
TRACE_EVENT(afs_notify_call, TRACE_EVENT(afs_notify_call,
......
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