From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:10
As the 32-bit arch with 64-bit DMA seems to rare those days,
and page pool is carrying a lot of code and complexity for
systems that possibly don't exist.
So disable dma mapping support for such systems, if drivers
really want to work on such systems, they have to implement
their own DMA-mapping fallback tracking outside page_pool.
Signed-off-by: Yunsheng Lin <redacted>
---
include/linux/mm_types.h | 13 +------------
include/net/page_pool.h | 12 +-----------
net/core/page_pool.c | 10 ++++++----
3 files changed, 8 insertions(+), 27 deletions(-)
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;+if((pool->p.dma_dir!=DMA_FROM_DEVICE)&&(pool->p.dma_dir!=DMA_BIDIRECTIONAL))return-EINVAL;
@@ -69,10 +75,6 @@ static int page_pool_init(struct page_pool *pool,*/}-if(PAGE_POOL_DMA_USE_PP_FRAG_COUNT&&-pool->p.flags&PP_FLAG_PAGE_FRAG)-return-EINVAL;-if(ptr_ring_init(&pool->ring,ring_qsize,GFP_KERNEL)<0)return-ENOMEM;
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:13
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Signed-off-by: Yunsheng Lin <redacted>
---
include/linux/skbuff.h | 2 +-
net/core/page_pool.c | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:17
As the page->pp_frag_count need incrementing for pp page
tracking support, so change BIAS_MAX to (LONG_MAX / 2) to
avoid overflowing.
Signed-off-by: Yunsheng Lin <redacted>
---
net/core/page_pool.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:18
As pp_magic is used to identify pp page for a skb's frag page
in previous patch, so do the similar handling for the head
page of a skb too.
And it seems head to frag converting for a skb during GRO and
GSO processing does not need handling when using pp_magic to
identify pp page for a skb' head page and frag page, see
NAPI_GRO_FREE_STOLEN_HEAD for GRO in skb_gro_receive() and
skb_head_frag_to_page_desc() for GSO in skb_segment().
As pp_magic only exist in the head page of a compound page,
and the freeing of a head page for a skb is eventually operated
on the head page of a compound page for both pp and non-pp
page, so use virt_to_head_page() and __page_frag_cache_drain()
in skb_free_head() to avoid unnecessary virt_to_head_page()
calling in page_frag_free().
Signed-off-by: Yunsheng Lin <redacted>
---
include/linux/skbuff.h | 15 ---------------
net/core/skbuff.c | 11 +++++++++--
2 files changed, 9 insertions(+), 17 deletions(-)
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:24
As we have used pp_magic to identify pp page for the head
and frag page of a skb, the skb->pp_recycle is not used, so
remove it.
Signed-off-by: Yunsheng Lin <redacted>
---
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ------
drivers/net/ethernet/marvell/mvneta.c | 2 --
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 4 +---
drivers/net/ethernet/ti/cpsw.c | 2 --
drivers/net/ethernet/ti/cpsw_new.c | 2 --
include/linux/skbuff.h | 12 +----------
net/core/skbuff.c | 21 +------------------
7 files changed, 3 insertions(+), 46 deletions(-)
@@ -430,8 +430,6 @@ static void cpsw_rx_handler(void *token, int len, int status)cpts_rx_timestamp(cpsw->cpts,skb);skb->protocol=eth_type_trans(skb,ndev);-/* mark skb for recycling */-skb_mark_for_recycle(skb);netif_receive_skb(skb);ndev->stats.rx_bytes+=len;
@@ -374,8 +374,6 @@ static void cpsw_rx_handler(void *token, int len, int status)cpts_rx_timestamp(cpsw->cpts,skb);skb->protocol=eth_type_trans(skb,ndev);-/* mark skb for recycling */-skb_mark_for_recycle(skb);netif_receive_skb(skb);ndev->stats.rx_bytes+=len;
@@ -681,17 +681,6 @@ static void skb_release_data(struct sk_buff *skb)kfree_skb_list(shinfo->frag_list);skb_free_head(skb);-exit:-/* When we clone an SKB we copy the reycling bit. The pp_recycle-*bitisonlysetontheheadthough,soinordertoavoidraces-*whiletryingtorecyclefragmentson__skb_frag_unref()weneed-*tomakeoneSKBresponsiblefortriggeringtherecyclepath.-*SodisabletherecyclingbitifanSKBisclonedandwehave-*additionalreferencestotothefragmentedpartoftheSKB.-*EventuallythelastSKBwillhavetherecyclingbitsetandit's-*datarefsetto0,whichwilltriggertherecycling-*/-skb->pp_recycle=0;}/*
@@ -5368,13 +5356,6 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,if(skb_cloned(to))returnfalse;-/* The page pool signature of struct page will eventually figure out-*whichpagescanberecycledornotbutfornowlet'sprohibitslab-*allocatedandpage_poolallocatedSKBsfrombeingcoalesced.-*/-if(to->pp_recycle!=from->pp_recycle)-returnfalse;-if(len<=skb_tailroom(to)){if(len)BUG_ON(skb_copy_bits(from,0,skb_put(to,len),len));
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:29
Currently when PP_FLAG_PAGE_FRAG is set, the caller is not
expected to call page_pool_alloc_pages() directly because of
the PP_FLAG_PAGE_FRAG checking in __page_pool_put_page().
The patch removes the above checking to enable non-split page
support when PP_FLAG_PAGE_FRAG is set.
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Yunsheng Lin <redacted>
---
net/core/page_pool.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
@@ -315,11 +315,14 @@ struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp)/* Fast-path: Get a page from cache */page=__page_pool_get_cached(pool);-if(page)-returnpage;/* Slow-path: cache empty, do real allocation */-page=__page_pool_alloc_pages_slow(pool,gfp);+if(!page)+page=__page_pool_alloc_pages_slow(pool,gfp);++if(likely(page))+page_pool_set_frag_count(page,1);+returnpage;}EXPORT_SYMBOL(page_pool_alloc_pages);
@@ -428,8 +431,7 @@ __page_pool_put_page(struct page_pool *pool, struct page *page,unsignedintdma_sync_size,boolallow_direct){/* It is not the last user for the page frag case */-if(pool->p.flags&PP_FLAG_PAGE_FRAG&&-page_pool_atomic_sub_frag_count_return(page,1))+if(page_pool_atomic_sub_frag_count_return(page,1))returnNULL;/* This allocator is optimized for the XDP mode that uses
From: Yunsheng Lin <hidden> Date: 2021-09-22 09:43:30
As the skb->pp_recycle and page->pp_magic may not be enough
to track if a frag page is from page pool after the calling
of __skb_frag_ref(), mostly because of a data race, see:
commit 2cc3aeb5eccc ("skbuff: Fix a potential race while
recycling page_pool packets").
There may be clone and expand head case that might lose the
track if a frag page is from page pool or not.
And not being able to keep track of pp page may cause problem
for the skb_split() case in tso_fragment() too:
Supposing a skb has 3 frag pages, all coming from a page pool,
and is split to skb1 and skb2:
skb1: first frag page + first half of second frag page
skb2: second half of second frag page + third frag page
How do we set the skb->pp_recycle of skb1 and skb2?
1. If we set both of them to 1, then we may have a similar
race as the above commit for second frag page.
2. If we set only one of them to 1, then we may have resource
leaking problem as both first frag page and third frag page
are indeed from page pool.
So increment the frag count when __skb_frag_ref() is called,
and only use page->pp_magic to indicate if a frag page is from
page pool, to avoid the above data race.
Signed-off-by: Yunsheng Lin <redacted>
---
drivers/net/ethernet/marvell/sky2.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +-
include/linux/skbuff.h | 30 +++++++++++++++++-----
include/net/page_pool.h | 19 +++++++++++++-
net/core/page_pool.c | 14 +---------
net/core/skbuff.c | 4 +--
net/tls/tls_device.c | 2 +-
7 files changed, 48 insertions(+), 25 deletions(-)
@@ -231,6 +231,23 @@ static inline void page_pool_set_frag_count(struct page *page, long nr)atomic_long_set(&page->pp_frag_count,nr);}+staticinlinevoidpage_pool_atomic_inc_frag_count(structpage*page)+{+atomic_long_inc(&page->pp_frag_count);+}++staticinlineboolpage_pool_is_pp_page(structpage*page)+{+/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation+*inordertopreserveanyexistingbits,suchasbit0forthe+*headpageofcompoundpageandbit1forpfmemallocpage,so+*maskthosebitsforfreeingsidewhendoingbelowchecking,+*andpage_is_pfmemalloc()ischeckedin__page_pool_put_page()+*toavoidrecyclingthepfmemallocpage.+*/+return(page->pp_magic&~0x3UL)==PP_SIGNATURE;+}+staticinlinelongpage_pool_atomic_sub_frag_count_return(structpage*page,longnr){
@@ -738,20 +738,10 @@ void page_pool_update_nid(struct page_pool *pool, int new_nid)}EXPORT_SYMBOL(page_pool_update_nid);-boolpage_pool_return_skb_page(structpage*page)+voidpage_pool_return_skb_page(structpage*page){structpage_pool*pp;-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation-*inordertopreserveanyexistingbits,suchasbit0forthe-*headpageofcompoundpageandbit1forpfmemallocpage,so-*maskthosebitsforfreeingsidewhendoingbelowchecking,-*andpage_is_pfmemalloc()ischeckedin__page_pool_put_page()-*toavoidrecyclingthepfmemallocpage.-*/-if(unlikely((page->pp_magic&~0x3UL)!=PP_SIGNATURE))-returnfalse;-pp=page->pp;/* Driver set this to memory recycling info. Reset it on recycle.
@@ -3563,7 +3563,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)fragto=&skb_shinfo(tgt)->frags[merge];skb_frag_size_add(fragto,skb_frag_size(fragfrom));-__skb_frag_unref(fragfrom,skb->pp_recycle);+__skb_frag_unref(fragfrom);}/* Reposition in the original skb */
Hi Yunsheng,
On Wed, Sep 22, 2021 at 05:41:24PM +0800, Yunsheng Lin wrote:
Patch 1: disable dma mapping support for 32-bit arch with 64-bit
DMA.
Patch 2: support non-split page when PP_FLAG_PAGE_FRAG is set.
patch 3: avoid calling compound_head() for skb frag page
Patch 4-7: use pp_magic to identify pp page uniquely.
There's some subtle changes in this patchset that might affect XDP.
What I forgot when I proposed removing the recycling bit, is that it also
serves as an 'opt-in' mechanism for drivers that want to use page_pool but
do the recycling internally. With that removed we need to make sure
nothing bad happens to them. In theory the page refcnt for mlx5
specifically will be elevated, so we'll just end up unmapping the buffer.
Arguably we could add a similar mechanism internally into page pool,
which would allow us to enable and disable recycling, but that's
an extra if per packet allocation and I don't know if we want that on the XDP
case.
A few numbers pre/post patch for XDP would help, but iirc hns3 doesn't have
XDP support yet?
It's plumbers week so I'll do some testing starting Monday.
Thanks
/Ilias
V3:
1. add patch 1/4/6/7.
2. use pp_magic to identify pp page uniquely too.
3. avoid unnecessary compound_head() calling.
V2: add patch 2, adjust the commit log accroding to the discussion
in V1, and fix a compiler error reported by kernel test robot.
Yunsheng Lin (7):
page_pool: disable dma mapping support for 32-bit arch with 64-bit DMA
page_pool: support non-split page with PP_FLAG_PAGE_FRAG
pool_pool: avoid calling compound_head() for skb frag page
page_pool: change BIAS_MAX to support incrementing
skbuff: keep track of pp page when __skb_frag_ref() is called
skbuff: only use pp_magic identifier for a skb' head page
skbuff: remove unused skb->pp_recycle
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ---
drivers/net/ethernet/marvell/mvneta.c | 2 -
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 4 +-
drivers/net/ethernet/marvell/sky2.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +-
drivers/net/ethernet/ti/cpsw.c | 2 -
drivers/net/ethernet/ti/cpsw_new.c | 2 -
include/linux/mm_types.h | 13 +-----
include/linux/skbuff.h | 39 ++++++++----------
include/net/page_pool.h | 31 ++++++++------
net/core/page_pool.c | 40 +++++++------------
net/core/skbuff.c | 36 ++++++-----------
net/tls/tls_device.c | 2 +-
13 files changed, 67 insertions(+), 114 deletions(-)
--
2.33.0
On Wed, Sep 22, 2021 at 05:41:27PM +0800, Yunsheng Lin wrote:
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Doesn't that rely on the driver mostly (i.e what's passed in skb_frag_set_page() ?
None of the current netstack code assumes bv_page is the head page of a
compound page. Since our page_pool allocator can will allocate compound
pages for order > 0, why should we rely on it ?
Thanks
/Ilias
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so
(+cc Matthew) but this looks safe to me.
On Wed, 22 Sept 2021 at 12:43, Yunsheng Lin [off-list ref] wrote:
quoted hunk
As the 32-bit arch with 64-bit DMA seems to rare those days,
and page pool is carrying a lot of code and complexity for
systems that possibly don't exist.
So disable dma mapping support for such systems, if drivers
really want to work on such systems, they have to implement
their own DMA-mapping fallback tracking outside page_pool.
Signed-off-by: Yunsheng Lin <redacted>
---
include/linux/mm_types.h | 13 +------------
include/net/page_pool.h | 12 +-----------
net/core/page_pool.c | 10 ++++++----
3 files changed, 8 insertions(+), 27 deletions(-)
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;+if((pool->p.dma_dir!=DMA_FROM_DEVICE)&&(pool->p.dma_dir!=DMA_BIDIRECTIONAL))return-EINVAL;
@@ -69,10 +75,6 @@ static int page_pool_init(struct page_pool *pool,*/}-if(PAGE_POOL_DMA_USE_PP_FRAG_COUNT&&-pool->p.flags&PP_FLAG_PAGE_FRAG)-return-EINVAL;-if(ptr_ring_init(&pool->ring,ring_qsize,GFP_KERNEL)<0)return-ENOMEM;--
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
-Jesper
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
I am fine with both. In any case though the aforementioned driver can
just remove PP_FLAG_DMA_MAP and do it's own mappings.
Regards
/Ilias
From: Yunsheng Lin <hidden> Date: 2021-09-23 11:12:46
On 2021/9/23 15:07, Ilias Apalodimas wrote:
Hi Yunsheng,
On Wed, Sep 22, 2021 at 05:41:24PM +0800, Yunsheng Lin wrote:
quoted
Patch 1: disable dma mapping support for 32-bit arch with 64-bit
DMA.
Patch 2: support non-split page when PP_FLAG_PAGE_FRAG is set.
patch 3: avoid calling compound_head() for skb frag page
Patch 4-7: use pp_magic to identify pp page uniquely.
There's some subtle changes in this patchset that might affect XDP.
What I forgot when I proposed removing the recycling bit, is that it also
serves as an 'opt-in' mechanism for drivers that want to use page_pool but
do the recycling internally. With that removed we need to make sure
nothing bad happens to them. In theory the page refcnt for mlx5
It seems odd that mlx5 is adding its own page cache on top of page pool,
is it about support both "struct sk_buff" and "struct xdp_buff" for the
same queue?
specifically will be elevated, so we'll just end up unmapping the buffer.
Arguably we could add a similar mechanism internally into page pool,
which would allow us to enable and disable recycling, but that's
an extra if per packet allocation and I don't know if we want that on the XDP
case.
Or we could change mlx5e_rx_cache_get() to check for "page->pp_frag_count
== 1" too, and adjust mlx5e_page_release() accordingly?
A few numbers pre/post patch for XDP would help, but iirc hns3 doesn't have
XDP support yet?
You are right, hns3 doesn't have XDP support yet.
It's plumbers week so I'll do some testing starting Monday.
Thanks
/Ilias
quoted
V3:
1. add patch 1/4/6/7.
2. use pp_magic to identify pp page uniquely too.
3. avoid unnecessary compound_head() calling.
V2: add patch 2, adjust the commit log accroding to the discussion
in V1, and fix a compiler error reported by kernel test robot.
Yunsheng Lin (7):
page_pool: disable dma mapping support for 32-bit arch with 64-bit DMA
page_pool: support non-split page with PP_FLAG_PAGE_FRAG
pool_pool: avoid calling compound_head() for skb frag page
page_pool: change BIAS_MAX to support incrementing
skbuff: keep track of pp page when __skb_frag_ref() is called
skbuff: only use pp_magic identifier for a skb' head page
skbuff: remove unused skb->pp_recycle
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ---
drivers/net/ethernet/marvell/mvneta.c | 2 -
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 4 +-
drivers/net/ethernet/marvell/sky2.c | 2 +-
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +-
drivers/net/ethernet/ti/cpsw.c | 2 -
drivers/net/ethernet/ti/cpsw_new.c | 2 -
include/linux/mm_types.h | 13 +-----
include/linux/skbuff.h | 39 ++++++++----------
include/net/page_pool.h | 31 ++++++++------
net/core/page_pool.c | 40 +++++++------------
net/core/skbuff.c | 36 ++++++-----------
net/tls/tls_device.c | 2 +-
13 files changed, 67 insertions(+), 114 deletions(-)
--
2.33.0
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
Will change it to EOPNOTSUPP, thanks.
I am fine with both. In any case though the aforementioned driver can
just remove PP_FLAG_DMA_MAP and do it's own mappings.
Regards
/Ilias
From: Yunsheng Lin <hidden> Date: 2021-09-23 11:24:30
On 2021/9/23 16:33, Ilias Apalodimas wrote:
On Wed, Sep 22, 2021 at 05:41:27PM +0800, Yunsheng Lin wrote:
quoted
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Doesn't that rely on the driver mostly (i.e what's passed in skb_frag_set_page() ?
None of the current netstack code assumes bv_page is the head page of a
compound page. Since our page_pool allocator can will allocate compound
pages for order > 0, why should we rely on it ?
As the page pool alloc function return 'struct page *' to the caller, which
is the head page of a compound pages for order > 0, so I assume the caller
will pass that to skb_frag_set_page().
For non-pp page, I assume it is ok whether the page is a head page or tail
page, as the pp_magic for both of them are not set with PP_SIGNATURE.
Or should we play safe here, and do the trick as skb_free_head() does in
patch 6?
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so
On Thu, 23 Sept 2021 at 14:24, Yunsheng Lin [off-list ref] wrote:
On 2021/9/23 16:33, Ilias Apalodimas wrote:
quoted
On Wed, Sep 22, 2021 at 05:41:27PM +0800, Yunsheng Lin wrote:
quoted
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Doesn't that rely on the driver mostly (i.e what's passed in skb_frag_set_page() ?
None of the current netstack code assumes bv_page is the head page of a
compound page. Since our page_pool allocator can will allocate compound
pages for order > 0, why should we rely on it ?
As the page pool alloc function return 'struct page *' to the caller, which
is the head page of a compound pages for order > 0, so I assume the caller
will pass that to skb_frag_set_page().
Yea that's exactly the assumption I was afraid of.
Sure not passing the head page might seem weird atm and the assumption
stands, but the point is we shouldn't blow up the entire network stack
if someone does that eventually.
For non-pp page, I assume it is ok whether the page is a head page or tail
page, as the pp_magic for both of them are not set with PP_SIGNATURE.
Yea that's true, although we removed the checking for coalescing
recyclable and non-recyclable SKBs, the next patch first checks the
signature before trying to do anything with the skb.
Or should we play safe here, and do the trick as skb_free_head() does in
patch 6?
I don't think the &1 will even be measurable, so I'd suggest just
dropping this and play safe?
Cheers
/Ilias
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so--
Currently when PP_FLAG_PAGE_FRAG is set, the caller is not
expected to call page_pool_alloc_pages() directly because of
the PP_FLAG_PAGE_FRAG checking in __page_pool_put_page().
The patch removes the above checking to enable non-split page
support when PP_FLAG_PAGE_FRAG is set.
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Yunsheng Lin <redacted>
---
net/core/page_pool.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
@@ -315,11 +315,14 @@ struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp)/* Fast-path: Get a page from cache */page=__page_pool_get_cached(pool);-if(page)-returnpage;/* Slow-path: cache empty, do real allocation */-page=__page_pool_alloc_pages_slow(pool,gfp);+if(!page)+page=__page_pool_alloc_pages_slow(pool,gfp);++if(likely(page))+page_pool_set_frag_count(page,1);+
@@ -428,8 +431,7 @@ __page_pool_put_page(struct page_pool *pool, struct page *page, unsigned int dma_sync_size, bool allow_direct) { /* It is not the last user for the page frag case */- if (pool->p.flags & PP_FLAG_PAGE_FRAG &&- page_pool_atomic_sub_frag_count_return(page, 1))+ if (page_pool_atomic_sub_frag_count_return(page, 1)) return NULL;
This adds an atomic_long_read, even when PP_FLAG_PAGE_FRAG is not set.
/* This allocator is optimized for the XDP mode that uses
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
Will change it to EOPNOTSUPP, thanks.
Mind sending this one separately (and you can keep my reviewed-by). It
fits nicely on it's own and since I am not sure about the rest of the
changes yet, it would be nice to get this one in.
Cheers
/Ilias
quoted
I am fine with both. In any case though the aforementioned driver can
just remove PP_FLAG_DMA_MAP and do it's own mappings.
Regards
/Ilias
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
Will change it to EOPNOTSUPP, thanks.
Mind sending this one separately (and you can keep my reviewed-by). It
fits nicely on it's own and since I am not sure about the rest of the
changes yet, it would be nice to get this one in.
I am not sure sending this one separately really makes sense, as it is
mainly used to make supporting the "keep track of pp page when __skb_frag_ref()
is called" in patch 5 easier.
Cheers
/Ilias
quoted
quoted
I am fine with both. In any case though the aforementioned driver can
just remove PP_FLAG_DMA_MAP and do it's own mappings.
Regards
/Ilias
From: Yunsheng Lin <hidden> Date: 2021-09-24 07:23:23
On 2021/9/23 20:08, Jesper Dangaard Brouer wrote:
On 22/09/2021 11.41, Yunsheng Lin wrote:
quoted
Currently when PP_FLAG_PAGE_FRAG is set, the caller is not
expected to call page_pool_alloc_pages() directly because of
the PP_FLAG_PAGE_FRAG checking in __page_pool_put_page().
The patch removes the above checking to enable non-split page
support when PP_FLAG_PAGE_FRAG is set.
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Yunsheng Lin <redacted>
---
net/core/page_pool.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
@@ -315,11 +315,14 @@ struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp)/* Fast-path: Get a page from cache */page=__page_pool_get_cached(pool);-if(page)-returnpage;/* Slow-path: cache empty, do real allocation */-page=__page_pool_alloc_pages_slow(pool,gfp);+if(!page)+page=__page_pool_alloc_pages_slow(pool,gfp);++if(likely(page))+page_pool_set_frag_count(page,1);+
@@ -428,8 +431,7 @@ __page_pool_put_page(struct page_pool *pool, struct page *page, unsigned int dma_sync_size, bool allow_direct) { /* It is not the last user for the page frag case */- if (pool->p.flags & PP_FLAG_PAGE_FRAG &&- page_pool_atomic_sub_frag_count_return(page, 1))+ if (page_pool_atomic_sub_frag_count_return(page, 1)) return NULL;
This adds an atomic_long_read, even when PP_FLAG_PAGE_FRAG is not set.
The point here is to have consistent handling for both PP_FLAG_PAGE_FRAG
and non-PP_FLAG_PAGE_FRAG case in the following patch.
As the page->_refcount is accessed in "page_ref_count(page) == 1" checking
in __page_pool_put_page(), and page->pp_frag_count is most likely in the
same cache line as the page->_refcount, So I am not expecting a noticable
overhead here.
Anyway, will use the above benchmarks as an example to verify it.
quoted
/* This allocator is optimized for the XDP mode that uses
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
Will change it to EOPNOTSUPP, thanks.
Mind sending this one separately (and you can keep my reviewed-by). It
fits nicely on it's own and since I am not sure about the rest of the
changes yet, it would be nice to get this one in.
I am not sure sending this one separately really makes sense, as it is
mainly used to make supporting the "keep track of pp page when __skb_frag_ref()
is called" in patch 5 easier.
It rips out support for devices that are 32bit and have 64bit dma and
make the whole code easier to follow. I thought we agreed on removing
the support for those devices regardless didn't we?
Regards
/Ilias
From: Yunsheng Lin <hidden> Date: 2021-09-24 07:33:59
On 2021/9/23 19:47, Ilias Apalodimas wrote:
On Thu, 23 Sept 2021 at 14:24, Yunsheng Lin [off-list ref] wrote:
quoted
On 2021/9/23 16:33, Ilias Apalodimas wrote:
quoted
On Wed, Sep 22, 2021 at 05:41:27PM +0800, Yunsheng Lin wrote:
quoted
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Doesn't that rely on the driver mostly (i.e what's passed in skb_frag_set_page() ?
None of the current netstack code assumes bv_page is the head page of a
compound page. Since our page_pool allocator can will allocate compound
pages for order > 0, why should we rely on it ?
As the page pool alloc function return 'struct page *' to the caller, which
is the head page of a compound pages for order > 0, so I assume the caller
will pass that to skb_frag_set_page().
Yea that's exactly the assumption I was afraid of.
Sure not passing the head page might seem weird atm and the assumption
stands, but the point is we shouldn't blow up the entire network stack
if someone does that eventually.
quoted
For non-pp page, I assume it is ok whether the page is a head page or tail
page, as the pp_magic for both of them are not set with PP_SIGNATURE.
Yea that's true, although we removed the checking for coalescing
recyclable and non-recyclable SKBs, the next patch first checks the
signature before trying to do anything with the skb.
quoted
Or should we play safe here, and do the trick as skb_free_head() does in
patch 6?
I don't think the &1 will even be measurable, so I'd suggest just
dropping this and play safe?
I am not sure what does '&1' mean above.
The one thing I am not sure about the trick done in patch 6 is that
if __page_frag_cache_drain() is right API to use here, I used it because
it is the only API that is expecting a head page.
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so--
On Fri, 24 Sept 2021 at 10:33, Yunsheng Lin [off-list ref] wrote:
On 2021/9/23 19:47, Ilias Apalodimas wrote:
quoted
On Thu, 23 Sept 2021 at 14:24, Yunsheng Lin [off-list ref] wrote:
quoted
On 2021/9/23 16:33, Ilias Apalodimas wrote:
quoted
On Wed, Sep 22, 2021 at 05:41:27PM +0800, Yunsheng Lin wrote:
quoted
As the pp page for a skb frag is always a head page, so make
sure skb_pp_recycle() passes a head page to avoid calling
compound_head() for skb frag page case.
Doesn't that rely on the driver mostly (i.e what's passed in skb_frag_set_page() ?
None of the current netstack code assumes bv_page is the head page of a
compound page. Since our page_pool allocator can will allocate compound
pages for order > 0, why should we rely on it ?
As the page pool alloc function return 'struct page *' to the caller, which
is the head page of a compound pages for order > 0, so I assume the caller
will pass that to skb_frag_set_page().
Yea that's exactly the assumption I was afraid of.
Sure not passing the head page might seem weird atm and the assumption
stands, but the point is we shouldn't blow up the entire network stack
if someone does that eventually.
quoted
For non-pp page, I assume it is ok whether the page is a head page or tail
page, as the pp_magic for both of them are not set with PP_SIGNATURE.
Yea that's true, although we removed the checking for coalescing
recyclable and non-recyclable SKBs, the next patch first checks the
signature before trying to do anything with the skb.
quoted
Or should we play safe here, and do the trick as skb_free_head() does in
patch 6?
I don't think the &1 will even be measurable, so I'd suggest just
dropping this and play safe?
I am not sure what does '&1' mean above.
I meant the check compound_head() is doing before deciding on the head page.
The one thing I am not sure about the trick done in patch 6 is that
if __page_frag_cache_drain() is right API to use here, I used it because
it is the only API that is expecting a head page.
Yea seemed a bit funny to me in the first place, until I figured out
what exactly it was doing.
Regards
/Ilias
@@ -742,8 +742,6 @@ bool page_pool_return_skb_page(struct page *page){structpage_pool*pp;-page=compound_head(page);-/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation*inordertopreserveanyexistingbits,suchasbit0forthe*headpageofcompoundpageandbit1forpfmemallocpage,so--
@@ -49,6 +49,12 @@ static int page_pool_init(struct page_pool *pool,*whichistheXDP_TXuse-case.*/if(pool->p.flags&PP_FLAG_DMA_MAP){+/* DMA-mapping is not supported on 32-bit systems with+*64-bitDMAmapping.+*/+if(sizeof(dma_addr_t)>sizeof(unsignedlong))+return-EINVAL;
As I said before, can we please use another error than EINVAL.
We should give drivers a chance/ability to detect this error, and e.g.
fallback to doing DMA mappings inside driver instead.
I suggest using EOPNOTSUPP 95 (Operation not supported).
Will change it to EOPNOTSUPP, thanks.
Mind sending this one separately (and you can keep my reviewed-by). It
fits nicely on it's own and since I am not sure about the rest of the
changes yet, it would be nice to get this one in.
I am not sure sending this one separately really makes sense, as it is
mainly used to make supporting the "keep track of pp page when __skb_frag_ref()
is called" in patch 5 easier.
It rips out support for devices that are 32bit and have 64bit dma and
make the whole code easier to follow. I thought we agreed on removing
the support for those devices regardless didn't we?
I am actually not convinced that the code about PAGE_POOL_DMA_USE_PP_FRAG_COUNT
(maybe the name is somewhat confusiong) as it it now, but it is after adding patch
5, and it seems we are not handing the skb_split() case in tso_fragment() for 32bit
arch with 64bit dma too if we still keep PAGE_POOL_DMA_USE_PP_FRAG_COUNT macro.
From: Yunsheng Lin <hidden> Date: 2021-09-30 07:28:46
On 2021/9/24 15:23, Yunsheng Lin wrote:
On 2021/9/23 20:08, Jesper Dangaard Brouer wrote:
quoted
On 22/09/2021 11.41, Yunsheng Lin wrote:
quoted
Currently when PP_FLAG_PAGE_FRAG is set, the caller is not
expected to call page_pool_alloc_pages() directly because of
the PP_FLAG_PAGE_FRAG checking in __page_pool_put_page().
The patch removes the above checking to enable non-split page
support when PP_FLAG_PAGE_FRAG is set.
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Yunsheng Lin <redacted>
---
net/core/page_pool.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
@@ -315,11 +315,14 @@ struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp)/* Fast-path: Get a page from cache */page=__page_pool_get_cached(pool);-if(page)-returnpage;/* Slow-path: cache empty, do real allocation */-page=__page_pool_alloc_pages_slow(pool,gfp);+if(!page)+page=__page_pool_alloc_pages_slow(pool,gfp);++if(likely(page))+page_pool_set_frag_count(page,1);+
Will running these benchmarks to see if any performance overhead noticable here,
thanks for the benchmarks.
You are right, there is notiable overhead for bench_page_pool_cross_cpu test
case above, possibly due to the cache bouncing caused by page_pool_set_frag_count().
As memntioned by Ilias, mlx5 use page pool and also do the recycling internally,
so handling the page frag tracking consistently for both PP_FLAG_PAGE_FRAG and
non-PP_FLAG_PAGE_FRAG will break the mlx5 driver.
So I will drop this patch for now.
@@ -428,8 +431,7 @@ __page_pool_put_page(struct page_pool *pool, struct page *page, unsigned int dma_sync_size, bool allow_direct) { /* It is not the last user for the page frag case */- if (pool->p.flags & PP_FLAG_PAGE_FRAG &&- page_pool_atomic_sub_frag_count_return(page, 1))+ if (page_pool_atomic_sub_frag_count_return(page, 1)) return NULL;
This adds an atomic_long_read, even when PP_FLAG_PAGE_FRAG is not set.
The point here is to have consistent handling for both PP_FLAG_PAGE_FRAG
and non-PP_FLAG_PAGE_FRAG case in the following patch.
As the page->_refcount is accessed in "page_ref_count(page) == 1" checking
in __page_pool_put_page(), and page->pp_frag_count is most likely in the
same cache line as the page->_refcount, So I am not expecting a noticable
overhead here.
Anyway, will use the above benchmarks as an example to verify it.
quoted
quoted
/* This allocator is optimized for the XDP mode that uses
.
_______________________________________________
Linuxarm mailing list -- linuxarm@openeuler.org
To unsubscribe send an email to linuxarm-leave@openeuler.org