Skip to content

Commit 9d35d88

Browse files
committed
rxrpc: Move client call connection to the I/O thread
Move the connection setup of client calls to the I/O thread so that a whole load of locking and barrierage can be eliminated. This necessitates the app thread waiting for connection to complete before it can begin encrypting data. This also completes the fix for a race that exists between call connection and call disconnection whereby the data transmission code adds the call to the peer error distribution list after the call has been disconnected (say by the rxrpc socket getting closed). The fix is to complete the process of moving call connection, data transmission and call disconnection into the I/O thread and thus forcibly serialising them. Note that the issue may predate the overhaul to an I/O thread model that were included in the merge window for v6.2, but the timing is very much changed by the change given below. Fixes: cf37b59 ("rxrpc: Move DATA transmission into call processor work item") Reported-by: [email protected] Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent 0d6bf31 commit 9d35d88

File tree

14 files changed

+297
-530
lines changed

14 files changed

+297
-530
lines changed

include/trace/events/rxrpc.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@
218218
EM(rxrpc_conn_put_call, "PUT call ") \
219219
EM(rxrpc_conn_put_call_input, "PUT inp-call") \
220220
EM(rxrpc_conn_put_conn_input, "PUT inp-conn") \
221-
EM(rxrpc_conn_put_discard, "PUT discard ") \
222221
EM(rxrpc_conn_put_discard_idle, "PUT disc-idl") \
223222
EM(rxrpc_conn_put_local_dead, "PUT loc-dead") \
224223
EM(rxrpc_conn_put_noreuse, "PUT noreuse ") \
@@ -240,12 +239,11 @@
240239
EM(rxrpc_client_chan_activate, "ChActv") \
241240
EM(rxrpc_client_chan_disconnect, "ChDisc") \
242241
EM(rxrpc_client_chan_pass, "ChPass") \
243-
EM(rxrpc_client_chan_wait_failed, "ChWtFl") \
244242
EM(rxrpc_client_cleanup, "Clean ") \
245243
EM(rxrpc_client_discard, "Discar") \
246-
EM(rxrpc_client_duplicate, "Duplic") \
247244
EM(rxrpc_client_exposed, "Expose") \
248245
EM(rxrpc_client_replace, "Replac") \
246+
EM(rxrpc_client_queue_new_call, "Q-Call") \
249247
EM(rxrpc_client_to_active, "->Actv") \
250248
E_(rxrpc_client_to_idle, "->Idle")
251249

@@ -273,6 +271,7 @@
273271
EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \
274272
EM(rxrpc_call_put_unnotify, "PUT unnotify") \
275273
EM(rxrpc_call_put_userid_exists, "PUT u-exists") \
274+
EM(rxrpc_call_put_userid, "PUT user-id ") \
276275
EM(rxrpc_call_see_accept, "SEE accept ") \
277276
EM(rxrpc_call_see_activate_client, "SEE act-clnt") \
278277
EM(rxrpc_call_see_connect_failed, "SEE con-fail") \

