Skip to content

Commit 3d18cbb

Browse files
committed
rxrpc: Fix conn expiry timers
Fix the rxrpc connection expiry timers so that connections for closed AF_RXRPC sockets get deleted in a more timely fashion, freeing up the transport UDP port much more quickly. (1) Replace the delayed work items with work items plus timers so that timer_reduce() can be used to shorten them and so that the timer doesn't requeue the work item if the net namespace is dead. (2) Don't use queue_delayed_work() as that won't alter the timeout if the timer is already running. (3) Don't rearm the timers if the network namespace is dead. Signed-off-by: David Howells <[email protected]>
1 parent f859ab6 commit 3d18cbb

File tree

5 files changed

+68
-28
lines changed

5 files changed

+68
-28
lines changed

net/rxrpc/af_rxrpc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,8 @@ static int rxrpc_release_sock(struct sock *sk)
895895
rxrpc_release_calls_on_socket(rx);
896896
flush_workqueue(rxrpc_workqueue);
897897
rxrpc_purge_queue(&sk->sk_receive_queue);
898+
rxrpc_queue_work(&rx->local->rxnet->service_conn_reaper);
899+
rxrpc_queue_work(&rx->local->rxnet->client_conn_reaper);
898900

899901
rxrpc_put_local(rx->local);
900902
rx->local = NULL;

net/rxrpc/ar-internal.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ struct rxrpc_net {
7979
struct list_head conn_proc_list; /* List of conns in this namespace for proc */
8080
struct list_head service_conns; /* Service conns in this namespace */
8181
rwlock_t conn_lock; /* Lock for ->conn_proc_list, ->service_conns */
82-
struct delayed_work service_conn_reaper;
82+
struct work_struct service_conn_reaper;
83+
struct timer_list service_conn_reap_timer;
8384

8485
unsigned int nr_client_conns;
8586
unsigned int nr_active_client_conns;
@@ -90,7 +91,8 @@ struct rxrpc_net {
9091
struct list_head waiting_client_conns;
9192
struct list_head active_client_conns;
9293
struct list_head idle_client_conns;
93-
struct delayed_work client_conn_reaper;
94+
struct work_struct client_conn_reaper;
95+
struct timer_list client_conn_reap_timer;
9496

9597
struct list_head local_endpoints;
9698
struct mutex local_mutex; /* Lock for ->local_endpoints */

net/rxrpc/conn_client.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ int rxrpc_connect_call(struct rxrpc_call *call,
691691

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

694-
rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper.work);
694+
rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper);
695695
rxrpc_cull_active_client_conns(rxnet);
696696

697697
ret = rxrpc_get_client_conn(call, cp, srx, gfp);
@@ -756,6 +756,18 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
756756
}
757757
}
758758

759+
/*
760+
* Set the reap timer.
761+
*/
762+
static void rxrpc_set_client_reap_timer(struct rxrpc_net *rxnet)
763+
{
764+
unsigned long now = jiffies;
765+
unsigned long reap_at = now + rxrpc_conn_idle_client_expiry;
766+
767+
if (rxnet->live)
768+
timer_reduce(&rxnet->client_conn_reap_timer, reap_at);
769+
}
770+
759771
/*
760772
* Disconnect a client call.
761773
*/
@@ -896,9 +908,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
896908
list_move_tail(&conn->cache_link, &rxnet->idle_client_conns);
897909
if (rxnet->idle_client_conns.next == &conn->cache_link &&
898910
!rxnet->kill_all_client_conns)
899-
queue_delayed_work(rxrpc_workqueue,
900-
&rxnet->client_conn_reaper,
901-
rxrpc_conn_idle_client_expiry);
911+
rxrpc_set_client_reap_timer(rxnet);
902912
} else {
903913
trace_rxrpc_client(conn, channel, rxrpc_client_to_inactive);
904914
conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
@@ -1036,8 +1046,7 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
10361046
{
10371047
struct rxrpc_connection *conn;
10381048
struct rxrpc_net *rxnet =
1039-
container_of(to_delayed_work(work),
1040-
struct rxrpc_net, client_conn_reaper);
1049+
container_of(work, struct rxrpc_net, client_conn_reaper);
10411050
unsigned long expiry, conn_expires_at, now;
10421051
unsigned int nr_conns;
10431052
bool did_discard = false;
@@ -1116,9 +1125,8 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
11161125
*/
11171126
_debug("not yet");
11181127
if (!rxnet->kill_all_client_conns)
1119-
queue_delayed_work(rxrpc_workqueue,
1120-
&rxnet->client_conn_reaper,
1121-
conn_expires_at - now);
1128+
timer_reduce(&rxnet->client_conn_reap_timer,
1129+
conn_expires_at);
11221130

11231131
out:
11241132
spin_unlock(&rxnet->client_conn_cache_lock);
@@ -1138,9 +1146,9 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
11381146
rxnet->kill_all_client_conns = true;
11391147
spin_unlock(&rxnet->client_conn_cache_lock);
11401148

1141-
cancel_delayed_work(&rxnet->client_conn_reaper);
1149+
del_timer_sync(&rxnet->client_conn_reap_timer);
11421150

1143-
if (!queue_delayed_work(rxrpc_workqueue, &rxnet->client_conn_reaper, 0))
1151+
if (!rxrpc_queue_work(&rxnet->client_conn_reaper))
11441152
_debug("destroy: queue failed");
11451153

11461154
_leave("");

net/rxrpc/conn_object.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,22 +310,30 @@ rxrpc_get_connection_maybe(struct rxrpc_connection *conn)
310310
return conn;
311311
}
312312

313+
/*
314+
* Set the service connection reap timer.
315+
*/
316+
static void rxrpc_set_service_reap_timer(struct rxrpc_net *rxnet,
317+
unsigned long reap_at)
318+
{
319+
if (rxnet->live)
320+
timer_reduce(&rxnet->service_conn_reap_timer, reap_at);
321+
}
322+
313323
/*
314324
* Release a service connection
315325
*/
316326
void rxrpc_put_service_conn(struct rxrpc_connection *conn)
317327
{
318-
struct rxrpc_net *rxnet;
319328
const void *here = __builtin_return_address(0);
320329
int n;
321330

322331
n = atomic_dec_return(&conn->usage);
323332
trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here);
324333
ASSERTCMP(n, >=, 0);
325-
if (n == 1) {
326-
rxnet = conn->params.local->rxnet;
327-
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, 0);
328-
}
334+
if (n == 1)
335+
rxrpc_set_service_reap_timer(conn->params.local->rxnet,
336+
jiffies + rxrpc_connection_expiry);
329337
}
330338

