aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-09-17 05:49:12 -0400
committerDavid Howells <dhowells@redhat.com>2016-09-17 05:53:20 -0400
commit66d58af7f4af53e8318e852efa31a7cb0e31bfb6 (patch)
tree8641f5171ac22ca4742be90e2c757715fe16e0e4
parent0360da6db7d6390e7bd2f6c93b01af29bcd36ad5 (diff)
rxrpc: Fix the putting of client connections
In rxrpc_put_one_client_conn(), if a connection has RXRPC_CONN_COUNTED set on it, then it's accounted for in rxrpc_nr_client_conns and may be on various lists - and this is cleaned up correctly. However, if the connection doesn't have RXRPC_CONN_COUNTED set on it, then the put routine returns rather than just skipping the extra bit of cleanup. Fix this by making the extra bit of clean up conditional instead and always killing off the connection. This manifests itself as connections with a zero usage count hanging around in /proc/net/rxrpc_conns because the connection allocated, but discarded, due to a race with another process that set up a parallel connection, which was then shared instead. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/conn_client.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 9344a8416ceb..5a675c43cace 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -818,7 +818,7 @@ idle_connection:
818static struct rxrpc_connection * 818static struct rxrpc_connection *
819rxrpc_put_one_client_conn(struct rxrpc_connection *conn) 819rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
820{ 820{
821 struct rxrpc_connection *next; 821 struct rxrpc_connection *next = NULL;
822 struct rxrpc_local *local = conn->params.local; 822 struct rxrpc_local *local = conn->params.local;
823 unsigned int nr_conns; 823 unsigned int nr_conns;
824 824
@@ -834,24 +834,22 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
834 834
835 ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_INACTIVE); 835 ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_INACTIVE);
836 836
837 if (!test_bit(RXRPC_CONN_COUNTED, &conn->flags)) 837 if (test_bit(RXRPC_CONN_COUNTED, &conn->flags)) {
838 return NULL; 838 spin_lock(&rxrpc_client_conn_cache_lock);
839 839 nr_conns = --rxrpc_nr_client_conns;
840 spin_lock(&rxrpc_client_conn_cache_lock); 840
841 nr_conns = --rxrpc_nr_client_conns; 841 if (nr_conns < rxrpc_max_client_connections &&
842 !list_empty(&rxrpc_waiting_client_conns)) {
843 next = list_entry(rxrpc_waiting_client_conns.next,
844 struct rxrpc_connection, cache_link);
845 rxrpc_get_connection(next);
846 rxrpc_activate_conn(next);
847 }
842 848
843 next = NULL; 849 spin_unlock(&rxrpc_client_conn_cache_lock);
844 if (nr_conns < rxrpc_max_client_connections &&
845 !list_empty(&rxrpc_waiting_client_conns)) {
846 next = list_entry(rxrpc_waiting_client_conns.next,
847 struct rxrpc_connection, cache_link);
848 rxrpc_get_connection(next);
849 rxrpc_activate_conn(next);
850 } 850 }
851 851
852 spin_unlock(&rxrpc_client_conn_cache_lock);
853 rxrpc_kill_connection(conn); 852 rxrpc_kill_connection(conn);
854
855 if (next) 853 if (next)
856 rxrpc_activate_channels(next); 854 rxrpc_activate_channels(next);
857 855