Skip to content

Commit f859ab6

Browse files
committed
rxrpc: Fix service endpoint expiry
RxRPC service endpoints expire like they're supposed to by the following means: (1) Mark dead rxrpc_net structs (with ->live) rather than twiddling the global service conn timeout, otherwise the first rxrpc_net struct to die will cause connections on all others to expire immediately from then on. (2) Mark local service endpoints for which the socket has been closed (->service_closed) so that the expiration timeout can be much shortened for service and client connections going through that endpoint. (3) rxrpc_put_service_conn() needs to schedule the reaper when the usage count reaches 1, not 0, as idle conns have a 1 count. (4) The accumulator for the earliest time we might want to schedule for should be initialised to jiffies + MAX_JIFFY_OFFSET, not ULONG_MAX as the comparison functions use signed arithmetic. (5) Simplify the expiration handling, adding the expiration value to the idle timestamp each time rather than keeping track of the time in the past before which the idle timestamp must go to be expired. This is much easier to read. (6) Ignore the timeouts if the net namespace is dead. (7) Restart the service reaper work item rather the client reaper. Signed-off-by: David Howells <[email protected]>
1 parent 415f44e commit f859ab6

File tree

6 files changed

+47
-18
lines changed

6 files changed

+47
-18
lines changed

include/trace/events/rxrpc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum rxrpc_conn_trace {
4949
rxrpc_conn_put_client,
5050
rxrpc_conn_put_service,
5151
rxrpc_conn_queued,
52+
rxrpc_conn_reap_service,
5253
rxrpc_conn_seen,
5354
};
5455

@@ -221,6 +222,7 @@ enum rxrpc_congest_change {
221222
EM(rxrpc_conn_put_client, "PTc") \
222223
EM(rxrpc_conn_put_service, "PTs") \
223224
EM(rxrpc_conn_queued, "QUE") \
225+
EM(rxrpc_conn_reap_service, "RPs") \
224226
E_(rxrpc_conn_seen, "SEE")
225227

226228
#define rxrpc_client_traces \

net/rxrpc/af_rxrpc.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,19 @@ static int rxrpc_release_sock(struct sock *sk)
867867
sock_orphan(sk);
868868
sk->sk_shutdown = SHUTDOWN_MASK;
869869

870+
/* We want to kill off all connections from a service socket
871+
* as fast as possible because we can't share these; client
872+
* sockets, on the other hand, can share an endpoint.
873+
*/
874+
switch (sk->sk_state) {
875+
case RXRPC_SERVER_BOUND:
876+
case RXRPC_SERVER_BOUND2:
877+
case RXRPC_SERVER_LISTENING:
878+
case RXRPC_SERVER_LISTEN_DISABLED:
879+
rx->local->service_closed = true;
880+
break;
881+
}
882+
870883
spin_lock_bh(&sk->sk_receive_queue.lock);
871884
sk->sk_state = RXRPC_CLOSE;
872885
spin_unlock_bh(&sk->sk_receive_queue.lock);

net/rxrpc/ar-internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct rxrpc_net {
8484
unsigned int nr_client_conns;
8585
unsigned int nr_active_client_conns;
8686
bool kill_all_client_conns;
87+
bool live;
8788
spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */
8889
spinlock_t client_conn_discard_lock; /* Prevent multiple discarders */
8990
struct list_head waiting_client_conns;
@@ -265,6 +266,7 @@ struct rxrpc_local {
265266
rwlock_t services_lock; /* lock for services list */
266267
int debug_id; /* debug ID for printks */
267268
bool dead;
269+
bool service_closed; /* Service socket closed */
268270
struct sockaddr_rxrpc srx; /* local address */
269271
};
270272

@@ -881,6 +883,7 @@ void rxrpc_process_connection(struct work_struct *);
881883
* conn_object.c
882884
*/
883885
extern unsigned int rxrpc_connection_expiry;
886+
extern unsigned int rxrpc_closed_conn_expiry;
884887

885888
struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
886889
struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *,

net/rxrpc/conn_client.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,8 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
10791079
expiry = rxrpc_conn_idle_client_expiry;
10801080
if (nr_conns > rxrpc_reap_client_connections)
10811081
expiry = rxrpc_conn_idle_client_fast_expiry;
1082+
if (conn->params.local->service_closed)
1083+
expiry = rxrpc_closed_conn_expiry * HZ;
10821084

10831085
conn_expires_at = conn->idle_timestamp + expiry;
10841086

net/rxrpc/conn_object.c

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
/*
2121
* Time till a connection expires after last use (in seconds).
2222
*/
23-
unsigned int rxrpc_connection_expiry = 10 * 60;
23+
unsigned int __read_mostly rxrpc_connection_expiry = 10 * 60;
24+
unsigned int __read_mostly rxrpc_closed_conn_expiry = 10;
2425

2526
static void rxrpc_destroy_connection(struct rcu_head *);
2627

@@ -321,7 +322,7 @@ void rxrpc_put_service_conn(struct rxrpc_connection *conn)
321322
n = atomic_dec_return(&conn->usage);
322323
trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here);
323324
ASSERTCMP(n, >=, 0);
324-
if (n == 0) {
325+
if (n == 1) {
325326
rxnet = conn->params.local->rxnet;
326327
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, 0);
327328
}
@@ -363,15 +364,14 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
363364
struct rxrpc_net *rxnet =
364365
container_of(to_delayed_work(work),
365366
struct rxrpc_net, service_conn_reaper);
366-
unsigned long reap_older_than, earliest, idle_timestamp, now;
367+
unsigned long expire_at, earliest, idle_timestamp, now;
367368

368369
LIST_HEAD(graveyard);
369370

370371
_enter("");
371372

372373
now = jiffies;
373-
reap_older_than = now - rxrpc_connection_expiry * HZ;
374-
earliest = ULONG_MAX;
374+
earliest = now + MAX_JIFFY_OFFSET;
375375

376376
write_lock(&rxnet->conn_lock);
377377
list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) {
@@ -381,22 +381,29 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
381381
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
382382
continue;
383383

384-
idle_timestamp = READ_ONCE(conn->idle_timestamp);
385-
_debug("reap CONN %d { u=%d,t=%ld }",
386-
conn->debug_id, atomic_read(&conn->usage),
387-
(long)reap_older_than - (long)idle_timestamp);
388-
389-
if (time_after(idle_timestamp, reap_older_than)) {
390-
if (time_before(idle_timestamp, earliest))
391-
earliest = idle_timestamp;
392-
continue;
384+
if (rxnet->live) {
385+
idle_timestamp = READ_ONCE(conn->idle_timestamp);
386+
expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
387+
if (conn->params.local->service_closed)
388+
expire_at = idle_timestamp + rxrpc_closed_conn_expiry * HZ;
389+
390+
_debug("reap CONN %d { u=%d,t=%ld }",
391+
conn->debug_id, atomic_read(&conn->usage),
392+
(long)expire_at - (long)now);
393+
394+
if (time_before(now, expire_at)) {
395+
if (time_before(expire_at, earliest))
396+
earliest = expire_at;
397+
continue;
398+
}
393399
}
394400

395401
/* The usage count sits at 1 whilst the object is unused on the
396402
* list; we reduce that to 0 to make the object unavailable.
397403
*/
398404
if (atomic_cmpxchg(&conn->usage, 1, 0) != 1)
399405
continue;
406+
trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, 0);
400407

401408
if (rxrpc_conn_is_client(conn))
402409
BUG();
@@ -407,10 +414,10 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
407414
}
408415
write_unlock(&rxnet->conn_lock);
409416

