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>
This commit is contained in:
parent
e32123e598
commit
0ebd0ac5ff
|
@ -651,6 +651,12 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
|
||||||
return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
|
return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct sk_buff *__alloc_skb_head(gfp_t priority, int node);
|
||||||
|
static inline struct sk_buff *alloc_skb_head(gfp_t priority)
|
||||||
|
{
|
||||||
|
return __alloc_skb_head(priority, -1);
|
||||||
|
}
|
||||||
|
|
||||||
extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
|
extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
|
||||||
extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
|
extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
|
||||||
extern struct sk_buff *skb_clone(struct sk_buff *skb,
|
extern struct sk_buff *skb_clone(struct sk_buff *skb,
|
||||||
|
|
|
@ -179,6 +179,33 @@ out:
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
/* Get the HEAD */
|
||||||
|
skb = kmem_cache_alloc_node(skbuff_head_cache,
|
||||||
|
gfp_mask & ~__GFP_DMA, node);
|
||||||
|
if (!skb)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only clear those fields we need to clear, not those that we will
|
||||||
|
* actually initialise below. Hence, don't put any more fields after
|
||||||
|
* the tail pointer in struct sk_buff!
|
||||||
|
*/
|
||||||
|
memset(skb, 0, offsetof(struct sk_buff, tail));
|
||||||
|
skb->data = NULL;
|
||||||
|
skb->truesize = sizeof(struct sk_buff);
|
||||||
|
atomic_set(&skb->users, 1);
|
||||||
|
|
||||||
|
#ifdef NET_SKBUFF_DATA_USES_OFFSET
|
||||||
|
skb->mac_header = ~0U;
|
||||||
|
#endif
|
||||||
|
out:
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __alloc_skb - allocate a network buffer
|
* __alloc_skb - allocate a network buffer
|
||||||
* @size: size to allocate
|
* @size: size to allocate
|
||||||
|
@ -584,6 +611,7 @@ static void skb_release_head_state(struct sk_buff *skb)
|
||||||
static void skb_release_all(struct sk_buff *skb)
|
static void skb_release_all(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
skb_release_head_state(skb);
|
skb_release_head_state(skb);
|
||||||
|
if (likely(skb->data))
|
||||||
skb_release_data(skb);
|
skb_release_data(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue