aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc/output.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-30 09:49:28 +0100
committerDavid Howells <dhowells@redhat.com>2016-08-30 15:58:31 +0100
commitf5c17aaeb2aee9b6c30d082bbe652a7e5589adff (patch)
treebc2ec0c32190f3a2de5e1d322d745232ff96771b /net/rxrpc/output.c
parentrxrpc: Fix a potential NULL-pointer deref in rxrpc_abort_calls (diff)
downloadlinux-dev-f5c17aaeb2aee9b6c30d082bbe652a7e5589adff.tar.xz
linux-dev-f5c17aaeb2aee9b6c30d082bbe652a7e5589adff.zip
rxrpc: Calls should only have one terminal state
Condense the terminal states of a call state machine to a single state, plus a separate completion type value. The value is then set, along with error and abort code values, only when the call is transitioned to the completion state. Helpers are provided to simplify this. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/output.c')
-rw-r--r--net/rxrpc/output.c27
1 files changed, 10 insertions, 17 deletions
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 8a9917cba6fe..036e1112b0c5 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -115,12 +115,12 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
*/
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);
- if (call->state <= RXRPC_CALL_COMPLETE) {
- call->state = RXRPC_CALL_LOCALLY_ABORTED;
- call->local_abort = abort_code;
- set_bit(RXRPC_CALL_EV_ABORT, &call->events);
+ if (__rxrpc_abort_call(call, abort_code, ECONNABORTED)) {
del_timer_sync(&call->resend_timer);
del_timer_sync(&call->ack_timer);
clear_bit(RXRPC_CALL_EV_RESEND_TIMER, &call->events);
@@ -212,7 +212,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
if (call->state >= RXRPC_CALL_COMPLETE) {
/* it's too late for this call */
- ret = -ECONNRESET;
+ ret = -ESHUTDOWN;
} else if (cmd == RXRPC_CMD_SEND_ABORT) {
rxrpc_send_abort(call, abort_code);
ret = 0;
@@ -295,8 +295,7 @@ void rxrpc_kernel_abort_call(struct rxrpc_call *call, u32 abort_code)
_debug("CALL %d USR %lx ST %d on CONN %p",
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);
_leave("");
@@ -640,8 +639,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
/* check for the far side aborting the call or a network error
* occurring */
- if (call->state > RXRPC_CALL_COMPLETE)
- goto call_aborted;
+ if (call->state == RXRPC_CALL_COMPLETE)
+ goto call_terminated;
/* add the packet to the send queue if it's now full */
if (sp->remain <= 0 ||
@@ -702,15 +701,9 @@ out:
_leave(" = %d", ret);
return ret;
-call_aborted:
+call_terminated:
rxrpc_free_skb(skb);
- if (call->state == RXRPC_CALL_NETWORK_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);
+ _leave(" = %d", -call->error);
return ret;
maybe_error: