diff options
-rw-r--r-- | include/linux/skbuff.h | 6 | ||||
-rw-r--r-- | net/core/skbuff.c | 30 |
2 files changed, 35 insertions, 1 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f5bed7b31954..2e0ced1af3b1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -651,6 +651,12 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, | |||
651 | return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); | 651 | return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); |
652 | } | 652 | } |
653 | 653 | ||
654 | extern struct sk_buff *__alloc_skb_head(gfp_t priority, int node); | ||
655 | static inline struct sk_buff *alloc_skb_head(gfp_t priority) | ||
656 | { | ||
657 | return __alloc_skb_head(priority, -1); | ||
658 | } | ||
659 | |||
654 | extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); | 660 | extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); |
655 | extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); | 661 | extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); |
656 | extern struct sk_buff *skb_clone(struct sk_buff *skb, | 662 | extern struct sk_buff *skb_clone(struct sk_buff *skb, |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a92d9e7d10f7..898cf5c566f9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -179,6 +179,33 @@ out: | |||
179 | * | 179 | * |
180 | */ | 180 | */ |
181 | 181 | ||
182 | struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node) | ||
183 | { | ||
184 | struct sk_buff *skb; | ||
185 | |||
186 | /* Get the HEAD */ | ||
187 | skb = kmem_cache_alloc_node(skbuff_head_cache, | ||
188 | gfp_mask & ~__GFP_DMA, node); | ||
189 | if (!skb) | ||
190 | goto out; | ||
191 | |||
192 | /* | ||
193 | * Only clear those fields we need to clear, not those that we will | ||
194 | * actually initialise below. Hence, don't put any more fields after | ||
195 | * the tail pointer in struct sk_buff! | ||
196 | */ | ||
197 | memset(skb, 0, offsetof(struct sk_buff, tail)); | ||
198 | skb->data = NULL; | ||
199 | skb->truesize = sizeof(struct sk_buff); | ||
200 | atomic_set(&skb->users, 1); | ||
201 | |||
202 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | ||
203 | skb->mac_header = ~0U; | ||
204 | #endif | ||
205 | out: | ||
206 | return skb; | ||
207 | } | ||
208 | |||
182 | /** | 209 | /** |
183 | * __alloc_skb - allocate a network buffer | 210 | * __alloc_skb - allocate a network buffer |
184 | * @size: size to allocate | 211 | * @size: size to allocate |
@@ -584,7 +611,8 @@ static void skb_release_head_state(struct sk_buff *skb) | |||
584 | static void skb_release_all(struct sk_buff *skb) | 611 | static void skb_release_all(struct sk_buff *skb) |
585 | { | 612 | { |
586 | skb_release_head_state(skb); | 613 | skb_release_head_state(skb); |
587 | skb_release_data(skb); | 614 | if (likely(skb->data)) |
615 | skb_release_data(skb); | ||
588 | } | 616 | } |
589 | 617 | ||
590 | /** | 618 | /** |