diff options
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 47 |
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; | |||
71 | static kmem_cache_t *skbuff_fclone_cache __read_mostly; | 71 | static kmem_cache_t *skbuff_fclone_cache __read_mostly; |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * lockdep: lock class key used by skb_queue_head_init(): | ||
75 | */ | ||
76 | struct lock_class_key skb_queue_lock_key; | ||
77 | |||
78 | EXPORT_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 | */ | ||
265 | struct 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 | ||
260 | static void skb_drop_list(struct sk_buff **listp) | 278 | static 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 | ||
881 | drop_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 | ||
923 | done: | ||
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); | |||
2042 | EXPORT_SYMBOL(kfree_skb); | 2066 | EXPORT_SYMBOL(kfree_skb); |
2043 | EXPORT_SYMBOL(__pskb_pull_tail); | 2067 | EXPORT_SYMBOL(__pskb_pull_tail); |
2044 | EXPORT_SYMBOL(__alloc_skb); | 2068 | EXPORT_SYMBOL(__alloc_skb); |
2069 | EXPORT_SYMBOL(__netdev_alloc_skb); | ||
2045 | EXPORT_SYMBOL(pskb_copy); | 2070 | EXPORT_SYMBOL(pskb_copy); |
2046 | EXPORT_SYMBOL(pskb_expand_head); | 2071 | EXPORT_SYMBOL(pskb_expand_head); |
2047 | EXPORT_SYMBOL(skb_checksum); | 2072 | EXPORT_SYMBOL(skb_checksum); |