diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/skbuff.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 168e949df6a1..19afb18abae9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2676,21 +2676,26 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2676 | goto merge; | 2676 | goto merge; |
2677 | else if (headlen <= offset) { | 2677 | else if (headlen <= offset) { |
2678 | skb_frag_t *frag; | 2678 | skb_frag_t *frag; |
2679 | int i; | 2679 | skb_frag_t *frag2; |
2680 | int i = skb_shinfo(skb)->nr_frags; | ||
2681 | int nr_frags = skb_shinfo(p)->nr_frags + i; | ||
2682 | |||
2683 | offset -= headlen; | ||
2680 | 2684 | ||
2681 | if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags > | 2685 | if (nr_frags > MAX_SKB_FRAGS) |
2682 | MAX_SKB_FRAGS) | ||
2683 | return -E2BIG; | 2686 | return -E2BIG; |
2684 | 2687 | ||
2685 | skb_shinfo(skb)->frags[0].page_offset += offset - headlen; | 2688 | skb_shinfo(p)->nr_frags = nr_frags; |
2686 | skb_shinfo(skb)->frags[0].size -= offset - headlen; | 2689 | skb_shinfo(skb)->nr_frags = 0; |
2687 | 2690 | ||
2688 | frag = skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags; | 2691 | frag = skb_shinfo(p)->frags + nr_frags; |
2689 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | 2692 | frag2 = skb_shinfo(skb)->frags + i; |
2690 | *frag++ = skb_shinfo(skb)->frags[i]; | 2693 | do { |
2694 | *--frag = *--frag2; | ||
2695 | } while (--i); | ||
2691 | 2696 | ||
2692 | skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags; | 2697 | frag->page_offset += offset; |
2693 | skb_shinfo(skb)->nr_frags = 0; | 2698 | frag->size -= offset; |
2694 | 2699 | ||
2695 | skb->truesize -= skb->data_len; | 2700 | skb->truesize -= skb->data_len; |
2696 | skb->len -= skb->data_len; | 2701 | skb->len -= skb->data_len; |