Skip to content

Commit d41b3f5

Browse files
committed
rxrpc: Wrap accesses to get call state to put the barrier in one place
Wrap accesses to get the state of a call from outside of the I/O thread in a single place so that the barrier needed to order wrt the error code and abort code is in just that place. Also use a barrier when setting the call state and again when reading the call state such that the auxiliary completion info (error code, abort code) can be read without taking a read lock on the call state lock. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent 0b9bb32 commit d41b3f5

File tree

5 files changed

+38
-24
lines changed

5 files changed

+38
-24
lines changed

net/rxrpc/af_rxrpc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ EXPORT_SYMBOL(rxrpc_kernel_end_call);
379379
bool rxrpc_kernel_check_life(const struct socket *sock,
380380
const struct rxrpc_call *call)
381381
{
382-
return call->state != RXRPC_CALL_COMPLETE;
382+
return !rxrpc_call_is_complete(call);
383383
}
384384
EXPORT_SYMBOL(rxrpc_kernel_check_life);
385385

net/rxrpc/ar-internal.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,22 @@ bool __rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
903903
bool rxrpc_abort_call(struct rxrpc_call *call, rxrpc_seq_t seq,
904904
u32 abort_code, int error, enum rxrpc_abort_reason why);
905905

906+
static inline enum rxrpc_call_state rxrpc_call_state(const struct rxrpc_call *call)
907+
{
908+
/* Order read ->state before read ->error. */
909+
return smp_load_acquire(&call->state);
910+
}
911+
912+
static inline bool rxrpc_call_is_complete(const struct rxrpc_call *call)
913+
{
914+
return rxrpc_call_state(call) == RXRPC_CALL_COMPLETE;
915+
}
916+
917+
static inline bool rxrpc_call_has_failed(const struct rxrpc_call *call)
918+
{
919+
return rxrpc_call_is_complete(call) && call->completion != RXRPC_CALL_SUCCEEDED;
920+
}
921+
906922
/*
907923
* conn_client.c
908924
*/

net/rxrpc/call_state.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ bool __rxrpc_set_call_completion(struct rxrpc_call *call,
1919
call->abort_code = abort_code;
2020
call->error = error;
2121
call->completion = compl;
22-
call->state = RXRPC_CALL_COMPLETE;
22+
/* Allow reader of completion state to operate locklessly */
23+
smp_store_release(&call->state, RXRPC_CALL_COMPLETE);
2324
trace_rxrpc_call_complete(call);
2425
wake_up(&call->waitq);
2526
rxrpc_notify_socket(call);

net/rxrpc/recvmsg.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static int rxrpc_recvmsg_term(struct rxrpc_call *call, struct msghdr *msg)
8989
ret = put_cmsg(msg, SOL_RXRPC, RXRPC_LOCAL_ERROR, 4, &tmp);
9090
break;
9191
default:
92-
pr_err("Invalid terminal call state %u\n", call->state);
92+
pr_err("Invalid terminal call state %u\n", call->completion);
9393
BUG();
9494
break;
9595
}
@@ -111,7 +111,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
111111

112112
trace_rxrpc_receive(call, rxrpc_receive_end, 0, whigh);
113113

114-
if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY)
114+
if (rxrpc_call_state(call) == RXRPC_CALL_CLIENT_RECV_REPLY)
115115
rxrpc_propose_delay_ACK(call, serial, rxrpc_propose_ack_terminal_ack);
116116

117117
write_lock(&call->state_lock);
@@ -210,7 +210,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
210210
rx_pkt_offset = call->rx_pkt_offset;
211211
rx_pkt_len = call->rx_pkt_len;
212212

213-
if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
213+
if (rxrpc_call_state(call) >= RXRPC_CALL_SERVER_ACK_REQUEST) {
214214
seq = lower_32_bits(atomic64_read(&call->ackr_window)) - 1;
215215
ret = 1;
216216
goto done;
@@ -416,7 +416,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
416416
msg->msg_namelen = len;
417417
}
418418

