lkml.org 
[lkml]   [2021]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH NET v4 1/7] skbuff: introduce skb_expand_head()
    Date
    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 <vvs@virtuozzo.com>
    ---
    include/linux/skbuff.h | 1 +
    net/core/skbuff.c | 42 ++++++++++++++++++++++++++++++++++++++++++
    2 files changed, 43 insertions(+)

    diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
    index b2db9cd..ec8a783 100644
    --- a/include/linux/skbuff.h
    +++ b/include/linux/skbuff.h
    @@ -1179,6 +1179,7 @@ static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom,
    int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask);
    struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
    unsigned int headroom);
    +struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom);
    struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
    int newtailroom, gfp_t priority);
    int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
    diff --git a/net/core/skbuff.c b/net/core/skbuff.c
    index fc7942c..0c70b2b 100644
    --- a/net/core/skbuff.c
    +++ b/net/core/skbuff.c
    @@ -1786,6 +1786,48 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
    EXPORT_SYMBOL(skb_realloc_headroom);

    /**
    + * skb_expand_head - reallocate header of &sk_buff
    + * @skb: buffer to reallocate
    + * @headroom: needed headroom
    + *
    + * Unlike skb_realloc_headroom, this one does not allocate a new skb
    + * if possible; copies skb->sk to new skb as needed
    + * and frees original skb in case of failures.
    + *
    + * It expect increased headroom and generates warning otherwise.
    + */
    +
    +struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom)
    +{
    + int delta = headroom - skb_headroom(skb);
    +
    + if (WARN_ONCE(delta <= 0,
    + "%s is expecting an increase in the headroom", __func__))
    + return skb;
    +
    + /* pskb_expand_head() might crash, if skb is shared */
    + if (skb_shared(skb)) {
    + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
    +
    + if (likely(nskb)) {
    + if (skb->sk)
    + skb_set_owner_w(nskb, skb->sk);
    + consume_skb(skb);
    + } else {
    + kfree_skb(skb);
    + }
    + skb = nskb;
    + }
    + if (skb &&
    + pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
    + kfree_skb(skb);
    + skb = NULL;
    + }
    + return skb;
    +}
    +EXPORT_SYMBOL(skb_expand_head);
    +
    +/**
    * skb_copy_expand - copy and expand sk_buff
    * @skb: buffer to copy
    * @newheadroom: new free bytes at head
    --
    1.8.3.1
    \
     
     \ /
      Last update: 2021-08-06 09:52    [W:4.182 / U:0.424 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site