Skip to content

Commit 0d6bf31

Browse files
committed
rxrpc: Move the client conn cache management to the I/O thread
Move the management of the client connection cache to the I/O thread rather than managing it from the namespace as an aggregate across all the local endpoints within the namespace. This will allow a load of locking to be got rid of in a future patch as only the I/O thread will be looking at the this. The downside is that the total number of cached connections on the system can get higher because the limit is now per-local rather than per-netns. We can, however, keep the number of client conns in use across the entire netfs and use that to reduce the expiration time of idle connection. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent 96b4059 commit 0d6bf31

File tree

6 files changed

+62
-86
lines changed

6 files changed

+62
-86
lines changed

net/rxrpc/ar-internal.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,7 @@ struct rxrpc_net {
7676

7777
bool live;
7878

79-
bool kill_all_client_conns;
8079
atomic_t nr_client_conns;
81-
spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */
82-
struct mutex client_conn_discard_lock; /* Prevent multiple discarders */
83-
struct list_head idle_client_conns;
84-
struct work_struct client_conn_reaper;
85-
struct timer_list client_conn_reap_timer;
8680

8781
struct hlist_head local_endpoints;
8882
struct mutex local_mutex; /* Lock for ->local_endpoints */
@@ -294,8 +288,16 @@ struct rxrpc_local {
294288
struct sk_buff_head rx_queue; /* Received packets */
295289
struct list_head conn_attend_q; /* Conns requiring immediate attention */
296290
struct list_head call_attend_q; /* Calls requiring immediate attention */
291+
297292
struct rb_root client_bundles; /* Client connection bundles by socket params */
298293
spinlock_t client_bundles_lock; /* Lock for client_bundles */
294+
bool kill_all_client_conns;
295+
spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */
296+
struct list_head idle_client_conns;
297+
struct timer_list client_conn_reap_timer;
298+
unsigned long client_conn_flags;
299+
#define RXRPC_CLIENT_CONN_REAP_TIMER 0 /* The client conn reap timer expired */
300+
299301
spinlock_t lock; /* access lock */
300302
rwlock_t services_lock; /* lock for services list */
301303
int debug_id; /* debug ID for printks */
@@ -946,8 +948,7 @@ void rxrpc_expose_client_call(struct rxrpc_call *);
946948
void rxrpc_disconnect_client_call(struct rxrpc_bundle *, struct rxrpc_call *);
947949
void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle);
948950
void rxrpc_put_client_conn(struct rxrpc_connection *, enum rxrpc_conn_trace);
949-
void rxrpc_discard_expired_client_conns(struct work_struct *);
950-
void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
951+
void rxrpc_discard_expired_client_conns(struct rxrpc_local *local);
951952
void rxrpc_clean_up_local_conns(struct rxrpc_local *);
952953

953954
/*

net/rxrpc/conn_client.c

Lines changed: 32 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -578,17 +578,17 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
578578
*/
579579
static void rxrpc_unidle_conn(struct rxrpc_bundle *bundle, struct rxrpc_connection *conn)
580580
{
581-
struct rxrpc_net *rxnet = bundle->local->rxnet;
581+
struct rxrpc_local *local = bundle->local;
582582
bool drop_ref;
583583

584584
if (!list_empty(&conn->cache_link)) {
585585
drop_ref = false;
586-
spin_lock(&rxnet->client_conn_cache_lock);
586+
spin_lock(&local->client_conn_cache_lock);
587587
if (!list_empty(&conn->cache_link)) {
588588
list_del_init(&conn->cache_link);
589589
drop_ref = true;
590590
}
591-
spin_unlock(&rxnet->client_conn_cache_lock);
591+
spin_unlock(&local->client_conn_cache_lock);
592592
if (drop_ref)
593593
rxrpc_put_connection(conn, rxrpc_conn_put_unidle);
594594
}
@@ -710,14 +710,10 @@ static int rxrpc_wait_for_channel(struct rxrpc_bundle *bundle,
710710
int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
711711
{
712712
struct rxrpc_bundle *bundle;
713-
struct rxrpc_local *local = call->local;
714-
struct rxrpc_net *rxnet = local->rxnet;
715713
int ret = 0;
716714

717715
_enter("{%d,%lx},", call->debug_id, call->user_call_ID);
718716

719-
rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper);
720-
721717
rxrpc_get_call(call, rxrpc_call_get_io_thread);
722718

723719
bundle = rxrpc_prep_call(call, gfp);
@@ -787,14 +783,14 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
787783
/*
788784
* Set the reap timer.
789785
*/
790-
static void rxrpc_set_client_reap_timer(struct rxrpc_net *rxnet)
786+
static void rxrpc_set_client_reap_timer(struct rxrpc_local *local)
791787
{
792-
if (!rxnet->kill_all_client_conns) {
788+
if (!local->kill_all_client_conns) {
793789
unsigned long now = jiffies;
794790
unsigned long reap_at = now + rxrpc_conn_idle_client_expiry;
795791

796-
if (rxnet->live)
797-
timer_reduce(&rxnet->client_conn_reap_timer, reap_at);
792+
if (local->rxnet->live)
793+
timer_reduce(&local->client_conn_reap_timer, reap_at);
798794
}
799795
}
800796

@@ -805,7 +801,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call
805801
{
806802
struct rxrpc_connection *conn;
807803
struct rxrpc_channel *chan = NULL;
808-
struct rxrpc_net *rxnet = bundle->local->rxnet;
804+
struct rxrpc_local *local = bundle->local;
809805
unsigned int channel;
810806
bool may_reuse;
811807
u32 cid;
@@ -895,11 +891,11 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call
895891
conn->idle_timestamp = jiffies;
896892

897893
rxrpc_get_connection(conn, rxrpc_conn_get_idle);
898-
spin_lock(&rxnet->client_conn_cache_lock);
899-
list_move_tail(&conn->cache_link, &rxnet->idle_client_conns);
900-
spin_unlock(&rxnet->client_conn_cache_lock);
894+
spin_lock(&local->client_conn_cache_lock);
895+
list_move_tail(&conn->cache_link, &local->idle_client_conns);
896+
spin_unlock(&local->client_conn_cache_lock);
901897

902-
rxrpc_set_client_reap_timer(rxnet);
898+
rxrpc_set_client_reap_timer(local);
903899
}
904900

905901
out:
@@ -986,42 +982,34 @@ void rxrpc_kill_client_conn(struct rxrpc_connection *conn)
986982
* This may be called from conn setup or from a work item so cannot be
987983
* considered non-reentrant.
988984
*/
989-
void rxrpc_discard_expired_client_conns(struct work_struct *work)
985+
void rxrpc_discard_expired_client_conns(struct rxrpc_local *local)
990986
{
991987
struct rxrpc_connection *conn;
992-
struct rxrpc_net *rxnet =
993-
container_of(work, struct rxrpc_net, client_conn_reaper);
994988
unsigned long expiry, conn_expires_at, now;
995989
unsigned int nr_conns;
996990

997991
_enter("");
998992

999-
if (list_empty(&rxnet->idle_client_conns)) {
993+
if (list_empty(&local->idle_client_conns)) {
1000994
_leave(" [empty]");
1001995
return;
1002996
}
1003997

1004-
/* Don't double up on the discarding */
1005-
if (!mutex_trylock(&rxnet->client_conn_discard_lock)) {
1006-
_leave(" [already]");
1007-
return;
1008-
}
1009-
1010998
/* We keep an estimate of what the number of conns ought to be after
1011999
* we've discarded some so that we don't overdo the discarding.
10121000
*/
1013-
nr_conns = atomic_read(&rxnet->nr_client_conns);
1001+
nr_conns = atomic_read(&local->rxnet->nr_client_conns);
10141002

10151003
next:
1016-
spin_lock(&rxnet->client_conn_cache_lock);
1004+
spin_lock(&local->client_conn_cache_lock);
10171005

1018-
if (list_empty(&rxnet->idle_client_conns))
1006+
if (list_empty(&local->idle_client_conns))
10191007
goto out;
10201008

1021-
conn = list_entry(rxnet->idle_client_conns.next,
1009+
conn = list_entry(local->idle_client_conns.next,
10221010
struct rxrpc_connection, cache_link);
10231011

1024-
if (!rxnet->kill_all_client_conns) {
1012+
if (!local->kill_all_client_conns) {
10251013
/* If the number of connections is over the reap limit, we
10261014
* expedite discard by reducing the expiry timeout. We must,
10271015
* however, have at least a short grace period to be able to do
@@ -1044,7 +1032,7 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
10441032
trace_rxrpc_client(conn, -1, rxrpc_client_discard);
10451033
list_del_init(&conn->cache_link);
10461034

1047-
spin_unlock(&rxnet->client_conn_cache_lock);
1035+
spin_unlock(&local->client_conn_cache_lock);
10481036

10491037
rxrpc_unbundle_conn(conn);
10501038
/* Drop the ->cache_link ref */
@@ -1062,32 +1050,11 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
10621050
* then things get messier.
10631051
*/
10641052
_debug("not yet");
1065-
if (!rxnet->kill_all_client_conns)
1066-
timer_reduce(&rxnet->client_conn_reap_timer, conn_expires_at);
1053+
if (!local->kill_all_client_conns)
1054+
timer_reduce(&local->client_conn_reap_timer, conn_expires_at);
10671055

10681056
out:
1069-
spin_unlock(&rxnet->client_conn_cache_lock);
1070-
mutex_unlock(&rxnet->client_conn_discard_lock);
1071-
_leave("");
1072-
}
1073-
1074-
/*
1075-
* Preemptively destroy all the client connection records rather than waiting
1076-
* for them to time out
1077-
*/
1078-
void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
1079-
{
1080-
_enter("");
1081-
1082-
spin_lock(&rxnet->client_conn_cache_lock);
1083-
rxnet->kill_all_client_conns = true;
1084-
spin_unlock(&rxnet->client_conn_cache_lock);
1085-
1086-
del_timer_sync(&rxnet->client_conn_reap_timer);
1087-
1088-
if (!rxrpc_queue_work(&rxnet->client_conn_reaper))
1089-
_debug("destroy: queue failed");
1090-
1057+
spin_unlock(&local->client_conn_cache_lock);
10911058
_leave("");
10921059
}
10931060

@@ -1097,14 +1064,19 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
10971064
void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
10981065
{
10991066
struct rxrpc_connection *conn, *tmp;
1100-
struct rxrpc_net *rxnet = local->rxnet;
11011067
LIST_HEAD(graveyard);
11021068

11031069
_enter("");
11041070

1105-
spin_lock(&rxnet->client_conn_cache_lock);
1071+
spin_lock(&local->client_conn_cache_lock);
1072+
local->kill_all_client_conns = true;
1073+
spin_unlock(&local->client_conn_cache_lock);
1074+
1075+
del_timer_sync(&local->client_conn_reap_timer);
1076+
1077+
spin_lock(&local->client_conn_cache_lock);
11061078

1107-
list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
1079+
list_for_each_entry_safe(conn, tmp, &local->idle_client_conns,
11081080
cache_link) {
11091081
if (conn->local == local) {
11101082
atomic_dec(&conn->active);
@@ -1113,7 +1085,7 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
11131085
}
11141086
}
11151087

1116-
spin_unlock(&rxnet->client_conn_cache_lock);
1088+
spin_unlock(&local->client_conn_cache_lock);
11171089

11181090
while (!list_empty(&graveyard)) {
11191091
conn = list_entry(graveyard.next,

net/rxrpc/conn_object.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
470470
_enter("");
471471

472472
atomic_dec(&rxnet->nr_conns);
473-
rxrpc_destroy_all_client_connections(rxnet);
474473

475474
del_timer_sync(&rxnet->service_conn_reap_timer);
476475
rxrpc_queue_work(&rxnet->service_conn_reaper);

net/rxrpc/io_thread.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,10 @@ int rxrpc_io_thread(void *data)
435435
continue;
436436
}
437437

438+
if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
439+
&local->client_conn_flags))
440+
rxrpc_discard_expired_client_conns(local);
441+
438442
/* Deal with calls that want immediate attention. */
439443
if ((call = list_first_entry_or_null(&local->call_attend_q,
440444
struct rxrpc_call,

net/rxrpc/local_object.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ static long rxrpc_local_cmp_key(const struct rxrpc_local *local,
8282
}
8383
}
8484

85+
static void rxrpc_client_conn_reap_timeout(struct timer_list *timer)
86+
{
87+
struct rxrpc_local *local =
88+
container_of(timer, struct rxrpc_local, client_conn_reap_timer);
89+
90+
if (local->kill_all_client_conns &&
91+
test_and_set_bit(RXRPC_CLIENT_CONN_REAP_TIMER, &local->client_conn_flags))
92+
rxrpc_wake_up_io_thread(local);
93+
}
94+
8595
/*
8696
* Allocate a new local endpoint.
8797
*/
@@ -103,8 +113,15 @@ static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
103113
skb_queue_head_init(&local->rx_queue);
104114
INIT_LIST_HEAD(&local->conn_attend_q);
105115
INIT_LIST_HEAD(&local->call_attend_q);
116+
106117
local->client_bundles = RB_ROOT;
107118
spin_lock_init(&local->client_bundles_lock);
119+
local->kill_all_client_conns = false;
120+
spin_lock_init(&local->client_conn_cache_lock);
121+
INIT_LIST_HEAD(&local->idle_client_conns);
122+
timer_setup(&local->client_conn_reap_timer,
123+
rxrpc_client_conn_reap_timeout, 0);
124+
108125
spin_lock_init(&local->lock);
109126
rwlock_init(&local->services_lock);
110127
local->debug_id = atomic_inc_return(&rxrpc_debug_id);

net/rxrpc/net_ns.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,6 @@
1010

1111
unsigned int rxrpc_net_id;
1212

13-
static void rxrpc_client_conn_reap_timeout(struct timer_list *timer)
14-
{
15-
struct rxrpc_net *rxnet =
16-
container_of(timer, struct rxrpc_net, client_conn_reap_timer);
17-
18-
if (rxnet->live)
19-
rxrpc_queue_work(&rxnet->client_conn_reaper);
20-
}
21-
2213
static void rxrpc_service_conn_reap_timeout(struct timer_list *timer)
2314
{
2415
struct rxrpc_net *rxnet =
@@ -63,14 +54,6 @@ static __net_init int rxrpc_init_net(struct net *net)
6354
rxrpc_service_conn_reap_timeout, 0);
6455

6556
atomic_set(&rxnet->nr_client_conns, 0);
66-
rxnet->kill_all_client_conns = false;
67-
spin_lock_init(&rxnet->client_conn_cache_lock);
68-
mutex_init(&rxnet->client_conn_discard_lock);
69-
INIT_LIST_HEAD(&rxnet->idle_client_conns);
70-
INIT_WORK(&rxnet->client_conn_reaper,
71-
rxrpc_discard_expired_client_conns);
72-
timer_setup(&rxnet->client_conn_reap_timer,
73-
rxrpc_client_conn_reap_timeout, 0);
7457

7558
INIT_HLIST_HEAD(&rxnet->local_endpoints);
7659
mutex_init(&rxnet->local_mutex);

0 commit comments

Comments
 (0)