aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-01-14 23:40:03 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-14 23:40:03 -0500
commitf557206800801410c30e53ce7a27219b2c4cf0ba (patch)
tree0c18a5766787a9dcc038eb60c8cbdf78c585ff6b /net
parentfc8c7dc1b29560c016a67a34ccff32a712b5aa86 (diff)
gro: Fix page ref count for skbs freed normally
When an skb with page frags is merged into an existing one, we cannibalise its reference count. This is OK when the skb is reused because we set nr_frags to zero in that case. However, for the case where the skb is freed through kfree_skb, we didn't clear nr_frags which causes the page to be freed prematurely. This is fixed by moving the skb resetting into skb_gro_receive. Reported-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c6
-rw-r--r--net/core/skbuff.c6
2 files changed, 6 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 7dec715293b1..60377b6c0a80 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2491,12 +2491,6 @@ EXPORT_SYMBOL(napi_gro_receive);
2491 2491
2492void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) 2492void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
2493{ 2493{
2494 skb_shinfo(skb)->nr_frags = 0;
2495
2496 skb->len -= skb->data_len;
2497 skb->truesize -= skb->data_len;
2498 skb->data_len = 0;
2499
2500 __skb_pull(skb, skb_headlen(skb)); 2494 __skb_pull(skb, skb_headlen(skb));
2501 skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); 2495 skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
2502 2496
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5110b359c758..65eac7739033 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2602,6 +2602,12 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2602 skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); 2602 skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
2603 2603
2604 skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags; 2604 skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags;
2605 skb_shinfo(skb)->nr_frags = 0;
2606
2607 skb->truesize -= skb->data_len;
2608 skb->len -= skb->data_len;
2609 skb->data_len = 0;
2610
2605 NAPI_GRO_CB(skb)->free = 1; 2611 NAPI_GRO_CB(skb)->free = 1;
2606 goto done; 2612 goto done;
2607 } 2613 }