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.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 476aa3978504..c54f3664bce5 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -71,13 +71,6 @@ static kmem_cache_t *skbuff_head_cache __read_mostly;
71static kmem_cache_t *skbuff_fclone_cache __read_mostly; 71static kmem_cache_t *skbuff_fclone_cache __read_mostly;
72 72
73/* 73/*
74 * lockdep: lock class key used by skb_queue_head_init():
75 */
76struct lock_class_key skb_queue_lock_key;
77
78EXPORT_SYMBOL(skb_queue_lock_key);
79
80/*
81 * Keep out-of-line to prevent kernel bloat. 74 * Keep out-of-line to prevent kernel bloat.
82 * __builtin_return_address is not used because it is not always 75 * __builtin_return_address is not used because it is not always
83 * reliable. 76 * reliable.
@@ -256,6 +249,31 @@ nodata:
256 goto out; 249 goto out;
257} 250}
258 251
252/**
253 * __netdev_alloc_skb - allocate an skbuff for rx on a specific device
254 * @dev: network device to receive on
255 * @length: length to allocate
256 * @gfp_mask: get_free_pages mask, passed to alloc_skb
257 *
258 * Allocate a new &sk_buff and assign it a usage count of one. The
259 * buffer has unspecified headroom built in. Users should allocate
260 * the headroom they think they need without accounting for the
261 * built in space. The built in space is used for optimisations.
262 *
263 * %NULL is returned if there is no free memory.
264 */
265struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
266 unsigned int length, gfp_t gfp_mask)
267{
268 struct sk_buff *skb;
269
270 skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
271 if (likely(skb)) {
272 skb_reserve(skb, NET_SKB_PAD);
273 skb->dev = dev;
274 }
275 return skb;
276}
259 277
260static void skb_drop_list(struct sk_buff **listp) 278static void skb_drop_list(struct sk_buff **listp)
261{ 279{
@@ -846,7 +864,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
846 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) 864 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
847 return err; 865 return err;
848 866
849 for (i = 0; i < nfrags; i++) { 867 i = 0;
868 if (offset >= len)
869 goto drop_pages;
870
871 for (; i < nfrags; i++) {
850 int end = offset + skb_shinfo(skb)->frags[i].size; 872 int end = offset + skb_shinfo(skb)->frags[i].size;
851 873
852 if (end < len) { 874 if (end < len) {
@@ -854,9 +876,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
854 continue; 876 continue;
855 } 877 }
856 878
857 if (len > offset) 879 skb_shinfo(skb)->frags[i++].size = len - offset;
858 skb_shinfo(skb)->frags[i++].size = len - offset;
859 880
881drop_pages:
860 skb_shinfo(skb)->nr_frags = i; 882 skb_shinfo(skb)->nr_frags = i;
861 883
862 for (; i < nfrags; i++) 884 for (; i < nfrags; i++)
@@ -864,7 +886,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
864 886
865 if (skb_shinfo(skb)->frag_list) 887 if (skb_shinfo(skb)->frag_list)
866 skb_drop_fraglist(skb); 888 skb_drop_fraglist(skb);
867 break; 889 goto done;
868 } 890 }
869 891
870 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); 892 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +901,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
879 return -ENOMEM; 901 return -ENOMEM;
880 902
881 nfrag->next = frag->next; 903 nfrag->next = frag->next;
904 kfree_skb(frag);
882 frag = nfrag; 905 frag = nfrag;
883 *fragp = frag; 906 *fragp = frag;
884 } 907 }
@@ -897,6 +920,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
897 break; 920 break;
898 } 921 }
899 922
923done:
900 if (len > skb_headlen(skb)) { 924 if (len > skb_headlen(skb)) {
901 skb->data_len -= skb->len - len; 925 skb->data_len -= skb->len - len;
902 skb->len = len; 926 skb->len = len;
@@ -2042,6 +2066,7 @@ EXPORT_SYMBOL(__kfree_skb);
2042EXPORT_SYMBOL(kfree_skb); 2066EXPORT_SYMBOL(kfree_skb);
2043EXPORT_SYMBOL(__pskb_pull_tail); 2067EXPORT_SYMBOL(__pskb_pull_tail);
2044EXPORT_SYMBOL(__alloc_skb); 2068EXPORT_SYMBOL(__alloc_skb);
2069EXPORT_SYMBOL(__netdev_alloc_skb);
2045EXPORT_SYMBOL(pskb_copy); 2070EXPORT_SYMBOL(pskb_copy);
2046EXPORT_SYMBOL(pskb_expand_head); 2071EXPORT_SYMBOL(pskb_expand_head);
2047EXPORT_SYMBOL(skb_checksum); 2072EXPORT_SYMBOL(skb_checksum);