diff options
author | Patrick McHardy <kaber@trash.net> | 2013-04-17 02:46:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-19 14:57:57 -0400 |
commit | 0ebd0ac5ff01ebf412e1bd3c33620ef7ffc5d866 (patch) | |
tree | 0f91f0bb25b2674c97ac97ff05e572f6d2394562 /net/core | |
parent | e32123e59871b9389d5b3fe9318611c7f1d1307a (diff) |
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>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 30 |
1 files changed, 29 insertions, 1 deletions
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 | /** |