net/rxrpc/ar-internal.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ struct rxrpc_local {
292292
struct rb_root client_bundles; /* Client connection bundles by socket params */
293293
spinlock_t client_bundles_lock; /* Lock for client_bundles */
294294
bool kill_all_client_conns;
295-
spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */
296295
struct list_head idle_client_conns;
297296
struct timer_list client_conn_reap_timer;
298297
unsigned long client_conn_flags;
@@ -304,7 +303,8 @@ struct rxrpc_local {
304303
bool dead;
305304
bool service_closed; /* Service socket closed */
306305
struct idr conn_ids; /* List of connection IDs */
307-
spinlock_t conn_lock; /* Lock for client connection pool */
306+
struct list_head new_client_calls; /* Newly created client calls need connection */
307+
spinlock_t client_call_lock; /* Lock for ->new_client_calls */
308308
struct sockaddr_rxrpc srx; /* local address */
309309
};
310310

@@ -385,7 +385,6 @@ enum rxrpc_call_completion {
385385
* Bits in the connection flags.
386386
*/
387387
enum rxrpc_conn_flag {
388-
RXRPC_CONN_HAS_IDR, /* Has a client conn ID assigned */
389388
RXRPC_CONN_IN_SERVICE_CONNS, /* Conn is in peer->service_conns */
390389
RXRPC_CONN_DONT_REUSE, /* Don't reuse this connection */
391390
RXRPC_CONN_PROBING_FOR_UPGRADE, /* Probing for service upgrade */
@@ -413,6 +412,7 @@ enum rxrpc_conn_event {
413412
*/
414413
enum rxrpc_conn_proto_state {
415414
RXRPC_CONN_UNUSED, /* Connection not yet attempted */
415+
RXRPC_CONN_CLIENT_UNSECURED, /* Client connection needs security init */
416416
RXRPC_CONN_CLIENT, /* Client connection */
417417
RXRPC_CONN_SERVICE_PREALLOC, /* Service connection preallocation */
418418
RXRPC_CONN_SERVICE_UNSECURED, /* Service unsecured connection */
@@ -436,11 +436,9 @@ struct rxrpc_bundle {
436436
u32 security_level; /* Security level selected */
437437
u16 service_id; /* Service ID for this connection */
438438
bool try_upgrade; /* True if the bundle is attempting upgrade */
439-
bool alloc_conn; /* True if someone's getting a conn */
440439
bool exclusive; /* T if conn is exclusive */
441440
bool upgrade; /* T if service ID can be upgraded */
442-
short alloc_error; /* Error from last conn allocation */
443-
spinlock_t channel_lock;
441+
unsigned short alloc_error; /* Error from last conn allocation */
444442
struct rb_node local_node; /* Node in local->client_conns */
445443
struct list_head waiting_calls; /* Calls waiting for channels */
446444
unsigned long avail_chans; /* Mask of available channels */
@@ -468,7 +466,7 @@ struct rxrpc_connection {
468466
unsigned char act_chans; /* Mask of active channels */
469467
struct rxrpc_channel {
470468
unsigned long final_ack_at; /* Time at which to issue final ACK */
471-
struct rxrpc_call __rcu *call; /* Active call */
469+
struct rxrpc_call *call; /* Active call */
472470
unsigned int call_debug_id; /* call->debug_id */
473471
u32 call_id; /* ID of current call */
474472
u32 call_counter; /* Call ID counter */
@@ -489,6 +487,7 @@ struct rxrpc_connection {
489487
struct list_head link; /* link in master connection list */
490488
struct sk_buff_head rx_queue; /* received conn-level packets */
491489

490+
struct mutex security_lock; /* Lock for security management */
492491
const struct rxrpc_security *security; /* applied security module */
493492
union {
494493
struct {
@@ -619,7 +618,7 @@ struct rxrpc_call {
619618
struct work_struct destroyer; /* In-process-context destroyer */
620619
rxrpc_notify_rx_t notify_rx; /* kernel service Rx notification function */
621620
struct list_head link; /* link in master call list */
622-
struct list_head chan_wait_link; /* Link in conn->bundle->waiting_calls */
621+
struct list_head wait_link; /* Link in local->new_client_calls */
623622
struct hlist_node error_link; /* link in error distribution list */
624623
struct list_head accept_link; /* Link in rx->acceptq */
625624
struct list_head recvmsg_link; /* Link in rx->recvmsg_q */
@@ -866,6 +865,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
866865
struct sockaddr_rxrpc *,
867866
struct rxrpc_call_params *, gfp_t,
868867
unsigned int);
868+
void rxrpc_start_call_timer(struct rxrpc_call *call);
869869
void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
870870
struct sk_buff *);
871871
void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
@@ -905,6 +905,7 @@ static inline void rxrpc_set_call_state(struct rxrpc_call *call,
905905
{
906906
/* Order write of completion info before write of ->state. */
907907
smp_store_release(&call->_state, state);
908+
wake_up(&call->waitq);
908909
}
909910

910911
static inline enum rxrpc_call_state __rxrpc_call_state(const struct rxrpc_call *call)
@@ -940,10 +941,11 @@ extern unsigned int rxrpc_reap_client_connections;
940941
extern unsigned long rxrpc_conn_idle_client_expiry;
941942
extern unsigned long rxrpc_conn_idle_client_fast_expiry;
942943

943-
void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local);
944+
void rxrpc_purge_client_connections(struct rxrpc_local *local);
944945
struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *, enum rxrpc_bundle_trace);
945946
void rxrpc_put_bundle(struct rxrpc_bundle *, enum rxrpc_bundle_trace);
946-
int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp);
947+
int rxrpc_look_up_bundle(struct rxrpc_call *call, gfp_t gfp);
948+
void rxrpc_connect_client_calls(struct rxrpc_local *local);
947949
void rxrpc_expose_client_call(struct rxrpc_call *);
948950
void rxrpc_disconnect_client_call(struct rxrpc_bundle *, struct rxrpc_call *);
949951
void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle);

net/rxrpc/call_object.c

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
150150
timer_setup(&call->timer, rxrpc_call_timer_expired, 0);
151151
INIT_WORK(&call->destroyer, rxrpc_destroy_call);
152152
INIT_LIST_HEAD(&call->link);
153-
INIT_LIST_HEAD(&call->chan_wait_link);
153+
INIT_LIST_HEAD(&call->wait_link);
154154
INIT_LIST_HEAD(&call->accept_link);
155155
INIT_LIST_HEAD(&call->recvmsg_link);
156156
INIT_LIST_HEAD(&call->sock_link);
@@ -242,7 +242,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
242242
/*
243243
* Initiate the call ack/resend/expiry timer.
244244
*/
245-
static void rxrpc_start_call_timer(struct rxrpc_call *call)
245+
void rxrpc_start_call_timer(struct rxrpc_call *call)
246246
{
247247
unsigned long now = jiffies;
248248
unsigned long j = now + MAX_JIFFY_OFFSET;
@@ -286,6 +286,39 @@ static void rxrpc_put_call_slot(struct rxrpc_call *call)
286286
up(limiter);
287287
}
288288

289+
/*
290+
* Start the process of connecting a call. We obtain a peer and a connection
291+
* bundle, but the actual association of a call with a connection is offloaded
292+
* to the I/O thread to simplify locking.
293+
*/
294+
static int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
295+
{
296+
struct rxrpc_local *local = call->local;
297+
int ret = 0;
298+
299+
_enter("{%d,%lx},", call->debug_id, call->user_call_ID);
300+
301+
call->peer = rxrpc_lookup_peer(local, &call->dest_srx, gfp);
302+
if (!call->peer)
303+
goto error;
304+
305+
ret = rxrpc_look_up_bundle(call, gfp);
306+
if (ret < 0)
307+
goto error;
308+
309+
trace_rxrpc_client(NULL, -1, rxrpc_client_queue_new_call);
310+
rxrpc_get_call(call, rxrpc_call_get_io_thread);
311+
spin_lock(&local->client_call_lock);
312+
list_add_tail(&call->wait_link, &local->new_client_calls);
313+
spin_unlock(&local->client_call_lock);
314+
rxrpc_wake_up_io_thread(local);
315+
return 0;
316+
317+
error:
318+
__set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
319+
return ret;
320+
}
321+
289322
/*
290323
* Set up a call for the given parameters.
291324
* - Called with the socket lock held, which it must release.
@@ -369,10 +402,6 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
369402
if (ret < 0)
370403
goto error_attached_to_socket;
371404

372-
rxrpc_see_call(call, rxrpc_call_see_connected);
373-
374-
rxrpc_start_call_timer(call);
375-
376405
_leave(" = %p [new]", call);
377406
return call;
378407

@@ -387,22 +416,20 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
387416
rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, -EEXIST);
388417
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), 0,
389418
rxrpc_call_see_userid_exists);
390-
rxrpc_release_call(rx, call);
391419
mutex_unlock(&call->user_mutex);
392420
rxrpc_put_call(call, rxrpc_call_put_userid_exists);
393421
_leave(" = -EEXIST");
394422
return ERR_PTR(-EEXIST);
395423

396424
/* We got an error, but the call is attached to the socket and is in
397-
* need of release. However, we might now race with recvmsg() when
398-
* completing the call queues it. Return 0 from sys_sendmsg() and
425+
* need of release. However, we might now race with recvmsg() when it
426+
* completion notifies the socket. Return 0 from sys_sendmsg() and
399427
* leave the error to recvmsg() to deal with.
400428
*/
401429
error_attached_to_socket:
402430
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref), ret,
403431
rxrpc_call_see_connect_failed);
404-
set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
405-
rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, ret);
432+
rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 0, ret);
406433
_leave(" = c=%08x [err]", call->debug_id);
407434
return call;
408435
}
@@ -460,7 +487,7 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx,
460487
chan = sp->hdr.cid & RXRPC_CHANNELMASK;
461488
conn->channels[chan].call_counter = call->call_id;
462489
conn->channels[chan].call_id = call->call_id;
463-
rcu_assign_pointer(conn->channels[chan].call, call);
490+
conn->channels[chan].call = call;
464491
spin_unlock(&conn->state_lock);
465492

466493
spin_lock(&conn->peer->lock);
@@ -520,7 +547,7 @@ static void rxrpc_cleanup_ring(struct rxrpc_call *call)
520547
void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
521548
{
522549
struct rxrpc_connection *conn = call->conn;
523-
bool put = false;
550+
bool put = false, putu = false;
524551

525552
_enter("{%d,%d}", call->debug_id, refcount_read(&call->ref));
526553

@@ -555,14 +582,17 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
555582
if (test_and_clear_bit(RXRPC_CALL_HAS_USERID, &call->flags)) {
556583
rb_erase(&call->sock_node, &rx->calls);
557584
memset(&call->sock_node, 0xdd, sizeof(call->sock_node));
558-
rxrpc_put_call(call, rxrpc_call_put_userid_exists);
585+
putu = true;
559586
}
560587

561588
list_del(&call->sock_link);
562589
write_unlock(&rx->call_lock);
563590

564591
_debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn);
565592

593+
if (putu)
594+
rxrpc_put_call(call, rxrpc_call_put_userid);
595+
566596
_leave("");
567597
}
568598

net/rxrpc/call_state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,5 @@ void rxrpc_prefail_call(struct rxrpc_call *call, enum rxrpc_call_completion comp
6565
call->completion = compl;
6666
call->_state = RXRPC_CALL_COMPLETE;
6767
trace_rxrpc_call_complete(call);
68-
__set_bit(RXRPC_CALL_RELEASED, &call->flags);
68+
WARN_ON_ONCE(__test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags));
6969
}

0 commit comments

Comments
 (0)