Skip to content

Commit 2d68942

Browse files
committed
rxrpc: Move call state changes from sendmsg to I/O thread
Move all the call state changes that are made in rxrpc_sendmsg() to the I/O thread. This is a step towards removing the call state lock. This requires the switch to the RXRPC_CALL_CLIENT_AWAIT_REPLY and RXRPC_CALL_SERVER_SEND_REPLY states to be done when the last packet is decanted from ->tx_sendmsg to ->tx_buffer in the I/O thread, not when it is added to ->tx_sendmsg by sendmsg(). Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent d41b3f5 commit 2d68942

File tree

3 files changed

+63
-60
lines changed

3 files changed

+63
-60
lines changed

Documentation/networking/rxrpc.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -880,8 +880,8 @@ The kernel interface functions are as follows:
880880

881881
notify_end_rx can be NULL or it can be used to specify a function to be
882882
called when the call changes state to end the Tx phase. This function is
883-
called with the call-state spinlock held to prevent any reply or final ACK
884-
from being delivered first.
883+
called with a spinlock held to prevent the last DATA packet from being
884+
transmitted until the function returns.
885885

886886
(#) Receive data from a call::
887887

net/rxrpc/call_event.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,50 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
251251
_leave("");
252252
}
253253

254+
/*
255+
* Start transmitting the reply to a service. This cancels the need to ACK the
256+
* request if we haven't yet done so.
257+
*/
258+
static void rxrpc_begin_service_reply(struct rxrpc_call *call)
259+
{
260+
unsigned long now;
261+
262+
write_lock(&call->state_lock);
263+
264+
if (call->state == RXRPC_CALL_SERVER_ACK_REQUEST) {
265+
now = jiffies;
266+
call->state = RXRPC_CALL_SERVER_SEND_REPLY;
267+
WRITE_ONCE(call->delay_ack_at, now + MAX_JIFFY_OFFSET);
268+
if (call->ackr_reason == RXRPC_ACK_DELAY)
269+
call->ackr_reason = 0;
270+
trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now);
271+
}
272+
273+
write_unlock(&call->state_lock);
274+
}
275+
276+
/*
277+
* Close the transmission phase. After this point there is no more data to be
278+
* transmitted in the call.
279+
*/
280+
static void rxrpc_close_tx_phase(struct rxrpc_call *call)
281+
{
282+
_debug("________awaiting reply/ACK__________");
283+
284+
write_lock(&call->state_lock);
285+
switch (call->state) {
286+
case RXRPC_CALL_CLIENT_SEND_REQUEST:
287+
call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
288+
break;
289+
case RXRPC_CALL_SERVER_SEND_REPLY:
290+
call->state = RXRPC_CALL_SERVER_AWAIT_ACK;
291+
break;
292+
default:
293+
break;
294+
}
295+
write_unlock(&call->state_lock);
296+
}
297+
254298
static bool rxrpc_tx_window_has_space(struct rxrpc_call *call)
255299
{
256300
unsigned int winsize = min_t(unsigned int, call->tx_winsize,
@@ -285,6 +329,9 @@ static void rxrpc_decant_prepared_tx(struct rxrpc_call *call)
285329
call->tx_top = txb->seq;
286330
list_add_tail(&txb->call_link, &call->tx_buffer);
287331

332+
if (txb->wire.flags & RXRPC_LAST_PACKET)
333+
rxrpc_close_tx_phase(call);
334+
288335
rxrpc_transmit_one(call, txb);
289336

290337
if (!rxrpc_tx_window_has_space(call))
@@ -298,12 +345,11 @@ static void rxrpc_transmit_some_data(struct rxrpc_call *call)
298345
case RXRPC_CALL_SERVER_ACK_REQUEST:
299346
if (list_empty(&call->tx_sendmsg))
300347
return;
348+
rxrpc_begin_service_reply(call);
301349
fallthrough;
302350

303351
case RXRPC_CALL_SERVER_SEND_REPLY:
304-
case RXRPC_CALL_SERVER_AWAIT_ACK:
305352
case RXRPC_CALL_CLIENT_SEND_REQUEST:
306-
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
307353
if (!rxrpc_tx_window_has_space(call))
308354
return;
309355
if (list_empty(&call->tx_sendmsg)) {

net/rxrpc/sendmsg.c

Lines changed: 13 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
189189
struct rxrpc_txbuf *txb,
190190
rxrpc_notify_end_tx_t notify_end_tx)
191191
{
192-
unsigned long now;
193192
rxrpc_seq_t seq = txb->seq;
194193
bool last = test_bit(RXRPC_TXBUF_LAST, &txb->flags), poke;
195194

@@ -212,36 +211,10 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
212211
poke = list_empty(&call->tx_sendmsg);
213212
list_add_tail(&txb->call_link, &call->tx_sendmsg);
214213
call->tx_prepared = seq;
214+
if (last)
215+
rxrpc_notify_end_tx(rx, call, notify_end_tx);
215216
spin_unlock(&call->tx_lock);
216217

217-
if (last || call->state == RXRPC_CALL_SERVER_ACK_REQUEST) {
218-
_debug("________awaiting reply/ACK__________");
219-
write_lock(&call->state_lock);
220-
switch (call->state) {
221-
case RXRPC_CALL_CLIENT_SEND_REQUEST:
222-
call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
223-
rxrpc_notify_end_tx(rx, call, notify_end_tx);
224-
break;
225-
case RXRPC_CALL_SERVER_ACK_REQUEST:
226-
call->state = RXRPC_CALL_SERVER_SEND_REPLY;
227-
now = jiffies;
228-
WRITE_ONCE(call->delay_ack_at, now + MAX_JIFFY_OFFSET);
229-
if (call->ackr_reason == RXRPC_ACK_DELAY)
230-
call->ackr_reason = 0;
231-
trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now);
232-
if (!last)
233-
break;
234-
fallthrough;
235-
case RXRPC_CALL_SERVER_SEND_REPLY:
236-
call->state = RXRPC_CALL_SERVER_AWAIT_ACK;
237-
rxrpc_notify_end_tx(rx, call, notify_end_tx);
238-
break;
239-
default:
240-
break;
241-
}
242-
write_unlock(&call->state_lock);
243-
}
244-
245218
if (poke)
246219
rxrpc_poke_call(call, rxrpc_call_poke_start);
247220
}
@@ -280,8 +253,13 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
280253
ret = -EPROTO;
281254
if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
282255
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
283-
state != RXRPC_CALL_SERVER_SEND_REPLY)
256+
state != RXRPC_CALL_SERVER_SEND_REPLY) {
257+
/* Request phase complete for this client call */
258+
trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
259+
call->cid, call->call_id, call->rx_consumed,
260+
0, -EPROTO);
284261
goto maybe_error;
262+
}
285263