419-
switch (READ_ONCE(call->state)) {
419+
switch (rxrpc_call_state(call)) {
420420
case RXRPC_CALL_CLIENT_RECV_REPLY:
421421
case RXRPC_CALL_SERVER_RECV_REQUEST:
422422
case RXRPC_CALL_SERVER_ACK_REQUEST:
@@ -436,7 +436,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
436436
if (ret < 0)
437437
goto error_unlock_call;
438438

439-
if (call->state == RXRPC_CALL_COMPLETE) {
439+
if (rxrpc_call_is_complete(call)) {
440440
ret = rxrpc_recvmsg_term(call, msg);
441441
if (ret < 0)
442442
goto error_unlock_call;
@@ -516,7 +516,7 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
516516

517517
mutex_lock(&call->user_mutex);
518518

519-
switch (READ_ONCE(call->state)) {
519+
switch (rxrpc_call_state(call)) {
520520
case RXRPC_CALL_CLIENT_RECV_REPLY:
521521
case RXRPC_CALL_SERVER_RECV_REQUEST:
522522
case RXRPC_CALL_SERVER_ACK_REQUEST:

net/rxrpc/sendmsg.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool rxrpc_propose_abort(struct rxrpc_call *call, s32 abort_code, int error,
2525
{
2626
_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
2727

28-
if (!call->send_abort && call->state < RXRPC_CALL_COMPLETE) {
28+
if (!call->send_abort && !rxrpc_call_is_complete(call)) {
2929
call->send_abort_why = why;
3030
call->send_abort_err = error;
3131
call->send_abort_seq = 0;
@@ -60,7 +60,7 @@ static int rxrpc_wait_for_tx_window_intr(struct rxrpc_sock *rx,
6060
if (rxrpc_check_tx_space(call, NULL))
6161
return 0;
6262

63-
if (call->state >= RXRPC_CALL_COMPLETE)
63+
if (rxrpc_call_is_complete(call))
6464
return call->error;
6565

6666
if (signal_pending(current))
@@ -95,7 +95,7 @@ static int rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx,
9595
if (rxrpc_check_tx_space(call, &tx_win))
9696
return 0;
9797

98-
if (call->state >= RXRPC_CALL_COMPLETE)
98+
if (rxrpc_call_is_complete(call))
9999
return call->error;
100100

101101
if (timeout == 0 &&
@@ -124,7 +124,7 @@ static int rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx,
124124
if (rxrpc_check_tx_space(call, NULL))
125125
return 0;
126126

127-
if (call->state >= RXRPC_CALL_COMPLETE)
127+
if (rxrpc_call_is_complete(call))
128128
return call->error;
129129

130130
trace_rxrpc_txqueue(call, rxrpc_txqueue_wait);
@@ -273,7 +273,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
273273
ret = -EPIPE;
274274
if (sk->sk_shutdown & SEND_SHUTDOWN)
275275
goto maybe_error;
276-
state = READ_ONCE(call->state);
276+
state = rxrpc_call_state(call);
277277
ret = -ESHUTDOWN;
278278
if (state >= RXRPC_CALL_COMPLETE)
279279
goto maybe_error;
@@ -350,7 +350,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
350350

351351
/* check for the far side aborting the call or a network error
352352
* occurring */
353-
if (call->state == RXRPC_CALL_COMPLETE)
353+
if (rxrpc_call_is_complete(call))
354354
goto call_terminated;
355355

356356
/* add the packet to the send queue if it's now full */
@@ -375,12 +375,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
375375

376376
success:
377377
ret = copied;
378-
if (READ_ONCE(call->state) == RXRPC_CALL_COMPLETE) {
379-
read_lock(&call->state_lock);
380-
if (call->error < 0)
381-
ret = call->error;
382-
read_unlock(&call->state_lock);
383-
}
378+
if (rxrpc_call_is_complete(call) &&
379+
call->error < 0)
380+
ret = call->error;
384381
out:
385382
call->tx_pending = txb;
386383
_leave(" = %d", ret);
@@ -618,10 +615,10 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
618615
return PTR_ERR(call);
619616
/* ... and we have the call lock. */
620617
ret = 0;
621-
if (READ_ONCE(call->state) == RXRPC_CALL_COMPLETE)
618+
if (rxrpc_call_is_complete(call))
622619
goto out_put_unlock;
623620
} else {
624-
switch (READ_ONCE(call->state)) {
621+
switch (rxrpc_call_state(call)) {
625622
case RXRPC_CALL_UNINITIALISED:
626623
case RXRPC_CALL_CLIENT_AWAIT_CONN:
627624
case RXRPC_CALL_SERVER_PREALLOC:
@@ -675,7 +672,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
675672
break;
676673
}
677674

678-
state = READ_ONCE(call->state);
675+
state = rxrpc_call_state(call);
679676
_debug("CALL %d USR %lx ST %d on CONN %p",
680677
call->debug_id, call->user_call_ID, state, call->conn);
681678

@@ -735,7 +732,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
735732
_debug("CALL %d USR %lx ST %d on CONN %p",
736733
call->debug_id, call->user_call_ID, call->state, call->conn);
737734

738-
switch (READ_ONCE(call->state)) {
735+
switch (rxrpc_call_state(call)) {
739736
case RXRPC_CALL_CLIENT_SEND_REQUEST:
740737
case RXRPC_CALL_SERVER_ACK_REQUEST:
741738
case RXRPC_CALL_SERVER_SEND_REPLY:

0 commit comments

Comments
 (0)