|
@@ -56,6 +56,7 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
|
|
|
atomic_set(&conn->avail_chans, RXRPC_MAXCALLS);
|
|
|
conn->size_align = 4;
|
|
|
conn->header_size = sizeof(struct rxrpc_wire_header);
|
|
|
+ conn->idle_timestamp = jiffies;
|
|
|
}
|
|
|
|
|
|
_leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
|
|
@@ -191,29 +192,16 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
|
|
|
spin_unlock(&conn->channel_lock);
|
|
|
|
|
|
call->conn = NULL;
|
|
|
+ conn->idle_timestamp = jiffies;
|
|
|
rxrpc_put_connection(conn);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* release a virtual connection
|
|
|
*/
|
|
|
-void rxrpc_put_connection(struct rxrpc_connection *conn)
|
|
|
+void __rxrpc_put_connection(struct rxrpc_connection *conn)
|
|
|
{
|
|
|
- if (!conn)
|
|
|
- return;
|
|
|
-
|
|
|
- _enter("%p{u=%d,d=%d}",
|
|
|
- conn, atomic_read(&conn->usage), conn->debug_id);
|
|
|
-
|
|
|
- ASSERTCMP(atomic_read(&conn->usage), >, 1);
|
|
|
-
|
|
|
- conn->put_time = ktime_get_seconds();
|
|
|
- if (atomic_dec_return(&conn->usage) == 1) {
|
|
|
- _debug("zombie");
|
|
|
- rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
|
|
|
- }
|
|
|
-
|
|
|
- _leave("");
|
|
|
+ rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -248,14 +236,14 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
|
|
|
static void rxrpc_connection_reaper(struct work_struct *work)
|
|
|
{
|
|
|
struct rxrpc_connection *conn, *_p;
|
|
|
- unsigned long reap_older_than, earliest, put_time, now;
|
|
|
+ unsigned long reap_older_than, earliest, idle_timestamp, now;
|
|
|
|
|
|
LIST_HEAD(graveyard);
|
|
|
|
|
|
_enter("");
|
|
|
|
|
|
- now = ktime_get_seconds();
|
|
|
- reap_older_than = now - rxrpc_connection_expiry;
|
|
|
+ now = jiffies;
|
|
|
+ reap_older_than = now - rxrpc_connection_expiry * HZ;
|
|
|
earliest = ULONG_MAX;
|
|
|
|
|
|
write_lock(&rxrpc_connection_lock);
|
|
@@ -264,10 +252,14 @@ static void rxrpc_connection_reaper(struct work_struct *work)
|
|
|
if (likely(atomic_read(&conn->usage) > 1))
|
|
|
continue;
|
|
|
|
|
|
- put_time = READ_ONCE(conn->put_time);
|
|
|
- if (time_after(put_time, reap_older_than)) {
|
|
|
- if (time_before(put_time, earliest))
|
|
|
- earliest = put_time;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
@@ -288,9 +280,9 @@ static void rxrpc_connection_reaper(struct work_struct *work)
|
|
|
|
|
|
if (earliest != ULONG_MAX) {
|
|
|
_debug("reschedule reaper %ld", (long) earliest - now);
|
|
|
- ASSERTCMP(earliest, >, now);
|
|
|
+ ASSERT(time_after(earliest, now));
|
|
|
rxrpc_queue_delayed_work(&rxrpc_connection_reap,
|
|
|
- (earliest - now) * HZ);
|
|
|
+ earliest - now);
|
|
|
}
|
|
|
|
|
|
while (!list_empty(&graveyard)) {
|