diff options
author | Thomas Graf <tgraf@suug.ch> | 2014-08-02 05:47:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-02 22:49:38 -0400 |
commit | e341694e3eb57fcda9f1adc7bfea42fe080d8d7a (patch) | |
tree | 12ac538a44609b3075bfaf98999ba68d9ff575cc /net/netlink/af_netlink.h | |
parent | 7e1e77636e36075ebf118298855268468f1028e8 (diff) |
netlink: Convert netlink_lookup() to use RCU protected hash table
Heavy Netlink users such as Open vSwitch spend a considerable amount of
time in netlink_lookup() due to the read-lock on nl_table_lock. Use of
RCU relieves the lock contention.
Makes use of the new resizable hash table to avoid locking on the
lookup.
The hash table will grow if entries exceeds 75% of table size up to a
total table size of 64K. It will automatically shrink if usage falls
below 30%.
Also splits nl_table_lock into a separate mutex to protect hash table
mutations and allow synchronize_rcu() to sleep while waiting for readers
during expansion and shrinking.
Before:
9.16% kpktgend_0 [openvswitch] [k] masked_flow_lookup
6.42% kpktgend_0 [pktgen] [k] mod_cur_headers
6.26% kpktgend_0 [pktgen] [k] pktgen_thread_worker
6.23% kpktgend_0 [kernel.kallsyms] [k] memset
4.79% kpktgend_0 [kernel.kallsyms] [k] netlink_lookup
4.37% kpktgend_0 [kernel.kallsyms] [k] memcpy
3.60% kpktgend_0 [openvswitch] [k] ovs_flow_extract
2.69% kpktgend_0 [kernel.kallsyms] [k] jhash2
After:
15.26% kpktgend_0 [openvswitch] [k] masked_flow_lookup
8.12% kpktgend_0 [pktgen] [k] pktgen_thread_worker
7.92% kpktgend_0 [pktgen] [k] mod_cur_headers
5.11% kpktgend_0 [kernel.kallsyms] [k] memset
4.11% kpktgend_0 [openvswitch] [k] ovs_flow_extract
4.06% kpktgend_0 [kernel.kallsyms] [k] _raw_spin_lock
3.90% kpktgend_0 [kernel.kallsyms] [k] jhash2
[...]
0.67% kpktgend_0 [kernel.kallsyms] [k] netlink_lookup
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.h')
-rw-r--r-- | net/netlink/af_netlink.h | 18 |
1 files changed, 4 insertions, 14 deletions
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 0b59d441f5b6..60f631fb7087 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _AF_NETLINK_H | 1 | #ifndef _AF_NETLINK_H |
2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
3 | 3 | ||
4 | #include <linux/rhashtable.h> | ||
4 | #include <net/sock.h> | 5 | #include <net/sock.h> |
5 | 6 | ||
6 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
@@ -47,6 +48,8 @@ struct netlink_sock { | |||
47 | struct netlink_ring tx_ring; | 48 | struct netlink_ring tx_ring; |
48 | atomic_t mapped; | 49 | atomic_t mapped; |
49 | #endif /* CONFIG_NETLINK_MMAP */ | 50 | #endif /* CONFIG_NETLINK_MMAP */ |
51 | |||
52 | struct rhash_head node; | ||
50 | }; | 53 | }; |
51 | 54 | ||
52 | static inline struct netlink_sock *nlk_sk(struct sock *sk) | 55 | static inline struct netlink_sock *nlk_sk(struct sock *sk) |
@@ -54,21 +57,8 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) | |||
54 | return container_of(sk, struct netlink_sock, sk); | 57 | return container_of(sk, struct netlink_sock, sk); |
55 | } | 58 | } |
56 | 59 | ||
57 | struct nl_portid_hash { | ||
58 | struct hlist_head *table; | ||
59 | unsigned long rehash_time; | ||
60 | |||
61 | unsigned int mask; | ||
62 | unsigned int shift; | ||
63 | |||
64 | unsigned int entries; | ||
65 | unsigned int max_shift; | ||
66 | |||
67 | u32 rnd; | ||
68 | }; | ||
69 | |||
70 | struct netlink_table { | 60 | struct netlink_table { |
71 | struct nl_portid_hash hash; | 61 | struct rhashtable hash; |
72 | struct hlist_head mc_list; | 62 | struct hlist_head mc_list; |
73 | struct listeners __rcu *listeners; | 63 | struct listeners __rcu *listeners; |
74 | unsigned int flags; | 64 | unsigned int flags; |