diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-31 22:25:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-31 22:25:39 -0400 |
commit | ac694dbdbc403c00e2c14d10bc7b8412cc378259 (patch) | |
tree | e37328cfbeaf43716dd5914cad9179e57e84df76 /net/core/dev.c | |
parent | a40a1d3d0a2fd613fdec6d89d3c053268ced76ed (diff) | |
parent | 437ea90cc3afdca5229b41c6b1d38c4842756cb9 (diff) |
Merge branch 'akpm' (Andrew's patch-bomb)
Merge Andrew's second set of patches:
- MM
- a few random fixes
- a couple of RTC leftovers
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (120 commits)
rtc/rtc-88pm80x: remove unneed devm_kfree
rtc/rtc-88pm80x: assign ret only when rtc_register_driver fails
mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables
tmpfs: distribute interleave better across nodes
mm: remove redundant initialization
mm: warn if pg_data_t isn't initialized with zero
mips: zero out pg_data_t when it's allocated
memcg: gix memory accounting scalability in shrink_page_list
mm/sparse: remove index_init_lock
mm/sparse: more checks on mem_section number
mm/sparse: optimize sparse_index_alloc
memcg: add mem_cgroup_from_css() helper
memcg: further prevent OOM with too many dirty pages
memcg: prevent OOM with too many dirty pages
mm: mmu_notifier: fix freed page still mapped in secondary MMU
mm: memcg: only check anon swapin page charges for swap cache
mm: memcg: only check swap cache pages for repeated charging
mm: memcg: split swapin charge function into private and public part
mm: memcg: remove needless !mm fixup to init_mm when charging
mm: memcg: remove unneeded shmem charge type
...
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index c8569f826b71..0cb3fe8d8e72 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3156,6 +3156,23 @@ void netdev_rx_handler_unregister(struct net_device *dev) | |||
3156 | } | 3156 | } |
3157 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); | 3157 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); |
3158 | 3158 | ||
3159 | /* | ||
3160 | * Limit the use of PFMEMALLOC reserves to those protocols that implement | ||
3161 | * the special handling of PFMEMALLOC skbs. | ||
3162 | */ | ||
3163 | static bool skb_pfmemalloc_protocol(struct sk_buff *skb) | ||
3164 | { | ||
3165 | switch (skb->protocol) { | ||
3166 | case __constant_htons(ETH_P_ARP): | ||
3167 | case __constant_htons(ETH_P_IP): | ||
3168 | case __constant_htons(ETH_P_IPV6): | ||
3169 | case __constant_htons(ETH_P_8021Q): | ||
3170 | return true; | ||
3171 | default: | ||
3172 | return false; | ||
3173 | } | ||
3174 | } | ||
3175 | |||
3159 | static int __netif_receive_skb(struct sk_buff *skb) | 3176 | static int __netif_receive_skb(struct sk_buff *skb) |
3160 | { | 3177 | { |
3161 | struct packet_type *ptype, *pt_prev; | 3178 | struct packet_type *ptype, *pt_prev; |
@@ -3165,14 +3182,27 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
3165 | bool deliver_exact = false; | 3182 | bool deliver_exact = false; |
3166 | int ret = NET_RX_DROP; | 3183 | int ret = NET_RX_DROP; |
3167 | __be16 type; | 3184 | __be16 type; |
3185 | unsigned long pflags = current->flags; | ||
3168 | 3186 | ||
3169 | net_timestamp_check(!netdev_tstamp_prequeue, skb); | 3187 | net_timestamp_check(!netdev_tstamp_prequeue, skb); |
3170 | 3188 | ||
3171 | trace_netif_receive_skb(skb); | 3189 | trace_netif_receive_skb(skb); |
3172 | 3190 | ||
3191 | /* | ||
3192 | * PFMEMALLOC skbs are special, they should | ||
3193 | * - be delivered to SOCK_MEMALLOC sockets only | ||
3194 | * - stay away from userspace | ||
3195 | * - have bounded memory usage | ||
3196 | * | ||
3197 | * Use PF_MEMALLOC as this saves us from propagating the allocation | ||
3198 | * context down to all allocation sites. | ||
3199 | */ | ||
3200 | if (sk_memalloc_socks() && skb_pfmemalloc(skb)) | ||
3201 | current->flags |= PF_MEMALLOC; | ||
3202 | |||
3173 | /* if we've gotten here through NAPI, check netpoll */ | 3203 | /* if we've gotten here through NAPI, check netpoll */ |
3174 | if (netpoll_receive_skb(skb)) | 3204 | if (netpoll_receive_skb(skb)) |
3175 | return NET_RX_DROP; | 3205 | goto out; |
3176 | 3206 | ||
3177 | orig_dev = skb->dev; | 3207 | orig_dev = skb->dev; |
3178 | 3208 | ||
@@ -3192,7 +3222,7 @@ another_round: | |||
3192 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { | 3222 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { |
3193 | skb = vlan_untag(skb); | 3223 | skb = vlan_untag(skb); |
3194 | if (unlikely(!skb)) | 3224 | if (unlikely(!skb)) |
3195 | goto out; | 3225 | goto unlock; |
3196 | } | 3226 | } |
3197 | 3227 | ||
3198 | #ifdef CONFIG_NET_CLS_ACT | 3228 | #ifdef CONFIG_NET_CLS_ACT |
@@ -3202,6 +3232,9 @@ another_round: | |||
3202 | } | 3232 | } |
3203 | #endif | 3233 | #endif |
3204 | 3234 | ||
3235 | if (sk_memalloc_socks() && skb_pfmemalloc(skb)) | ||
3236 | goto skip_taps; | ||
3237 | |||
3205 | list_for_each_entry_rcu(ptype, &ptype_all, list) { | 3238 | list_for_each_entry_rcu(ptype, &ptype_all, list) { |
3206 | if (!ptype->dev || ptype->dev == skb->dev) { | 3239 | if (!ptype->dev || ptype->dev == skb->dev) { |
3207 | if (pt_prev) | 3240 | if (pt_prev) |
@@ -3210,13 +3243,18 @@ another_round: | |||
3210 | } | 3243 | } |
3211 | } | 3244 | } |
3212 | 3245 | ||
3246 | skip_taps: | ||
3213 | #ifdef CONFIG_NET_CLS_ACT | 3247 | #ifdef CONFIG_NET_CLS_ACT |
3214 | skb = handle_ing(skb, &pt_prev, &ret, orig_dev); | 3248 | skb = handle_ing(skb, &pt_prev, &ret, orig_dev); |
3215 | if (!skb) | 3249 | if (!skb) |
3216 | goto out; | 3250 | goto unlock; |
3217 | ncls: | 3251 | ncls: |
3218 | #endif | 3252 | #endif |
3219 | 3253 | ||
3254 | if (sk_memalloc_socks() && skb_pfmemalloc(skb) | ||
3255 | && !skb_pfmemalloc_protocol(skb)) | ||
3256 | goto drop; | ||
3257 | |||
3220 | rx_handler = rcu_dereference(skb->dev->rx_handler); | 3258 | rx_handler = rcu_dereference(skb->dev->rx_handler); |
3221 | if (vlan_tx_tag_present(skb)) { | 3259 | if (vlan_tx_tag_present(skb)) { |
3222 | if (pt_prev) { | 3260 | if (pt_prev) { |
@@ -3226,7 +3264,7 @@ ncls: | |||
3226 | if (vlan_do_receive(&skb, !rx_handler)) | 3264 | if (vlan_do_receive(&skb, !rx_handler)) |
3227 | goto another_round; | 3265 | goto another_round; |
3228 | else if (unlikely(!skb)) | 3266 | else if (unlikely(!skb)) |
3229 | goto out; | 3267 | goto unlock; |
3230 | } | 3268 | } |
3231 | 3269 | ||
3232 | if (rx_handler) { | 3270 | if (rx_handler) { |
@@ -3236,7 +3274,7 @@ ncls: | |||
3236 | } | 3274 | } |
3237 | switch (rx_handler(&skb)) { | 3275 | switch (rx_handler(&skb)) { |
3238 | case RX_HANDLER_CONSUMED: | 3276 | case RX_HANDLER_CONSUMED: |
3239 | goto out; | 3277 | goto unlock; |
3240 | case RX_HANDLER_ANOTHER: | 3278 | case RX_HANDLER_ANOTHER: |
3241 | goto another_round; | 3279 | goto another_round; |
3242 | case RX_HANDLER_EXACT: | 3280 | case RX_HANDLER_EXACT: |
@@ -3269,6 +3307,7 @@ ncls: | |||
3269 | else | 3307 | else |
3270 | ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); | 3308 | ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); |
3271 | } else { | 3309 | } else { |
3310 | drop: | ||
3272 | atomic_long_inc(&skb->dev->rx_dropped); | 3311 | atomic_long_inc(&skb->dev->rx_dropped); |
3273 | kfree_skb(skb); | 3312 | kfree_skb(skb); |
3274 | /* Jamal, now you will not able to escape explaining | 3313 | /* Jamal, now you will not able to escape explaining |
@@ -3277,8 +3316,10 @@ ncls: | |||
3277 | ret = NET_RX_DROP; | 3316 | ret = NET_RX_DROP; |
3278 | } | 3317 | } |
3279 | 3318 | ||
3280 | out: | 3319 | unlock: |
3281 | rcu_read_unlock(); | 3320 | rcu_read_unlock(); |
3321 | out: | ||
3322 | tsk_restore_flags(current, pflags, PF_MEMALLOC); | ||
3282 | return ret; | 3323 | return ret; |
3283 | } | 3324 | } |
3284 | 3325 | ||