linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK
@ 2026-02-06 16:58 Harry Yoo
  2026-02-06 17:08 ` Zi Yan
  0 siblings, 1 reply; 5+ messages in thread
From: Harry Yoo @ 2026-02-06 16:58 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner, Zi Yan, David Hildenbrand,
	Lorenzo Stoakes, Liam R . Howlett, Mike Rapoport,
	Alexei Starovoitov, Sebastian Andrzej Siewior, Shakeel Butt,
	linux-mm, Harry Yoo, stable

When CONFIG_DEBUG_OBJECTS_FREE is enabled,
debug_check_no_{obj,locks}_freed() functions are called.

Since both of them spin on a lock, they are not safe to be called
if the FPI_TRYLOCK flag is specified. This leads to a lockdep splat:

  ================================
  WARNING: inconsistent lock state
  6.19.0-rc5-slab-for-next+ #326 Tainted: G                 N
  --------------------------------
  inconsistent {INITIAL USE} -> {IN-NMI} usage.
  kunit_try_catch/9046 [HC2[2]:SC0[0]:HE0:SE1] takes:
  ffffffff84ed6bf8 (&obj_hash[i].lock){-.-.}-{2:2}, at: __debug_check_no_obj_freed+0xe0/0x300
  {INITIAL USE} state was registered at:
    lock_acquire+0xd9/0x2f0
    _raw_spin_lock_irqsave+0x4c/0x80
    __debug_object_init+0x9d/0x1f0
    debug_object_init+0x34/0x50
    __init_work+0x28/0x40
    init_cgroup_housekeeping+0x151/0x210
    init_cgroup_root+0x3d/0x140
    cgroup_init_early+0x30/0x240
    start_kernel+0x3e/0xcd0
    x86_64_start_reservations+0x18/0x30
    x86_64_start_kernel+0xf3/0x140
    common_startup_64+0x13e/0x148
  irq event stamp: 2998
  hardirqs last  enabled at (2997): [<ffffffff8298b77a>] exc_nmi+0x11a/0x240
  hardirqs last disabled at (2998): [<ffffffff8298b991>] sysvec_irq_work+0x11/0x110
  softirqs last  enabled at (1416): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
  softirqs last disabled at (1303): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0

  other info that might help us debug this:
   Possible unsafe locking scenario:

         CPU0
         ----
    lock(&obj_hash[i].lock);
    <Interrupt>
      lock(&obj_hash[i].lock);

   *** DEADLOCK ***

Fix this by adding an fpi_t parameter to free_pages_prepare() and
skipping those checks if FPI_TRYLOCK is set. Since mm/compaction.c
calls free_pages_prepare(), move the fpi_t definition to mm/internal.h.

Fixes: 8c57b687e833 ("mm, bpf: Introduce free_pages_nolock()")
Cc: <stable@vger.kernel.org>
Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
---
 mm/compaction.c |  2 +-
 mm/internal.h   | 35 ++++++++++++++++++++++++++++++++++-
 mm/page_alloc.c | 42 ++++++------------------------------------
 3 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index 1e8f8eca318c..9ffeb7c6d2b0 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1859,7 +1859,7 @@ static void compaction_free(struct folio *dst, unsigned long data)
 	struct page *page = &dst->page;
 
 	if (folio_put_testzero(dst)) {
-		free_pages_prepare(page, order);
+		free_pages_prepare(page, order, FPI_NONE);
 		list_add(&dst->lru, &cc->freepages[order]);
 		cc->nr_freepages += 1 << order;
 	}
diff --git a/mm/internal.h b/mm/internal.h
index 1f44ccb4badf..8fdffbe5cf1f 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -820,7 +820,40 @@ static inline void prep_compound_tail(struct page *head, int tail_idx)
 }
 
 void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags);
-extern bool free_pages_prepare(struct page *page, unsigned int order);
+
+/* Free Page Internal flags: for internal, non-pcp variants of free_pages(). */
+typedef int __bitwise fpi_t;
+
+/* No special request */
+#define FPI_NONE		((__force fpi_t)0)
+
+/*
+ * Skip free page reporting notification for the (possibly merged) page.
+ * This does not hinder free page reporting from grabbing the page,
+ * reporting it and marking it "reported" -  it only skips notifying
+ * the free page reporting infrastructure about a newly freed page. For
+ * example, used when temporarily pulling a page from a freelist and
+ * putting it back unmodified.
+ */
+#define FPI_SKIP_REPORT_NOTIFY	((__force fpi_t)BIT(0))
+
+/*
+ * Place the (possibly merged) page to the tail of the freelist. Will ignore
+ * page shuffling (relevant code - e.g., memory onlining - is expected to
+ * shuffle the whole zone).
+ *
+ * Note: No code should rely on this flag for correctness - it's purely
+ *       to allow for optimizations when handing back either fresh pages
+ *       (memory onlining) or untouched pages (page isolation, free page
+ *       reporting).
+ */
+#define FPI_TO_TAIL		((__force fpi_t)BIT(1))
+
+/* Free the page without taking locks. Rely on trylock only. */
+#define FPI_TRYLOCK		((__force fpi_t)BIT(2))
+
+extern bool free_pages_prepare(struct page *page, unsigned int order,
+			       fpi_t fpi_flags);
 
 extern int user_min_free_kbytes;
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 0127e9d661ad..328c4d996ae8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -60,37 +60,6 @@
 #include "shuffle.h"
 #include "page_reporting.h"
 
-/* Free Page Internal flags: for internal, non-pcp variants of free_pages(). */
-typedef int __bitwise fpi_t;
-
-/* No special request */
-#define FPI_NONE		((__force fpi_t)0)
-
-/*
- * Skip free page reporting notification for the (possibly merged) page.
- * This does not hinder free page reporting from grabbing the page,
- * reporting it and marking it "reported" -  it only skips notifying
- * the free page reporting infrastructure about a newly freed page. For
- * example, used when temporarily pulling a page from a freelist and
- * putting it back unmodified.
- */
-#define FPI_SKIP_REPORT_NOTIFY	((__force fpi_t)BIT(0))
-
-/*
- * Place the (possibly merged) page to the tail of the freelist. Will ignore
- * page shuffling (relevant code - e.g., memory onlining - is expected to
- * shuffle the whole zone).
- *
- * Note: No code should rely on this flag for correctness - it's purely
- *       to allow for optimizations when handing back either fresh pages
- *       (memory onlining) or untouched pages (page isolation, free page
- *       reporting).
- */
-#define FPI_TO_TAIL		((__force fpi_t)BIT(1))
-
-/* Free the page without taking locks. Rely on trylock only. */
-#define FPI_TRYLOCK		((__force fpi_t)BIT(2))
-
 /* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
 static DEFINE_MUTEX(pcp_batch_high_lock);
 #define MIN_PERCPU_PAGELIST_HIGH_FRACTION (8)
@@ -1314,7 +1283,8 @@ static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr)
 #endif /* CONFIG_MEM_ALLOC_PROFILING */
 
 __always_inline bool free_pages_prepare(struct page *page,
-			unsigned int order)
+					unsigned int order,
+					fpi_t fpi_flags)
 {
 	int bad = 0;
 	bool skip_kasan_poison = should_skip_kasan_poison(page);
@@ -1407,7 +1377,7 @@ __always_inline bool free_pages_prepare(struct page *page,
 	page_table_check_free(page, order);
 	pgalloc_tag_sub(page, 1 << order);
 
-	if (!PageHighMem(page)) {
+	if (!PageHighMem(page) && !(fpi_flags & FPI_TRYLOCK)) {
 		debug_check_no_locks_freed(page_address(page),
 					   PAGE_SIZE << order);
 		debug_check_no_obj_freed(page_address(page),
@@ -1579,7 +1549,7 @@ static void __free_pages_ok(struct page *page, unsigned int order,
 	unsigned long pfn = page_to_pfn(page);
 	struct zone *zone = page_zone(page);
 
-	if (free_pages_prepare(page, order))
+	if (free_pages_prepare(page, order, fpi_flags))
 		free_one_page(zone, page, pfn, order, fpi_flags);
 }
 
@@ -2940,7 +2910,7 @@ static void __free_frozen_pages(struct page *page, unsigned int order,
 		return;
 	}
 
-	if (!free_pages_prepare(page, order))
+	if (!free_pages_prepare(page, order, fpi_flags))
 		return;
 
 	/*
@@ -3002,7 +2972,7 @@ void free_unref_folios(struct folio_batch *folios)
 		unsigned long pfn = folio_pfn(folio);
 		unsigned int order = folio_order(folio);
 
-		if (!free_pages_prepare(&folio->page, order))
+		if (!free_pages_prepare(&folio->page, order, FPI_NONE))
 			continue;
 		/*
 		 * Free orders not handled on the PCP directly to the
-- 
2.43.0



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

* Re: [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK
  2026-02-06 16:58 [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK Harry Yoo
@ 2026-02-06 17:08 ` Zi Yan
  2026-02-06 17:20   ` Harry Yoo
  0 siblings, 1 reply; 5+ messages in thread
From: Zi Yan @ 2026-02-06 17:08 UTC (permalink / raw)
  To: Harry Yoo
  Cc: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner, David Hildenbrand,
	Lorenzo Stoakes, Liam R . Howlett, Mike Rapoport,
	Alexei Starovoitov, Sebastian Andrzej Siewior, Shakeel Butt,
	linux-mm, stable

On 6 Feb 2026, at 11:58, Harry Yoo wrote:

> When CONFIG_DEBUG_OBJECTS_FREE is enabled,
> debug_check_no_{obj,locks}_freed() functions are called.
>
> Since both of them spin on a lock, they are not safe to be called
> if the FPI_TRYLOCK flag is specified. This leads to a lockdep splat:
>
>   ================================
>   WARNING: inconsistent lock state
>   6.19.0-rc5-slab-for-next+ #326 Tainted: G                 N
>   --------------------------------
>   inconsistent {INITIAL USE} -> {IN-NMI} usage.
>   kunit_try_catch/9046 [HC2[2]:SC0[0]:HE0:SE1] takes:
>   ffffffff84ed6bf8 (&obj_hash[i].lock){-.-.}-{2:2}, at: __debug_check_no_obj_freed+0xe0/0x300
>   {INITIAL USE} state was registered at:
>     lock_acquire+0xd9/0x2f0
>     _raw_spin_lock_irqsave+0x4c/0x80
>     __debug_object_init+0x9d/0x1f0
>     debug_object_init+0x34/0x50
>     __init_work+0x28/0x40
>     init_cgroup_housekeeping+0x151/0x210
>     init_cgroup_root+0x3d/0x140
>     cgroup_init_early+0x30/0x240
>     start_kernel+0x3e/0xcd0
>     x86_64_start_reservations+0x18/0x30
>     x86_64_start_kernel+0xf3/0x140
>     common_startup_64+0x13e/0x148
>   irq event stamp: 2998
>   hardirqs last  enabled at (2997): [<ffffffff8298b77a>] exc_nmi+0x11a/0x240
>   hardirqs last disabled at (2998): [<ffffffff8298b991>] sysvec_irq_work+0x11/0x110
>   softirqs last  enabled at (1416): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
>   softirqs last disabled at (1303): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
>
>   other info that might help us debug this:
>    Possible unsafe locking scenario:
>
>          CPU0
>          ----
>     lock(&obj_hash[i].lock);
>     <Interrupt>
>       lock(&obj_hash[i].lock);
>
>    *** DEADLOCK ***
>
> Fix this by adding an fpi_t parameter to free_pages_prepare() and
> skipping those checks if FPI_TRYLOCK is set. Since mm/compaction.c
> calls free_pages_prepare(), move the fpi_t definition to mm/internal.h.
>
> Fixes: 8c57b687e833 ("mm, bpf: Introduce free_pages_nolock()")
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
> ---
>  mm/compaction.c |  2 +-
>  mm/internal.h   | 35 ++++++++++++++++++++++++++++++++++-
>  mm/page_alloc.c | 42 ++++++------------------------------------
>  3 files changed, 41 insertions(+), 38 deletions(-)
>
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 1e8f8eca318c..9ffeb7c6d2b0 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1859,7 +1859,7 @@ static void compaction_free(struct folio *dst, unsigned long data)
>  	struct page *page = &dst->page;
>
>  	if (folio_put_testzero(dst)) {
> -		free_pages_prepare(page, order);
> +		free_pages_prepare(page, order, FPI_NONE);

Is it OK to add something like free_pages_prepare_fpi_none() for this one
to avoid the FPI flag move?



Best Regards,
Yan, Zi


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

* Re: [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK
  2026-02-06 17:08 ` Zi Yan
