2022-10-26 19:16:55 -04:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/* Call state changing functions.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
|
|
|
|
* Written by David Howells (dhowells@redhat.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ar-internal.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Transition a call to the complete state.
|
|
|
|
*/
|
|
|
|
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;
|
2022-12-19 10:32:32 -05:00
|
|
|
/* Allow reader of completion state to operate locklessly */
|
|
|
|
smp_store_release(&call->state, RXRPC_CALL_COMPLETE);
|
2022-10-26 19:16:55 -04:00
|
|
|
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 (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
|
|
|
|
u32 abort_code, int error, enum rxrpc_abort_reason why)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|