Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: add function to allocate sk_buff head without data area

Add a function to allocate a sk_buff head without any data. This will
be used by memory mapped netlink to attach data from the mmaped area
to the skb.

Additionally change skb_release_all() to check whether the skb has a
data area to allow the skb destructor to clear the data pointer in case
only a head has been allocated.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
0ebd0ac5 e32123e5

+35 -1
+6
include/linux/skbuff.h
··· 651 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 660 extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); 655 661 extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); 656 662 extern struct sk_buff *skb_clone(struct sk_buff *skb,
+29 -1
net/core/skbuff.c
··· 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 210 * __alloc_skb - allocate a network buffer 184 211 * @size: size to allocate ··· 611 584 static void skb_release_all(struct sk_buff *skb) 612 585 { 613 586 skb_release_head_state(skb); 614 - skb_release_data(skb); 587 + if (likely(skb->data)) 588 + skb_release_data(skb); 615 589 } 616 590 617 591 /**