summaryrefslogtreecommitdiff
path: root/net/rxrpc/call_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rxrpc/call_state.c')
-rw-r--r--net/rxrpc/call_state.c87
1 files changed, 33 insertions, 54 deletions
diff --git a/net/rxrpc/call_state.c b/net/rxrpc/call_state.c
index 649fb9e5d1af..27dc1242b712 100644
--- a/net/rxrpc/call_state.c
+++ b/net/rxrpc/call_state.c
@@ -10,81 +10,60 @@
/*
* Transition a call to the complete state.
*/
-bool __rxrpc_set_call_completion(struct rxrpc_call *call,
+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;
- /* Allow reader of completion state to operate locklessly */
- smp_store_release(&call->state, RXRPC_CALL_COMPLETE);
- trace_rxrpc_call_complete(call);
- wake_up(&call->waitq);
- rxrpc_notify_socket(call);
- return true;
- }
- return false;
-}
-
-bool rxrpc_set_call_completion(struct rxrpc_call *call,
- enum rxrpc_call_completion compl,
- u32 abort_code,
- int error)
-{
- bool ret = false;
+ if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE)
+ return false;
- if (call->state < RXRPC_CALL_COMPLETE) {
- write_lock(&call->state_lock);
- ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
- write_unlock(&call->state_lock);
- }
- return ret;
+ call->abort_code = abort_code;
+ call->error = error;
+ call->completion = compl;
+ /* Allow reader of completion state to operate locklessly */
+ rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE);
+ trace_rxrpc_call_complete(call);
+ wake_up(&call->waitq);
+ rxrpc_notify_socket(call);
+ return true;
}
/*
* Record that a call successfully completed.
*/
-bool __rxrpc_call_completed(struct rxrpc_call *call)
-{
- return __rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
-}
-
bool rxrpc_call_completed(struct rxrpc_call *call)
{
- bool ret = false;
-
- if (call->state < RXRPC_CALL_COMPLETE) {
- write_lock(&call->state_lock);
- ret = __rxrpc_call_completed(call);
- write_unlock(&call->state_lock);
- }
- return ret;
+ return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
}
/*
* Record that a call is locally aborted.
*/
-bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
- u32 abort_code, int error, enum rxrpc_abort_reason why)
+bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
+ u32 abort_code, int error, enum rxrpc_abort_reason why)
{
trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
abort_code, error);
- return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
- abort_code, error);
+ if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
+ abort_code, error))
+ return false;
+ if (test_bit(RXRPC_CALL_EXPOSED, &call->flags))
+ rxrpc_send_abort_packet(call);
+ return true;
}
-bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
- u32 abort_code, int error, enum rxrpc_abort_reason why)
+/*
+ * Record that a call errored out before even getting off the ground, thereby
+ * setting the state to allow it to be destroyed.
+ */
+void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl,
+ int error)
{
- bool ret;
-
- write_lock(&call->state_lock);
- ret = __rxrpc_abort_call(call, seq, abort_code, error, why);
- write_unlock(&call->state_lock);
- if (ret && test_bit(RXRPC_CALL_EXPOSED, &call->flags))
- rxrpc_send_abort_packet(call);
- return ret;
+ call->abort_code = RX_CALL_DEAD;
+ call->error = error;
+ call->completion = compl;
+ call->_state = RXRPC_CALL_COMPLETE;
+ trace_rxrpc_call_complete(call);
+ __set_bit(RXRPC_CALL_RELEASED, &call->flags);
}