diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
| commit | bb799d3b980eb803ca2da4a4eefbd9308f8d988a (patch) | |
| tree | 69fbe0cd6d47b23a50f5e1d87bf7489532fae149 /net/packet/af_packet.c | |
| parent | 919fc6e34831d1c2b58bfb5ae261dc3facc9b269 (diff) | |
| parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) | |
Merge tag 'v3.13-rc4' into core/locking
Merge Linux 3.13-rc4, to refresh this rather old tree with the latest fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/packet/af_packet.c')
| -rw-r--r-- | net/packet/af_packet.c | 108 |
1 files changed, 67 insertions, 41 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2e8286b47c28..88cfbc189558 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()). |
| @@ -244,11 +268,13 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); | |||
| 244 | static void register_prot_hook(struct sock *sk) | 268 | static void register_prot_hook(struct sock *sk) |
| 245 | { | 269 | { |
| 246 | struct packet_sock *po = pkt_sk(sk); | 270 | struct packet_sock *po = pkt_sk(sk); |
| 271 | |||
| 247 | if (!po->running) { | 272 | if (!po->running) { |
| 248 | if (po->fanout) | 273 | if (po->fanout) |
| 249 | __fanout_link(sk, po); | 274 | __fanout_link(sk, po); |
| 250 | else | 275 | else |
| 251 | dev_add_pack(&po->prot_hook); | 276 | dev_add_pack(&po->prot_hook); |
| 277 | |||
| 252 | sock_hold(sk); | 278 | sock_hold(sk); |
| 253 | po->running = 1; | 279 | po->running = 1; |
| 254 | } | 280 | } |
| @@ -266,10 +292,12 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) | |||
| 266 | struct packet_sock *po = pkt_sk(sk); | 292 | struct packet_sock *po = pkt_sk(sk); |
| 267 | 293 | ||
| 268 | po->running = 0; | 294 | po->running = 0; |
| 295 | |||
| 269 | if (po->fanout) | 296 | if (po->fanout) |
| 270 | __fanout_unlink(sk, po); | 297 | __fanout_unlink(sk, po); |
| 271 | else | 298 | else |
| 272 | __dev_remove_pack(&po->prot_hook); | 299 | __dev_remove_pack(&po->prot_hook); |
| 300 | |||
| 273 | __sock_put(sk); | 301 | __sock_put(sk); |
| 274 | 302 | ||
| 275 | if (sync) { | 303 | if (sync) { |
| @@ -432,9 +460,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po, | |||
| 432 | 460 | ||
| 433 | pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc; | 461 | pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc; |
| 434 | 462 | ||
| 435 | spin_lock(&rb_queue->lock); | 463 | spin_lock_bh(&rb_queue->lock); |
| 436 | pkc->delete_blk_timer = 1; | 464 | pkc->delete_blk_timer = 1; |
| 437 | spin_unlock(&rb_queue->lock); | 465 | spin_unlock_bh(&rb_queue->lock); |
| 438 | 466 | ||
| 439 | prb_del_retire_blk_timer(pkc); | 467 | prb_del_retire_blk_timer(pkc); |
| 440 | } | 468 | } |
| @@ -2057,7 +2085,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2057 | struct sk_buff *skb; | 2085 | struct sk_buff *skb; |
| 2058 | struct net_device *dev; | 2086 | struct net_device *dev; |
| 2059 | __be16 proto; | 2087 | __be16 proto; |
| 2060 | bool need_rls_dev = false; | ||
| 2061 | int err, reserve = 0; | 2088 | int err, reserve = 0; |
| 2062 | void *ph; | 2089 | void *ph; |
| 2063 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; | 2090 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; |
| @@ -2069,8 +2096,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2069 | 2096 | ||
| 2070 | mutex_lock(&po->pg_vec_lock); | 2097 | mutex_lock(&po->pg_vec_lock); |
| 2071 | 2098 | ||
| 2072 | if (saddr == NULL) { | 2099 | if (likely(saddr == NULL)) { |
| 2073 | dev = po->prot_hook.dev; | 2100 | dev = packet_cached_dev_get(po); |
| 2074 | proto = po->num; | 2101 | proto = po->num; |
| 2075 | addr = NULL; | 2102 | addr = NULL; |
| 2076 | } else { | 2103 | } else { |
| @@ -2084,19 +2111,17 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2084 | proto = saddr->sll_protocol; | 2111 | proto = saddr->sll_protocol; |
| 2085 | addr = saddr->sll_addr; | 2112 | addr = saddr->sll_addr; |
| 2086 | dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); | 2113 | dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); |
| 2087 | need_rls_dev = true; | ||
| 2088 | } | 2114 | } |
| 2089 | 2115 | ||
| 2090 | err = -ENXIO; | 2116 | err = -ENXIO; |
| 2091 | if (unlikely(dev == NULL)) | 2117 | if (unlikely(dev == NULL)) |
| 2092 | goto out; | 2118 | goto out; |
| 2093 | |||
| 2094 | reserve = dev->hard_header_len; | ||
| 2095 | |||
| 2096 | err = -ENETDOWN; | 2119 | err = -ENETDOWN; |
| 2097 | if (unlikely(!(dev->flags & IFF_UP))) | 2120 | if (unlikely(!(dev->flags & IFF_UP))) |
| 2098 | goto out_put; | 2121 | goto out_put; |
| 2099 | 2122 | ||
| 2123 | reserve = dev->hard_header_len; | ||
| 2124 | |||
| 2100 | size_max = po->tx_ring.frame_size | 2125 | size_max = po->tx_ring.frame_size |
| 2101 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 2126 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); |
| 2102 | 2127 | ||
| @@ -2173,8 +2198,7 @@ out_status: | |||
| 2173 | __packet_set_status(po, ph, status); | 2198 | __packet_set_status(po, ph, status); |
| 2174 | kfree_skb(skb); | 2199 | kfree_skb(skb); |
| 2175 | out_put: | 2200 | out_put: |
| 2176 | if (need_rls_dev) | 2201 | dev_put(dev); |
| 2177 | dev_put(dev); | ||
| 2178 | out: | 2202 | out: |
| 2179 | mutex_unlock(&po->pg_vec_lock); | 2203 | mutex_unlock(&po->pg_vec_lock); |
| 2180 | return err; | 2204 | return err; |
| @@ -2212,7 +2236,6 @@ static int packet_snd(struct socket *sock, | |||
| 2212 | struct sk_buff *skb; | 2236 | struct sk_buff *skb; |
| 2213 | struct net_device *dev; | 2237 | struct net_device *dev; |
| 2214 | __be16 proto; | 2238 | __be16 proto; |
| 2215 | bool need_rls_dev = false; | ||
| 2216 | unsigned char *addr; | 2239 | unsigned char *addr; |
| 2217 | int err, reserve = 0; | 2240 | int err, reserve = 0; |
| 2218 | struct virtio_net_hdr vnet_hdr = { 0 }; | 2241 | struct virtio_net_hdr vnet_hdr = { 0 }; |
| @@ -2227,8 +2250,8 @@ static int packet_snd(struct socket *sock, | |||
| 2227 | * Get and verify the address. | 2250 | * Get and verify the address. |
| 2228 | */ | 2251 | */ |
| 2229 | 2252 | ||
| 2230 | if (saddr == NULL) { | 2253 | if (likely(saddr == NULL)) { |
| 2231 | dev = po->prot_hook.dev; | 2254 | dev = packet_cached_dev_get(po); |
| 2232 | proto = po->num; | 2255 | proto = po->num; |
| 2233 | addr = NULL; | 2256 | addr = NULL; |
| 2234 | } else { | 2257 | } else { |
| @@ -2240,19 +2263,17 @@ static int packet_snd(struct socket *sock, | |||
| 2240 | proto = saddr->sll_protocol; | 2263 | proto = saddr->sll_protocol; |
| 2241 | addr = saddr->sll_addr; | 2264 | addr = saddr->sll_addr; |
| 2242 | dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); | 2265 | dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); |
| 2243 | need_rls_dev = true; | ||
| 2244 | } | 2266 | } |
| 2245 | 2267 | ||
| 2246 | err = -ENXIO; | 2268 | err = -ENXIO; |
| 2247 | if (dev == NULL) | 2269 | if (unlikely(dev == NULL)) |
| 2248 | goto out_unlock; | 2270 | goto out_unlock; |
| 2249 | if (sock->type == SOCK_RAW) | ||
| 2250 | reserve = dev->hard_header_len; | ||
| 2251 | |||
| 2252 | err = -ENETDOW | ||
