diff options
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 3 | ||||
-rw-r--r-- | net/rxrpc/ar-internal.h | 1 | ||||
-rw-r--r-- | net/rxrpc/conn_client.c | 44 | ||||
-rw-r--r-- | net/rxrpc/conn_object.c | 2 | ||||
-rw-r--r-- | net/rxrpc/local_object.c | 5 |
5 files changed, 50 insertions, 5 deletions
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 0dbbfd1b6487..d72ddb67bb74 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk) | |||
862 | static int rxrpc_release_sock(struct sock *sk) | 862 | static int rxrpc_release_sock(struct sock *sk) |
863 | { | 863 | { |
864 | struct rxrpc_sock *rx = rxrpc_sk(sk); | 864 | struct rxrpc_sock *rx = rxrpc_sk(sk); |
865 | struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); | ||
866 | 865 | ||
867 | _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); | 866 | _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); |
868 | 867 | ||
@@ -898,8 +897,6 @@ static int rxrpc_release_sock(struct sock *sk) | |||
898 | rxrpc_release_calls_on_socket(rx); | 897 | rxrpc_release_calls_on_socket(rx); |
899 | flush_workqueue(rxrpc_workqueue); | 898 | flush_workqueue(rxrpc_workqueue); |
900 | rxrpc_purge_queue(&sk->sk_receive_queue); | 899 | rxrpc_purge_queue(&sk->sk_receive_queue); |
901 | rxrpc_queue_work(&rxnet->service_conn_reaper); | ||
902 | rxrpc_queue_work(&rxnet->client_conn_reaper); | ||
903 | 900 | ||
904 | rxrpc_unuse_local(rx->local); | 901 | rxrpc_unuse_local(rx->local); |
905 | rx->local = NULL; | 902 | rx->local = NULL; |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 852e58781fda..8051dfdcf26d 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -910,6 +910,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *); | |||
910 | void rxrpc_put_client_conn(struct rxrpc_connection *); | 910 | void rxrpc_put_client_conn(struct rxrpc_connection *); |
911 | void rxrpc_discard_expired_client_conns(struct work_struct *); | 911 | void rxrpc_discard_expired_client_conns(struct work_struct *); |
912 | void rxrpc_destroy_all_client_connections(struct rxrpc_net *); | 912 | void rxrpc_destroy_all_client_connections(struct rxrpc_net *); |
913 | void rxrpc_clean_up_local_conns(struct rxrpc_local *); | ||
913 | 914 | ||
914 | /* | 915 | /* |
915 | * conn_event.c | 916 | * conn_event.c |
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index aea82f909c60..3f1da1b49f69 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c | |||
@@ -1162,3 +1162,47 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet) | |||
1162 | 1162 | ||
1163 | _leave(""); | 1163 | _leave(""); |
1164 | } | 1164 | } |
1165 | |||
1166 | /* | ||
1167 | * Clean up the client connections on a local endpoint. | ||
1168 | */ | ||
1169 | void rxrpc_clean_up_local_conns(struct rxrpc_local *local) | ||
1170 | { | ||
1171 | struct rxrpc_connection *conn, *tmp; | ||
1172 | struct rxrpc_net *rxnet = local->rxnet; | ||
1173 | unsigned int nr_active; | ||
1174 | LIST_HEAD(graveyard); | ||
1175 | |||
1176 | _enter(""); | ||
1177 | |||
1178 | spin_lock(&rxnet->client_conn_cache_lock); | ||
1179 | nr_active = rxnet->nr_active_client_conns; | ||
1180 | |||
1181 | list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns, | ||
1182 | cache_link) { | ||
1183 | if (conn->params.local == local) { | ||
1184 | ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE); | ||
1185 | |||
1186 | trace_rxrpc_client(conn, -1, rxrpc_client_discard); | ||
1187 | if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags)) | ||
1188 | BUG(); | ||
1189 | conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE; | ||
1190 | list_move(&conn->cache_link, &graveyard); | ||
1191 | nr_active--; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | rxnet->nr_active_client_conns = nr_active; | ||
1196 | spin_unlock(&rxnet->client_conn_cache_lock); | ||
1197 | ASSERTCMP(nr_active, >=, 0); | ||
1198 | |||
1199 | while (!list_empty(&graveyard)) { | ||
1200 | conn = list_entry(graveyard.next, | ||
1201 | struct rxrpc_connection, cache_link); | ||
1202 | list_del_init(&conn->cache_link); | ||
1203 | |||
1204 | rxrpc_put_connection(conn); | ||
1205 | } | ||
1206 | |||
1207 | _leave(" [culled]"); | ||
1208 | } | ||
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 434ef392212b..ed05b6922132 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c | |||
@@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) | |||
398 | if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) | 398 | if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) |
399 | continue; | 399 | continue; |
400 | 400 | ||
401 | if (rxnet->live) { | 401 | if (rxnet->live && !conn->params.local->dead) { |
402 | idle_timestamp = READ_ONCE(conn->idle_timestamp); | 402 | idle_timestamp = READ_ONCE(conn->idle_timestamp); |
403 | expire_at = idle_timestamp + rxrpc_connection_expiry * HZ; | 403 | expire_at = idle_timestamp + rxrpc_connection_expiry * HZ; |
404 | if (conn->params.local->service_closed) | 404 | if (conn->params.local->service_closed) |
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 72a6e12a9304..36587260cabd 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c | |||
@@ -426,11 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local) | |||
426 | 426 | ||
427 | _enter("%d", local->debug_id); | 427 | _enter("%d", local->debug_id); |
428 | 428 | ||
429 | local->dead = true; | ||
430 | |||
429 | mutex_lock(&rxnet->local_mutex); | 431 | mutex_lock(&rxnet->local_mutex); |
430 | list_del_init(&local->link); | 432 | list_del_init(&local->link); |
431 | mutex_unlock(&rxnet->local_mutex); | 433 | mutex_unlock(&rxnet->local_mutex); |
432 | 434 | ||
433 | ASSERT(RB_EMPTY_ROOT(&local->client_conns)); | 435 | rxrpc_clean_up_local_conns(local); |
436 | rxrpc_service_connection_reaper(&rxnet->service_conn_reaper); | ||
434 | ASSERT(!local->service); | 437 | ASSERT(!local->service); |
435 | 438 | ||
436 | if (socket) { | 439 | if (socket) { |