net: do not deplete pfmemalloc reserve
[linux-2.6-block.git] / net / core / skbuff.c
index 8e4ac97c84775f15c786020ff87a2ef22a8dbac8..456ead534e10777c680bd0a48535e02362fb03ca 100644 (file)
@@ -311,7 +311,11 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = SKB_TRUESIZE(size);
-       skb->head_frag = frag_size != 0;
+       if (frag_size) {
+               skb->head_frag = 1;
+               if (virt_to_head_page(data)->pfmemalloc)
+                       skb->pfmemalloc = 1;
+       }
        atomic_set(&skb->users, 1);
        skb->head = data;
        skb->data = data;
@@ -348,7 +352,8 @@ static struct page *__page_frag_refill(struct netdev_alloc_cache *nc,
        gfp_t gfp = gfp_mask;
 
        if (order) {
-               gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;
+               gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY |
+                           __GFP_NOMEMALLOC;
                page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
                nc->frag.size = PAGE_SIZE << (page ? order : 0);
        }
@@ -2865,7 +2870,6 @@ static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
  * @from: search offset
  * @to: search limit
  * @config: textsearch configuration
- * @state: uninitialized textsearch state variable
  *
  * Finds a pattern in the skb data according to the specified
  * textsearch configuration. Use textsearch_next() to retrieve
@@ -2873,17 +2877,17 @@ static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
  * to the first occurrence or UINT_MAX if no match was found.
  */
 unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
-                          unsigned int to, struct ts_config *config,
-                          struct ts_state *state)
+                          unsigned int to, struct ts_config *config)
 {
+       struct ts_state state;
        unsigned int ret;
 
        config->get_next_block = skb_ts_get_next_block;
        config->finish = skb_ts_finish;
 
-       skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state));
+       skb_prepare_seq_read(skb, from, to, TS_SKB_CB(&state));
 
-       ret = textsearch_find(config, state);
+       ret = textsearch_find(config, &state);
        return (ret <= to - from ? ret : UINT_MAX);
 }
 EXPORT_SYMBOL(skb_find_text);
@@ -3207,10 +3211,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
        unsigned int offset = skb_gro_offset(skb);
        unsigned int headlen = skb_headlen(skb);
-       struct sk_buff *nskb, *lp, *p = *head;
        unsigned int len = skb_gro_len(skb);
+       struct sk_buff *lp, *p = *head;
        unsigned int delta_truesize;
-       unsigned int headroom;
 
        if (unlikely(p->len + len >= 65536))
                return -E2BIG;
@@ -3277,48 +3280,6 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
                NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
                goto done;
        }
-       /* switch back to head shinfo */
-       pinfo = skb_shinfo(p);
-
-       if (pinfo->frag_list)
-               goto merge;
-       if (skb_gro_len(p) != pinfo->gso_size)
-               return -E2BIG;
-
-       headroom = skb_headroom(p);
-       nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
-       if (unlikely(!nskb))
-               return -ENOMEM;
-
-       __copy_skb_header(nskb, p);
-       nskb->mac_len = p->mac_len;
-
-       skb_reserve(nskb, headroom);
-       __skb_put(nskb, skb_gro_offset(p));
-
-       skb_set_mac_header(nskb, skb_mac_header(p) - p->data);
-       skb_set_network_header(nskb, skb_network_offset(p));
-       skb_set_transport_header(nskb, skb_transport_offset(p));
-
-       __skb_pull(p, skb_gro_offset(p));
-       memcpy(skb_mac_header(nskb), skb_mac_header(p),
-              p->data - skb_mac_header(p));
-
-       skb_shinfo(nskb)->frag_list = p;
-       skb_shinfo(nskb)->gso_size = pinfo->gso_size;
-       pinfo->gso_size = 0;
-       __skb_header_release(p);
-       NAPI_GRO_CB(nskb)->last = p;
-
-       nskb->data_len += p->len;
-       nskb->truesize += p->truesize;
-       nskb->len += p->len;
-
-       *head = nskb;
-       nskb->next = p->next;
-       p->next = NULL;
-
-       p = nskb;
 
 merge:
        delta_truesize = skb->truesize;
@@ -3796,7 +3757,6 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
 }
 EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
 
-
 /**
  * skb_partial_csum_set - set up and verify partial csum values for packet
  * @skb: the skb to set
@@ -4169,19 +4129,21 @@ EXPORT_SYMBOL(skb_try_coalesce);
  */
 void skb_scrub_packet(struct sk_buff *skb, bool xnet)
 {
-       if (xnet)
-               skb_orphan(skb);
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
        skb->skb_iif = 0;
        skb->ignore_df = 0;
        skb_dst_drop(skb);
-       skb->mark = 0;
        skb_sender_cpu_clear(skb);
-       skb_init_secmark(skb);
        secpath_reset(skb);
        nf_reset(skb);
        nf_reset_trace(skb);
+
+       if (!xnet)
+               return;
+
+       skb_orphan(skb);
+       skb->mark = 0;
 }
 EXPORT_SYMBOL_GPL(skb_scrub_packet);