[RFC PATCH V3 32/43] rv64ilp32_abi: mm: Remove _folio_nr_pages

guoren
2025-03-25T12:24:24Z

BITS_PER_LONG defines the layout of the struct page, and
_folio_nr_pages would conflict with page->_mapcount for RV64ILP32
ABI. Here is problem:

BUG: Bad page state in process kworker/u4:0 pfn:61eed
page: refcount:0 mapcount:5 mapping:00000000 index:0x0 pfn:0x61eed
flags: 0x0(zone=0)
raw: 00000000 00000000 ffffffff 00000000 00000000 00000000 00000004 00000000
raw: 00000000 00000000
page dumped because: nonzero mapcount
Modules linked in:
CPU: 0 UID: 0 PID: 11 Comm: kworker/u4:0 Not tainted 6.13.0-rc4
Hardware name: riscv-virtio,qemu (DT)
Workqueue: async async_run_entry_fn
Call Trace:
[<bc015096>] dump_backtrace+0x1e/0x26
[<bc002330>] show_stack+0x2a/0x38
[<bc00f38c>] dump_stack_lvl+0x4a/0x68
[<bc00f3c0>] dump_stack+0x16/0x1e
[<bc1cadd8>] bad_page+0x120/0x142
[<bc1cf2c2>] free_unref_page+0x510/0x5f8
[<bc17fb16>] __folio_put+0x6a/0xbc
[<bc1d6090>] free_large_kmalloc+0x6a/0xb8
[<bc1d9144>] kfree+0x23c/0x300
[<bcc02834>] unpack_to_rootfs+0x27c/0x2c0
[<bcc02e96>] do_populate_rootfs+0x24/0x12e
[<bc04c80c>] async_run_entry_fn+0x26/0xcc
[<bc03e116>] process_one_work+0x136/0x224
[<bc03e9e4>] worker_thread+0x234/0x30a
[<bc046334>] kthread+0xca/0xe6
[<bca47bea>] ret_from_fork+0xe/0x18
Disabling lock debugging due to kernel taint

So, remove _folio_nr_pages just like CONFIG_32BIT and use
"_flags_1 & 0xff" instead.

Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren@kernel.org>
---
include/linux/mm.h | 4 ++--
include/linux/mm_types.h | 2 +-
mm/internal.h | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7b1068ddcbb7..454fb8ca724c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2058,7 +2058,7 @@ static inline long folio_nr_pages(const struct folio *folio)
{
if (!folio_test_large(folio))
return 1;
-#ifdef CONFIG_64BIT
+#if BITS_PER_LONG == 64
return folio->_folio_nr_pages;
#else
return 1L << (folio->_flags_1 & 0xff);
@@ -2083,7 +2083,7 @@ static inline unsigned long compound_nr(struct page *page)

if (!test_bit(PG_head, &folio->flags))
return 1;
-#ifdef CONFIG_64BIT
+#if BITS_PER_LONG == 64
return folio->_folio_nr_pages;
#else
return 1L << (folio->_flags_1 & 0xff);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6b27db7f9496..da3ba1a79ad5 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -370,7 +370,7 @@ struct folio {
atomic_t _entire_mapcount;
atomic_t _nr_pages_mapped;
atomic_t _pincount;
-#ifdef CONFIG_64BIT
+#if BITS_PER_LONG == 64
unsigned int _folio_nr_pages;
#endif
/* private: the union with struct page is transitional */
diff --git a/mm/internal.h b/mm/internal.h
index 109ef30fee11..c9372a8552ba 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -682,7 +682,7 @@ static inline void folio_set_order(struct folio *folio, unsigned int order)
return;

folio->_flags_1 = (folio->_flags_1 & ~0xffUL) | order;
-#ifdef CONFIG_64BIT
+#if BITS_PER_LONG == 64
folio->_folio_nr_pages = 1U << order;
#endif
}
--
2.40.1