Commit 96b4059f authored by David Howells's avatar David Howells

rxrpc: Remove call->state_lock

All the setters of call->state are now in the I/O thread and thus the state
lock is now unnecessary.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent 93368b6b
...@@ -631,14 +631,13 @@ struct rxrpc_call { ...@@ -631,14 +631,13 @@ struct rxrpc_call {
unsigned long flags; unsigned long flags;
unsigned long events; unsigned long events;
spinlock_t notify_lock; /* Kernel notification lock */ spinlock_t notify_lock; /* Kernel notification lock */
rwlock_t state_lock; /* lock for state transition */
unsigned int send_abort_why; /* Why the abort [enum rxrpc_abort_reason] */ unsigned int send_abort_why; /* Why the abort [enum rxrpc_abort_reason] */
s32 send_abort; /* Abort code to be sent */ s32 send_abort; /* Abort code to be sent */
short send_abort_err; /* Error to be associated with the abort */ short send_abort_err; /* Error to be associated with the abort */
rxrpc_seq_t send_abort_seq; /* DATA packet that incurred the abort (or 0) */ rxrpc_seq_t send_abort_seq; /* DATA packet that incurred the abort (or 0) */
s32 abort_code; /* Local/remote abort code */ s32 abort_code; /* Local/remote abort code */
int error; /* Local error incurred */ int error; /* Local error incurred */
enum rxrpc_call_state state; /* current state of call */ enum rxrpc_call_state _state; /* Current state of call (needs barrier) */
enum rxrpc_call_completion completion; /* Call completion condition */ enum rxrpc_call_completion completion; /* Call completion condition */
refcount_t ref; refcount_t ref;
u8 security_ix; /* Security type */ u8 security_ix; /* Security type */
...@@ -889,25 +888,37 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call) ...@@ -889,25 +888,37 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call)
/* /*
* call_state.c * call_state.c
*/ */
bool __rxrpc_set_call_completion(struct rxrpc_call *call,
enum rxrpc_call_completion compl,
u32 abort_code,
int error);
bool rxrpc_set_call_completion(struct rxrpc_call *call, bool rxrpc_set_call_completion(struct rxrpc_call *call,
enum rxrpc_call_completion compl, enum rxrpc_call_completion compl,
u32 abort_code, u32 abort_code,
int error); int error);
bool __rxrpc_call_completed(struct rxrpc_call *call);
bool rxrpc_call_completed(struct rxrpc_call *call); bool rxrpc_call_completed(struct rxrpc_call *call);
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, bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why); u32 abort_code, int error, enum rxrpc_abort_reason why);
void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion compl,
int error);
static inline void rxrpc_set_call_state(struct rxrpc_call *call,
enum rxrpc_call_state state)
{
/* Order write of completion info before write of ->state. */
smp_store_release(&call->_state, state);
}
static inline enum rxrpc_call_state __rxrpc_call_state(const struct rxrpc_call *call)
{
return call->_state; /* Only inside I/O thread */
}
static inline bool __rxrpc_call_is_complete(const struct rxrpc_call *call)
{
return __rxrpc_call_state(call) == RXRPC_CALL_COMPLETE;
}
static inline enum rxrpc_call_state rxrpc_call_state(const struct rxrpc_call *call) static inline enum rxrpc_call_state rxrpc_call_state(const struct rxrpc_call *call)
{ {
/* Order read ->state before read ->error. */ /* Order read ->state before read of completion info. */
return smp_load_acquire(&call->state); return smp_load_acquire(&call->_state);
} }
static inline bool rxrpc_call_is_complete(const struct rxrpc_call *call) static inline bool rxrpc_call_is_complete(const struct rxrpc_call *call)
......
...@@ -99,7 +99,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, ...@@ -99,7 +99,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
if (!call) if (!call)
return -ENOMEM; return -ENOMEM;
call->flags |= (1 << RXRPC_CALL_IS_SERVICE); call->flags |= (1 << RXRPC_CALL_IS_SERVICE);
call->state = RXRPC_CALL_SERVER_PREALLOC; rxrpc_set_call_state(call, RXRPC_CALL_SERVER_PREALLOC);
__set_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events); __set_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events);
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), trace_rxrpc_call(call->debug_id, refcount_read(&call->ref),
......
...@@ -257,20 +257,13 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) ...@@ -257,20 +257,13 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
*/ */
static void rxrpc_begin_service_reply(struct rxrpc_call *call) static void rxrpc_begin_service_reply(struct rxrpc_call *call)
{ {
unsigned long now; unsigned long now = jiffies;
write_lock(&call->state_lock);
if (call->state == RXRPC_CALL_SERVER_ACK_REQUEST) {
now = jiffies;
call->state = RXRPC_CALL_SERVER_SEND_REPLY;
WRITE_ONCE(call->delay_ack_at, now + MAX_JIFFY_OFFSET);
if (call->ackr_reason == RXRPC_ACK_DELAY)
call->ackr_reason = 0;
trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now);
}
write_unlock(&call->state_lock); rxrpc_set_call_state(call, RXRPC_CALL_SERVER_SEND_REPLY);
WRITE_ONCE(call->delay_ack_at, now + MAX_JIFFY_OFFSET);
if (call->ackr_reason == RXRPC_ACK_DELAY)
call->ackr_reason = 0;
trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now);
} }
/* /*
...@@ -281,18 +274,16 @@ static void rxrpc_close_tx_phase(struct rxrpc_call *call) ...@@ -281,18 +274,16 @@ static void rxrpc_close_tx_phase(struct rxrpc_call *call)
{ {
_debug("________awaiting reply/ACK__________"); _debug("________awaiting reply/ACK__________");
write_lock(&call->state_lock); switch (__rxrpc_call_state(call)) {
switch (call->state) {
case RXRPC_CALL_CLIENT_SEND_REQUEST: case RXRPC_CALL_CLIENT_SEND_REQUEST:
call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY; rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY);
break; break;
case RXRPC_CALL_SERVER_SEND_REPLY: case RXRPC_CALL_SERVER_SEND_REPLY:
call->state = RXRPC_CALL_SERVER_AWAIT_ACK; rxrpc_set_call_state(call, RXRPC_CALL_SERVER_AWAIT_ACK);
break; break;
default: default:
break; break;
} }
write_unlock(&call->state_lock);
} }
static bool rxrpc_tx_window_has_space(struct rxrpc_call *call) static bool rxrpc_tx_window_has_space(struct rxrpc_call *call)
...@@ -341,7 +332,7 @@ static void rxrpc_decant_prepared_tx(struct rxrpc_call *call) ...@@ -341,7 +332,7 @@ static void rxrpc_decant_prepared_tx(struct rxrpc_call *call)
static void rxrpc_transmit_some_data(struct rxrpc_call *call) static void rxrpc_transmit_some_data(struct rxrpc_call *call)
{ {
switch (call->state) { switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_SERVER_ACK_REQUEST: case RXRPC_CALL_SERVER_ACK_REQUEST:
if (list_empty(&call->tx_sendmsg)) if (list_empty(&call->tx_sendmsg))
return; return;
...@@ -390,9 +381,10 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -390,9 +381,10 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
//printk("\n--------------------\n"); //printk("\n--------------------\n");
_enter("{%d,%s,%lx}", _enter("{%d,%s,%lx}",
call->debug_id, rxrpc_call_states[call->state], call->events); call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)],
call->events);
if (call->state == RXRPC_CALL_COMPLETE) if (__rxrpc_call_is_complete(call))
goto out; goto out;
/* Handle abort request locklessly, vs rxrpc_propose_abort(). */ /* Handle abort request locklessly, vs rxrpc_propose_abort(). */
...@@ -415,7 +407,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -415,7 +407,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
} }
t = READ_ONCE(call->expect_req_by); t = READ_ONCE(call->expect_req_by);
if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST && if (__rxrpc_call_state(call) == RXRPC_CALL_SERVER_RECV_REQUEST &&
time_after_eq(now, t)) { time_after_eq(now, t)) {
trace_rxrpc_timer(call, rxrpc_timer_exp_idle, now); trace_rxrpc_timer(call, rxrpc_timer_exp_idle, now);
expired = true; expired = true;
...@@ -499,7 +491,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -499,7 +491,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
rxrpc_propose_ack_ping_for_lost_ack); rxrpc_propose_ack_ping_for_lost_ack);
if (resend && call->state != RXRPC_CALL_CLIENT_RECV_REPLY) if (resend && __rxrpc_call_state(call) != RXRPC_CALL_CLIENT_RECV_REPLY)
rxrpc_resend(call, NULL); rxrpc_resend(call, NULL);
if (test_and_clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags)) if (test_and_clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags))
...@@ -511,7 +503,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -511,7 +503,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_propose_ack_input_data); rxrpc_propose_ack_input_data);
/* Make sure the timer is restarted */ /* Make sure the timer is restarted */
if (call->state != RXRPC_CALL_COMPLETE) { if (!__rxrpc_call_is_complete(call)) {
next = call->expect_rx_by; next = call->expect_rx_by;
#define set(T) { t = READ_ONCE(T); if (time_before(t, next)) next = t; } #define set(T) { t = READ_ONCE(T); if (time_before(t, next)) next = t; }
...@@ -532,7 +524,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -532,7 +524,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
} }
out: out:
if (call->state == RXRPC_CALL_COMPLETE) { if (__rxrpc_call_is_complete(call)) {
del_timer_sync(&call->timer); del_timer_sync(&call->timer);
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
rxrpc_disconnect_call(call); rxrpc_disconnect_call(call);
......
...@@ -69,7 +69,7 @@ static void rxrpc_call_timer_expired(struct timer_list *t) ...@@ -69,7 +69,7 @@ static void rxrpc_call_timer_expired(struct timer_list *t)
_enter("%d", call->debug_id); _enter("%d", call->debug_id);
if (call->state < RXRPC_CALL_COMPLETE) { if (!__rxrpc_call_is_complete(call)) {
trace_rxrpc_timer_expired(call, jiffies); trace_rxrpc_timer_expired(call, jiffies);
rxrpc_poke_call(call, rxrpc_call_poke_timer); rxrpc_poke_call(call, rxrpc_call_poke_timer);
} }
...@@ -162,7 +162,6 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp, ...@@ -162,7 +162,6 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
init_waitqueue_head(&call->waitq); init_waitqueue_head(&call->waitq);
spin_lock_init(&call->notify_lock); spin_lock_init(&call->notify_lock);
spin_lock_init(&call->tx_lock); spin_lock_init(&call->tx_lock);
rwlock_init(&call->state_lock);
refcount_set(&call->ref, 1); refcount_set(&call->ref, 1);
call->debug_id = debug_id; call->debug_id = debug_id;
call->tx_total_len = -1; call->tx_total_len = -1;
...@@ -211,7 +210,6 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, ...@@ -211,7 +210,6 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
now = ktime_get_real(); now = ktime_get_real();
call->acks_latest_ts = now; call->acks_latest_ts = now;
call->cong_tstamp = now; call->cong_tstamp = now;
call->state = RXRPC_CALL_CLIENT_AWAIT_CONN;
call->dest_srx = *srx; call->dest_srx = *srx;
call->interruptibility = p->interruptibility; call->interruptibility = p->interruptibility;
call->tx_total_len = p->tx_total_len; call->tx_total_len = p->tx_total_len;
...@@ -227,11 +225,13 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, ...@@ -227,11 +225,13 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
ret = rxrpc_init_client_call_security(call); ret = rxrpc_init_client_call_security(call);
if (ret < 0) { if (ret < 0) {
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 0, ret); rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, ret);
rxrpc_put_call(call, rxrpc_call_put_discard_error); rxrpc_put_call(call, rxrpc_call_put_discard_error);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_CONN);
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), trace_rxrpc_call(call->debug_id, refcount_read(&call->ref),
p->user_call_ID, rxrpc_call_new_client); p->user_call_ID, rxrpc_call_new_client);
...@@ -384,8 +384,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -384,8 +384,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
error_dup_user_ID: error_dup_user_ID:
write_unlock(&rx->call_lock); write_unlock(&rx->call_lock);
release_sock(&rx->sk); release_sock(&rx->sk);
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, -EEXIST);
RX_CALL_DEAD, -EEXIST);
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), 0, trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), 0,
rxrpc_call_see_userid_exists); rxrpc_call_see_userid_exists);
rxrpc_release_call(rx, call); rxrpc_release_call(rx, call);
...@@ -403,8 +402,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -403,8 +402,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), ret, trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), ret,
rxrpc_call_see_connect_failed); rxrpc_call_see_connect_failed);
set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, ret);
RX_CALL_DEAD, ret);
_leave(" = c=%08x [err]", call->debug_id); _leave(" = c=%08x [err]", call->debug_id);
return call; return call;
} }
...@@ -427,25 +425,25 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx, ...@@ -427,25 +425,25 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx,
call->call_id = sp->hdr.callNumber; call->call_id = sp->hdr.callNumber;
call->dest_srx.srx_service = sp->hdr.serviceId; call->dest_srx.srx_service = sp->hdr.serviceId;
call->cid = sp->hdr.cid; call->cid = sp->hdr.cid;
call->state = RXRPC_CALL_SERVER_SECURING;
call->cong_tstamp = skb->tstamp; call->cong_tstamp = skb->tstamp;
__set_bit(RXRPC_CALL_EXPOSED, &call->flags); __set_bit(RXRPC_CALL_EXPOSED, &call->flags);
rxrpc_set_call_state(call, RXRPC_CALL_SERVER_SECURING);
spin_lock(&conn->state_lock); spin_lock(&conn->state_lock);
switch (conn->state) { switch (conn->state) {
case RXRPC_CONN_SERVICE_UNSECURED: case RXRPC_CONN_SERVICE_UNSECURED:
case RXRPC_CONN_SERVICE_CHALLENGING: case RXRPC_CONN_SERVICE_CHALLENGING:
call->state = RXRPC_CALL_SERVER_SECURING; rxrpc_set_call_state(call, RXRPC_CALL_SERVER_SECURING);
break; break;
case RXRPC_CONN_SERVICE: case RXRPC_CONN_SERVICE:
call->state = RXRPC_CALL_SERVER_RECV_REQUEST; rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST);
break; break;
case RXRPC_CONN_ABORTED: case RXRPC_CONN_ABORTED:
__rxrpc_set_call_completion(call, conn->completion, rxrpc_set_call_completion(call, conn->completion,
conn->abort_code, conn->error); conn->abort_code, conn->error);
break; break;
default: default:
BUG(); BUG();
...@@ -614,7 +612,7 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why) ...@@ -614,7 +612,7 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)
dead = __refcount_dec_and_test(&call->ref, &r); dead = __refcount_dec_and_test(&call->ref, &r);
trace_rxrpc_call(debug_id, r - 1, 0, why); trace_rxrpc_call(debug_id, r - 1, 0, why);
if (dead) { if (dead) {
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE);
if (!list_empty(&call->link)) { if (!list_empty(&call->link)) {
spin_lock(&rxnet->call_lock); spin_lock(&rxnet->call_lock);
...@@ -677,7 +675,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) ...@@ -677,7 +675,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
{ {
memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE);
ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
del_timer(&call->timer); del_timer(&call->timer);
...@@ -715,7 +713,7 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) ...@@ -715,7 +713,7 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
call, refcount_read(&call->ref), call, refcount_read(&call->ref),
rxrpc_call_states[call->state], rxrpc_call_states[__rxrpc_call_state(call)],
call->flags, call->events); call->flags, call->events);
spin_unlock(&rxnet->call_lock); spin_unlock(&rxnet->call_lock);
......
...@@ -10,81 +10,60 @@ ...@@ -10,81 +10,60 @@
/* /*
* Transition a call to the complete state. * 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, enum rxrpc_call_completion compl,
u32 abort_code, u32 abort_code,
int error) int error)
{ {
if (call->state < RXRPC_CALL_COMPLETE) { if (__rxrpc_call_state(call) == RXRPC_CALL_COMPLETE)
call->abort_code = abort_code; return false;
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 (call->state < RXRPC_CALL_COMPLETE) { call->abort_code = abort_code;
write_lock(&call->state_lock); call->error = error;
ret = __rxrpc_set_call_completion(call, compl, abort_code, error); call->completion = compl;
write_unlock(&call->state_lock); /* Allow reader of completion state to operate locklessly */
} rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE);
return ret; trace_rxrpc_call_complete(call);
wake_up(&call->waitq);
rxrpc_notify_socket(call);
return true;
} }
/* /*
* Record that a call successfully completed. * 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 rxrpc_call_completed(struct rxrpc_call *call)
{ {
bool ret = false; return rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
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. * Record that a call is locally aborted.
*/ */
bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq, bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
u32 abort_code, int error, enum rxrpc_abort_reason why) u32 abort_code, int error, enum rxrpc_abort_reason why)
{ {
trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq, trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
abort_code, error); abort_code, error);
return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED, if (!rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
abort_code, error); 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; call->abort_code = RX_CALL_DEAD;
call->error = error;
write_lock(&call->state_lock); call->completion = compl;
ret = __rxrpc_abort_call(call, seq, abort_code, error, why); call->_state = RXRPC_CALL_COMPLETE;
write_unlock(&call->state_lock); trace_rxrpc_call_complete(call);
if (ret && test_bit(RXRPC_CALL_EXPOSED, &call->flags)) __set_bit(RXRPC_CALL_RELEASED, &call->flags);
rxrpc_send_abort_packet(call);
return ret;
} }
...@@ -553,9 +553,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn, ...@@ -553,9 +553,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
trace_rxrpc_connect_call(call); trace_rxrpc_connect_call(call);
write_lock(&call->state_lock); rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_SEND_REQUEST);
call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
write_unlock(&call->state_lock);
/* Paired with the read barrier in rxrpc_connect_call(). This orders /* Paired with the read barrier in rxrpc_connect_call(). This orders
* cid and epoch in the connection wrt to call_id without the need to * cid and epoch in the connection wrt to call_id without the need to
...@@ -687,7 +685,7 @@ static int rxrpc_wait_for_channel(struct rxrpc_bundle *bundle, ...@@ -687,7 +685,7 @@ static int rxrpc_wait_for_channel(struct rxrpc_bundle *bundle,
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
break; break;
} }
if (READ_ONCE(call->state) != RXRPC_CALL_CLIENT_AWAIT_CONN) if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN)
break; break;
if ((call->interruptibility == RXRPC_INTERRUPTIBLE || if ((call->interruptibility == RXRPC_INTERRUPTIBLE ||
call->interruptibility == RXRPC_PREINTERRUPTIBLE) && call->interruptibility == RXRPC_PREINTERRUPTIBLE) &&
...@@ -729,7 +727,7 @@ int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp) ...@@ -729,7 +727,7 @@ int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
goto out; goto out;
} }
if (call->state == RXRPC_CALL_CLIENT_AWAIT_CONN) { if (rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_CONN) {
ret = rxrpc_wait_for_channel(bundle, call, gfp); ret = rxrpc_wait_for_channel(bundle, call, gfp);
if (ret < 0) if (ret < 0)
goto wait_failed; goto wait_failed;
...@@ -748,7 +746,7 @@ int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp) ...@@ -748,7 +746,7 @@ int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
list_del_init(&call->chan_wait_link); list_del_init(&call->chan_wait_link);
spin_unlock(&bundle->channel_lock); spin_unlock(&bundle->channel_lock);
if (call->state != RXRPC_CALL_CLIENT_AWAIT_CONN) { if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN) {
ret = 0; ret = 0;
goto granted_channel; goto granted_channel;
} }
......
...@@ -230,14 +230,9 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn) ...@@ -230,14 +230,9 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn)
*/ */
static void rxrpc_call_is_secure(struct rxrpc_call *call) static void rxrpc_call_is_secure(struct rxrpc_call *call)
{ {
_enter("%p", call); if (call && __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SECURING) {
if (call) { rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST);
write_lock(&call->state_lock); rxrpc_notify_socket(call);
if (call->state == RXRPC_CALL_SERVER_SECURING) {
call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
rxrpc_notify_socket(call);
}
write_unlock(&call->state_lock);
} }
} }
......
...@@ -184,7 +184,7 @@ void rxrpc_congestion_degrade(struct rxrpc_call *call) ...@@ -184,7 +184,7 @@ void rxrpc_congestion_degrade(struct rxrpc_call *call)
if (call->cong_mode != RXRPC_CALL_SLOW_START && if (call->cong_mode != RXRPC_CALL_SLOW_START &&
call->cong_mode != RXRPC_CALL_CONGEST_AVOIDANCE) call->cong_mode != RXRPC_CALL_CONGEST_AVOIDANCE)
return; return;
if (call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY) if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
return; return;
rtt = ns_to_ktime(call->peer->srtt_us * (1000 / 8)); rtt = ns_to_ktime(call->peer->srtt_us * (1000 / 8));
...@@ -252,43 +252,31 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to, ...@@ -252,43 +252,31 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun, static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
enum rxrpc_abort_reason abort_why) enum rxrpc_abort_reason abort_why)
{ {
unsigned int state;
ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags)); ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags));
write_lock(&call->state_lock); switch (__rxrpc_call_state(call)) {
state = call->state;
switch (state) {
case RXRPC_CALL_CLIENT_SEND_REQUEST: case RXRPC_CALL_CLIENT_SEND_REQUEST:
case RXRPC_CALL_CLIENT_AWAIT_REPLY: case RXRPC_CALL_CLIENT_AWAIT_REPLY:
if (reply_begun) if (reply_begun) {
call->state = state = RXRPC_CALL_CLIENT_RECV_REPLY; rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_RECV_REPLY);
else trace_rxrpc_txqueue(call, rxrpc_txqueue_end);
call->state = state = RXRPC_CALL_CLIENT_AWAIT_REPLY; break;
}
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY);
trace_rxrpc_txqueue(call, rxrpc_txqueue_await_reply);
break; break;
case RXRPC_CALL_SERVER_AWAIT_ACK: case RXRPC_CALL_SERVER_AWAIT_ACK:
__rxrpc_call_completed(call); rxrpc_call_completed(call);
state = call->state; trace_rxrpc_txqueue(call, rxrpc_txqueue_end);
break; break;
default: default:
goto bad_state; kdebug("end_tx %s", rxrpc_call_states[__rxrpc_call_state(call)]);
rxrpc_proto_abort(call, call->tx_top, abort_why);
break;
} }
write_unlock(&call->state_lock);
if (state == RXRPC_CALL_CLIENT_AWAIT_REPLY)
trace_rxrpc_txqueue(call, rxrpc_txqueue_await_reply);
else
trace_rxrpc_txqueue(call, rxrpc_txqueue_end);
_leave(" = ok");
return;
bad_state:
write_unlock(&call->state_lock);
kdebug("end_tx %s", rxrpc_call_states[call->state]);
rxrpc_proto_abort(call, call->tx_top, abort_why);
} }
/* /*
...@@ -303,7 +291,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call) ...@@ -303,7 +291,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
if (call->ackr_reason) { if (call->ackr_reason) {
now = jiffies; now = jiffies;
timo = now + MAX_JIFFY_OFFSET; timo = now + MAX_JIFFY_OFFSET;
WRITE_ONCE(call->resend_at, timo);
WRITE_ONCE(call->delay_ack_at, timo); WRITE_ONCE(call->delay_ack_at, timo);
trace_rxrpc_timer(call, rxrpc_timer_init_for_reply, now); trace_rxrpc_timer(call, rxrpc_timer_init_for_reply, now);
} }
...@@ -326,30 +314,23 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial) ...@@ -326,30 +314,23 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
{ {
rxrpc_seq_t whigh = READ_ONCE(call->rx_highest_seq); rxrpc_seq_t whigh = READ_ONCE(call->rx_highest_seq);
_enter("%d,%s", call->debug_id, rxrpc_call_states[call->state]); _enter("%d,%s", call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)]);
trace_rxrpc_receive(call, rxrpc_receive_end, 0, whigh); trace_rxrpc_receive(call, rxrpc_receive_end, 0, whigh);
if (rxrpc_call_state(call) == RXRPC_CALL_CLIENT_RECV_REPLY) switch (__rxrpc_call_state(call)) {
rxrpc_propose_delay_ACK(call, serial, rxrpc_propose_ack_terminal_ack);
write_lock(&call->state_lock);
switch (call->state) {
case RXRPC_CALL_CLIENT_RECV_REPLY: case RXRPC_CALL_CLIENT_RECV_REPLY:
__rxrpc_call_completed(call); rxrpc_propose_delay_ACK(call, serial, rxrpc_propose_ack_terminal_ack);
write_unlock(&call->state_lock); rxrpc_call_completed(call);
break; break;
case RXRPC_CALL_SERVER_RECV_REQUEST: case RXRPC_CALL_SERVER_RECV_REQUEST:
call->state = RXRPC_CALL_SERVER_ACK_REQUEST; rxrpc_set_call_state(call, RXRPC_CALL_SERVER_ACK_REQUEST);
call->expect_req_by = jiffies + MAX_JIFFY_OFFSET; call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
write_unlock(&call->state_lock); rxrpc_propose_delay_ACK(call, serial, rxrpc_propose_ack_processing_op);
rxrpc_propose_delay_ACK(call, serial,
rxrpc_propose_ack_processing_op);
break; break;
default: default:
write_unlock(&call->state_lock);
break; break;
} }
} }
...@@ -583,7 +564,6 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb ...@@ -583,7 +564,6 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb) static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
{ {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
enum rxrpc_call_state state;
rxrpc_serial_t serial = sp->hdr.serial; rxrpc_serial_t serial = sp->hdr.serial;
rxrpc_seq_t seq0 = sp->hdr.seq; rxrpc_seq_t seq0 = sp->hdr.seq;
...@@ -591,11 +571,20 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -591,11 +571,20 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
atomic64_read(&call->ackr_window), call->rx_highest_seq, atomic64_read(&call->ackr_window), call->rx_highest_seq,
skb->len, seq0); skb->len, seq0);
state = READ_ONCE(call->state); if (__rxrpc_call_is_complete(call))
if (state >= RXRPC_CALL_COMPLETE)
return; return;
if (state == RXRPC_CALL_SERVER_RECV_REQUEST) { switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
/* Received data implicitly ACKs all of the request
* packets we sent when we're acting as a client.
*/
if (!rxrpc_receiving_reply(call))
goto out_notify;
break;
case RXRPC_CALL_SERVER_RECV_REQUEST: {
unsigned long timo = READ_ONCE(call->next_req_timo); unsigned long timo = READ_ONCE(call->next_req_timo);
unsigned long now, expect_req_by; unsigned long now, expect_req_by;
...@@ -606,15 +595,12 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -606,15 +595,12 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_reduce_call_timer(call, expect_req_by, now, rxrpc_reduce_call_timer(call, expect_req_by, now,
rxrpc_timer_set_for_idle); rxrpc_timer_set_for_idle);
} }
break;
} }
/* Received data implicitly ACKs all of the request packets we sent default:
* when we're acting as a client. break;
*/ }
if ((state == RXRPC_CALL_CLIENT_SEND_REQUEST ||
state == RXRPC_CALL_CLIENT_AWAIT_REPLY) &&
!rxrpc_receiving_reply(call))
goto out_notify;
if (!rxrpc_input_split_jumbo(call, skb)) { if (!rxrpc_input_split_jumbo(call, skb)) {
rxrpc_proto_abort(call, sp->hdr.seq, rxrpc_badmsg_bad_jumbo); rxrpc_proto_abort(call, sp->hdr.seq, rxrpc_badmsg_bad_jumbo);
...@@ -904,7 +890,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -904,7 +890,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero); return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
/* Ignore ACKs unless we are or have just been transmitting. */ /* Ignore ACKs unless we are or have just been transmitting. */
switch (READ_ONCE(call->state)) { switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST: case RXRPC_CALL_CLIENT_SEND_REQUEST:
case RXRPC_CALL_CLIENT_AWAIT_REPLY: case RXRPC_CALL_CLIENT_AWAIT_REPLY:
case RXRPC_CALL_SERVER_SEND_REPLY: case RXRPC_CALL_SERVER_SEND_REPLY:
...@@ -1027,7 +1013,7 @@ void rxrpc_input_call_packet(struct rxrpc_call *call, struct sk_buff *skb) ...@@ -1027,7 +1013,7 @@ void rxrpc_input_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
*/ */
void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb) void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
{ {
switch (READ_ONCE(call->state)) { switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_SERVER_AWAIT_ACK: case RXRPC_CALL_SERVER_AWAIT_ACK:
rxrpc_call_completed(call); rxrpc_call_completed(call);
fallthrough; fallthrough;
......
...@@ -261,7 +261,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) ...@@ -261,7 +261,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
rxrpc_tx_point_call_ack); rxrpc_tx_point_call_ack);
rxrpc_tx_backoff(call, ret); rxrpc_tx_backoff(call, ret);
if (call->state < RXRPC_CALL_COMPLETE) { if (!__rxrpc_call_is_complete(call)) {
if (ret < 0) if (ret < 0)
rxrpc_cancel_rtt_probe(call, serial, rtt_slot); rxrpc_cancel_rtt_probe(call, serial, rtt_slot);
rxrpc_set_keepalive(call); rxrpc_set_keepalive(call);
...@@ -723,7 +723,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer) ...@@ -723,7 +723,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer)
static inline void rxrpc_instant_resend(struct rxrpc_call *call, static inline void rxrpc_instant_resend(struct rxrpc_call *call,
struct rxrpc_txbuf *txb) struct rxrpc_txbuf *txb)
{ {
if (call->state < RXRPC_CALL_COMPLETE) if (!__rxrpc_call_is_complete(call))
kdebug("resend"); kdebug("resend");
} }
......
...@@ -50,6 +50,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) ...@@ -50,6 +50,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
struct rxrpc_local *local; struct rxrpc_local *local;
struct rxrpc_call *call; struct rxrpc_call *call;
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
enum rxrpc_call_state state;
unsigned long timeout = 0; unsigned long timeout = 0;
rxrpc_seq_t acks_hard_ack; rxrpc_seq_t acks_hard_ack;
char lbuff[50], rbuff[50]; char lbuff[50], rbuff[50];
...@@ -74,7 +75,8 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) ...@@ -74,7 +75,8 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
sprintf(rbuff, "%pISpc", &call->dest_srx.transport); sprintf(rbuff, "%pISpc", &call->dest_srx.transport);
if (call->state != RXRPC_CALL_SERVER_PREALLOC) { state = rxrpc_call_state(call);
if (state != RXRPC_CALL_SERVER_PREALLOC) {
timeout = READ_ONCE(call->expect_rx_by); timeout = READ_ONCE(call->expect_rx_by);
timeout -= jiffies; timeout -= jiffies;
} }
...@@ -91,7 +93,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) ...@@ -91,7 +93,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
call->call_id, call->call_id,
rxrpc_is_service_call(call) ? "Svc" : "Clt", rxrpc_is_service_call(call) ? "Svc" : "Clt",
refcount_read(&call->ref), refcount_read(&call->ref),
rxrpc_call_states[call->state], rxrpc_call_states[state],
call->abort_code, call->abort_code,
call->debug_id, call->debug_id,
acks_hard_ack, READ_ONCE(call->tx_top) - acks_hard_ack, acks_hard_ack, READ_ONCE(call->tx_top) - acks_hard_ack,
......
...@@ -1143,7 +1143,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, ...@@ -1143,7 +1143,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
call = rcu_dereference_protected( call = rcu_dereference_protected(
conn->channels[i].call, conn->channels[i].call,
lockdep_is_held(&conn->bundle->channel_lock)); lockdep_is_held(&conn->bundle->channel_lock));
if (call && call->state < RXRPC_CALL_COMPLETE) { if (call && !__rxrpc_call_is_complete(call)) {
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
rxkad_abort_resp_call_state); rxkad_abort_resp_call_state);
goto protocol_error_unlock; goto protocol_error_unlock;
......
...@@ -702,9 +702,6 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call, ...@@ -702,9 +702,6 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
mutex_lock(&call->user_mutex); mutex_lock(&call->user_mutex);
_debug("CALL %d USR %lx ST %d on CONN %p",
call->debug_id, call->user_call_ID, call->state, call->conn);
ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len, ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
notify_end_tx, &dropped_lock); notify_end_tx, &dropped_lock);
if (ret == -ESHUTDOWN) if (ret == -ESHUTDOWN)
......
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