diff options
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r-- | net/ipv4/inet_hashtables.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 95fac5532994..bfc39066e730 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -124,8 +124,10 @@ EXPORT_SYMBOL(inet_listen_wlock); | |||
124 | * remote address for the connection. So always assume those are both | 124 | * remote address for the connection. So always assume those are both |
125 | * wildcarded during the search since they can never be otherwise. | 125 | * wildcarded during the search since they can never be otherwise. |
126 | */ | 126 | */ |
127 | struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr, | 127 | static struct sock *__inet_lookup_listener(const struct hlist_head *head, |
128 | const unsigned short hnum, const int dif) | 128 | const u32 daddr, |
129 | const unsigned short hnum, | ||
130 | const int dif) | ||
129 | { | 131 | { |
130 | struct sock *result = NULL, *sk; | 132 | struct sock *result = NULL, *sk; |
131 | const struct hlist_node *node; | 133 | const struct hlist_node *node; |
@@ -159,7 +161,34 @@ struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 dad | |||
159 | return result; | 161 | return result; |
160 | } | 162 | } |
161 | 163 | ||
162 | EXPORT_SYMBOL_GPL(__inet_lookup_listener); | 164 | /* Optimize the common listener case. */ |
165 | struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, | ||
166 | const u32 daddr, const unsigned short hnum, | ||
167 | const int dif) | ||
168 | { | ||
169 | struct sock *sk = NULL; | ||
170 | const struct hlist_head *head; | ||
171 | |||
172 | read_lock(&hashinfo->lhash_lock); | ||
173 | head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; | ||
174 | if (!hlist_empty(head)) { | ||
175 | const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); | ||
176 | |||
177 | if (inet->num == hnum && !sk->sk_node.next && | ||
178 | (!inet->rcv_saddr || inet->rcv_saddr == daddr) && | ||
179 | (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && | ||
180 | !sk->sk_bound_dev_if) | ||
181 | goto sherry_cache; | ||
182 | sk = __inet_lookup_listener(head, daddr, hnum, dif); | ||
183 | } | ||
184 | if (sk) { | ||
185 | sherry_cache: | ||
186 | sock_hold(sk); | ||
187 | } | ||
188 | read_unlock(&hashinfo->lhash_lock); | ||
189 | return sk; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(inet_lookup_listener); | ||
163 | 192 | ||
164 | /* called with local bh disabled */ | 193 | /* called with local bh disabled */ |
165 | static int __inet_check_established(struct inet_timewait_death_row *death_row, | 194 | static int __inet_check_established(struct inet_timewait_death_row *death_row, |