diff options
author | David S. Miller <davem@davemloft.net> | 2013-12-09 20:20:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-09 20:20:14 -0500 |
commit | 34f9f437104b86f6ddfa2770e2cd852846385dc3 (patch) | |
tree | 6c78386b3db9dd47fd2b79efb4dcf8c1472de99e /net/packet | |
parent | 95dc19299f741c986227ec33e23cbf9b3321f812 (diff) | |
parent | 66e56cd46b93ef407c60adcac62cf33b06119d50 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Merge 'net' into 'net-next' to get the AF_PACKET bug fix that
Daniel's direct transmit changes depend upon.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c235da940019..e4171dd98590 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -237,6 +237,30 @@ struct packet_skb_cb { | |||
237 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); | 237 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); |
238 | static void __fanout_link(struct sock *sk, struct packet_sock *po); | 238 | static void __fanout_link(struct sock *sk, struct packet_sock *po); |
239 | 239 | ||
240 | static struct net_device *packet_cached_dev_get(struct packet_sock *po) | ||
241 | { | ||
242 | struct net_device *dev; | ||
243 | |||
244 | rcu_read_lock(); | ||
245 | dev = rcu_dereference(po->cached_dev); | ||
246 | if (likely(dev)) | ||
247 | dev_hold(dev); | ||
248 | rcu_read_unlock(); | ||
249 | |||
250 | return dev; | ||
251 | } | ||
252 | |||
253 | static void packet_cached_dev_assign(struct packet_sock *po, | ||
254 | struct net_device *dev) | ||
255 | { | ||
256 | rcu_assign_pointer(po->cached_dev, dev); | ||
257 | } | ||
258 | |||
259 | static void packet_cached_dev_reset(struct packet_sock *po) | ||
260 | { | ||
261 | RCU_INIT_POINTER(po->cached_dev, NULL); | ||
262 | } | ||
263 | |||
240 | /* register_prot_hook must be invoked with the po->bind_lock held, | 264 | /* register_prot_hook must be invoked with the po->bind_lock held, |
241 | * or from a context in which asynchronous accesses to the packet | 265 | * or from a context in which asynchronous accesses to the packet |
242 | * socket is not possible (packet_create()). | 266 | * socket is not possible (packet_create()). |
@@ -246,12 +270,10 @@ static void register_prot_hook(struct sock *sk) | |||
246 | struct packet_sock *po = pkt_sk(sk); | 270 | struct packet_sock *po = pkt_sk(sk); |
247 | 271 | ||
248 | if (!po->running) { | 272 | if (!po->running) { |
249 | if (po->fanout) { | 273 | if (po->fanout) |
250 | __fanout_link(sk, po); | 274 | __fanout_link(sk, po); |
251 | } else { | 275 | else |
252 | dev_add_pack(&po->prot_hook); | 276 | dev_add_pack(&po->prot_hook); |
253 | rcu_assign_pointer(po->cached_dev, po->prot_hook.dev); | ||
254 | } | ||
255 | 277 | ||
256 | sock_hold(sk); | 278 | sock_hold(sk); |
257 | po->running = 1; | 279 | po->running = 1; |
@@ -270,12 +292,11 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) | |||
270 | struct packet_sock *po = pkt_sk(sk); | 292 | struct packet_sock *po = pkt_sk(sk); |
271 | 293 | ||
272 | po->running = 0; | 294 | po->running = 0; |
273 | if (po->fanout) { | 295 | |
296 | if (po->fanout) | ||
274 | __fanout_unlink(sk, po); | 297 | __fanout_unlink(sk, po); |
275 | } else { | 298 | else |
276 | __dev_remove_pack(&po->prot_hook); | 299 | __dev_remove_pack(&po->prot_hook); |
277 | RCU_INIT_POINTER(po->cached_dev, NULL); | ||
278 | } | ||
279 | 300 | ||
280 | __sock_put(sk); | 301 | __sock_put(sk); |
281 | 302 | ||
@@ -2061,19 +2082,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2061 | return tp_len; | 2082 | return tp_len; |
2062 | } | 2083 | } |
2063 | 2084 | ||
2064 | static struct net_device *packet_cached_dev_get(struct packet_sock *po) | ||
2065 | { | ||
2066 | struct net_device *dev; | ||
2067 | |||
2068 | rcu_read_lock(); | ||
2069 | dev = rcu_dereference(po->cached_dev); | ||
2070 | if (dev) | ||
2071 | dev_hold(dev); | ||
2072 | rcu_read_unlock(); | ||
2073 | |||
2074 | return dev; | ||
2075 | } | ||
2076 | |||
2077 | static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | 2085 | static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) |
2078 | { | 2086 | { |
2079 | struct sk_buff *skb; | 2087 | struct sk_buff *skb; |
@@ -2090,7 +2098,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2090 | 2098 | ||
2091 | mutex_lock(&po->pg_vec_lock); | 2099 | mutex_lock(&po->pg_vec_lock); |
2092 | 2100 | ||
2093 | if (saddr == NULL) { | 2101 | if (likely(saddr == NULL)) { |
2094 | dev = packet_cached_dev_get(po); | 2102 | dev = packet_cached_dev_get(po); |
2095 | proto = po->num; | 2103 | proto = po->num; |
2096 | addr = NULL; | 2104 | addr = NULL; |
@@ -2244,7 +2252,7 @@ static int packet_snd(struct socket *sock, | |||
2244 | * Get and verify the address. | 2252 | * Get and verify the address. |
2245 | */ | 2253 | */ |
2246 | 2254 | ||
2247 | if (saddr == NULL) { | 2255 | if (likely(saddr == NULL)) { |
2248 | dev = packet_cached_dev_get(po); | 2256 | dev = packet_cached_dev_get(po); |
2249 | proto = po->num; | 2257 | proto = po->num; |
2250 | addr = NULL; | 2258 | addr = NULL; |
@@ -2453,6 +2461,8 @@ static int packet_release(struct socket *sock) | |||
2453 | 2461 | ||
2454 | spin_lock(&po->bind_lock); | 2462 | spin_lock(&po->bind_lock); |
2455 | unregister_prot_hook(sk, false); | 2463 | unregister_prot_hook(sk, false); |
2464 | packet_cached_dev_reset(po); | ||
2465 | |||
2456 | if (po->prot_hook.dev) { | 2466 | if (po->prot_hook.dev) { |
2457 | dev_put(po->prot_hook.dev); | 2467 | dev_put(po->prot_hook.dev); |
2458 | po->prot_hook.dev = NULL; | 2468 | po->prot_hook.dev = NULL; |
@@ -2508,14 +2518,17 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc | |||
2508 | 2518 | ||
2509 | spin_lock(&po->bind_lock); | 2519 | spin_lock(&po->bind_lock); |
2510 | unregister_prot_hook(sk, true); | 2520 | unregister_prot_hook(sk, true); |
2521 | |||
2511 | po->num = protocol; | 2522 | po->num = protocol; |
2512 | po->prot_hook.type = protocol; | 2523 | po->prot_hook.type = protocol; |
2513 | if (po->prot_hook.dev) | 2524 | if (po->prot_hook.dev) |
2514 | dev_put(po->prot_hook.dev); | 2525 | dev_put(po->prot_hook.dev); |
2515 | po->prot_hook.dev = dev; | ||
2516 | 2526 | ||
2527 | po->prot_hook.dev = dev; | ||
2517 | po->ifindex = dev ? dev->ifindex : 0; | 2528 | po->ifindex = dev ? dev->ifindex : 0; |
2518 | 2529 | ||
2530 | packet_cached_dev_assign(po, dev); | ||
2531 | |||
2519 | if (protocol == 0) | 2532 | if (protocol == 0) |
2520 | goto out_unlock; | 2533 | goto out_unlock; |
2521 | 2534 | ||
@@ -2628,7 +2641,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, | |||
2628 | po = pkt_sk(sk); | 2641 | po = pkt_sk(sk); |
2629 | sk->sk_family = PF_PACKET; | 2642 | sk->sk_family = PF_PACKET; |
2630 | po->num = proto; | 2643 | po->num = proto; |
2631 | RCU_INIT_POINTER(po->cached_dev, NULL); | 2644 | |
2645 | packet_cached_dev_reset(po); | ||
2632 | 2646 | ||
2633 | sk->sk_destruct = packet_sock_destruct; | 2647 | sk->sk_destruct = packet_sock_destruct; |
2634 | sk_refcnt_debug_inc(sk); | 2648 | sk_refcnt_debug_inc(sk); |
@@ -3339,6 +3353,7 @@ static int packet_notifier(struct notifier_block *this, | |||
3339 | sk->sk_error_report(sk); | 3353 | sk->sk_error_report(sk); |
3340 | } | 3354 | } |
3341 | if (msg == NETDEV_UNREGISTER) { | 3355 | if (msg == NETDEV_UNREGISTER) { |
3356 | packet_cached_dev_reset(po); | ||
3342 | po->ifindex = -1; | 3357 | po->ifindex = -1; |
3343 | if (po->prot_hook.dev) | 3358 | if (po->prot_hook.dev) |
3344 | dev_put(po->prot_hook.dev); | 3359 | dev_put(po->prot_hook.dev); |