Commit 792438e5 authored by David S. Miller's avatar David S. Miller

Merge tag 'rxrpc-rewrite-20160830-1' of...

Merge tag 'rxrpc-rewrite-20160830-1' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

David Howells says:

====================
rxrpc: Preparation for removal of use of skbs from AFS

Here's a set of patches that prepare the way for the removal of the use of
sk_buffs from fs/afs (they'll be entirely retained within net/rxrpc):

 (1) Fix a potential NULL-pointer deref in rxrpc_abort_calls().

 (2) Condense all the terminal call state machine states to a single one
     plus supplementary info.

 (3) Add a trace point for rxrpc call usage debugging.

 (4) Cleanups and missing headers.

 (5) Provide a way for AFS to ask about a call's peer address without
     having an sk_buff to query.

 (6) Use call->peer directly rather than going via call->conn (which might
     be NULL).

 (7) Pass struct socket * to various rxrpc kernel interface functions so
     they can use that directly rather than getting it from the rxrpc_call
     struct.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cf4d13fe 4de48af6
...@@ -725,7 +725,8 @@ The kernel interface functions are as follows: ...@@ -725,7 +725,8 @@ The kernel interface functions are as follows:
(*) End a client call. (*) End a client call.
void rxrpc_kernel_end_call(struct rxrpc_call *call); void rxrpc_kernel_end_call(struct socket *sock,
struct rxrpc_call *call);
This is used to end a previously begun call. The user_call_ID is expunged This is used to end a previously begun call. The user_call_ID is expunged
from AF_RXRPC's knowledge and will not be seen again in association with from AF_RXRPC's knowledge and will not be seen again in association with
...@@ -733,7 +734,9 @@ The kernel interface functions are as follows: ...@@ -733,7 +734,9 @@ The kernel interface functions are as follows:
(*) Send data through a call. (*) Send data through a call.
int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg, int rxrpc_kernel_send_data(struct socket *sock,
struct rxrpc_call *call,
struct msghdr *msg,
size_t len); size_t len);
This is used to supply either the request part of a client call or the This is used to supply either the request part of a client call or the
...@@ -747,7 +750,9 @@ The kernel interface functions are as follows: ...@@ -747,7 +750,9 @@ The kernel interface functions are as follows:
(*) Abort a call. (*) Abort a call.
void rxrpc_kernel_abort_call(struct rxrpc_call *call, u32 abort_code); void rxrpc_kernel_abort_call(struct socket *sock,
struct rxrpc_call *call,
u32 abort_code);
This is used to abort a call if it's still in an abortable state. The This is used to abort a call if it's still in an abortable state. The
abort code specified will be placed in the ABORT message sent. abort code specified will be placed in the ABORT message sent.
...@@ -868,6 +873,13 @@ The kernel interface functions are as follows: ...@@ -868,6 +873,13 @@ The kernel interface functions are as follows:
This is used to allocate a null RxRPC key that can be used to indicate This is used to allocate a null RxRPC key that can be used to indicate
anonymous security for a particular domain. anonymous security for a particular domain.
(*) Get the peer address of a call.
void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call,
struct sockaddr_rxrpc *_srx);
This is used to find the remote peer address of a call.
======================= =======================
CONFIGURABLE PARAMETERS CONFIGURABLE PARAMETERS
......
...@@ -17,10 +17,6 @@ ...@@ -17,10 +17,6 @@
#include "internal.h" #include "internal.h"
#include "afs_cm.h" #include "afs_cm.h"
#if 0
struct workqueue_struct *afs_cm_workqueue;
#endif /* 0 */
static int afs_deliver_cb_init_call_back_state(struct afs_call *, static int afs_deliver_cb_init_call_back_state(struct afs_call *,
struct sk_buff *, bool); struct sk_buff *, bool);
static int afs_deliver_cb_init_call_back_state3(struct afs_call *, static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
...@@ -171,9 +167,9 @@ static void SRXAFSCB_CallBack(struct work_struct *work) ...@@ -171,9 +167,9 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
bool last) bool last)
{ {
struct sockaddr_rxrpc srx;
struct afs_callback *cb; struct afs_callback *cb;
struct afs_server *server; struct afs_server *server;
struct in_addr addr;
__be32 *bp; __be32 *bp;
u32 tmp; u32 tmp;
int ret, loop; int ret, loop;
...@@ -182,6 +178,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, ...@@ -182,6 +178,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
switch (call->unmarshall) { switch (call->unmarshall) {
case 0: case 0:
rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
call->offset = 0; call->offset = 0;
call->unmarshall++; call->unmarshall++;
...@@ -282,13 +279,11 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, ...@@ -282,13 +279,11 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
break; break;
} }
call->state = AFS_CALL_REPLYING; call->state = AFS_CALL_REPLYING;
/* we'll need the file server record as that tells us which set of /* we'll need the file server record as that tells us which set of
* vnodes to operate upon */ * vnodes to operate upon */
memcpy(&addr, &ip_hdr(skb)->saddr, 4); server = afs_find_server(&srx);
server = afs_find_server(&addr);
if (!server) if (!server)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
...@@ -319,12 +314,14 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call, ...@@ -319,12 +314,14 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
struct sk_buff *skb, struct sk_buff *skb,
bool last) bool last)
{ {
struct sockaddr_rxrpc srx;
struct afs_server *server; struct afs_server *server;
struct in_addr addr;
int ret; int ret;
_enter(",{%u},%d", skb->len, last); _enter(",{%u},%d", skb->len, last);
rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
ret = afs_data_complete(call, skb, last); ret = afs_data_complete(call, skb, last);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -334,8 +331,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call, ...@@ -334,8 +331,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
/* we'll need the file server record as that tells us which set of /* we'll need the file server record as that tells us which set of
* vnodes to operate upon */ * vnodes to operate upon */
memcpy(&addr, &ip_hdr(skb)->saddr, 4); server = afs_find_server(&srx);
server = afs_find_server(&addr);
if (!server) if (!server)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
...@@ -352,11 +348,13 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, ...@@ -352,11 +348,13 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
struct sk_buff *skb, struct sk_buff *skb,
bool last) bool last)
{ {
struct sockaddr_rxrpc srx;
struct afs_server *server; struct afs_server *server;
struct in_addr addr;
_enter(",{%u},%d", skb->len, last); _enter(",{%u},%d", skb->len, last);
rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
/* There are some arguments that we ignore */ /* There are some arguments that we ignore */
afs_data_consumed(call, skb); afs_data_consumed(call, skb);
if (!last) if (!last)
...@@ -367,8 +365,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, ...@@ -367,8 +365,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
/* we'll need the file server record as that tells us which set of /* we'll need the file server record as that tells us which set of
* vnodes to operate upon */ * vnodes to operate upon */
memcpy(&addr, &ip_hdr(skb)->saddr, 4); server = afs_find_server(&srx);
server = afs_find_server(&addr);
if (!server) if (!server)
return -ENOTCONN; return -ENOTCONN;
call->server = server; call->server = server;
...@@ -426,7 +423,6 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work) ...@@ -426,7 +423,6 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
_enter(""); _enter("");
if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0) if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
reply.match = htonl(0); reply.match = htonl(0);
else else
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fscache.h> #include <linux/fscache.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <net/af_rxrpc.h>
#include "afs.h" #include "afs.h"
#include "afs_vl.h" #include "afs_vl.h"
...@@ -607,6 +608,8 @@ extern void afs_proc_cell_remove(struct afs_cell *); ...@@ -607,6 +608,8 @@ extern void afs_proc_cell_remove(struct afs_cell *);
/* /*
* rxrpc.c * rxrpc.c
*/ */
extern struct socket *afs_socket;
extern int afs_open_socket(void); extern int afs_open_socket(void);
extern void afs_close_socket(void); extern void afs_close_socket(void);
extern void afs_data_consumed(struct afs_call *, struct sk_buff *); extern void afs_data_consumed(struct afs_call *, struct sk_buff *);
...@@ -654,7 +657,7 @@ do { \ ...@@ -654,7 +657,7 @@ do { \
extern struct afs_server *afs_lookup_server(struct afs_cell *, extern struct afs_server *afs_lookup_server(struct afs_cell *,
const struct in_addr *); const struct in_addr *);
extern struct afs_server *afs_find_server(const struct in_addr *); extern struct afs_server *afs_find_server(const struct sockaddr_rxrpc *);
extern void afs_put_server(struct afs_server *); extern void afs_put_server(struct afs_server *);
extern void __exit afs_purge_servers(void); extern void __exit afs_purge_servers(void);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/random.h>
#include "internal.h" #include "internal.h"
MODULE_DESCRIPTION("AFS Client File System"); MODULE_DESCRIPTION("AFS Client File System");
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "internal.h" #include "internal.h"
#include "afs_cm.h" #include "afs_cm.h"
static struct socket *afs_socket; /* my RxRPC socket */ struct socket *afs_socket; /* my RxRPC socket */
static struct workqueue_struct *afs_async_calls; static struct workqueue_struct *afs_async_calls;
static atomic_t afs_outstanding_calls; static atomic_t afs_outstanding_calls;
static atomic_t afs_outstanding_skbs; static atomic_t afs_outstanding_skbs;
...@@ -207,7 +207,7 @@ static void afs_free_call(struct afs_call *call) ...@@ -207,7 +207,7 @@ static void afs_free_call(struct afs_call *call)
static void afs_end_call_nofree(struct afs_call *call) static void afs_end_call_nofree(struct afs_call *call)
{ {
if (call->rxcall) { if (call->rxcall) {
rxrpc_kernel_end_call(call->rxcall); rxrpc_kernel_end_call(afs_socket, call->rxcall);
call->rxcall = NULL; call->rxcall = NULL;
} }
if (call->type->destructor) if (call->type->destructor)
...@@ -325,8 +325,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg, ...@@ -325,8 +325,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
* returns from sending the request */ * returns from sending the request */
if (first + loop >= last) if (first + loop >= last)
call->state = AFS_CALL_AWAIT_REPLY; call->state = AFS_CALL_AWAIT_REPLY;
ret = rxrpc_kernel_send_data(call->rxcall, msg, ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
to - offset); msg, to - offset);
kunmap(pages[loop]); kunmap(pages[loop]);
if (ret < 0) if (ret < 0)
break; break;
...@@ -406,7 +406,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, ...@@ -406,7 +406,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
* request */ * request */
if (!call->send_pages) if (!call->send_pages)
call->state = AFS_CALL_AWAIT_REPLY; call->state = AFS_CALL_AWAIT_REPLY;
ret = rxrpc_kernel_send_data(rxcall, &msg, call->request_size); ret = rxrpc_kernel_send_data(afs_socket, rxcall,
&msg, call->request_size);
if (ret < 0) if (ret < 0)
goto error_do_abort; goto error_do_abort;
...@@ -421,7 +422,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, ...@@ -421,7 +422,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
return wait_mode->wait(call); return wait_mode->wait(call);
error_do_abort: error_do_abort:
rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); rxrpc_kernel_abort_call(afs_socket, rxcall, RX_USER_ABORT);
while ((skb = skb_dequeue(&call->rx_queue))) while ((skb = skb_dequeue(&call->rx_queue)))
afs_free_skb(skb); afs_free_skb(skb);
error_kill_call: error_kill_call:
...@@ -509,7 +510,8 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -509,7 +510,8 @@ static void afs_deliver_to_call(struct afs_call *call)
if (call->state != AFS_CALL_AWAIT_REPLY) if (call->state != AFS_CALL_AWAIT_REPLY)
abort_code = RXGEN_SS_UNMARSHAL; abort_code = RXGEN_SS_UNMARSHAL;
do_abort: do_abort:
rxrpc_kernel_abort_call(call->rxcall, rxrpc_kernel_abort_call(afs_socket,
call->rxcall,
abort_code); abort_code);
call->error = ret; call->error = ret;
call->state = AFS_CALL_ERROR; call->state = AFS_CALL_ERROR;
...@@ -605,7 +607,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) ...@@ -605,7 +607,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
/* kill the call */ /* kill the call */
if (call->state < AFS_CALL_COMPLETE) { if (call->state < AFS_CALL_COMPLETE) {
_debug("call incomplete"); _debug("call incomplete");
rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD); rxrpc_kernel_abort_call(afs_socket, call->rxcall, RX_CALL_DEAD);
while ((skb = skb_dequeue(&call->rx_queue))) while ((skb = skb_dequeue(&call->rx_queue)))
afs_free_skb(skb); afs_free_skb(skb);
} }
...@@ -823,14 +825,15 @@ void afs_send_empty_reply(struct afs_call *call) ...@@ -823,14 +825,15 @@ void afs_send_empty_reply(struct afs_call *call)
msg.msg_flags = 0; msg.msg_flags = 0;
call->state = AFS_CALL_AWAIT_ACK; call->state = AFS_CALL_AWAIT_ACK;
switch (rxrpc_kernel_send_data(call->rxcall, &msg, 0)) { switch (rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, 0)) {
case 0: case 0:
_leave(" [replied]"); _leave(" [replied]");
return; return;
case -ENOMEM: case -ENOMEM:
_debug("oom"); _debug("oom");
rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); rxrpc_kernel_abort_call(afs_socket, call->rxcall,
RX_USER_ABORT);
default: default:
afs_end_call(call); afs_end_call(call);
_leave(" [error]"); _leave(" [error]");
...@@ -859,7 +862,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) ...@@ -859,7 +862,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
msg.msg_flags = 0; msg.msg_flags = 0;
call->state = AFS_CALL_AWAIT_ACK; call->state = AFS_CALL_AWAIT_ACK;
n = rxrpc_kernel_send_data(call->rxcall, &msg, len); n = rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, len);
if (n >= 0) { if (n >= 0) {
/* Success */ /* Success */
_leave(" [replied]"); _leave(" [replied]");
...@@ -868,7 +871,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) ...@@ -868,7 +871,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
if (n == -ENOMEM) { if (n == -ENOMEM) {
_debug("oom"); _debug("oom");
rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); rxrpc_kernel_abort_call(afs_socket, call->rxcall,
RX_USER_ABORT);
} }
afs_end_call(call); afs_end_call(call);
_leave(" [error]"); _leave(" [error]");
......
...@@ -178,13 +178,18 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell, ...@@ -178,13 +178,18 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell,
/* /*
* look up a server by its IP address * look up a server by its IP address
*/ */
struct afs_server *afs_find_server(const struct in_addr *_addr) struct afs_server *afs_find_server(const struct sockaddr_rxrpc *srx)
{ {
struct afs_server *server = NULL; struct afs_server *server = NULL;
struct rb_node *p; struct rb_node *p;
struct in_addr addr = *_addr; struct in_addr addr = srx->transport.sin.sin_addr;
_enter("%pI4", &addr.s_addr); _enter("{%d,%pI4}", srx->transport.family, &addr.s_addr);
if (srx->transport.family != AF_INET) {
WARN(true, "AFS does not yes support non-IPv4 addresses\n");
return NULL;
}
read_lock(&afs_servers_lock); read_lock(&afs_servers_lock);
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/rxrpc.h> #include <linux/rxrpc.h>
struct key;
struct sock;
struct socket;
struct rxrpc_call; struct rxrpc_call;
/* /*
...@@ -39,15 +42,18 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *, ...@@ -39,15 +42,18 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
struct key *, struct key *,
unsigned long, unsigned long,
gfp_t); gfp_t);
int rxrpc_kernel_send_data(struct rxrpc_call *, struct msghdr *, size_t); int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
struct msghdr *, size_t);
void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
void rxrpc_kernel_abort_call(struct rxrpc_call *, u32); void rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *, u32);
void rxrpc_kernel_end_call(struct rxrpc_call *); void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
bool rxrpc_kernel_is_data_last(struct sk_buff *); bool rxrpc_kernel_is_data_last(struct sk_buff *);
u32 rxrpc_kernel_get_abort_code(struct sk_buff *); u32 rxrpc_kernel_get_abort_code(struct sk_buff *);
int rxrpc_kernel_get_error_number(struct sk_buff *); int rxrpc_kernel_get_error_number(struct sk_buff *);
void rxrpc_kernel_free_skb(struct sk_buff *); void rxrpc_kernel_free_skb(struct sk_buff *);
struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long); struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long);
int rxrpc_kernel_reject_call(struct socket *); int rxrpc_kernel_reject_call(struct socket *);
void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
struct sockaddr_rxrpc *);
#endif /* _NET_RXRPC_H */ #endif /* _NET_RXRPC_H */
...@@ -16,6 +16,45 @@ ...@@ -16,6 +16,45 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
TRACE_EVENT(rxrpc_call,
TP_PROTO(struct rxrpc_call *call, int op, int usage, int nskb,
const void *where, const void *aux),
TP_ARGS(call, op, usage, nskb, where, aux),
TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(int, op )
__field(int, usage )
__field(int, nskb )
__field(const void *, where )
__field(const void *, aux )
),
TP_fast_assign(
__entry->call = call;
__entry->op = op;
__entry->usage = usage;
__entry->nskb = nskb;
__entry->where = where;
__entry->aux = aux;
),
TP_printk("c=%p %s u=%d s=%d p=%pSR a=%p",
__entry->call,
(__entry->op == 0 ? "NWc" :
__entry->op == 1 ? "NWs" :
__entry->op == 2 ? "SEE" :
__entry->op == 3 ? "GET" :
__entry->op == 4 ? "Gsb" :
__entry->op == 5 ? "PUT" :
"Psb"),
__entry->usage,
__entry->nskb,
__entry->where,
__entry->aux)
);
TRACE_EVENT(rxrpc_skb, TRACE_EVENT(rxrpc_skb,
TP_PROTO(struct sk_buff *skb, int op, int usage, int mod_count, TP_PROTO(struct sk_buff *skb, int op, int usage, int mod_count,
const void *where), const void *where),
......
...@@ -279,15 +279,16 @@ EXPORT_SYMBOL(rxrpc_kernel_begin_call); ...@@ -279,15 +279,16 @@ EXPORT_SYMBOL(rxrpc_kernel_begin_call);
/** /**
* rxrpc_kernel_end_call - Allow a kernel service to end a call it was using * rxrpc_kernel_end_call - Allow a kernel service to end a call it was using
* @sock: The socket the call is on
* @call: The call to end * @call: The call to end
* *
* Allow a kernel service to end a call it was using. The call must be * Allow a kernel service to end a call it was using. The call must be
* complete before this is called (the call should be aborted if necessary). * complete before this is called (the call should be aborted if necessary).
*/ */
void rxrpc_kernel_end_call(struct rxrpc_call *call) void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call)
{ {
_enter("%d{%d}", call->debug_id, atomic_read(&call->usage)); _enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
rxrpc_remove_user_ID(call->socket, call); rxrpc_remove_user_ID(rxrpc_sk(sock->sk), call);
rxrpc_put_call(call); rxrpc_put_call(call);
} }
EXPORT_SYMBOL(rxrpc_kernel_end_call); EXPORT_SYMBOL(rxrpc_kernel_end_call);
......
...@@ -289,8 +289,6 @@ enum rxrpc_conn_proto_state { ...@@ -289,8 +289,6 @@ enum rxrpc_conn_proto_state {
RXRPC_CONN_SERVICE, /* Service secured connection */ RXRPC_CONN_SERVICE, /* Service secured connection */
RXRPC_CONN_REMOTELY_ABORTED, /* Conn aborted by peer */ RXRPC_CONN_REMOTELY_ABORTED, /* Conn aborted by peer */
RXRPC_CONN_LOCALLY_ABORTED, /* Conn aborted locally */ RXRPC_CONN_LOCALLY_ABORTED, /* Conn aborted locally */
RXRPC_CONN_NETWORK_ERROR, /* Conn terminated by network error */
RXRPC_CONN_LOCAL_ERROR, /* Conn terminated by local error */
RXRPC_CONN__NR_STATES RXRPC_CONN__NR_STATES
}; };
...@@ -344,7 +342,6 @@ struct rxrpc_connection { ...@@ -344,7 +342,6 @@ struct rxrpc_connection {
enum rxrpc_conn_proto_state state : 8; /* current state of connection */ enum rxrpc_conn_proto_state state : 8; /* current state of connection */
u32 local_abort; /* local abort code */ u32 local_abort; /* local abort code */
u32 remote_abort; /* remote abort code */ u32 remote_abort; /* remote abort code */
int error; /* local error incurred */
int debug_id; /* debug ID for printks */ int debug_id; /* debug ID for printks */
atomic_t serial; /* packet serial number counter */ atomic_t serial; /* packet serial number counter */
unsigned int hi_serial; /* highest serial number received */ unsigned int hi_serial; /* highest serial number received */
...@@ -411,13 +408,22 @@ enum rxrpc_call_state { ...@@ -411,13 +408,22 @@ enum rxrpc_call_state {
RXRPC_CALL_SERVER_ACK_REQUEST, /* - server pending ACK of request */ RXRPC_CALL_SERVER_ACK_REQUEST, /* - server pending ACK of request */
RXRPC_CALL_SERVER_SEND_REPLY, /* - server sending reply */ RXRPC_CALL_SERVER_SEND_REPLY, /* - server sending reply */
RXRPC_CALL_SERVER_AWAIT_ACK, /* - server awaiting final ACK */ RXRPC_CALL_SERVER_AWAIT_ACK, /* - server awaiting final ACK */
RXRPC_CALL_COMPLETE, /* - call completed */ RXRPC_CALL_COMPLETE, /* - call complete */
RXRPC_CALL_DEAD, /* - call is dead */
NR__RXRPC_CALL_STATES
};
/*
* Call completion condition (state == RXRPC_CALL_COMPLETE).
*/
enum rxrpc_call_completion {
RXRPC_CALL_SUCCEEDED, /* - Normal termination */
RXRPC_CALL_SERVER_BUSY, /* - call rejected by busy server */ RXRPC_CALL_SERVER_BUSY, /* - call rejected by busy server */
RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */ RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */
RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */ RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */
RXRPC_CALL_LOCAL_ERROR, /* - call failed due to local error */
RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */ RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */
RXRPC_CALL_DEAD, /* - call is dead */ NR__RXRPC_CALL_COMPLETIONS
NR__RXRPC_CALL_STATES
}; };
/* /*
...@@ -451,14 +457,13 @@ struct rxrpc_call { ...@@ -451,14 +457,13 @@ struct rxrpc_call {
unsigned long events; unsigned long events;
spinlock_t lock; spinlock_t lock;
rwlock_t state_lock; /* lock for state transition */ rwlock_t state_lock; /* lock for state transition */
u32 abort_code; /* Local/remote abort code */
int error; /* Local error incurred */
enum rxrpc_call_state state : 8; /* current state of call */
enum rxrpc_call_completion completion : 8; /* Call completion condition */
atomic_t usage; atomic_t usage;
atomic_t skb_count; /* Outstanding packets on this call */ atomic_t skb_count; /* Outstanding packets on this call */
atomic_t sequence; /* Tx data packet sequence counter */ atomic_t sequence; /* Tx data packet sequence counter */
u32 local_abort; /* local abort code */
u32 remote_abort; /* remote abort code */
int error_report; /* Network error (ICMP/local transport) */
int error; /* Local error incurred */
enum rxrpc_call_state state : 8; /* current state of call */
u16 service_id; /* service ID */ u16 service_id; /* service ID */
u32 call_id; /* call ID on connection */ u32 call_id; /* call ID on connection */
u32 cid; /* connection ID plus channel index */ u32 cid; /* connection ID plus channel index */
...@@ -493,20 +498,6 @@ struct rxrpc_call { ...@@ -493,20 +498,6 @@ struct rxrpc_call {
unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1];
}; };
/*
* locally abort an RxRPC call
*/
static inline void rxrpc_abort_call(struct rxrpc_call *call, u32 abort_code)
{
write_lock_bh(&call->state_lock);
if (call->state < RXRPC_CALL_COMPLETE) {
call->local_abort = abort_code;
call->state = RXRPC_CALL_LOCALLY_ABORTED;
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
}
write_unlock_bh(&call->state_lock);
}
#include <trace/events/rxrpc.h> #include <trace/events/rxrpc.h>
/* /*
...@@ -534,6 +525,8 @@ void rxrpc_process_call(struct work_struct *); ...@@ -534,6 +525,8 @@ void rxrpc_process_call(struct work_struct *);
/* /*
* call_object.c * call_object.c
*/ */
extern const char *const rxrpc_call_states[];
extern const char *const rxrpc_call_completions[];
extern unsigned int rxrpc_max_call_lifetime; extern unsigned int rxrpc_max_call_lifetime;
extern unsigned int rxrpc_dead_call_expiry; extern unsigned int rxrpc_dead_call_expiry;
extern struct kmem_cache *rxrpc_call_jar; extern struct kmem_cache *rxrpc_call_jar;
...@@ -550,7 +543,11 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *, ...@@ -550,7 +543,11 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *,
struct sk_buff *); struct sk_buff *);
void rxrpc_release_call(struct rxrpc_call *); void rxrpc_release_call(struct rxrpc_call *);
void rxrpc_release_calls_on_socket(struct rxrpc_sock *); void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
void __rxrpc_put_call(struct rxrpc_call *); void rxrpc_see_call(struct rxrpc_call *);
void rxrpc_get_call(struct rxrpc_call *);
void rxrpc_put_call(struct rxrpc_call *);
void rxrpc_get_call_for_skb(struct rxrpc_call *, struct sk_buff *);
void rxrpc_put_call_for_skb(struct rxrpc_call *, struct sk_buff *);
void __exit rxrpc_destroy_all_calls(void); void __exit rxrpc_destroy_all_calls(void);
static inline bool rxrpc_is_service_call(const struct rxrpc_call *call) static inline bool rxrpc_is_service_call(const struct rxrpc_call *call)
...@@ -563,6 +560,78 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call) ...@@ -563,6 +560,78 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call)
return !rxrpc_is_service_call(call); return !rxrpc_is_service_call(call);
} }
/*
* Transition a call to the complete state.
*/
static inline bool __rxrpc_set_call_completion(struct rxrpc_call *call,
enum rxrpc_call_completion compl,
u32 abort_code,
int error)
{
if (call->state < RXRPC_CALL_COMPLETE) {
call->abort_code = abort_code;
call->error = error;
call->completion = compl,
call->state = RXRPC_CALL_COMPLETE;
return true;
}
return false;
}
static inline bool rxrpc_set_call_completion(struct rxrpc_call *call,
enum rxrpc_call_completion compl,
u32 abort_code,
int error)
{
int ret;
write_lock_bh(&call->state_lock);
ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
write_unlock_bh(&call->state_lock);
return ret;
}
/*
* Record that a call successfully completed.
*/
static inline void __rxrpc_call_completed(struct rxrpc_call *call)
{
__rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
}
static inline void rxrpc_call_completed(struct rxrpc_call *call)
{
write_lock_bh(&call->state_lock);
__rxrpc_call_completed(call);
write_unlock_bh(&call->state_lock);
}
/*
* Record that a call is locally aborted.
*/
static inline bool __rxrpc_abort_call(struct rxrpc_call *call,
u32 abort_code, int error)
{
if (__rxrpc_set_call_completion(call,
RXRPC_CALL_LOCALLY_ABORTED,
abort_code, error)) {
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
return true;
}
return false;
}
static inline bool rxrpc_abort_call(struct rxrpc_call *call,
u32 abort_code, int error)
{
bool ret;
write_lock_bh(&call->state_lock);
ret = __rxrpc_abort_call(call, abort_code, error);
write_unlock_bh(&call->state_lock);
return ret;
}
/* /*
* conn_client.c * conn_client.c
*/ */
...@@ -778,7 +847,6 @@ static inline void rxrpc_put_peer(struct rxrpc_peer *peer) ...@@ -778,7 +847,6 @@ static inline void rxrpc_put_peer(struct rxrpc_peer *peer)
/* /*
* proc.c * proc.c
*/ */
extern const char *const rxrpc_call_states[];
extern const struct file_operations rxrpc_call_seq_fops; extern const struct file_operations rxrpc_call_seq_fops;
extern const struct file_operations rxrpc_connection_seq_fops; extern const struct file_operations rxrpc_connection_seq_fops;
...@@ -958,16 +1026,3 @@ do { \ ...@@ -958,16 +1026,3 @@ do { \
} while (0) } while (0)
#endif /* __KDEBUGALL */ #endif /* __KDEBUGALL */
#define rxrpc_get_call(CALL) \
do { \
CHECK_SLAB_OKAY(&(CALL)->usage); \
if (atomic_inc_return(&(CALL)->usage) == 1) \
BUG(); \
} while (0)
#define rxrpc_put_call(CALL) \
do { \
__rxrpc_put_call(CALL); \
} while (0)
...@@ -129,8 +129,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, ...@@ -129,8 +129,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local,
_debug("conn ready"); _debug("conn ready");
call->state = RXRPC_CALL_SERVER_ACCEPTING; call->state = RXRPC_CALL_SERVER_ACCEPTING;
list_add_tail(&call->accept_link, &rx->acceptq); list_add_tail(&call->accept_link, &rx->acceptq);
rxrpc_get_call(call); rxrpc_get_call_for_skb(call, notification);
atomic_inc(&call->skb_count);
nsp = rxrpc_skb(notification); nsp = rxrpc_skb(notification);
nsp->call = call; nsp->call = call;
...@@ -323,18 +322,15 @@ struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx, ...@@ -323,18 +322,15 @@ struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,
call = list_entry(rx->acceptq.next, struct rxrpc_call, accept_link); call = list_entry(rx->acceptq.next, struct rxrpc_call, accept_link);
list_del_init(&call->accept_link); list_del_init(&call->accept_link);
sk_acceptq_removed(&rx->sk); sk_acceptq_removed(&rx->sk);
rxrpc_see_call(call);
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
switch (call->state) { switch (call->state) {
case RXRPC_CALL_SERVER_ACCEPTING: case RXRPC_CALL_SERVER_ACCEPTING:
call->state = RXRPC_CALL_SERVER_RECV_REQUEST; call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
break; break;
case RXRPC_CALL_REMOTELY_ABORTED: case RXRPC_CALL_COMPLETE:
case RXRPC_CALL_LOCALLY_ABORTED: ret = call->error;
ret = -ECONNABORTED;
goto out_release;
case RXRPC_CALL_NETWORK_ERROR:
ret = call->conn->error;
goto out_release; goto out_release;
case RXRPC_CALL_DEAD: case RXRPC_CALL_DEAD:
ret = -ETIME; ret = -ETIME;
...@@ -399,21 +395,19 @@ int rxrpc_reject_call(struct rxrpc_sock *rx) ...@@ -399,21 +395,19 @@ int rxrpc_reject_call(struct rxrpc_sock *rx)
call = list_entry(rx->acceptq.next, struct rxrpc_call, accept_link); call = list_entry(rx->acceptq.next, struct rxrpc_call, accept_link);
list_del_init(&call->accept_link); list_del_init(&call->accept_link);
sk_acceptq_removed(&rx->sk); sk_acceptq_removed(&rx->sk);
rxrpc_see_call(call);
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
switch (call->state) { switch (call->state) {
case RXRPC_CALL_SERVER_ACCEPTING: case RXRPC_CALL_SERVER_ACCEPTING:
call->state = RXRPC_CALL_SERVER_BUSY; __rxrpc_set_call_completion(call, RXRPC_CALL_SERVER_BUSY,
0, ECONNABORTED);
if (test_and_set_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events)) if (test_and_set_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events))
rxrpc_queue_call(call); rxrpc_queue_call(call);
ret = 0; ret = 0;
goto out_release; goto out_release;
case RXRPC_CALL_REMOTELY_ABORTED: case RXRPC_CALL_COMPLETE:
case RXRPC_CALL_LOCALLY_ABORTED: ret = call->error;
ret = -ECONNABORTED;
goto out_release;
case RXRPC_CALL_NETWORK_ERROR:
ret = call->conn->error;
goto out_release; goto out_release;
case RXRPC_CALL_DEAD: case RXRPC_CALL_DEAD:
ret = -ETIME; ret = -ETIME;
......
...@@ -95,7 +95,7 @@ void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, ...@@ -95,7 +95,7 @@ void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
_debug("cancel timer %%%u", serial); _debug("cancel timer %%%u", serial);
try_to_del_timer_sync(&call->ack_timer); try_to_del_timer_sync(&call->ack_timer);
read_lock_bh(&call->state_lock); read_lock_bh(&call->state_lock);
if (call->state <= RXRPC_CALL_COMPLETE && if (call->state < RXRPC_CALL_COMPLETE &&
!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events)) !test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events))
rxrpc_queue_call(call); rxrpc_queue_call(call);
read_unlock_bh(&call->state_lock); read_unlock_bh(&call->state_lock);
...@@ -123,7 +123,7 @@ static void rxrpc_set_resend(struct rxrpc_call *call, u8 resend, ...@@ -123,7 +123,7 @@ static void rxrpc_set_resend(struct rxrpc_call *call, u8 resend,
unsigned long resend_at) unsigned long resend_at)
{ {
read_lock_bh(&call->state_lock); read_lock_bh(&call->state_lock);
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state == RXRPC_CALL_COMPLETE)
resend = 0; resend = 0;
if (resend & 1) { if (resend & 1) {
...@@ -230,7 +230,7 @@ static void rxrpc_resend_timer(struct rxrpc_call *call) ...@@ -230,7 +230,7 @@ static void rxrpc_resend_timer(struct rxrpc_call *call)
_enter("%d,%d,%d", _enter("%d,%d,%d",
call->acks_tail, call->acks_unacked, call->acks_head); call->acks_tail, call->acks_unacked, call->acks_head);
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state == RXRPC_CALL_COMPLETE)
return; return;
resend = 0; resend = 0;
...@@ -465,8 +465,7 @@ static void rxrpc_insert_oos_packet(struct rxrpc_call *call, ...@@ -465,8 +465,7 @@ static void rxrpc_insert_oos_packet(struct rxrpc_call *call,
skb->destructor = rxrpc_packet_destructor; skb->destructor = rxrpc_packet_destructor;
ASSERTCMP(sp->call, ==, NULL); ASSERTCMP(sp->call, ==, NULL);
sp->call = call; sp->call = call;
rxrpc_get_call(call); rxrpc_get_call_for_skb(call, skb);
atomic_inc(&call->skb_count);
/* insert into the buffer in sequence order */ /* insert into the buffer in sequence order */
spin_lock_bh(&call->lock); spin_lock_bh(&call->lock);
...@@ -552,7 +551,7 @@ static void rxrpc_extract_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, ...@@ -552,7 +551,7 @@ static void rxrpc_extract_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
mtu = min(ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU)); mtu = min(ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU));
peer = call->conn->params.peer; peer = call->peer;
if (mtu < peer->maxdata) { if (mtu < peer->maxdata) {
spin_lock_bh(&peer->lock); spin_lock_bh(&peer->lock);
peer->maxdata = mtu; peer->maxdata = mtu;
...@@ -711,7 +710,7 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call, ...@@ -711,7 +710,7 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call,
break; break;
case RXRPC_CALL_SERVER_AWAIT_ACK: case RXRPC_CALL_SERVER_AWAIT_ACK:
_debug("srv complete"); _debug("srv complete");
call->state = RXRPC_CALL_COMPLETE; __rxrpc_call_completed(call);
post_ACK = true; post_ACK = true;
break; break;
case RXRPC_CALL_CLIENT_SEND_REQUEST: case RXRPC_CALL_CLIENT_SEND_REQUEST:
...@@ -741,8 +740,7 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call, ...@@ -741,8 +740,7 @@ static int rxrpc_process_rx_queue(struct rxrpc_call *call,
_debug("post ACK"); _debug("post ACK");
skb->mark = RXRPC_SKB_MARK_FINAL_ACK; skb->mark = RXRPC_SKB_MARK_FINAL_ACK;
sp->call = call; sp->call = call;
rxrpc_get_call(call); rxrpc_get_call_for_skb(call, skb);
atomic_inc(&call->skb_count);
spin_lock_bh(&call->lock); spin_lock_bh(&call->lock);
if (rxrpc_queue_rcv_skb(call, skb, true, true) < 0) if (rxrpc_queue_rcv_skb(call, skb, true, true) < 0)
BUG(); BUG();
...@@ -801,8 +799,7 @@ static int rxrpc_post_message(struct rxrpc_call *call, u32 mark, u32 error, ...@@ -801,8 +799,7 @@ static int rxrpc_post_message(struct rxrpc_call *call, u32 mark, u32 error,
memset(sp, 0, sizeof(*sp)); memset(sp, 0, sizeof(*sp));
sp->error = error; sp->error = error;
sp->call = call; sp->call = call;
rxrpc_get_call(call); rxrpc_get_call_for_skb(call, skb);
atomic_inc(&call->skb_count);
spin_lock_bh(&call->lock); spin_lock_bh(&call->lock);
ret = rxrpc_queue_rcv_skb(call, skb, true, fatal); ret = rxrpc_queue_rcv_skb(call, skb, true, fatal);
...@@ -834,6 +831,8 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -834,6 +831,8 @@ void rxrpc_process_call(struct work_struct *work)
u32 serial, abort_code = RX_PROTOCOL_ERROR; u32 serial, abort_code = RX_PROTOCOL_ERROR;
u8 *acks = NULL; u8 *acks = NULL;
rxrpc_see_call(call);
//printk("\n--------------------\n"); //printk("\n--------------------\n");
_enter("{%d,%s,%lx} [%lu]", _enter("{%d,%s,%lx} [%lu]",
call->debug_id, rxrpc_call_states[call->state], call->events, call->debug_id, rxrpc_call_states[call->state], call->events,
...@@ -844,8 +843,8 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -844,8 +843,8 @@ void rxrpc_process_call(struct work_struct *work)
/* there's a good chance we're going to have to send a message, so set /* there's a good chance we're going to have to send a message, so set
* one up in advance */ * one up in advance */
msg.msg_name = &call->conn->params.peer->srx.transport; msg.msg_name = &call->peer->srx.transport;
msg.msg_namelen = call->conn->params.peer->srx.transport_len; msg.msg_namelen = call->peer->srx.transport_len;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = 0; msg.msg_flags = 0;
...@@ -875,24 +874,22 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -875,24 +874,22 @@ void rxrpc_process_call(struct work_struct *work)
clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events); clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events);
clear_bit(RXRPC_CALL_EV_ABORT, &call->events); clear_bit(RXRPC_CALL_EV_ABORT, &call->events);
error = call->error_report; if (call->completion == RXRPC_CALL_NETWORK_ERROR) {
if (error < RXRPC_LOCAL_ERROR_OFFSET) {
mark = RXRPC_SKB_MARK_NET_ERROR; mark = RXRPC_SKB_MARK_NET_ERROR;
_debug("post net error %d", error); _debug("post net error %d", error);
} else { } else {
mark = RXRPC_SKB_MARK_LOCAL_ERROR; mark = RXRPC_SKB_MARK_LOCAL_ERROR;
error -= RXRPC_LOCAL_ERROR_OFFSET;
_debug("post net local error %d", error); _debug("post net local error %d", error);
} }
if (rxrpc_post_message(call, mark, error, true) < 0) if (rxrpc_post_message(call, mark, call->error, true) < 0)
goto no_mem; goto no_mem;
clear_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events); clear_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events);
goto kill_ACKs; goto kill_ACKs;
} }
if (test_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events)) { if (test_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events)) {
ASSERTCMP(call->state, >, RXRPC_CALL_COMPLETE); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events); clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events);
clear_bit(RXRPC_CALL_EV_ABORT, &call->events); clear_bit(RXRPC_CALL_EV_ABORT, &call->events);
...@@ -900,7 +897,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -900,7 +897,7 @@ void rxrpc_process_call(struct work_struct *work)
_debug("post conn abort"); _debug("post conn abort");
if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR, if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR,
call->conn->error, true) < 0) call->error, true) < 0)
goto no_mem; goto no_mem;
clear_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events); clear_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events);
goto kill_ACKs; goto kill_ACKs;
...@@ -913,13 +910,13 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -913,13 +910,13 @@ void rxrpc_process_call(struct work_struct *work)
} }
if (test_bit(RXRPC_CALL_EV_ABORT, &call->events)) { if (test_bit(RXRPC_CALL_EV_ABORT, &call->events)) {
ASSERTCMP(call->state, >, RXRPC_CALL_COMPLETE); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR, if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR,
ECONNABORTED, true) < 0) call->error, true) < 0)
goto no_mem; goto no_mem;
whdr.type = RXRPC_PACKET_TYPE_ABORT; whdr.type = RXRPC_PACKET_TYPE_ABORT;
data = htonl(call->local_abort); data = htonl(call->abort_code);
iov[1].iov_base = &data; iov[1].iov_base = &data;
iov[1].iov_len = sizeof(data); iov[1].iov_len = sizeof(data);
genbit = RXRPC_CALL_EV_ABORT; genbit = RXRPC_CALL_EV_ABORT;
...@@ -979,13 +976,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -979,13 +976,7 @@ void rxrpc_process_call(struct work_struct *work)
} }
if (test_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events)) { if (test_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events)) {
write_lock_bh(&call->state_lock); rxrpc_abort_call(call, RX_CALL_TIMEOUT, ETIME);
if (call->state <= RXRPC_CALL_COMPLETE) {
call->state = RXRPC_CALL_LOCALLY_ABORTED;
call->local_abort = RX_CALL_TIMEOUT;
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
}
write_unlock_bh(&call->state_lock);
_debug("post timeout"); _debug("post timeout");
if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR, if (rxrpc_post_message(call, RXRPC_SKB_MARK_LOCAL_ERROR,
...@@ -998,7 +989,8 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -998,7 +989,8 @@ void rxrpc_process_call(struct work_struct *work)
/* deal with assorted inbound messages */ /* deal with assorted inbound messages */
if (!skb_queue_empty(&call->rx_queue)) { if (!skb_queue_empty(&call->rx_queue)) {
switch (rxrpc_process_rx_queue(call, &abort_code)) { ret = rxrpc_process_rx_queue(call, &abort_code);
switch (ret) {
case 0: case 0:
case -EAGAIN: case -EAGAIN:
break; break;
...@@ -1007,7 +999,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -1007,7 +999,7 @@ void rxrpc_process_call(struct work_struct *work)
case -EKEYEXPIRED: case -EKEYEXPIRED:
case -EKEYREJECTED: case -EKEYREJECTED:
case -EPROTO: case -EPROTO:
rxrpc_abort_call(call, abort_code); rxrpc_abort_call(call, abort_code, -ret);
goto kill_ACKs; goto kill_ACKs;
} }
} }
...@@ -1159,8 +1151,8 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -1159,8 +1151,8 @@ void rxrpc_process_call(struct work_struct *work)
send_ACK_with_skew: send_ACK_with_skew:
ack.maxSkew = htons(call->ackr_skew); ack.maxSkew = htons(call->ackr_skew);
send_ACK: send_ACK:
mtu = call->conn->params.peer->if_mtu; mtu = call->peer->if_mtu;
mtu -= call->conn->params.peer->hdrsize; mtu -= call->peer->hdrsize;
ackinfo.maxMTU = htonl(mtu); ackinfo.maxMTU = htonl(mtu);
ackinfo.rwind = htonl(rxrpc_rx_window_size); ackinfo.rwind = htonl(rxrpc_rx_window_size);
...@@ -1232,10 +1224,7 @@ void rxrpc_process_call(struct work_struct *work) ...@@ -1232,10 +1224,7 @@ void rxrpc_process_call(struct work_struct *work)
goto kill_ACKs; goto kill_ACKs;
case RXRPC_CALL_EV_ACK_FINAL: case RXRPC_CALL_EV_ACK_FINAL:
write_lock_bh(&call->state_lock); rxrpc_call_completed(call);
if (call->state == RXRPC_CALL_CLIENT_FINAL_ACK)
call->state = RXRPC_CALL_COMPLETE;
write_unlock_bh(&call->state_lock);
goto kill_ACKs; goto kill_ACKs;
default: default:
......
...@@ -30,7 +30,7 @@ unsigned int rxrpc_max_call_lifetime = 60 * HZ; ...@@ -30,7 +30,7 @@ unsigned int rxrpc_max_call_lifetime = 60 * HZ;
unsigned int rxrpc_dead_call_expiry = 2 * HZ; unsigned int rxrpc_dead_call_expiry = 2 * HZ;
const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = { const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
[RXRPC_CALL_UNINITIALISED] = "Uninit", [RXRPC_CALL_UNINITIALISED] = "Uninit ",
[RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn", [RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn",
[RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq",
[RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl",
...@@ -43,11 +43,16 @@ const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = { ...@@ -43,11 +43,16 @@ const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
[RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl", [RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl",
[RXRPC_CALL_SERVER_AWAIT_ACK] = "SvAwtACK", [RXRPC_CALL_SERVER_AWAIT_ACK] = "SvAwtACK",
[RXRPC_CALL_COMPLETE] = "Complete", [RXRPC_CALL_COMPLETE] = "Complete",
[RXRPC_CALL_DEAD] = "Dead ",
};
const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = {
[RXRPC_CALL_SUCCEEDED] = "Complete",
[RXRPC_CALL_SERVER_BUSY] = "SvBusy ", [RXRPC_CALL_SERVER_BUSY] = "SvBusy ",
[RXRPC_CALL_REMOTELY_ABORTED] = "RmtAbort", [RXRPC_CALL_REMOTELY_ABORTED] = "RmtAbort",
[RXRPC_CALL_LOCALLY_ABORTED] = "LocAbort", [RXRPC_CALL_LOCALLY_ABORTED] = "LocAbort",
[RXRPC_CALL_LOCAL_ERROR] = "LocError",
[RXRPC_CALL_NETWORK_ERROR] = "NetError", [RXRPC_CALL_NETWORK_ERROR] = "NetError",
[RXRPC_CALL_DEAD] = "Dead ",
}; };
struct kmem_cache *rxrpc_call_jar; struct kmem_cache *rxrpc_call_jar;
...@@ -214,6 +219,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -214,6 +219,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
{ {
struct rxrpc_call *call, *xcall; struct rxrpc_call *call, *xcall;
struct rb_node *parent, **pp; struct rb_node *parent, **pp;
const void *here = __builtin_return_address(0);
int ret; int ret;
_enter("%p,%lx", rx, user_call_ID); _enter("%p,%lx", rx, user_call_ID);
...@@ -224,6 +230,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -224,6 +230,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
return call; return call;
} }
trace_rxrpc_call(call, 0, atomic_read(&call->usage), 0, here,
(const void *)user_call_ID);
/* Publish the call, even though it is incompletely set up as yet */ /* Publish the call, even though it is incompletely set up as yet */
call->user_call_ID = user_call_ID; call->user_call_ID = user_call_ID;
__set_bit(RXRPC_CALL_HAS_USERID, &call->flags); __set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
...@@ -303,6 +312,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, ...@@ -303,6 +312,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
{ {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_call *call, *candidate; struct rxrpc_call *call, *candidate;
const void *here = __builtin_return_address(0);
u32 call_id, chan; u32 call_id, chan;
_enter(",%d", conn->debug_id); _enter(",%d", conn->debug_id);
...@@ -313,6 +323,9 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, ...@@ -313,6 +323,9 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
if (!candidate) if (!candidate)
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
trace_rxrpc_call(candidate, 1, atomic_read(&candidate->usage),
0, here, NULL);
chan = sp->hdr.cid & RXRPC_CHANNELMASK; chan = sp->hdr.cid & RXRPC_CHANNELMASK;
candidate->socket = rx; candidate->socket = rx;
candidate->conn = conn; candidate->conn = conn;
...@@ -358,7 +371,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, ...@@ -358,7 +371,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
_debug("CALL: %u { %s }", _debug("CALL: %u { %s }",
call->debug_id, rxrpc_call_states[call->state]); call->debug_id, rxrpc_call_states[call->state]);
if (call->state >= RXRPC_CALL_COMPLETE) { if (call->state == RXRPC_CALL_COMPLETE) {
__rxrpc_disconnect_call(conn, call); __rxrpc_disconnect_call(conn, call);
} else { } else {
spin_unlock(&conn->channel_lock); spin_unlock(&conn->channel_lock);
...@@ -425,6 +438,44 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, ...@@ -425,6 +438,44 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
return ERR_PTR(-ECONNRESET); return ERR_PTR(-ECONNRESET);
} }
/*
* Note the re-emergence of a call.
*/
void rxrpc_see_call(struct rxrpc_call *call)
{
const void *here = __builtin_return_address(0);
if (call) {
int n = atomic_read(&call->usage);
int m = atomic_read(&call->skb_count);
trace_rxrpc_call(call, 2, n, m, here, 0);
}
}
/*
* Note the addition of a ref on a call.
*/
void rxrpc_get_call(struct rxrpc_call *call)
{
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(&call->usage);
int m = atomic_read(&call->skb_count);
trace_rxrpc_call(call, 3, n, m, here, 0);
}
/*
* Note the addition of a ref on a call for a socket buffer.
*/
void rxrpc_get_call_for_skb(struct rxrpc_call *call, struct sk_buff *skb)
{
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(&call->usage);
int m = atomic_inc_return(&call->skb_count);
trace_rxrpc_call(call, 4, n, m, here, skb);
}
/* /*
* detach a call from a socket and set up for release * detach a call from a socket and set up for release
*/ */
...@@ -438,6 +489,8 @@ void rxrpc_release_call(struct rxrpc_call *call) ...@@ -438,6 +489,8 @@ void rxrpc_release_call(struct rxrpc_call *call)
atomic_read(&call->ackr_not_idle), atomic_read(&call->ackr_not_idle),
call->rx_first_oos); call->rx_first_oos);
rxrpc_see_call(call);
spin_lock_bh(&call->lock); spin_lock_bh(&call->lock);
if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags)) if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags))
BUG(); BUG();
...@@ -472,8 +525,7 @@ void rxrpc_release_call(struct rxrpc_call *call) ...@@ -472,8 +525,7 @@ void rxrpc_release_call(struct rxrpc_call *call)
if (call->state < RXRPC_CALL_COMPLETE && if (call->state < RXRPC_CALL_COMPLETE &&
call->state != RXRPC_CALL_CLIENT_FINAL_ACK) { call->state != RXRPC_CALL_CLIENT_FINAL_ACK) {
_debug("+++ ABORTING STATE %d +++\n", call->state); _debug("+++ ABORTING STATE %d +++\n", call->state);
call->state = RXRPC_CALL_LOCALLY_ABORTED; __rxrpc_abort_call(call, RX_CALL_DEAD, ECONNRESET);
call->local_abort = RX_CALL_DEAD;
} }
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
...@@ -522,6 +574,7 @@ static void rxrpc_dead_call_expired(unsigned long _call) ...@@ -522,6 +574,7 @@ static void rxrpc_dead_call_expired(unsigned long _call)
_enter("{%d}", call->debug_id); _enter("{%d}", call->debug_id);
rxrpc_see_call(call);
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
call->state = RXRPC_CALL_DEAD; call->state = RXRPC_CALL_DEAD;
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
...@@ -536,22 +589,16 @@ static void rxrpc_mark_call_released(struct rxrpc_call *call) ...@@ -536,22 +589,16 @@ static void rxrpc_mark_call_released(struct rxrpc_call *call)
{ {
bool sched; bool sched;
rxrpc_see_call(call);
write_lock(&call->state_lock); write_lock(&call->state_lock);
if (call->state < RXRPC_CALL_DEAD) { if (call->state < RXRPC_CALL_DEAD) {
sched = false; sched = __rxrpc_abort_call(call, RX_CALL_DEAD, ECONNRESET);
if (call->state < RXRPC_CALL_COMPLETE) {
_debug("abort call %p", call);
call->state = RXRPC_CALL_LOCALLY_ABORTED;
call->local_abort = RX_CALL_DEAD;
if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events))
sched = true;
}
if (!test_and_set_bit(RXRPC_CALL_EV_RELEASE, &call->events)) if (!test_and_set_bit(RXRPC_CALL_EV_RELEASE, &call->events))
sched = true; sched = true;
if (sched)
rxrpc_queue_call(call);
} }
write_unlock(&call->state_lock); write_unlock(&call->state_lock);
if (sched)
rxrpc_queue_call(call);
} }
/* /*
...@@ -588,21 +635,43 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) ...@@ -588,21 +635,43 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)
/* /*
* release a call * release a call
*/ */
void __rxrpc_put_call(struct rxrpc_call *call) void rxrpc_put_call(struct rxrpc_call *call)
{ {
ASSERT(call != NULL); const void *here = __builtin_return_address(0);
int n, m;
_enter("%p{u=%d}", call, atomic_read(&call->usage)); ASSERT(call != NULL);
ASSERTCMP(atomic_read(&call->usage), >, 0); n = atomic_dec_return(&call->usage);
m = atomic_read(&call->skb_count);
trace_rxrpc_call(call, 5, n, m, here, NULL);
ASSERTCMP(n, >=, 0);
if (n == 0) {
_debug("call %d dead", call->debug_id);
WARN_ON(m != 0);
ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD);
rxrpc_queue_work(&call->destroyer);
}
}
if (atomic_dec_and_test(&call->usage)) { /*
* Release a call ref held by a socket buffer.
*/
void rxrpc_put_call_for_skb(struct rxrpc_call *call, struct sk_buff *skb)
{
const void *here = __builtin_return_address(0);
int n, m;
n = atomic_dec_return(&call->usage);
m = atomic_dec_return(&call->skb_count);
trace_rxrpc_call(call, 6, n, m, here, skb);
ASSERTCMP(n, >=, 0);
if (n == 0) {
_debug("call %d dead", call->debug_id); _debug("call %d dead", call->debug_id);
WARN_ON(atomic_read(&call->skb_count) != 0); WARN_ON(m != 0);
ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD); ASSERTCMP(call->state, ==, RXRPC_CALL_DEAD);
rxrpc_queue_work(&call->destroyer); rxrpc_queue_work(&call->destroyer);
} }
_leave("");
} }
/* /*
...@@ -708,6 +777,7 @@ void __exit rxrpc_destroy_all_calls(void) ...@@ -708,6 +777,7 @@ void __exit rxrpc_destroy_all_calls(void)
call = list_entry(rxrpc_calls.next, struct rxrpc_call, link); call = list_entry(rxrpc_calls.next, struct rxrpc_call, link);
_debug("Zapping call %p", call); _debug("Zapping call %p", call);
rxrpc_see_call(call);
list_del_init(&call->link); list_del_init(&call->link);
switch (atomic_read(&call->usage)) { switch (atomic_read(&call->usage)) {
...@@ -749,16 +819,14 @@ static void rxrpc_call_life_expired(unsigned long _call) ...@@ -749,16 +819,14 @@ static void rxrpc_call_life_expired(unsigned long _call)
{ {
struct rxrpc_call *call = (struct rxrpc_call *) _call; struct rxrpc_call *call = (struct rxrpc_call *) _call;
_enter("{%d}", call->debug_id);
rxrpc_see_call(call);
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state >= RXRPC_CALL_COMPLETE)
return; return;
_enter("{%d}", call->debug_id); set_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events);
read_lock_bh(&call->state_lock); rxrpc_queue_call(call);
if (call->state < RXRPC_CALL_COMPLETE) {
set_bit(RXRPC_CALL_EV_LIFE_TIMER, &call->events);
rxrpc_queue_call(call);
}
read_unlock_bh(&call->state_lock);
} }
/* /*
...@@ -771,6 +839,7 @@ static void rxrpc_resend_time_expired(unsigned long _call) ...@@ -771,6 +839,7 @@ static void rxrpc_resend_time_expired(unsigned long _call)
_enter("{%d}", call->debug_id); _enter("{%d}", call->debug_id);
rxrpc_see_call(call);
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state >= RXRPC_CALL_COMPLETE)
return; return;
...@@ -788,12 +857,10 @@ static void rxrpc_ack_time_expired(unsigned long _call) ...@@ -788,12 +857,10 @@ static void rxrpc_ack_time_expired(unsigned long _call)
_enter("{%d}", call->debug_id); _enter("{%d}", call->debug_id);
rxrpc_see_call(call);
if (call->state >= RXRPC_CALL_COMPLETE) if (call->state >= RXRPC_CALL_COMPLETE)
return; return;
read_lock_bh(&call->state_lock); if (!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events))
if (call->state < RXRPC_CALL_COMPLETE &&
!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events))
rxrpc_queue_call(call); rxrpc_queue_call(call);
read_unlock_bh(&call->state_lock);
} }
...@@ -537,6 +537,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn, ...@@ -537,6 +537,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
struct rxrpc_call, chan_wait_link); struct rxrpc_call, chan_wait_link);
u32 call_id = chan->call_counter + 1; u32 call_id = chan->call_counter + 1;
rxrpc_see_call(call);
list_del_init(&call->chan_wait_link); list_del_init(&call->chan_wait_link);
conn->active_chans |= 1 << channel; conn->active_chans |= 1 << channel;
call->peer = rxrpc_get_peer(conn->params.peer); call->peer = rxrpc_get_peer(conn->params.peer);
...@@ -741,7 +742,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call) ...@@ -741,7 +742,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
* terminal retransmission without requiring access to the call. * terminal retransmission without requiring access to the call.
*/ */
if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) { if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
_debug("exposed %u,%u", call->call_id, call->local_abort); _debug("exposed %u,%u", call->call_id, call->abort_code);
__rxrpc_disconnect_call(conn, call); __rxrpc_disconnect_call(conn, call);
} }
......
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
/* /*
* Retransmit terminal ACK or ABORT of the previous call. * Retransmit terminal ACK or ABORT of the previous call.
*/ */
static void rxrpc_conn_retransmit(struct rxrpc_connection *conn, static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_channel *chan; struct rxrpc_channel *chan;
...@@ -135,33 +135,39 @@ static void rxrpc_conn_retransmit(struct rxrpc_connection *conn, ...@@ -135,33 +135,39 @@ static void rxrpc_conn_retransmit(struct rxrpc_connection *conn,
/* /*
* pass a connection-level abort onto all calls on that connection * pass a connection-level abort onto all calls on that connection
*/ */
static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state, static void rxrpc_abort_calls(struct rxrpc_connection *conn,
u32 abort_code) enum rxrpc_call_completion compl,
u32 abort_code, int error)
{ {
struct rxrpc_call *call; struct rxrpc_call *call;
int i; bool queue;
int i, bit;
_enter("{%d},%x", conn->debug_id, abort_code); _enter("{%d},%x", conn->debug_id, abort_code);
if (compl == RXRPC_CALL_LOCALLY_ABORTED)
bit = RXRPC_CALL_EV_CONN_ABORT;
else
bit = RXRPC_CALL_EV_RCVD_ABORT;
spin_lock(&conn->channel_lock); spin_lock(&conn->channel_lock);
for (i = 0; i < RXRPC_MAXCALLS; i++) { for (i = 0; i < RXRPC_MAXCALLS; i++) {
call = rcu_dereference_protected( call = rcu_dereference_protected(
conn->channels[i].call, conn->channels[i].call,
lockdep_is_held(&conn->channel_lock)); lockdep_is_held(&conn->channel_lock));
write_lock_bh(&call->state_lock); if (call) {
if (call->state <= RXRPC_CALL_COMPLETE) { rxrpc_see_call(call);
call->state = state; write_lock_bh(&call->state_lock);
if (state == RXRPC_CALL_LOCALLY_ABORTED) { if (rxrpc_set_call_completion(call, compl, abort_code,
call->local_abort = conn->local_abort; error)) {
set_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events); set_bit(bit, &call->events);
} else { queue = true;
call->remote_abort = conn->remote_abort;
set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events);
} }
rxrpc_queue_call(call); write_unlock_bh(&call->state_lock);
if (queue)
rxrpc_queue_call(call);
} }
write_unlock_bh(&call->state_lock);
} }
spin_unlock(&conn->channel_lock); spin_unlock(&conn->channel_lock);
...@@ -186,17 +192,16 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn, ...@@ -186,17 +192,16 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
/* generate a connection-level abort */ /* generate a connection-level abort */
spin_lock_bh(&conn->state_lock); spin_lock_bh(&conn->state_lock);
if (conn->state < RXRPC_CONN_REMOTELY_ABORTED) { if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
conn->state = RXRPC_CONN_LOCALLY_ABORTED;
conn->error = error;
spin_unlock_bh(&conn->state_lock);
} else {
spin_unlock_bh(&conn->state_lock); spin_unlock_bh(&conn->state_lock);
_leave(" = 0 [already dead]"); _leave(" = 0 [already dead]");
return 0; return 0;
} }
rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code); conn->state = RXRPC_CONN_LOCALLY_ABORTED;
spin_unlock_bh(&conn->state_lock);
rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code, error);
msg.msg_name = &conn->params.peer->srx.transport; msg.msg_name = &conn->params.peer->srx.transport;
msg.msg_namelen = conn->params.peer->srx.transport_len; msg.msg_namelen = conn->params.peer->srx.transport_len;
...@@ -276,7 +281,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, ...@@ -276,7 +281,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
switch (sp->hdr.type) { switch (sp->hdr.type) {
case RXRPC_PACKET_TYPE_DATA: case RXRPC_PACKET_TYPE_DATA:
case RXRPC_PACKET_TYPE_ACK: case RXRPC_PACKET_TYPE_ACK:
rxrpc_conn_retransmit(conn, skb); rxrpc_conn_retransmit_call(conn, skb);
rxrpc_free_skb(skb); rxrpc_free_skb(skb);
return 0; return 0;
...@@ -287,7 +292,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, ...@@ -287,7 +292,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code); _proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);
conn->state = RXRPC_CONN_REMOTELY_ABORTED; conn->state = RXRPC_CONN_REMOTELY_ABORTED;
rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED, rxrpc_abort_calls(conn, 0, RXRPC_CALL_REMOTELY_ABORTED,
abort_code); abort_code);
return -ECONNABORTED; return -ECONNABORTED;
......
...@@ -165,8 +165,8 @@ void __rxrpc_disconnect_call(struct rxrpc_connection *conn, ...@@ -165,8 +165,8 @@ void __rxrpc_disconnect_call(struct rxrpc_connection *conn,
* through the channel, whilst disposing of the actual call record. * through the channel, whilst disposing of the actual call record.
*/ */
chan->last_service_id = call->service_id; chan->last_service_id = call->service_id;
if (call->local_abort) { if (call->abort_code) {
chan->last_abort = call->local_abort; chan->last_abort = call->abort_code;
chan->last_type = RXRPC_PACKET_TYPE_ABORT; chan->last_type = RXRPC_PACKET_TYPE_ABORT;
} else { } else {
chan->last_seq = call->rx_data_eaten; chan->last_seq = call->rx_data_eaten;
......
...@@ -196,8 +196,7 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call, ...@@ -196,8 +196,7 @@ static int rxrpc_fast_process_data(struct rxrpc_call *call,
goto enqueue_packet; goto enqueue_packet;
sp->call = call; sp->call = call;
rxrpc_get_call(call); rxrpc_get_call_for_skb(call, skb);
atomic_inc(&call->skb_count);
terminal = ((flags & RXRPC_LAST_PACKET) && terminal = ((flags & RXRPC_LAST_PACKET) &&
!(flags & RXRPC_CLIENT_INITIATED)); !(flags & RXRPC_CLIENT_INITIATED));
ret = rxrpc_queue_rcv_skb(call, skb, false, terminal); ret = rxrpc_queue_rcv_skb(call, skb, false, terminal);
...@@ -341,14 +340,13 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -341,14 +340,13 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb)
abort_code = ntohl(wtmp); abort_code = ntohl(wtmp);
_proto("Rx ABORT %%%u { %x }", sp->hdr.serial, abort_code); _proto("Rx ABORT %%%u { %x }", sp->hdr.serial, abort_code);
write_lock_bh(&call->state_lock); if (__rxrpc_set_call_completion(call,
if (call->state < RXRPC_CALL_COMPLETE) { RXRPC_CALL_REMOTELY_ABORTED,
call->state = RXRPC_CALL_REMOTELY_ABORTED; abort_code, ECONNABORTED)) {
call->remote_abort = abort_code;
set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events); set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events);
rxrpc_queue_call(call); rxrpc_queue_call(call);
} }
goto free_packet_unlock; goto free_packet;
case RXRPC_PACKET_TYPE_BUSY: case RXRPC_PACKET_TYPE_BUSY:
_proto("Rx BUSY %%%u", sp->hdr.serial); _proto("Rx BUSY %%%u", sp->hdr.serial);
...@@ -359,7 +357,9 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -359,7 +357,9 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb)
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
switch (call->state) { switch (call->state) {
case RXRPC_CALL_CLIENT_SEND_REQUEST: case RXRPC_CALL_CLIENT_SEND_REQUEST:
call->state = RXRPC_CALL_SERVER_BUSY; __rxrpc_set_call_completion(call,
RXRPC_CALL_SERVER_BUSY,
0, EBUSY);
set_bit(RXRPC_CALL_EV_RCVD_BUSY, &call->events); set_bit(RXRPC_CALL_EV_RCVD_BUSY, &call->events);
rxrpc_queue_call(call); rxrpc_queue_call(call);
case RXRPC_CALL_SERVER_BUSY: case RXRPC_CALL_SERVER_BUSY:
...@@ -415,12 +415,8 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -415,12 +415,8 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb)
_debug("protocol error"); _debug("protocol error");
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
protocol_error_locked: protocol_error_locked:
if (call->state <= RXRPC_CALL_COMPLETE) { if (__rxrpc_abort_call(call, RX_PROTOCOL_ERROR, EPROTO))
call->state = RXRPC_CALL_LOCALLY_ABORTED;
call->local_abort = RX_PROTOCOL_ERROR;
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
rxrpc_queue_call(call); rxrpc_queue_call(call);
}
free_packet_unlock: free_packet_unlock:
write_unlock_bh(&call->state_lock); write_unlock_bh(&call->state_lock);
free_packet: free_packet:
...@@ -486,14 +482,8 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call, ...@@ -486,14 +482,8 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call,
_debug("protocol error"); _debug("protocol error");
rxrpc_free_skb(part); rxrpc_free_skb(part);
rxrpc_free_skb(jumbo); rxrpc_free_skb(jumbo);
write_lock_bh(&call->state_lock); if (rxrpc_abort_call(call, RX_PROTOCOL_ERROR, EPROTO))
if (call->state <= RXRPC_CALL_COMPLETE) {
call->state = RXRPC_CALL_LOCALLY_ABORTED;
call->local_abort = RX_PROTOCOL_ERROR;
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
rxrpc_queue_call(call); rxrpc_queue_call(call);
}
write_unlock_bh(&call->state_lock);
_leave(""); _leave("");
} }
...@@ -514,26 +504,28 @@ static void rxrpc_post_packet_to_call(struct rxrpc_call *call, ...@@ -514,26 +504,28 @@ static void rxrpc_post_packet_to_call(struct rxrpc_call *call,
read_lock(&call->state_lock); read_lock(&call->state_lock);
switch (call->state) { switch (call->state) {
case RXRPC_CALL_LOCALLY_ABORTED:
if (!test_and_set_bit(RXRPC_CALL_EV_ABORT, &call->events)) {
rxrpc_queue_call(call);
goto free_unlock;
}
case RXRPC_CALL_REMOTELY_ABORTED:
case RXRPC_CALL_NETWORK_ERROR:
case RXRPC_CALL_DEAD: case RXRPC_CALL_DEAD:
goto dead_call; goto dead_call;
case RXRPC_CALL_COMPLETE: case RXRPC_CALL_COMPLETE:
case RXRPC_CALL_CLIENT_FINAL_ACK: switch (call->completion) {
/* complete server call */ case RXRPC_CALL_LOCALLY_ABORTED:
if (rxrpc_conn_is_service(call->conn)) if (!test_and_set_bit(RXRPC_CALL_EV_ABORT,
&call->events)) {
rxrpc_queue_call(call);
goto free_unlock;
}
default:
goto dead_call; goto dead_call;
/* resend last packet of a completed call */ case RXRPC_CALL_SUCCEEDED:
_debug("final ack again"); if (rxrpc_conn_is_service(call->conn))
rxrpc_get_call(call); goto dead_call;
set_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events); goto resend_final_ack;
rxrpc_queue_call(call); }
goto free_unlock;
case RXRPC_CALL_CLIENT_FINAL_ACK:
goto resend_final_ack;
default: default:
break; break;
} }
...@@ -550,6 +542,13 @@ static void rxrpc_post_packet_to_call(struct rxrpc_call *call, ...@@ -550,6 +542,13 @@ static void rxrpc_post_packet_to_call(struct rxrpc_call *call,
rxrpc_put_call(call); rxrpc_put_call(call);
goto done; goto done;
resend_final_ack:
_debug("final ack again");
rxrpc_get_call(call);
set_bit(RXRPC_CALL_EV_ACK_FINAL, &call->events);
rxrpc_queue_call(call);
goto free_unlock;
dead_call: dead_call:
if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) { if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) {
skb->priority = RX_CALL_DEAD; skb->priority = RX_CALL_DEAD;
...@@ -748,6 +747,7 @@ void rxrpc_data_ready(struct sock *sk) ...@@ -748,6 +747,7 @@ void rxrpc_data_ready(struct sock *sk)
if (!call || atomic_read(&call->usage) == 0) if (!call || atomic_read(&call->usage) == 0)
goto cant_route_call; goto cant_route_call;
rxrpc_see_call(call);
rxrpc_post_packet_to_call(call, skb); rxrpc_post_packet_to_call(call, skb);
goto out_unlock; goto out_unlock;
} }
......
...@@ -115,12 +115,12 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, ...@@ -115,12 +115,12 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
*/ */
static void rxrpc_send_abort(struct rxrpc_call *call, u32 abort_code) static void rxrpc_send_abort(struct rxrpc_call *call, u32 abort_code)
{ {
if (call->state >= RXRPC_CALL_COMPLETE)
return;
write_lock_bh(&call->state_lock); write_lock_bh(&call->state_lock);
if (call->state <= RXRPC_CALL_COMPLETE) { if (__rxrpc_abort_call(call, abort_code, ECONNABORTED)) {
call->state = RXRPC_CALL_LOCALLY_ABORTED;
call->local_abort = abort_code;
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
del_timer_sync(&call->resend_timer); del_timer_sync(&call->resend_timer);
del_timer_sync(&call->ack_timer); del_timer_sync(&call->ack_timer);
clear_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events); clear_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events);
...@@ -207,12 +207,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) ...@@ -207,12 +207,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
return PTR_ERR(call); return PTR_ERR(call);
} }
rxrpc_see_call(call);
_debug("CALL %d USR %lx ST %d on CONN %p", _debug("CALL %d USR %lx ST %d on CONN %p",
call->debug_id, call->user_call_ID, call->state, call->conn); call->debug_id, call->user_call_ID, call->state, call->conn);
if (call->state >= RXRPC_CALL_COMPLETE) { if (call->state >= RXRPC_CALL_COMPLETE) {
/* it's too late for this call */ /* it's too late for this call */
ret = -ECONNRESET; ret = -ESHUTDOWN;
} else if (cmd == RXRPC_CMD_SEND_ABORT) { } else if (cmd == RXRPC_CMD_SEND_ABORT) {
rxrpc_send_abort(call, abort_code); rxrpc_send_abort(call, abort_code);
ret = 0; ret = 0;
...@@ -238,6 +239,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) ...@@ -238,6 +239,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
/** /**
* rxrpc_kernel_send_data - Allow a kernel service to send data on a call * rxrpc_kernel_send_data - Allow a kernel service to send data on a call
* @sock: The socket the call is on
* @call: The call to send data through * @call: The call to send data through
* @msg: The data to send * @msg: The data to send
* @len: The amount of data to send * @len: The amount of data to send
...@@ -247,8 +249,8 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) ...@@ -247,8 +249,8 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
* nor should an address be supplied. MSG_MORE should be flagged if there's * nor should an address be supplied. MSG_MORE should be flagged if there's
* more data to come, otherwise this data will end the transmission phase. * more data to come, otherwise this data will end the transmission phase.
*/ */
int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg, int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
size_t len) struct msghdr *msg, size_t len)
{ {
int ret; int ret;
...@@ -257,7 +259,7 @@ int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg, ...@@ -257,7 +259,7 @@ int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg,
ASSERTCMP(msg->msg_name, ==, NULL); ASSERTCMP(msg->msg_name, ==, NULL);
ASSERTCMP(msg->msg_control, ==, NULL); ASSERTCMP(msg->msg_control, ==, NULL);
lock_sock(&call->socket->sk); lock_sock(sock->sk);
_debug("CALL %d USR %lx ST %d on CONN %p", _debug("CALL %d USR %lx ST %d on CONN %p",
call->debug_id, call->user_call_ID, call->state, call->conn); call->debug_id, call->user_call_ID, call->state, call->conn);
...@@ -269,36 +271,36 @@ int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg, ...@@ -269,36 +271,36 @@ int rxrpc_kernel_send_data(struct rxrpc_call *call, struct msghdr *msg,
call->state != RXRPC_CALL_SERVER_SEND_REPLY) { call->state != RXRPC_CALL_SERVER_SEND_REPLY) {
ret = -EPROTO; /* request phase complete for this client call */ ret = -EPROTO; /* request phase complete for this client call */
} else { } else {
ret = rxrpc_send_data(call->socket, call, msg, len); ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len);
} }
release_sock(&call->socket->sk); release_sock(sock->sk);
_leave(" = %d", ret); _leave(" = %d", ret);
return ret; return ret;
} }
EXPORT_SYMBOL(rxrpc_kernel_send_data); EXPORT_SYMBOL(rxrpc_kernel_send_data);
/** /**
* rxrpc_kernel_abort_call - Allow a kernel service to abort a call * rxrpc_kernel_abort_call - Allow a kernel service to abort a call
* @sock: The socket the call is on
* @call: The call to be aborted * @call: The call to be aborted
* @abort_code: The abort code to stick into the ABORT packet * @abort_code: The abort code to stick into the ABORT packet
* *
* Allow a kernel service to abort a call, if it's still in an abortable state. * Allow a kernel service to abort a call, if it's still in an abortable state.
*/ */
void rxrpc_kernel_abort_call(struct rxrpc_call *call, u32 abort_code) void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
u32 abort_code)
{ {
_enter("{%d},%d", call->debug_id, abort_code); _enter("{%d},%d", call->debug_id, abort_code);
lock_sock(&call->socket->sk); lock_sock(sock->sk);
_debug("CALL %d USR %lx ST %d on CONN %p", _debug("CALL %d USR %lx ST %d on CONN %p",
call->debug_id, call->user_call_ID, call->state, call->conn); call->debug_id, call->user_call_ID, call->state, call->conn);
if (call->state < RXRPC_CALL_COMPLETE) rxrpc_send_abort(call, abort_code);
rxrpc_send_abort(call, abort_code);
release_sock(&call->socket->sk); release_sock(sock->sk);
_leave(""); _leave("");
} }
...@@ -640,8 +642,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -640,8 +642,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
/* check for the far side aborting the call or a network error /* check for the far side aborting the call or a network error
* occurring */ * occurring */
if (call->state > RXRPC_CALL_COMPLETE) if (call->state == RXRPC_CALL_COMPLETE)
goto call_aborted; goto call_terminated;
/* add the packet to the send queue if it's now full */ /* add the packet to the send queue if it's now full */
if (sp->remain <= 0 || if (sp->remain <= 0 ||
...@@ -702,15 +704,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -702,15 +704,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
_leave(" = %d", ret); _leave(" = %d", ret);
return ret; return ret;
call_aborted: call_terminated:
rxrpc_free_skb(skb); rxrpc_free_skb(skb);
if (call->state == RXRPC_CALL_NETWORK_ERROR) _leave(" = %d", -call->error);
ret = call->error_report < RXRPC_LOCAL_ERROR_OFFSET ?
call->error_report :
call->error_report - RXRPC_LOCAL_ERROR_OFFSET;
else
ret = -ECONNABORTED;
_leave(" = %d", ret);
return ret; return ret;
maybe_error: maybe_error:
......
...@@ -248,13 +248,21 @@ void rxrpc_peer_error_distributor(struct work_struct *work) ...@@ -248,13 +248,21 @@ void rxrpc_peer_error_distributor(struct work_struct *work)
struct rxrpc_peer *peer = struct rxrpc_peer *peer =
container_of(work, struct rxrpc_peer, error_distributor); container_of(work, struct rxrpc_peer, error_distributor);
struct rxrpc_call *call; struct rxrpc_call *call;
int error_report; enum rxrpc_call_completion compl;
bool queue;
int error;
_enter(""); _enter("");
error_report = READ_ONCE(peer->error_report); error = READ_ONCE(peer->error_report);
if (error < RXRPC_LOCAL_ERROR_OFFSET) {
compl = RXRPC_CALL_NETWORK_ERROR;
} else {
compl = RXRPC_CALL_LOCAL_ERROR;
error -= RXRPC_LOCAL_ERROR_OFFSET;
}
_debug("ISSUE ERROR %d", error_report); _debug("ISSUE ERROR %s %d", rxrpc_call_completions[compl], error);
spin_lock_bh(&peer->lock); spin_lock_bh(&peer->lock);
...@@ -262,16 +270,17 @@ void rxrpc_peer_error_distributor(struct work_struct *work) ...@@ -262,16 +270,17 @@ void rxrpc_peer_error_distributor(struct work_struct *work)
call = hlist_entry(peer->error_targets.first, call = hlist_entry(peer->error_targets.first,
struct rxrpc_call, error_link); struct rxrpc_call, error_link);
hlist_del_init(&call->error_link); hlist_del_init(&call->error_link);
rxrpc_see_call(call);
queue = false;
write_lock(&call->state_lock); write_lock(&call->state_lock);
if (call->state != RXRPC_CALL_COMPLETE && if (__rxrpc_set_call_completion(call, compl, 0, error)) {
call->state < RXRPC_CALL_NETWORK_ERROR) {
call->error_report = error_report;
call->state = RXRPC_CALL_NETWORK_ERROR;
set_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events); set_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events);
rxrpc_queue_call(call); queue = true;
} }
write_unlock(&call->state_lock); write_unlock(&call->state_lock);
if (queue)
rxrpc_queue_call(call);
} }
spin_unlock_bh(&peer->lock); spin_unlock_bh(&peer->lock);
......
...@@ -313,3 +313,18 @@ void __rxrpc_put_peer(struct rxrpc_peer *peer) ...@@ -313,3 +313,18 @@ void __rxrpc_put_peer(struct rxrpc_peer *peer)
kfree_rcu(peer, rcu); kfree_rcu(peer, rcu);
} }
/**
* rxrpc_kernel_get_peer - Get the peer address of a call
* @sock: The socket on which the call is in progress.
* @call: The call to query
* @_srx: Where to place the result
*
* Get the address of the remote peer in a call.
*/
void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call,
struct sockaddr_rxrpc *_srx)
{
*_srx = call->peer->srx;
}
EXPORT_SYMBOL(rxrpc_kernel_get_peer);
...@@ -22,7 +22,6 @@ static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { ...@@ -22,7 +22,6 @@ static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
[RXRPC_CONN_SERVICE] = "SvSecure", [RXRPC_CONN_SERVICE] = "SvSecure",
[RXRPC_CONN_REMOTELY_ABORTED] = "RmtAbort", [RXRPC_CONN_REMOTELY_ABORTED] = "RmtAbort",
[RXRPC_CONN_LOCALLY_ABORTED] = "LocAbort", [RXRPC_CONN_LOCALLY_ABORTED] = "LocAbort",
[RXRPC_CONN_NETWORK_ERROR] = "NetError",
}; };
/* /*
...@@ -94,7 +93,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) ...@@ -94,7 +93,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
rxrpc_is_service_call(call) ? "Svc" : "Clt", rxrpc_is_service_call(call) ? "Svc" : "Clt",
atomic_read(&call->usage), atomic_read(&call->usage),
rxrpc_call_states[call->state], rxrpc_call_states[call->state],
call->remote_abort ?: call->local_abort, call->abort_code,
call->user_call_ID); call->user_call_ID);
return 0; return 0;
......
...@@ -115,6 +115,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -115,6 +115,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
sp = rxrpc_skb(skb); sp = rxrpc_skb(skb);
call = sp->call; call = sp->call;
ASSERT(call != NULL); ASSERT(call != NULL);
rxrpc_see_call(call);
_debug("next pkt %s", rxrpc_pkts[sp->hdr.type]); _debug("next pkt %s", rxrpc_pkts[sp->hdr.type]);
...@@ -294,12 +295,17 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -294,12 +295,17 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
ret = put_cmsg(msg, SOL_RXRPC, RXRPC_BUSY, 0, &abort_code); ret = put_cmsg(msg, SOL_RXRPC, RXRPC_BUSY, 0, &abort_code);
break; break;
case RXRPC_SKB_MARK_REMOTE_ABORT: case RXRPC_SKB_MARK_REMOTE_ABORT:
abort_code = call->remote_abort; abort_code = call->abort_code;
ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code); ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code);
break; break;
case RXRPC_SKB_MARK_LOCAL_ABORT: case RXRPC_SKB_MARK_LOCAL_ABORT:
abort_code = call->local_abort; abort_code = call->abort_code;
ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code); ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &abort_code);
if (call->error) {
abort_code = call->error;
ret = put_cmsg(msg, SOL_RXRPC, RXRPC_LOCAL_ERROR, 4,
&abort_code);
}
break; break;
case RXRPC_SKB_MARK_NET_ERROR: case RXRPC_SKB_MARK_NET_ERROR:
_debug("RECV NET ERROR %d", sp->error); _debug("RECV NET ERROR %d", sp->error);
...@@ -392,9 +398,8 @@ u32 rxrpc_kernel_get_abort_code(struct sk_buff *skb) ...@@ -392,9 +398,8 @@ u32 rxrpc_kernel_get_abort_code(struct sk_buff *skb)
switch (skb->mark) { switch (skb->mark) {
case RXRPC_SKB_MARK_REMOTE_ABORT: case RXRPC_SKB_MARK_REMOTE_ABORT:
return sp->call->remote_abort;
case RXRPC_SKB_MARK_LOCAL_ABORT: case RXRPC_SKB_MARK_LOCAL_ABORT:
return sp->call->local_abort; return sp->call->abort_code;
default: default:
BUG(); BUG();
} }
......
...@@ -140,9 +140,7 @@ void rxrpc_packet_destructor(struct sk_buff *skb) ...@@ -140,9 +140,7 @@ void rxrpc_packet_destructor(struct sk_buff *skb)
_enter("%p{%p}", skb, call); _enter("%p{%p}", skb, call);
if (call) { if (call) {
if (atomic_dec_return(&call->skb_count) < 0) rxrpc_put_call_for_skb(call, skb);
BUG();
rxrpc_put_call(call);
sp->call = NULL; sp->call = NULL;
} }
......
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