286264
ret = -EMSGSIZE;
287265
if (call->tx_total_len != -1) {
@@ -573,7 +551,6 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
573551
int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
574552
__releases(&rx->sk.sk_lock.slock)
575553
{
576-
enum rxrpc_call_state state;
577554
struct rxrpc_call *call;
578555
unsigned long now, j;
579556
bool dropped_lock = false;
@@ -672,11 +649,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
672649
break;
673650
}
674651

675-
state = rxrpc_call_state(call);
676-
_debug("CALL %d USR %lx ST %d on CONN %p",
677-
call->debug_id, call->user_call_ID, state, call->conn);
678-
679-
if (state >= RXRPC_CALL_COMPLETE) {
652+
if (rxrpc_call_is_complete(call)) {
680653
/* it's too late for this call */
681654
ret = -ESHUTDOWN;
682655
} else if (p.command == RXRPC_CMD_SEND_ABORT) {
@@ -722,7 +695,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
722695
bool dropped_lock = false;
723696
int ret;
724697

725-
_enter("{%d,%s},", call->debug_id, rxrpc_call_states[call->state]);
698+
_enter("{%d},", call->debug_id);
726699

727700
ASSERTCMP(msg->msg_name, ==, NULL);
728701
ASSERTCMP(msg->msg_control, ==, NULL);
@@ -732,26 +705,10 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
732705
_debug("CALL %d USR %lx ST %d on CONN %p",
733706
call->debug_id, call->user_call_ID, call->state, call->conn);
734707

735-
switch (rxrpc_call_state(call)) {
736-
case RXRPC_CALL_CLIENT_SEND_REQUEST:
737-
case RXRPC_CALL_SERVER_ACK_REQUEST:
738-
case RXRPC_CALL_SERVER_SEND_REPLY:
739-
ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
740-
notify_end_tx, &dropped_lock);
741-
break;
742-
case RXRPC_CALL_COMPLETE:
743-
read_lock(&call->state_lock);
708+
ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
709+
notify_end_tx, &dropped_lock);
710+
if (ret == -ESHUTDOWN)
744711
ret = call->error;
745-
read_unlock(&call->state_lock);
746-
break;
747-
default:
748-
/* Request phase complete for this client call */
749-
trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
750-
call->cid, call->call_id, call->rx_consumed,
751-
0, -EPROTO);
752-
ret = -EPROTO;
753-
break;
754-
}
755712

756713
if (!dropped_lock)
757714
mutex_unlock(&call->user_mutex);

0 commit comments

Comments
 (0)