netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next] page_pool: unlink from napi during destroy
@ 2023-04-19 18:20 Jakub Kicinski
  2023-04-20  8:56 ` Jesper Dangaard Brouer
  2023-04-21  2:30 ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 3+ messages in thread
From: Jakub Kicinski @ 2023-04-19 18:20 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, Jakub Kicinski, Jesper Dangaard Brouer,
	hawk, ilias.apalodimas, tariqt

Jesper points out that we must prevent recycling into cache
after page_pool_destroy() is called, because page_pool_destroy()
is not synchronized with recycling (some pages may still be
outstanding when destroy() gets called).

I assumed this will not happen because NAPI can't be scheduled
if its page pool is being destroyed. But I missed the fact that
NAPI may get reused. For instance when user changes ring configuration
driver may allocate a new page pool, stop NAPI, swap, start NAPI,
and then destroy the old pool. The NAPI is running so old page
pool will think it can recycle to the cache, but the consumer
at that point is the destroy() path, not NAPI.

To avoid extra synchronization let the drivers do "unlinking"
during the "swap" stage while NAPI is indeed disabled.

Fixes: 8c48eea3adf3 ("page_pool: allow caching from safely localized NAPI")
Reported-by: Jesper Dangaard Brouer <jbrouer@redhat.com>
Link: https://lore.kernel.org/all/e8df2654-6a5b-3c92-489d-2fe5e444135f@redhat.com/
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
bnxt does not do the live swap so no need to change it.
But let's export the API, anyway, I'm sure others will
need it. And knowing driver authors they will hack some
workaround into the driver rather than export the helper.

CC: hawk@kernel.org
CC: ilias.apalodimas@linaro.org
CC: tariqt@nvidia.com
---
 include/net/page_pool.h |  5 +++++
 net/core/page_pool.c    | 18 +++++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/include/net/page_pool.h b/include/net/page_pool.h
index 91b808dade82..c8ec2f34722b 100644
--- a/include/net/page_pool.h
+++ b/include/net/page_pool.h
@@ -247,6 +247,7 @@ struct page_pool *page_pool_create(const struct page_pool_params *params);
 struct xdp_mem_info;
 
 #ifdef CONFIG_PAGE_POOL
+void page_pool_unlink_napi(struct page_pool *pool);
 void page_pool_destroy(struct page_pool *pool);
 void page_pool_use_xdp_mem(struct page_pool *pool, void (*disconnect)(void *),
 			   struct xdp_mem_info *mem);
@@ -254,6 +255,10 @@ void page_pool_release_page(struct page_pool *pool, struct page *page);
 void page_pool_put_page_bulk(struct page_pool *pool, void **data,
 			     int count);
 #else
+static inline void page_pool_unlink_napi(struct page_pool *pool)
+{
+}
+
 static inline void page_pool_destroy(struct page_pool *pool)
 {
 }
diff --git a/net/core/page_pool.c b/net/core/page_pool.c
index 2f6bf422ed30..caa30a5a5abc 100644
--- a/net/core/page_pool.c
+++ b/net/core/page_pool.c
@@ -838,6 +838,21 @@ void page_pool_use_xdp_mem(struct page_pool *pool, void (*disconnect)(void *),
 	pool->xdp_mem_id = mem->id;
 }
 
+void page_pool_unlink_napi(struct page_pool *pool)
+{
+	if (!pool->p.napi)
+		return;
+
+	/* To avoid races with recycling and additional barriers make sure
+	 * pool and NAPI are unlinked when NAPI is disabled.
+	 */
+	WARN_ON(!test_bit(NAPI_STATE_SCHED, &pool->p.napi->state) ||
+		READ_ONCE(pool->p.napi->list_owner) != -1);
+
+	WRITE_ONCE(pool->p.napi, NULL);
+}
+EXPORT_SYMBOL(page_pool_unlink_napi);
+
 void page_pool_destroy(struct page_pool *pool)
 {
 	if (!pool)
@@ -846,6 +861,7 @@ void page_pool_destroy(struct page_pool *pool)
 	if (!page_pool_put(pool))
 		return;
 
+	page_pool_unlink_napi(pool);
 	page_pool_free_frag(pool);
 
 	if (!page_pool_release(pool))
@@ -899,7 +915,7 @@ bool page_pool_return_skb_page(struct page *page, bool napi_safe)
 	 * in the same context as the consumer would run, so there's
 	 * no possible race.
 	 */
-	napi = pp->p.napi;
+	napi = READ_ONCE(pp->p.napi);
 	allow_direct = napi_safe && napi &&
 		READ_ONCE(napi->list_owner) == smp_processor_id();
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] page_pool: unlink from napi during destroy
  2023-04-19 18:20 [PATCH net-next] page_pool: unlink from napi during destroy Jakub Kicinski
@ 2023-04-20  8:56 ` Jesper Dangaard Brouer
  2023-04-21  2:30 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: Jesper Dangaard Brouer @ 2023-04-20  8:56 UTC (permalink / raw)
  To: Jakub Kicinski, davem
  Cc: brouer, netdev, edumazet, pabeni, Jesper Dangaard Brouer, hawk,
	ilias.apalodimas, tariqt



