Skip to content

Commit f1260ff

Browse files
vaverindavem330
authored andcommitted
skbuff: introduce skb_expand_head()
Like skb_realloc_headroom(), new helper increases headroom of specified skb. Unlike skb_realloc_headroom(), it does not allocate a new skb if possible; copies skb->sk on new skb when as needed and frees original skb in case of failures. This helps to simplify ip[6]_finish_output2() and a few other similar cases. Signed-off-by: Vasily Averin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fa97662 commit f1260ff

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

include/linux/skbuff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,7 @@ static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom,
11831183
int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask);
11841184
struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
11851185
unsigned int headroom);
1186+
struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom);
11861187
struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
11871188
int newtailroom, gfp_t priority);
11881189
int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,

net/core/skbuff.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,48 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
17891789
}
17901790
EXPORT_SYMBOL(skb_realloc_headroom);
17911791

1792+
/**
1793+
* skb_expand_head - reallocate header of &sk_buff
1794+
* @skb: buffer to reallocate
1795+
* @headroom: needed headroom
1796+
*
1797+
* Unlike skb_realloc_headroom, this one does not allocate a new skb
1798+
* if possible; copies skb->sk to new skb as needed
1799+
* and frees original skb in case of failures.
1800+
*
1801+
* It expect increased headroom and generates warning otherwise.
1802+
*/
1803+
1804+
struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom)
1805+
{
1806+
int delta = headroom - skb_headroom(skb);
1807+
1808+
if (WARN_ONCE(delta <= 0,
1809+
"%s is expecting an increase in the headroom", __func__))
1810+
return skb;
1811+
1812+
/* pskb_expand_head() might crash, if skb is shared */
1813+
if (skb_shared(skb)) {
1814+
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
1815+
1816+
if (likely(nskb)) {
1817+
if (skb->sk)
1818+
skb_set_owner_w(nskb, skb->sk);
1819+
consume_skb(skb);
1820+
} else {
1821+
kfree_skb(skb);
1822+
}
1823+
skb = nskb;
1824+
}
1825+
if (skb &&
1826+
pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
1827+
kfree_skb(skb);
1828+
skb = NULL;
1829+
}
1830+
return skb;
1831+
}
1832+
EXPORT_SYMBOL(skb_expand_head);
1833+
17921834
/**
17931835
* skb_copy_expand - copy and expand sk_buff
17941836
* @skb: buffer to copy

0 commit comments

Comments
 (0)