410-
if (earliest != ULONG_MAX) {
411-
_debug("reschedule reaper %ld", (long) earliest - now);
417+
if (earliest != now + MAX_JIFFY_OFFSET) {
418+
_debug("reschedule reaper %ld", (long)earliest - (long)now);
412419
ASSERT(time_after(earliest, now));
413-
rxrpc_queue_delayed_work(&rxnet->client_conn_reaper,
420+
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper,
414421
earliest - now);
415422
}
416423

@@ -439,7 +446,6 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
439446

440447
rxrpc_destroy_all_client_connections(rxnet);
441448

442-
rxrpc_connection_expiry = 0;
443449
cancel_delayed_work(&rxnet->client_conn_reaper);
444450
rxrpc_queue_delayed_work(&rxnet->client_conn_reaper, 0);
445451
flush_workqueue(rxrpc_workqueue);

net/rxrpc/net_ns.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static __net_init int rxrpc_init_net(struct net *net)
2222
struct rxrpc_net *rxnet = rxrpc_net(net);
2323
int ret;
2424

25+
rxnet->live = true;
2526
get_random_bytes(&rxnet->epoch, sizeof(rxnet->epoch));
2627
rxnet->epoch |= RXRPC_RANDOM_EPOCH;
2728

@@ -60,6 +61,7 @@ static __net_init int rxrpc_init_net(struct net *net)
6061
return 0;
6162

6263
err_proc:
64+
rxnet->live = false;
6365
return ret;
6466
}
6567

@@ -70,6 +72,7 @@ static __net_exit void rxrpc_exit_net(struct net *net)
7072
{
7173
struct rxrpc_net *rxnet = rxrpc_net(net);
7274

75+
rxnet->live = false;
7376
rxrpc_destroy_all_calls(rxnet);
7477
rxrpc_destroy_all_connections(rxnet);
7578
rxrpc_destroy_all_locals(rxnet);

0 commit comments

Comments
 (0)