On 19/04/2023 20.20, Jakub Kicinski wrote:
> Jesper points out that we must prevent recycling into cache
> after page_pool_destroy() is called, because page_pool_destroy()
> is not synchronized with recycling (some pages may still be
> outstanding when destroy() gets called).
> 
> I assumed this will not happen because NAPI can't be scheduled
> if its page pool is being destroyed. But I missed the fact that
> NAPI may get reused. For instance when user changes ring configuration
> driver may allocate a new page pool, stop NAPI, swap, start NAPI,
> and then destroy the old pool. The NAPI is running so old page
> pool will think it can recycle to the cache, but the consumer
> at that point is the destroy() path, not NAPI.
> 
> To avoid extra synchronization let the drivers do "unlinking"
> during the "swap" stage while NAPI is indeed disabled.
> 
> Fixes: 8c48eea3adf3 ("page_pool: allow caching from safely localized NAPI")
> Reported-by: Jesper Dangaard Brouer <jbrouer@redhat.com>
> Link: https://lore.kernel.org/all/e8df2654-6a5b-3c92-489d-2fe5e444135f@redhat.com/
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> bnxt does not do the live swap so no need to change it.
> But let's export the API, anyway, I'm sure others will
> need it. And knowing driver authors they will hack some
> workaround into the driver rather than export the helper.
> 
> CC: hawk@kernel.org
> CC: ilias.apalodimas@linaro.org
> CC: tariqt@nvidia.com
> ---
>   include/net/page_pool.h |  5 +++++
>   net/core/page_pool.c    | 18 +++++++++++++++++-
>   2 files changed, 22 insertions(+), 1 deletion(-)
> 

Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>

Thanks for fixing this.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] page_pool: unlink from napi during destroy
  2023-04-19 18:20 [PATCH net-next] page_pool: unlink from napi during destroy Jakub Kicinski
  2023-04-20  8:56 ` Jesper Dangaard Brouer
@ 2023-04-21  2:30 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-04-21  2:30 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, jbrouer, hawk, ilias.apalodimas,
	tariqt

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 19 Apr 2023 11:20:06 -0700 you wrote:
> Jesper points out that we must prevent recycling into cache
> after page_pool_destroy() is called, because page_pool_destroy()
> is not synchronized with recycling (some pages may still be
> outstanding when destroy() gets called).
> 
> I assumed this will not happen because NAPI can't be scheduled
> if its page pool is being destroyed. But I missed the fact that
> NAPI may get reused. For instance when user changes ring configuration
> driver may allocate a new page pool, stop NAPI, swap, start NAPI,
> and then destroy the old pool. The NAPI is running so old page
> pool will think it can recycle to the cache, but the consumer
> at that point is the destroy() path, not NAPI.
> 
> [...]

Here is the summary with links:
  - [net-next] page_pool: unlink from napi during destroy
    https://git.kernel.org/netdev/net-next/c/dd64b232deb8

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-04-21  2:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-19 18:20 [PATCH net-next] page_pool: unlink from napi during destroy Jakub Kicinski
2023-04-20  8:56 ` Jesper Dangaard Brouer
2023-04-21  2:30 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).