aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index af72de1c8690..5f04216f35ce 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -163,7 +163,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
163 int (*saddr_comp)(const struct sock *sk1, 163 int (*saddr_comp)(const struct sock *sk1,
164 const struct sock *sk2)) 164 const struct sock *sk2))
165{ 165{
166 struct udp_hslot *hslot; 166 struct udp_hslot *hslot, *hslot2;
167 struct udp_table *udptable = sk->sk_prot->h.udp_table; 167 struct udp_table *udptable = sk->sk_prot->h.udp_table;
168 int error = 1; 168 int error = 1;
169 struct net *net = sock_net(sk); 169 struct net *net = sock_net(sk);
@@ -222,6 +222,13 @@ found:
222 sk_nulls_add_node_rcu(sk, &hslot->head); 222 sk_nulls_add_node_rcu(sk, &hslot->head);
223 hslot->count++; 223 hslot->count++;
224 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 224 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
225
226 hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
227 spin_lock(&hslot2->lock);
228 hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
229 &hslot2->head);
230 hslot2->count++;
231 spin_unlock(&hslot2->lock);
225 } 232 }
226 error = 0; 233 error = 0;
227fail_unlock: 234fail_unlock:
@@ -1062,14 +1069,22 @@ void udp_lib_unhash(struct sock *sk)
1062{ 1069{
1063 if (sk_hashed(sk)) { 1070 if (sk_hashed(sk)) {
1064 struct udp_table *udptable = sk->sk_prot->h.udp_table; 1071 struct udp_table *udptable = sk->sk_prot->h.udp_table;
1065 struct udp_hslot *hslot = udp_hashslot(udptable, sock_net(sk), 1072 struct udp_hslot *hslot, *hslot2;
1066 udp_sk(sk)->udp_port_hash); 1073
1074 hslot = udp_hashslot(udptable, sock_net(sk),
1075 udp_sk(sk)->udp_port_hash);
1076 hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
1067 1077
1068 spin_lock_bh(&hslot->lock); 1078 spin_lock_bh(&hslot->lock);
1069 if (sk_nulls_del_node_init_rcu(sk)) { 1079 if (sk_nulls_del_node_init_rcu(sk)) {
1070 hslot->count--; 1080 hslot->count--;
1071 inet_sk(sk)->inet_num = 0; 1081 inet_sk(sk)->inet_num = 0;
1072 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 1082 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
1083
1084 spin_lock(&hslot2->lock);
1085 hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
1086 hslot2->count--;
1087 spin_unlock(&hslot2->lock);
1073 } 1088 }
1074 spin_unlock_bh(&hslot->lock); 1089 spin_unlock_bh(&hslot->lock);
1075 } 1090 }
@@ -1857,7 +1872,7 @@ void __init udp_table_init(struct udp_table *table, const char *name)
1857 1872
1858 if (!CONFIG_BASE_SMALL) 1873 if (!CONFIG_BASE_SMALL)
1859 table->hash = alloc_large_system_hash(name, 1874 table->hash = alloc_large_system_hash(name,
1860 sizeof(struct udp_hslot), 1875 2 * sizeof(struct udp_hslot),
1861 uhash_entries, 1876 uhash_entries,
1862 21, /* one slot per 2 MB */ 1877 21, /* one slot per 2 MB */
1863 0, 1878 0,
@@ -1869,17 +1884,23 @@ void __init udp_table_init(struct udp_table *table, const char *name)
1869 */ 1884 */
1870 if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) { 1885 if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) {
1871 table->hash = kmalloc(UDP_HTABLE_SIZE_MIN * 1886 table->hash = kmalloc(UDP_HTABLE_SIZE_MIN *
1872 sizeof(struct udp_hslot), GFP_KERNEL); 1887 2 * sizeof(struct udp_hslot), GFP_KERNEL);
1873 if (!table->hash) 1888 if (!table->hash)
1874 panic(name); 1889 panic(name);
1875 table->log = ilog2(UDP_HTABLE_SIZE_MIN); 1890 table->log = ilog2(UDP_HTABLE_SIZE_MIN);
1876 table->mask = UDP_HTABLE_SIZE_MIN - 1; 1891 table->mask = UDP_HTABLE_SIZE_MIN - 1;
1877 } 1892 }
1893 table->hash2 = table->hash + (table->mask + 1);
1878 for (i = 0; i <= table->mask; i++) { 1894 for (i = 0; i <= table->mask; i++) {
1879 INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); 1895 INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i);
1880 table->hash[i].count = 0; 1896 table->hash[i].count = 0;
1881 spin_lock_init(&table->hash[i].lock); 1897 spin_lock_init(&table->hash[i].lock);
1882 } 1898 }
1899 for (i = 0; i <= table->mask; i++) {
1900 INIT_HLIST_NULLS_HEAD(&table->hash2[i].head, i);
1901 table->hash2[i].count = 0;
1902 spin_lock_init(&table->hash2[i].lock);
1903 }
1883} 1904}
1884 1905
1885void __init udp_init(void) 1906void __init udp_init(void)