|
@@ -20,7 +20,8 @@
|
|
|
/*
|
|
|
* Time till a connection expires after last use (in seconds).
|
|
|
*/
|
|
|
-unsigned int rxrpc_connection_expiry = 10 * 60;
|
|
|
+unsigned int __read_mostly rxrpc_connection_expiry = 10 * 60;
|
|
|
+unsigned int __read_mostly rxrpc_closed_conn_expiry = 10;
|
|
|
|
|
|
static void rxrpc_destroy_connection(struct rcu_head *);
|
|
|
|
|
@@ -321,7 +322,7 @@ void rxrpc_put_service_conn(struct rxrpc_connection *conn)
|
|
|
n = atomic_dec_return(&conn->usage);
|
|
|
trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here);
|
|
|
ASSERTCMP(n, >=, 0);
|
|
|
- if (n == 0) {
|
|
|
+ if (n == 1) {
|
|
|
rxnet = conn->params.local->rxnet;
|
|
|
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, 0);
|
|
|
}
|
|
@@ -363,15 +364,14 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
|
|
|
struct rxrpc_net *rxnet =
|
|
|
container_of(to_delayed_work(work),
|
|
|
struct rxrpc_net, service_conn_reaper);
|
|
|
- unsigned long reap_older_than, earliest, idle_timestamp, now;
|
|
|
+ unsigned long expire_at, earliest, idle_timestamp, now;
|
|
|
|
|
|
LIST_HEAD(graveyard);
|
|
|
|
|
|
_enter("");
|
|
|
|
|
|
now = jiffies;
|
|
|
- reap_older_than = now - rxrpc_connection_expiry * HZ;
|
|
|
- earliest = ULONG_MAX;
|
|
|
+ earliest = now + MAX_JIFFY_OFFSET;
|
|
|
|
|
|
write_lock(&rxnet->conn_lock);
|
|
|
list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) {
|
|
@@ -381,15 +381,21 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
|
|
|
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
|
|
|
continue;
|
|
|
|
|
|
- idle_timestamp = READ_ONCE(conn->idle_timestamp);
|
|
|
- _debug("reap CONN %d { u=%d,t=%ld }",
|
|
|
- conn->debug_id, atomic_read(&conn->usage),
|
|
|
- (long)reap_older_than - (long)idle_timestamp);
|
|
|
-
|
|
|
- if (time_after(idle_timestamp, reap_older_than)) {
|
|
|
- if (time_before(idle_timestamp, earliest))
|
|
|
- earliest = idle_timestamp;
|
|
|
- continue;
|
|
|
+ if (rxnet->live) {
|
|
|
+ idle_timestamp = READ_ONCE(conn->idle_timestamp);
|
|
|
+ expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
|
|
|
+ if (conn->params.local->service_closed)
|
|
|
+ expire_at = idle_timestamp + rxrpc_closed_conn_expiry * HZ;
|
|
|
+
|
|
|
+ _debug("reap CONN %d { u=%d,t=%ld }",
|
|
|
+ conn->debug_id, atomic_read(&conn->usage),
|
|
|
+ (long)expire_at - (long)now);
|
|
|
+
|
|
|
+ if (time_before(now, expire_at)) {
|
|
|
+ if (time_before(expire_at, earliest))
|
|
|
+ earliest = expire_at;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* The usage count sits at 1 whilst the object is unused on the
|
|
@@ -397,6 +403,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
|
|
|
*/
|
|
|
if (atomic_cmpxchg(&conn->usage, 1, 0) != 1)
|
|
|
continue;
|
|
|
+ trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, 0);
|
|
|
|
|
|
if (rxrpc_conn_is_client(conn))
|
|
|
BUG();
|
|
@@ -407,10 +414,10 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
|
|
|
}
|
|
|
write_unlock(&rxnet->conn_lock);
|
|
|
|
|
|
- if (earliest != ULONG_MAX) {
|
|
|
- _debug("reschedule reaper %ld", (long) earliest - now);
|
|
|
+ if (earliest != now + MAX_JIFFY_OFFSET) {
|
|
|
+ _debug("reschedule reaper %ld", (long)earliest - (long)now);
|
|
|
ASSERT(time_after(earliest, now));
|
|
|
- rxrpc_queue_delayed_work(&rxnet->client_conn_reaper,
|
|
|
+ rxrpc_queue_delayed_work(&rxnet->service_conn_reaper,
|
|
|
earliest - now);
|
|
|
}
|
|
|
|
|
@@ -439,7 +446,6 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
|
|
|
|
|
|
rxrpc_destroy_all_client_connections(rxnet);
|
|
|
|
|
|
- rxrpc_connection_expiry = 0;
|
|
|
cancel_delayed_work(&rxnet->client_conn_reaper);
|
|
|
rxrpc_queue_delayed_work(&rxnet->client_conn_reaper, 0);
|
|
|
flush_workqueue(rxrpc_workqueue);
|