rxrpc: Check that the client conns cache is empty before module removal
authorDavid Howells <dhowells@redhat.com>
Mon, 27 Jun 2016 09:32:02 +0000 (10:32 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 6 Jul 2016 09:43:51 +0000 (10:43 +0100)
Check that the client conns cache is empty before module removal and bug if
not, listing any offending connections that are still present.  Unfortunately,
if there are connections still around, then the transport socket is still
unexpectedly open and active, so we can't just unallocate the connections.

Signed-off-by: David Howells <dhowells@redhat.com>
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/conn_client.c

index 5d3e795a7c48de2f70b0f037968fe410632fb985..d5073eb02498bfc48a3d256c4f15f0611342aa27 100644 (file)
@@ -807,8 +807,7 @@ static void __exit af_rxrpc_exit(void)
        _debug("synchronise RCU");
        rcu_barrier();
        _debug("destroy locals");
-       ASSERT(idr_is_empty(&rxrpc_client_conn_ids));
-       idr_destroy(&rxrpc_client_conn_ids);
+       rxrpc_destroy_client_conn_ids();
        rxrpc_destroy_all_locals();
 
        remove_proc_entry("rxrpc_conns", init_net.proc_net);
index 3f0d0479a4dae43d7d7f20f0f1102b4a0d61c82e..6583a8399c893ca332c9d004b6f8dd3a1d38580f 100644 (file)
@@ -541,6 +541,7 @@ extern struct idr rxrpc_client_conn_ids;
 
 int rxrpc_get_client_connection_id(struct rxrpc_connection *, gfp_t);
 void rxrpc_put_client_connection_id(struct rxrpc_connection *);
+void rxrpc_destroy_client_conn_ids(void);
 
 /*
  * conn_event.c
index 82488d6adb8367f13625bbeee71f62dccc76e733..be437d5e90ce180b98f2028d655e73736154f75a 100644 (file)
@@ -92,3 +92,22 @@ void rxrpc_put_client_connection_id(struct rxrpc_connection *conn)
                spin_unlock(&rxrpc_conn_id_lock);
        }
 }
+
+/*
+ * Destroy the client connection ID tree.
+ */
+void rxrpc_destroy_client_conn_ids(void)
+{
+       struct rxrpc_connection *conn;
+       int id;
+
+       if (!idr_is_empty(&rxrpc_client_conn_ids)) {
+               idr_for_each_entry(&rxrpc_client_conn_ids, conn, id) {
+                       pr_err("AF_RXRPC: Leaked client conn %p {%d}\n",
+                              conn, atomic_read(&conn->usage));
+               }
+               BUG();
+       }
+
+       idr_destroy(&rxrpc_client_conn_ids);
+}