Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc: Move the client conn cache management to the I/O thread

Move the management of the client connection cache to the I/O thread rather
than managing it from the namespace as an aggregate across all the local
endpoints within the namespace.

This will allow a load of locking to be got rid of in a future patch as
only the I/O thread will be looking at the this.

The downside is that the total number of cached connections on the system
can get higher because the limit is now per-local rather than per-netns.
We can, however, keep the number of client conns in use across the entire
netfs and use that to reduce the expiration time of idle connection.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org

+62 -86
+9 -8
net/rxrpc/ar-internal.h
··· 76 76 77 77 bool live; 78 78 79 - bool kill_all_client_conns; 80 79 atomic_t nr_client_conns; 81 - spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */ 82 - struct mutex client_conn_discard_lock; /* Prevent multiple discarders */ 83 - struct list_head idle_client_conns; 84 - struct work_struct client_conn_reaper; 85 - struct timer_list client_conn_reap_timer; 86 80 87 81 struct hlist_head local_endpoints; 88 82 struct mutex local_mutex; /* Lock for ->local_endpoints */ ··· 288 294 struct sk_buff_head rx_queue; /* Received packets */ 289 295 struct list_head conn_attend_q; /* Conns requiring immediate attention */ 290 296 struct list_head call_attend_q; /* Calls requiring immediate attention */ 297 + 291 298 struct rb_root client_bundles; /* Client connection bundles by socket params */ 292 299 spinlock_t client_bundles_lock; /* Lock for client_bundles */ 300 + bool kill_all_client_conns; 301 + spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */ 302 + struct list_head idle_client_conns; 303 + struct timer_list client_conn_reap_timer; 304 + unsigned long client_conn_flags; 305 + #define RXRPC_CLIENT_CONN_REAP_TIMER 0 /* The client conn reap timer expired */ 306 + 293 307 spinlock_t lock; /* access lock */ 294 308 rwlock_t services_lock; /* lock for services list */ 295 309 int debug_id; /* debug ID for printks */ ··· 948 946 void rxrpc_disconnect_client_call(struct rxrpc_bundle *, struct rxrpc_call *); 949 947 void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle); 950 948 void rxrpc_put_client_conn(struct rxrpc_connection *, enum rxrpc_conn_trace); 951 - void rxrpc_discard_expired_client_conns(struct work_struct *); 952 - void rxrpc_destroy_all_client_connections(struct rxrpc_net *); 949 + void rxrpc_discard_expired_client_conns(struct rxrpc_local *local); 953 950 void rxrpc_clean_up_local_conns(struct rxrpc_local *); 954 951 955 952 /*
+32 -60
net/rxrpc/conn_client.c
··· 578 578 */ 579 579 static void rxrpc_unidle_conn(struct rxrpc_bundle *bundle, struct rxrpc_connection *conn) 580 580 { 581 - struct rxrpc_net *rxnet = bundle->local->rxnet; 581 + struct rxrpc_local *local = bundle->local; 582 582 bool drop_ref; 583 583 584 584 if (!list_empty(&conn->cache_link)) { 585 585 drop_ref = false; 586 - spin_lock(&rxnet->client_conn_cache_lock); 586 + spin_lock(&local->client_conn_cache_lock); 587 587 if (!list_empty(&conn->cache_link)) { 588 588 list_del_init(&conn->cache_link); 589 589 drop_ref = true; 590 590 } 591 - spin_unlock(&rxnet->client_conn_cache_lock); 591 + spin_unlock(&local->client_conn_cache_lock); 592 592 if (drop_ref) 593 593 rxrpc_put_connection(conn, rxrpc_conn_put_unidle); 594 594 } ··· 710 710 int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp) 711 711 { 712 712 struct rxrpc_bundle *bundle; 713 - struct rxrpc_local *local = call->local; 714 - struct rxrpc_net *rxnet = local->rxnet; 715 713 int ret = 0; 716 714 717 715 _enter("{%d,%lx},", call->debug_id, call->user_call_ID); 718 - 719 - rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper); 720 716 721 717 rxrpc_get_call(call, rxrpc_call_get_io_thread); 722 718 ··· 783 787 /* 784 788 * Set the reap timer. 785 789 */ 786 - static void rxrpc_set_client_reap_timer(struct rxrpc_net *rxnet) 790 + static void rxrpc_set_client_reap_timer(struct rxrpc_local *local) 787 791 { 788 - if (!rxnet->kill_all_client_conns) { 792 + if (!local->kill_all_client_conns) { 789 793 unsigned long now = jiffies; 790 794 unsigned long reap_at = now + rxrpc_conn_idle_client_expiry; 791 795 792 - if (rxnet->live) 793 - timer_reduce(&rxnet->client_conn_reap_timer, reap_at); 796 + if (local->rxnet->live) 797 + timer_reduce(&local->client_conn_reap_timer, reap_at); 794 798 } 795 799 } 796 800 ··· 801 805 { 802 806 struct rxrpc_connection *conn; 803 807 struct rxrpc_channel *chan = NULL; 804 - struct rxrpc_net *rxnet = bundle->local->rxnet; 808 + struct rxrpc_local *local = bundle->local; 805 809 unsigned int channel; 806 810 bool may_reuse; 807 811 u32 cid; ··· 891 895 conn->idle_timestamp = jiffies; 892 896 893 897 rxrpc_get_connection(conn, rxrpc_conn_get_idle); 894 - spin_lock(&rxnet->client_conn_cache_lock); 895 - list_move_tail(&conn->cache_link, &rxnet->idle_client_conns); 896 - spin_unlock(&rxnet->client_conn_cache_lock); 898 + spin_lock(&local->client_conn_cache_lock); 899 + list_move_tail(&conn->cache_link, &local->idle_client_conns); 900 + spin_unlock(&local->client_conn_cache_lock); 897 901 898 - rxrpc_set_client_reap_timer(rxnet); 902 + rxrpc_set_client_reap_timer(local); 899 903 } 900 904 901 905 out: ··· 982 986 * This may be called from conn setup or from a work item so cannot be 983 987 * considered non-reentrant. 984 988 */ 985 - void rxrpc_discard_expired_client_conns(struct work_struct *work) 989 + void rxrpc_discard_expired_client_conns(struct rxrpc_local *local) 986 990 { 987 991 struct rxrpc_connection *conn; 988 - struct rxrpc_net *rxnet = 989 - container_of(work, struct rxrpc_net, client_conn_reaper); 990 992 unsigned long expiry, conn_expires_at, now; 991 993 unsigned int nr_conns; 992 994 993 995 _enter(""); 994 996 995 - if (list_empty(&rxnet->idle_client_conns)) { 997 + if (list_empty(&local->idle_client_conns)) { 996 998 _leave(" [empty]"); 997 - return; 998 - } 999 - 1000 - /* Don't double up on the discarding */ 1001 - if (!mutex_trylock(&rxnet->client_conn_discard_lock)) { 1002 - _leave(" [already]"); 1003 999 return; 1004 1000 } 1005 1001 1006 1002 /* We keep an estimate of what the number of conns ought to be after 1007 1003 * we've discarded some so that we don't overdo the discarding. 1008 1004 */ 1009 - nr_conns = atomic_read(&rxnet->nr_client_conns); 1005 + nr_conns = atomic_read(&local->rxnet->nr_client_conns); 1010 1006 1011 1007 next: 1012 - spin_lock(&rxnet->client_conn_cache_lock); 1008 + spin_lock(&local->client_conn_cache_lock); 1013 1009 1014 - if (list_empty(&rxnet->idle_client_conns)) 1010 + if (list_empty(&local->idle_client_conns)) 1015 1011 goto out; 1016 1012 1017 - conn = list_entry(rxnet->idle_client_conns.next, 1013 + conn = list_entry(local->idle_client_conns.next, 1018 1014 struct rxrpc_connection, cache_link); 1019 1015 1020 - if (!rxnet->kill_all_client_conns) { 1016 + if (!local->kill_all_client_conns) { 1021 1017 /* If the number of connections is over the reap limit, we 1022 1018 * expedite discard by reducing the expiry timeout. We must, 1023 1019 * however, have at least a short grace period to be able to do ··· 1032 1044 trace_rxrpc_client(conn, -1, rxrpc_client_discard); 1033 1045 list_del_init(&conn->cache_link); 1034 1046 1035 - spin_unlock(&rxnet->client_conn_cache_lock); 1047 + spin_unlock(&local->client_conn_cache_lock); 1036 1048 1037 1049 rxrpc_unbundle_conn(conn); 1038 1050 /* Drop the ->cache_link ref */ ··· 1050 1062 * then things get messier. 1051 1063 */ 1052 1064 _debug("not yet"); 1053 - if (!rxnet->kill_all_client_conns) 1054 - timer_reduce(&rxnet->client_conn_reap_timer, conn_expires_at); 1065 + if (!local->kill_all_client_conns) 1066 + timer_reduce(&local->client_conn_reap_timer, conn_expires_at); 1055 1067 1056 1068 out: 1057 - spin_unlock(&rxnet->client_conn_cache_lock); 1058 - mutex_unlock(&rxnet->client_conn_discard_lock); 1059 - _leave(""); 1060 - } 1061 - 1062 - /* 1063 - * Preemptively destroy all the client connection records rather than waiting 1064 - * for them to time out 1065 - */ 1066 - void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet) 1067 - { 1068 - _enter(""); 1069 - 1070 - spin_lock(&rxnet->client_conn_cache_lock); 1071 - rxnet->kill_all_client_conns = true; 1072 - spin_unlock(&rxnet->client_conn_cache_lock); 1073 - 1074 - del_timer_sync(&rxnet->client_conn_reap_timer); 1075 - 1076 - if (!rxrpc_queue_work(&rxnet->client_conn_reaper)) 1077 - _debug("destroy: queue failed"); 1078 - 1069 + spin_unlock(&local->client_conn_cache_lock); 1079 1070 _leave(""); 1080 1071 } 1081 1072 ··· 1064 1097 void rxrpc_clean_up_local_conns(struct rxrpc_local *local) 1065 1098 { 1066 1099 struct rxrpc_connection *conn, *tmp; 1067 - struct rxrpc_net *rxnet = local->rxnet; 1068 1100 LIST_HEAD(graveyard); 1069 1101 1070 1102 _enter(""); 1071 1103 1072 - spin_lock(&rxnet->client_conn_cache_lock); 1104 + spin_lock(&local->client_conn_cache_lock); 1105 + local->kill_all_client_conns = true; 1106 + spin_unlock(&local->client_conn_cache_lock); 1073 1107 1074 - list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns, 1108 + del_timer_sync(&local->client_conn_reap_timer); 1109 + 1110 + spin_lock(&local->client_conn_cache_lock); 1111 + 1112 + list_for_each_entry_safe(conn, tmp, &local->idle_client_conns, 1075 1113 cache_link) { 1076 1114 if (conn->local == local) { 1077 1115 atomic_dec(&conn->active); ··· 1085 1113 } 1086 1114 } 1087 1115 1088 - spin_unlock(&rxnet->client_conn_cache_lock); 1116 + spin_unlock(&local->client_conn_cache_lock); 1089 1117 1090 1118 while (!list_empty(&graveyard)) { 1091 1119 conn = list_entry(graveyard.next,
-1
net/rxrpc/conn_object.c
··· 470 470 _enter(""); 471 471 472 472 atomic_dec(&rxnet->nr_conns); 473 - rxrpc_destroy_all_client_connections(rxnet); 474 473 475 474 del_timer_sync(&rxnet->service_conn_reap_timer); 476 475 rxrpc_queue_work(&rxnet->service_conn_reaper);
+4
net/rxrpc/io_thread.c
··· 435 435 continue; 436 436 } 437 437 438 + if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER, 439 + &local->client_conn_flags)) 440 + rxrpc_discard_expired_client_conns(local); 441 + 438 442 /* Deal with calls that want immediate attention. */ 439 443 if ((call = list_first_entry_or_null(&local->call_attend_q, 440 444 struct rxrpc_call,
+17
net/rxrpc/local_object.c
··· 82 82 } 83 83 } 84 84 85 + static void rxrpc_client_conn_reap_timeout(struct timer_list *timer) 86 + { 87 + struct rxrpc_local *local = 88 + container_of(timer, struct rxrpc_local, client_conn_reap_timer); 89 + 90 + if (local->kill_all_client_conns && 91 + test_and_set_bit(RXRPC_CLIENT_CONN_REAP_TIMER, &local->client_conn_flags)) 92 + rxrpc_wake_up_io_thread(local); 93 + } 94 + 85 95 /* 86 96 * Allocate a new local endpoint. 87 97 */ ··· 113 103 skb_queue_head_init(&local->rx_queue); 114 104 INIT_LIST_HEAD(&local->conn_attend_q); 115 105 INIT_LIST_HEAD(&local->call_attend_q); 106 + 116 107 local->client_bundles = RB_ROOT; 117 108 spin_lock_init(&local->client_bundles_lock); 109 + local->kill_all_client_conns = false; 110 + spin_lock_init(&local->client_conn_cache_lock); 111 + INIT_LIST_HEAD(&local->idle_client_conns); 112 + timer_setup(&local->client_conn_reap_timer, 113 + rxrpc_client_conn_reap_timeout, 0); 114 + 118 115 spin_lock_init(&local->lock); 119 116 rwlock_init(&local->services_lock); 120 117 local->debug_id = atomic_inc_return(&rxrpc_debug_id);
-17
net/rxrpc/net_ns.c
··· 10 10 11 11 unsigned int rxrpc_net_id; 12 12 13 - static void rxrpc_client_conn_reap_timeout(struct timer_list *timer) 14 - { 15 - struct rxrpc_net *rxnet = 16 - container_of(timer, struct rxrpc_net, client_conn_reap_timer); 17 - 18 - if (rxnet->live) 19 - rxrpc_queue_work(&rxnet->client_conn_reaper); 20 - } 21 - 22 13 static void rxrpc_service_conn_reap_timeout(struct timer_list *timer) 23 14 { 24 15 struct rxrpc_net *rxnet = ··· 54 63 rxrpc_service_conn_reap_timeout, 0); 55 64 56 65 atomic_set(&rxnet->nr_client_conns, 0); 57 - rxnet->kill_all_client_conns = false; 58 - spin_lock_init(&rxnet->client_conn_cache_lock); 59 - mutex_init(&rxnet->client_conn_discard_lock); 60 - INIT_LIST_HEAD(&rxnet->idle_client_conns); 61 - INIT_WORK(&rxnet->client_conn_reaper, 62 - rxrpc_discard_expired_client_conns); 63 - timer_setup(&rxnet->client_conn_reap_timer, 64 - rxrpc_client_conn_reap_timeout, 0); 65 66 66 67 INIT_HLIST_HEAD(&rxnet->local_endpoints); 67 68 mutex_init(&rxnet->local_mutex);