.. | .. |
---|
77 | 77 | #include <linux/string.h> |
---|
78 | 78 | #include <linux/netfilter_ipv4.h> |
---|
79 | 79 | #include <linux/slab.h> |
---|
| 80 | +#include <linux/locallock.h> |
---|
80 | 81 | #include <net/snmp.h> |
---|
81 | 82 | #include <net/ip.h> |
---|
82 | 83 | #include <net/route.h> |
---|
.. | .. |
---|
204 | 205 | * |
---|
205 | 206 | * On SMP we have one ICMP socket per-cpu. |
---|
206 | 207 | */ |
---|
| 208 | +static DEFINE_LOCAL_IRQ_LOCK(icmp_sk_lock); |
---|
| 209 | + |
---|
207 | 210 | static struct sock *icmp_sk(struct net *net) |
---|
208 | 211 | { |
---|
209 | 212 | return *this_cpu_ptr(net->ipv4.icmp_sk); |
---|
.. | .. |
---|
214 | 217 | { |
---|
215 | 218 | struct sock *sk; |
---|
216 | 219 | |
---|
| 220 | + if (!local_trylock(icmp_sk_lock)) |
---|
| 221 | + return NULL; |
---|
| 222 | + |
---|
217 | 223 | sk = icmp_sk(net); |
---|
218 | 224 | |
---|
219 | 225 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
---|
220 | 226 | /* This can happen if the output path signals a |
---|
221 | 227 | * dst_link_failure() for an outgoing ICMP packet. |
---|
222 | 228 | */ |
---|
| 229 | + local_unlock(icmp_sk_lock); |
---|
223 | 230 | return NULL; |
---|
224 | 231 | } |
---|
225 | 232 | return sk; |
---|
.. | .. |
---|
228 | 235 | static inline void icmp_xmit_unlock(struct sock *sk) |
---|
229 | 236 | { |
---|
230 | 237 | spin_unlock(&sk->sk_lock.slock); |
---|
| 238 | + local_unlock(icmp_sk_lock); |
---|
231 | 239 | } |
---|
232 | 240 | |
---|
233 | 241 | int sysctl_icmp_msgs_per_sec __read_mostly = 1000; |
---|