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); |
