aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 104f8444754..8814a9a52f4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -778,6 +778,28 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
778 778
779 size = SKB_DATA_ALIGN(size); 779 size = SKB_DATA_ALIGN(size);
780 780
781 /* Check if we can avoid taking references on fragments if we own
782 * the last reference on skb->head. (see skb_release_data())
783 */
784 if (!skb->cloned)
785 fastpath = true;
786 else {
787 int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1;
788
789 fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta;
790 }
791
792 if (fastpath &&
793 size + sizeof(struct skb_shared_info) <= ksize(skb->head)) {
794 memmove(skb->head + size, skb_shinfo(skb),
795 offsetof(struct skb_shared_info,
796 frags[skb_shinfo(skb)->nr_frags]));
797 memmove(skb->head + nhead, skb->head,
798 skb_tail_pointer(skb) - skb->head);
799 off = nhead;
800 goto adjust_others;
801 }
802
781 data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); 803 data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
782 if (!data) 804 if (!data)
783 goto nodata; 805 goto nodata;
@@ -791,17 +813,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
791 skb_shinfo(skb), 813 skb_shinfo(skb),
792 offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); 814 offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
793 815
794 /* Check if we can avoid taking references on fragments if we own
795 * the last reference on skb->head. (see skb_release_data())
796 */
797 if (!skb->cloned)
798 fastpath = true;
799 else {
800 int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1;
801
802 fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta;
803 }
804
805 if (fastpath) { 816 if (fastpath) {
806 kfree(skb->head); 817 kfree(skb->head);
807 } else { 818 } else {
@@ -816,6 +827,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
816 off = (data + nhead) - skb->head; 827 off = (data + nhead) - skb->head;
817 828
818 skb->head = data; 829 skb->head = data;
830adjust_others:
819 skb->data += off; 831 skb->data += off;
820#ifdef NET_SKBUFF_DATA_USES_OFFSET 832#ifdef NET_SKBUFF_DATA_USES_OFFSET
821 skb->end = size; 833 skb->end = size;