|
@@ -4767,6 +4767,7 @@ EXPORT_SYMBOL(kfree_skb_partial);
|
|
|
bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
bool *fragstolen, int *delta_truesize)
|
|
|
{
|
|
|
+ struct skb_shared_info *to_shinfo, *from_shinfo;
|
|
|
int i, delta, len = from->len;
|
|
|
|
|
|
*fragstolen = false;
|
|
@@ -4781,7 +4782,9 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- if (skb_has_frag_list(to) || skb_has_frag_list(from))
|
|
|
+ to_shinfo = skb_shinfo(to);
|
|
|
+ from_shinfo = skb_shinfo(from);
|
|
|
+ if (to_shinfo->frag_list || from_shinfo->frag_list)
|
|
|
return false;
|
|
|
if (skb_zcopy(to) || skb_zcopy(from))
|
|
|
return false;
|
|
@@ -4790,8 +4793,8 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
struct page *page;
|
|
|
unsigned int offset;
|
|
|
|
|
|
- if (skb_shinfo(to)->nr_frags +
|
|
|
- skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
|
|
|
+ if (to_shinfo->nr_frags +
|
|
|
+ from_shinfo->nr_frags >= MAX_SKB_FRAGS)
|
|
|
return false;
|
|
|
|
|
|
if (skb_head_is_locked(from))
|
|
@@ -4802,12 +4805,12 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
page = virt_to_head_page(from->head);
|
|
|
offset = from->data - (unsigned char *)page_address(page);
|
|
|
|
|
|
- skb_fill_page_desc(to, skb_shinfo(to)->nr_frags,
|
|
|
+ skb_fill_page_desc(to, to_shinfo->nr_frags,
|
|
|
page, offset, skb_headlen(from));
|
|
|
*fragstolen = true;
|
|
|
} else {
|
|
|
- if (skb_shinfo(to)->nr_frags +
|
|
|
- skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS)
|
|
|
+ if (to_shinfo->nr_frags +
|
|
|
+ from_shinfo->nr_frags > MAX_SKB_FRAGS)
|
|
|
return false;
|
|
|
|
|
|
delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from));
|
|
@@ -4815,19 +4818,19 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
|
|
|
WARN_ON_ONCE(delta < len);
|
|
|
|
|
|
- memcpy(skb_shinfo(to)->frags + skb_shinfo(to)->nr_frags,
|
|
|
- skb_shinfo(from)->frags,
|
|
|
- skb_shinfo(from)->nr_frags * sizeof(skb_frag_t));
|
|
|
- skb_shinfo(to)->nr_frags += skb_shinfo(from)->nr_frags;
|
|
|
+ memcpy(to_shinfo->frags + to_shinfo->nr_frags,
|
|
|
+ from_shinfo->frags,
|
|
|
+ from_shinfo->nr_frags * sizeof(skb_frag_t));
|
|
|
+ to_shinfo->nr_frags += from_shinfo->nr_frags;
|
|
|
|
|
|
if (!skb_cloned(from))
|
|
|
- skb_shinfo(from)->nr_frags = 0;
|
|
|
+ from_shinfo->nr_frags = 0;
|
|
|
|
|
|
/* if the skb is not cloned this does nothing
|
|
|
* since we set nr_frags to 0.
|
|
|
*/
|
|
|
- for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
|
|
|
- skb_frag_ref(from, i);
|
|
|
+ for (i = 0; i < from_shinfo->nr_frags; i++)
|
|
|
+ __skb_frag_ref(&from_shinfo->frags[i]);
|
|
|
|
|
|
to->truesize += delta;
|
|
|
to->len += len;
|