From d3d403b15c84f6afee2a0e6d7d96866ca86f34d7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 2 Sep 2010 23:09:32 +0000 Subject: [PATCH] --- yaml --- r: 214323 b: refs/heads/master c: 1fd63041c49c5c6ed1fe58b7bccc2de462d51e2b h: refs/heads/master i: 214321: 982de45cf87098ab26a8f1edd303658ae3238357 214319: 2e5d5d2b070278e3e00f11e59e676827a9a12064 v: v3 --- [refs] | 2 +- trunk/net/core/skbuff.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index f0967166e3c9..68caa5a5676f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9d348af47656a65a697ff55a53daf294ea4d5662 +refs/heads/master: 1fd63041c49c5c6ed1fe58b7bccc2de462d51e2b diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index c030cf894f57..2d1bc761fe4b 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -779,6 +779,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, u8 *data; int size = nhead + (skb_end_pointer(skb) - skb->head) + ntail; long off; + bool fastpath; BUG_ON(nhead < 0); @@ -800,14 +801,28 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, skb_shinfo(skb), offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - get_page(skb_shinfo(skb)->frags[i].page); + /* Check if we can avoid taking references on fragments if we own + * the last reference on skb->head. (see skb_release_data()) + */ + if (!skb->cloned) + fastpath = true; + else { + int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1; - if (skb_has_frag_list(skb)) - skb_clone_fraglist(skb); + fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta; + } - skb_release_data(skb); + if (fastpath) { + kfree(skb->head); + } else { + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + get_page(skb_shinfo(skb)->frags[i].page); + if (skb_has_frag_list(skb)) + skb_clone_fraglist(skb); + + skb_release_data(skb); + } off = (data + nhead) - skb->head; skb->head = data;