diff options
Diffstat (limited to 'net/core/skbuff.c')
| -rw-r--r-- | net/core/skbuff.c | 15 | 
1 files changed, 11 insertions, 4 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 10bde7c6db44..30b523fa4ad2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -5276,11 +5276,18 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,  	if (skb_cloned(to))  		return false; -	/* The page pool signature of struct page will eventually figure out -	 * which pages can be recycled or not but for now let's prohibit slab -	 * allocated and page_pool allocated SKBs from being coalesced. +	/* In general, avoid mixing slab allocated and page_pool allocated +	 * pages within the same SKB. However when @to is not pp_recycle and +	 * @from is cloned, we can transition frag pages from page_pool to +	 * reference counted. +	 * +	 * On the other hand, don't allow coalescing two pp_recycle SKBs if +	 * @from is cloned, in case the SKB is using page_pool fragment +	 * references (PP_FLAG_PAGE_FRAG). Since we only take full page +	 * references for cloned SKBs at the moment that would result in +	 * inconsistent reference counts.  	 */ -	if (to->pp_recycle != from->pp_recycle) +	if (to->pp_recycle != (from->pp_recycle && !skb_cloned(from)))  		return false;  	if (len <= skb_tailroom(to)) {  | 