331339
/*
@@ -362,8 +370,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
362370
{
363371
struct rxrpc_connection *conn, *_p;
364372
struct rxrpc_net *rxnet =
365-
container_of(to_delayed_work(work),
366-
struct rxrpc_net, service_conn_reaper);
373+
container_of(work, struct rxrpc_net, service_conn_reaper);
367374
unsigned long expire_at, earliest, idle_timestamp, now;
368375

369376
LIST_HEAD(graveyard);
@@ -417,8 +424,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
417424
if (earliest != now + MAX_JIFFY_OFFSET) {
418425
_debug("reschedule reaper %ld", (long)earliest - (long)now);
419426
ASSERT(time_after(earliest, now));
420-
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper,
421-
earliest - now);
427+
rxrpc_set_service_reap_timer(rxnet, earliest);
422428
}
423429

424430
while (!list_empty(&graveyard)) {
@@ -446,8 +452,8 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
446452

447453
rxrpc_destroy_all_client_connections(rxnet);
448454

449-
cancel_delayed_work(&rxnet->client_conn_reaper);
450-
rxrpc_queue_delayed_work(&rxnet->client_conn_reaper, 0);
455+
del_timer_sync(&rxnet->service_conn_reap_timer);
456+
rxrpc_queue_work(&rxnet->service_conn_reaper);
451457
flush_workqueue(rxrpc_workqueue);
452458

453459
write_lock(&rxnet->conn_lock);

net/rxrpc/net_ns.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@
1414

1515
unsigned int rxrpc_net_id;
1616

17+
static void rxrpc_client_conn_reap_timeout(struct timer_list *timer)
18+
{
19+
struct rxrpc_net *rxnet =
20+
container_of(timer, struct rxrpc_net, client_conn_reap_timer);
21+
22+
if (rxnet->live)
23+
rxrpc_queue_work(&rxnet->client_conn_reaper);
24+
}
25+
26+
static void rxrpc_service_conn_reap_timeout(struct timer_list *timer)
27+
{
28+
struct rxrpc_net *rxnet =
29+
container_of(timer, struct rxrpc_net, service_conn_reap_timer);
30+
31+
if (rxnet->live)
32+
rxrpc_queue_work(&rxnet->service_conn_reaper);
33+
}
34+
1735
/*
1836
* Initialise a per-network namespace record.
1937
*/
@@ -32,8 +50,10 @@ static __net_init int rxrpc_init_net(struct net *net)
3250
INIT_LIST_HEAD(&rxnet->conn_proc_list);
3351
INIT_LIST_HEAD(&rxnet->service_conns);
3452
rwlock_init(&rxnet->conn_lock);
35-
INIT_DELAYED_WORK(&rxnet->service_conn_reaper,
36-
rxrpc_service_connection_reaper);
53+
INIT_WORK(&rxnet->service_conn_reaper,
54+
rxrpc_service_connection_reaper);
55+
timer_setup(&rxnet->service_conn_reap_timer,
56+
rxrpc_service_conn_reap_timeout, 0);
3757

3858
rxnet->nr_client_conns = 0;
3959
rxnet->nr_active_client_conns = 0;
@@ -43,8 +63,10 @@ static __net_init int rxrpc_init_net(struct net *net)
4363
INIT_LIST_HEAD(&rxnet->waiting_client_conns);
4464
INIT_LIST_HEAD(&rxnet->active_client_conns);
4565
INIT_LIST_HEAD(&rxnet->idle_client_conns);
46-
INIT_DELAYED_WORK(&rxnet->client_conn_reaper,
47-
rxrpc_discard_expired_client_conns);
66+
INIT_WORK(&rxnet->client_conn_reaper,
67+
rxrpc_discard_expired_client_conns);
68+
timer_setup(&rxnet->client_conn_reap_timer,
69+
rxrpc_client_conn_reap_timeout, 0);
4870

4971
INIT_LIST_HEAD(&rxnet->local_endpoints);
5072
mutex_init(&rxnet->local_mutex);

0 commit comments

Comments
 (0)