@ 2026-02-06 17:20   ` Harry Yoo
  2026-02-06 17:34     ` Vlastimil Babka
  0 siblings, 1 reply; 5+ messages in thread
From: Harry Yoo @ 2026-02-06 17:20 UTC (permalink / raw)
  To: Zi Yan
  Cc: Andrew Morton, Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner, David Hildenbrand,
	Lorenzo Stoakes, Liam R . Howlett, Mike Rapoport,
	Alexei Starovoitov, Sebastian Andrzej Siewior, Shakeel Butt,
	linux-mm, stable

On Fri, Feb 06, 2026 at 12:08:04PM -0500, Zi Yan wrote:
> On 6 Feb 2026, at 11:58, Harry Yoo wrote:
> 
> > When CONFIG_DEBUG_OBJECTS_FREE is enabled,
> > debug_check_no_{obj,locks}_freed() functions are called.
> >
> > Since both of them spin on a lock, they are not safe to be called
> > if the FPI_TRYLOCK flag is specified. This leads to a lockdep splat:
> >
> >   ================================
> >   WARNING: inconsistent lock state
> >   6.19.0-rc5-slab-for-next+ #326 Tainted: G                 N
> >   --------------------------------
> >   inconsistent {INITIAL USE} -> {IN-NMI} usage.
> >   kunit_try_catch/9046 [HC2[2]:SC0[0]:HE0:SE1] takes:
> >   ffffffff84ed6bf8 (&obj_hash[i].lock){-.-.}-{2:2}, at: __debug_check_no_obj_freed+0xe0/0x300
> >   {INITIAL USE} state was registered at:
> >     lock_acquire+0xd9/0x2f0
> >     _raw_spin_lock_irqsave+0x4c/0x80
> >     __debug_object_init+0x9d/0x1f0
> >     debug_object_init+0x34/0x50
> >     __init_work+0x28/0x40
> >     init_cgroup_housekeeping+0x151/0x210
> >     init_cgroup_root+0x3d/0x140
> >     cgroup_init_early+0x30/0x240
> >     start_kernel+0x3e/0xcd0
> >     x86_64_start_reservations+0x18/0x30
> >     x86_64_start_kernel+0xf3/0x140
> >     common_startup_64+0x13e/0x148
> >   irq event stamp: 2998
> >   hardirqs last  enabled at (2997): [<ffffffff8298b77a>] exc_nmi+0x11a/0x240
> >   hardirqs last disabled at (2998): [<ffffffff8298b991>] sysvec_irq_work+0x11/0x110
> >   softirqs last  enabled at (1416): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
> >   softirqs last disabled at (1303): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
> >
> >   other info that might help us debug this:
> >    Possible unsafe locking scenario:
> >
> >          CPU0
> >          ----
> >     lock(&obj_hash[i].lock);
> >     <Interrupt>
> >       lock(&obj_hash[i].lock);
> >
> >    *** DEADLOCK ***
> >
> > Fix this by adding an fpi_t parameter to free_pages_prepare() and
> > skipping those checks if FPI_TRYLOCK is set. Since mm/compaction.c
> > calls free_pages_prepare(), move the fpi_t definition to mm/internal.h.
> >
> > Fixes: 8c57b687e833 ("mm, bpf: Introduce free_pages_nolock()")
> > Cc: <stable@vger.kernel.org>
> > Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
> > ---
> >  mm/compaction.c |  2 +-
> >  mm/internal.h   | 35 ++++++++++++++++++++++++++++++++++-
> >  mm/page_alloc.c | 42 ++++++------------------------------------
> >  3 files changed, 41 insertions(+), 38 deletions(-)
> >
> > diff --git a/mm/compaction.c b/mm/compaction.c
> > index 1e8f8eca318c..9ffeb7c6d2b0 100644
> > --- a/mm/compaction.c
> > +++ b/mm/compaction.c
> > @@ -1859,7 +1859,7 @@ static void compaction_free(struct folio *dst, unsigned long data)
> >  	struct page *page = &dst->page;
> >
> >  	if (folio_put_testzero(dst)) {
> > -		free_pages_prepare(page, order);
> > +		free_pages_prepare(page, order, FPI_NONE);
> 
> Is it OK to add something like free_pages_prepare_fpi_none() for this one
> to avoid the FPI flag move?

Yeah, moving FPI flag definition isn't great :)

I'm totally fine with your suggestion,
as long as page allocator/compaction folks are fine with it!

-- 
Cheers,
Harry / Hyeonggon


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

* Re: [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK
  2026-02-06 17:20   ` Harry Yoo
@ 2026-02-06 17:34     ` Vlastimil Babka
  2026-02-07  1:26       ` Harry Yoo
  0 siblings, 1 reply; 5+ messages in thread
From: Vlastimil Babka @ 2026-02-06 17:34 UTC (permalink / raw)
  To: Harry Yoo, Zi Yan
  Cc: Andrew Morton, Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner, David Hildenbrand, Lorenzo Stoakes,
	Liam R . Howlett, Mike Rapoport, Alexei Starovoitov,
	Sebastian Andrzej Siewior, Shakeel Butt, linux-mm, stable

On 2/6/26 18:20, Harry Yoo wrote:
> On Fri, Feb 06, 2026 at 12:08:04PM -0500, Zi Yan wrote:
>> On 6 Feb 2026, at 11:58, Harry Yoo wrote:
>> 
>> > When CONFIG_DEBUG_OBJECTS_FREE is enabled,
>> > debug_check_no_{obj,locks}_freed() functions are called.
>> >
>> > Since both of them spin on a lock, they are not safe to be called
>> > if the FPI_TRYLOCK flag is specified. This leads to a lockdep splat:
>> >
>> >   ================================
>> >   WARNING: inconsistent lock state
>> >   6.19.0-rc5-slab-for-next+ #326 Tainted: G                 N
>> >   --------------------------------
>> >   inconsistent {INITIAL USE} -> {IN-NMI} usage.
>> >   kunit_try_catch/9046 [HC2[2]:SC0[0]:HE0:SE1] takes:
>> >   ffffffff84ed6bf8 (&obj_hash[i].lock){-.-.}-{2:2}, at: __debug_check_no_obj_freed+0xe0/0x300
>> >   {INITIAL USE} state was registered at:
>> >     lock_acquire+0xd9/0x2f0
>> >     _raw_spin_lock_irqsave+0x4c/0x80
>> >     __debug_object_init+0x9d/0x1f0
>> >     debug_object_init+0x34/0x50
>> >     __init_work+0x28/0x40
>> >     init_cgroup_housekeeping+0x151/0x210
>> >     init_cgroup_root+0x3d/0x140
>> >     cgroup_init_early+0x30/0x240
>> >     start_kernel+0x3e/0xcd0
>> >     x86_64_start_reservations+0x18/0x30
>> >     x86_64_start_kernel+0xf3/0x140
>> >     common_startup_64+0x13e/0x148
>> >   irq event stamp: 2998
>> >   hardirqs last  enabled at (2997): [<ffffffff8298b77a>] exc_nmi+0x11a/0x240
>> >   hardirqs last disabled at (2998): [<ffffffff8298b991>] sysvec_irq_work+0x11/0x110
>> >   softirqs last  enabled at (1416): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
>> >   softirqs last disabled at (1303): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
>> >
>> >   other info that might help us debug this:
>> >    Possible unsafe locking scenario:
>> >
>> >          CPU0
>> >          ----
>> >     lock(&obj_hash[i].lock);
>> >     <Interrupt>
>> >       lock(&obj_hash[i].lock);
>> >
>> >    *** DEADLOCK ***
>> >
>> > Fix this by adding an fpi_t parameter to free_pages_prepare() and
>> > skipping those checks if FPI_TRYLOCK is set. Since mm/compaction.c
>> > calls free_pages_prepare(), move the fpi_t definition to mm/internal.h.
>> >
>> > Fixes: 8c57b687e833 ("mm, bpf: Introduce free_pages_nolock()")
>> > Cc: <stable@vger.kernel.org>
>> > Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
>> > ---
>> >  mm/compaction.c |  2 +-
>> >  mm/internal.h   | 35 ++++++++++++++++++++++++++++++++++-
>> >  mm/page_alloc.c | 42 ++++++------------------------------------
>> >  3 files changed, 41 insertions(+), 38 deletions(-)
>> >
>> > diff --git a/mm/compaction.c b/mm/compaction.c
>> > index 1e8f8eca318c..9ffeb7c6d2b0 100644
>> > --- a/mm/compaction.c
>> > +++ b/mm/compaction.c
>> > @@ -1859,7 +1859,7 @@ static void compaction_free(struct folio *dst, unsigned long data)
>> >  	struct page *page = &dst->page;
>> >
>> >  	if (folio_put_testzero(dst)) {
>> > -		free_pages_prepare(page, order);
>> > +		free_pages_prepare(page, order, FPI_NONE);
>> 
>> Is it OK to add something like free_pages_prepare_fpi_none() for this one
>> to avoid the FPI flag move?
> 
> Yeah, moving FPI flag definition isn't great :)
> 
> I'm totally fine with your suggestion,
> as long as page allocator/compaction folks are fine with it!

Maybe even like this?
free_pages_prepare() which calls __free_pages_prepare(FPI_NONE)



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

* Re: [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK
  2026-02-06 17:34     ` Vlastimil Babka
@ 2026-02-07  1:26       ` Harry Yoo
  0 siblings, 0 replies; 5+ messages in thread
From: Harry Yoo @ 2026-02-07  1:26 UTC (permalink / raw)
  To: Vlastimil Babka
  Cc: Zi Yan, Andrew Morton, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner, David Hildenbrand,
	Lorenzo Stoakes, Liam R . Howlett, Mike Rapoport,
	Alexei Starovoitov, Sebastian Andrzej Siewior, Shakeel Butt,
	linux-mm, stable

On Fri, Feb 06, 2026 at 06:34:25PM +0100, Vlastimil Babka wrote:
> On 2/6/26 18:20, Harry Yoo wrote:
> > On Fri, Feb 06, 2026 at 12:08:04PM -0500, Zi Yan wrote:
> >> On 6 Feb 2026, at 11:58, Harry Yoo wrote:
> >> 
> >> > When CONFIG_DEBUG_OBJECTS_FREE is enabled,
> >> > debug_check_no_{obj,locks}_freed() functions are called.
> >> >
> >> > Since both of them spin on a lock, they are not safe to be called
> >> > if the FPI_TRYLOCK flag is specified. This leads to a lockdep splat:
> >> >
> >> >   ================================
> >> >   WARNING: inconsistent lock state
> >> >   6.19.0-rc5-slab-for-next+ #326 Tainted: G                 N
> >> >   --------------------------------
> >> >   inconsistent {INITIAL USE} -> {IN-NMI} usage.
> >> >   kunit_try_catch/9046 [HC2[2]:SC0[0]:HE0:SE1] takes:
> >> >   ffffffff84ed6bf8 (&obj_hash[i].lock){-.-.}-{2:2}, at: __debug_check_no_obj_freed+0xe0/0x300
> >> >   {INITIAL USE} state was registered at:
> >> >     lock_acquire+0xd9/0x2f0
> >> >     _raw_spin_lock_irqsave+0x4c/0x80
> >> >     __debug_object_init+0x9d/0x1f0
> >> >     debug_object_init+0x34/0x50
> >> >     __init_work+0x28/0x40
> >> >     init_cgroup_housekeeping+0x151/0x210
> >> >     init_cgroup_root+0x3d/0x140
> >> >     cgroup_init_early+0x30/0x240
> >> >     start_kernel+0x3e/0xcd0
> >> >     x86_64_start_reservations+0x18/0x30
> >> >     x86_64_start_kernel+0xf3/0x140
> >> >     common_startup_64+0x13e/0x148
> >> >   irq event stamp: 2998
> >> >   hardirqs last  enabled at (2997): [<ffffffff8298b77a>] exc_nmi+0x11a/0x240
> >> >   hardirqs last disabled at (2998): [<ffffffff8298b991>] sysvec_irq_work+0x11/0x110
> >> >   softirqs last  enabled at (1416): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
> >> >   softirqs last disabled at (1303): [<ffffffff813c1f72>] __irq_exit_rcu+0x132/0x1c0
> >> >
> >> >   other info that might help us debug this:
> >> >    Possible unsafe locking scenario:
> >> >
> >> >          CPU0
> >> >          ----
> >> >     lock(&obj_hash[i].lock);
> >> >     <Interrupt>
> >> >       lock(&obj_hash[i].lock);
> >> >
> >> >    *** DEADLOCK ***
> >> >
> >> > Fix this by adding an fpi_t parameter to free_pages_prepare() and
> >> > skipping those checks if FPI_TRYLOCK is set. Since mm/compaction.c
> >> > calls free_pages_prepare(), move the fpi_t definition to mm/internal.h.
> >> >
> >> > Fixes: 8c57b687e833 ("mm, bpf: Introduce free_pages_nolock()")
> >> > Cc: <stable@vger.kernel.org>
> >> > Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
> >> > ---
> >> >  mm/compaction.c |  2 +-
> >> >  mm/internal.h   | 35 ++++++++++++++++++++++++++++++++++-
> >> >  mm/page_alloc.c | 42 ++++++------------------------------------
> >> >  3 files changed, 41 insertions(+), 38 deletions(-)
> >> >
> >> > diff --git a/mm/compaction.c b/mm/compaction.c
> >> > index 1e8f8eca318c..9ffeb7c6d2b0 100644
> >> > --- a/mm/compaction.c
> >> > +++ b/mm/compaction.c
> >> > @@ -1859,7 +1859,7 @@ static void compaction_free(struct folio *dst, unsigned long data)
> >> >  	struct page *page = &dst->page;
> >> >
> >> >  	if (folio_put_testzero(dst)) {
> >> > -		free_pages_prepare(page, order);
> >> > +		free_pages_prepare(page, order, FPI_NONE);
> >> 
> >> Is it OK to add something like free_pages_prepare_fpi_none() for this one
> >> to avoid the FPI flag move?
> > 
> > Yeah, moving FPI flag definition isn't great :)
> > 
> > I'm totally fine with your suggestion,
> > as long as page allocator/compaction folks are fine with it!
> 
> Maybe even like this?
> free_pages_prepare() which calls __free_pages_prepare(FPI_NONE)

Sounds good and will respin v2 soon, thanks!

-- 
Cheers,
Harry / Hyeonggon


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

end of thread, other threads:[~2026-02-07  1:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-06 16:58 [PATCH] mm/page_alloc: skip debug_check_no_{obj,locks}_freed with FPI_TRYLOCK Harry Yoo
2026-02-06 17:08 ` Zi Yan
2026-02-06 17:20   ` Harry Yoo
2026-02-06 17:34     ` Vlastimil Babka
2026-02-07  1:26       ` Harry Yoo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox