* [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers
@ 2026-07-02 11:06 Jinjiang Tu
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Jinjiang Tu @ 2026-07-02 11:06 UTC (permalink / raw)
To: akpm, ziy, david, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong, tujinjiang
This series cleans up stable_page_flags(), removing the remaining direct
flag manipulation and replacing with folio helpers.
Patch 1 replaces the "1 << KPF_*" expressions with BIT_ULL() marco, to
avoid -Wshift-count-overflow warning for KPF_* values larger than 32.
Patch 2 replaces direct accesses to folio->flags.f with the standard
folio_test_*() helper functions, which cleans up stable_page_flags() and
hides internal implementation details.
This series is based on [1].
[1] https://lore.kernel.org/all/20260629033122.774318-1-tujinjiang@huawei.com/
Jinjiang Tu (2):
fs: stable_page_flags(): use BIT_ULL() for KPF flags
fs: stable_page_flags(): use folio_test_*() helpers
fs/proc/page.c | 124 +++++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 60 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags
2026-07-02 11:06 [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
@ 2026-07-02 11:06 ` Jinjiang Tu
2026-07-02 13:10 ` David Hildenbrand (Arm)
2026-07-02 14:32 ` [PATCH 1/2] " Zi Yan
2026-07-02 11:06 ` [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-02 12:03 ` [PATCH 0/2] " David Hildenbrand (Arm)
2 siblings, 2 replies; 9+ messages in thread
From: Jinjiang Tu @ 2026-07-02 11:06 UTC (permalink / raw)
To: akpm, ziy, david, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong, tujinjiang
The stable_page_flags() function currently sets page flag bits using
"1 << KPF_xxx" for various KPF_* definitions. KPF_* may be larger than 32,
which will trigger -Wshift-count-overflow warning. All KPF_* values
currently used in "1 << KPF_xxx" are smaller than 33, so no warning is
triggered with current code. However, the later patch will cleanup
stable_page_flags() and "1 << KPF_xxx" will be used for KPF_* values larger
than 32, such as KPF_MLOCKED.
Replace all occurrences of "1 << KPF_*" with the BIT_ULL() macro to
ensure all shifts are performed on a 64-bit unsigned type. This makes
the code robust, and safe for future extension.
No functional change is intended.
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
---
fs/proc/page.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 7d9387143435..2717dbb0431b 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -157,7 +157,7 @@ u64 stable_page_flags(const struct page *page)
* it differentiates a memory hole from a page with no flags
*/
if (!page)
- return 1 << KPF_NOPAGE;
+ return BIT_ULL(KPF_NOPAGE);
snapshot_page(&ps, page);
folio = &ps.folio_snapshot;
@@ -170,11 +170,11 @@ u64 stable_page_flags(const struct page *page)
* pseudo flags for the well known (anonymous) memory mapped pages
*/
if (folio_mapped(folio))
- u |= 1 << KPF_MMAP;
+ u |= BIT_ULL(KPF_MMAP);
if (is_anon) {
- u |= 1 << KPF_ANON;
+ u |= BIT_ULL(KPF_ANON);
if ((mapping & FOLIO_MAPPING_FLAGS) == FOLIO_MAPPING_KSM)
- u |= 1 << KPF_KSM;
+ u |= BIT_ULL(KPF_KSM);
}
/*
@@ -184,35 +184,35 @@ u64 stable_page_flags(const struct page *page)
if (ps.idx == 0)
u |= kpf_copy_bit(k, KPF_COMPOUND_HEAD, PG_head);
else
- u |= 1 << KPF_COMPOUND_TAIL;
+ u |= BIT_ULL(KPF_COMPOUND_TAIL);
if (folio_test_hugetlb(folio))
- u |= 1 << KPF_HUGE;
+ u |= BIT_ULL(KPF_HUGE);
else if (folio_test_large(folio) &&
folio_test_large_rmappable(folio)) {
/* Note: we indicate any THPs here, not just PMD-sized ones */
- u |= 1 << KPF_THP;
+ u |= BIT_ULL(KPF_THP);
} else if (is_huge_zero_pfn(ps.pfn)) {
- u |= 1 << KPF_ZERO_PAGE;
- u |= 1 << KPF_THP;
+ u |= BIT_ULL(KPF_ZERO_PAGE);
+ u |= BIT_ULL(KPF_THP);
} else if (is_zero_pfn(ps.pfn)) {
- u |= 1 << KPF_ZERO_PAGE;
+ u |= BIT_ULL(KPF_ZERO_PAGE);
}
if (ps.flags & PAGE_SNAPSHOT_PG_BUDDY)
- u |= 1 << KPF_BUDDY;
+ u |= BIT_ULL(KPF_BUDDY);
if (folio_test_offline(folio))
- u |= 1 << KPF_OFFLINE;
+ u |= BIT_ULL(KPF_OFFLINE);
if (folio_test_pgtable(folio))
- u |= 1 << KPF_PGTABLE;
+ u |= BIT_ULL(KPF_PGTABLE);
if (folio_test_slab(folio))
- u |= 1 << KPF_SLAB;
+ u |= BIT_ULL(KPF_SLAB);
#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT)
u |= kpf_copy_bit(k, KPF_IDLE, PG_idle);
#else
if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
- u |= 1 << KPF_IDLE;
+ u |= BIT_ULL(KPF_IDLE);
#endif
u |= kpf_copy_bit(k, KPF_LOCKED, PG_locked);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers
2026-07-02 11:06 [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
@ 2026-07-02 11:06 ` Jinjiang Tu
2026-07-10 3:52 ` Jinjiang Tu
2026-07-10 11:29 ` David Hildenbrand (Arm)
2026-07-02 12:03 ` [PATCH 0/2] " David Hildenbrand (Arm)
2 siblings, 2 replies; 9+ messages in thread
From: Jinjiang Tu @ 2026-07-02 11:06 UTC (permalink / raw)
To: akpm, ziy, david, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong, tujinjiang
stable_page_flags() currently accesses folio->flags.f directly. Since
commit 476d87d6a061 ("fs: stable_page_flags(): use snapshot_page()"), we
can replace these raw flag accesses with the existing folio_test_*()
helpers, thereby cleaning up the open‑coded flag handling.
For KPF_IDLE, set_ps_flags() already handles both 64‑bit and 32‑bit
cases, so the duplicate code in stable_page_flags() that deals with
CONFIG_PAGE_IDLE_FLAG for the 64‑bit case is removed.
The flag bits that has no folio_test_*() helpers are left unchanged,
including PG_owner_priv_1, PG_arch_*.
No functional change is intended.
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
---
fs/proc/page.c | 94 ++++++++++++++++++++++++++------------------------
1 file changed, 49 insertions(+), 45 deletions(-)
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 2717dbb0431b..0dbd46fa84ea 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -148,8 +148,6 @@ u64 stable_page_flags(const struct page *page)
const struct folio *folio;
struct page_snapshot ps;
unsigned long k;
- unsigned long mapping;
- bool is_anon;
u64 u = 0;
/*
@@ -163,17 +161,14 @@ u64 stable_page_flags(const struct page *page)
folio = &ps.folio_snapshot;
k = folio->flags.f;
- mapping = (unsigned long)folio->mapping;
- is_anon = mapping & FOLIO_MAPPING_ANON;
-
/*
* pseudo flags for the well known (anonymous) memory mapped pages
*/
if (folio_mapped(folio))
u |= BIT_ULL(KPF_MMAP);
- if (is_anon) {
+ if (folio_test_anon(folio)) {
u |= BIT_ULL(KPF_ANON);
- if ((mapping & FOLIO_MAPPING_FLAGS) == FOLIO_MAPPING_KSM)
+ if (folio_test_ksm(folio))
u |= BIT_ULL(KPF_KSM);
}
@@ -181,10 +176,12 @@ u64 stable_page_flags(const struct page *page)
* compound pages: export both head/tail info
* they together define a compound page's start/end pos and order
*/
- if (ps.idx == 0)
- u |= kpf_copy_bit(k, KPF_COMPOUND_HEAD, PG_head);
- else
+ if (ps.idx == 0) {
+ if (folio_test_head(folio))
+ u |= BIT_ULL(KPF_COMPOUND_HEAD);
+ } else {
u |= BIT_ULL(KPF_COMPOUND_TAIL);
+ }
if (folio_test_hugetlb(folio))
u |= BIT_ULL(KPF_HUGE);
else if (folio_test_large(folio) &&
@@ -201,6 +198,9 @@ u64 stable_page_flags(const struct page *page)
if (ps.flags & PAGE_SNAPSHOT_PG_BUDDY)
u |= BIT_ULL(KPF_BUDDY);
+ if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
+ u |= BIT_ULL(KPF_IDLE);
+
if (folio_test_offline(folio))
u |= BIT_ULL(KPF_OFFLINE);
if (folio_test_pgtable(folio))
@@ -208,42 +208,46 @@ u64 stable_page_flags(const struct page *page)
if (folio_test_slab(folio))
u |= BIT_ULL(KPF_SLAB);
-#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT)
- u |= kpf_copy_bit(k, KPF_IDLE, PG_idle);
-#else
- if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
- u |= BIT_ULL(KPF_IDLE);
-#endif
-
- u |= kpf_copy_bit(k, KPF_LOCKED, PG_locked);
- u |= kpf_copy_bit(k, KPF_DIRTY, PG_dirty);
- u |= kpf_copy_bit(k, KPF_UPTODATE, PG_uptodate);
- u |= kpf_copy_bit(k, KPF_WRITEBACK, PG_writeback);
-
- u |= kpf_copy_bit(k, KPF_LRU, PG_lru);
- u |= kpf_copy_bit(k, KPF_REFERENCED, PG_referenced);
- u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active);
- u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim);
-
-#define SWAPCACHE ((1 << PG_swapbacked) | (1 << PG_swapcache))
- if ((k & SWAPCACHE) == SWAPCACHE)
- u |= 1 << KPF_SWAPCACHE;
- u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked);
-
- u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable);
- u |= kpf_copy_bit(k, KPF_MLOCKED, PG_mlocked);
-
-#ifdef CONFIG_MEMORY_FAILURE
- if (u & (1 << KPF_HUGE))
- u |= kpf_copy_bit(k, KPF_HWPOISON, PG_hwpoison);
- else
- u |= kpf_copy_bit(ps.page_snapshot.flags.f, KPF_HWPOISON, PG_hwpoison);
-#endif
+ if (folio_test_locked(folio))
+ u |= BIT_ULL(KPF_LOCKED);
+ if (folio_test_dirty(folio))
+ u |= BIT_ULL(KPF_DIRTY);
+ if (folio_test_uptodate(folio))
+ u |= BIT_ULL(KPF_UPTODATE);
+ if (folio_test_writeback(folio))
+ u |= BIT_ULL(KPF_WRITEBACK);
+
+ if (folio_test_lru(folio))
+ u |= BIT_ULL(KPF_LRU);
+ if (folio_test_referenced(folio))
+ u |= BIT_ULL(KPF_REFERENCED);
+ if (folio_test_active(folio))
+ u |= BIT_ULL(KPF_ACTIVE);
+ if (folio_test_reclaim(folio))
+ u |= BIT_ULL(KPF_RECLAIM);
+
+ if (folio_test_swapcache(folio))
+ u |= BIT_ULL(KPF_SWAPCACHE);
+ if (folio_test_swapbacked(folio))
+ u |= BIT_ULL(KPF_SWAPBACKED);
+ if (folio_test_unevictable(folio))
+ u |= BIT_ULL(KPF_UNEVICTABLE);
+ if (folio_test_mlocked(folio))
+ u |= BIT_ULL(KPF_MLOCKED);
+
+ if ((folio_test_hugetlb(folio) && folio_test_hwpoison(folio))
+ || PageHWPoison(&ps.page_snapshot))
+ u |= BIT_ULL(KPF_HWPOISON);
+
+ if (folio_test_reserved(folio))
+ u |= BIT_ULL(KPF_RESERVED);
+ if (folio_test_owner_2(folio))
+ u |= BIT_ULL(KPF_OWNER_2);
+ if (folio_test_private(folio))
+ u |= BIT_ULL(KPF_PRIVATE);
+ if (folio_test_private_2(folio))
+ u |= BIT_ULL(KPF_PRIVATE_2);
- u |= kpf_copy_bit(k, KPF_RESERVED, PG_reserved);
- u |= kpf_copy_bit(k, KPF_OWNER_2, PG_owner_2);
- u |= kpf_copy_bit(k, KPF_PRIVATE, PG_private);
- u |= kpf_copy_bit(k, KPF_PRIVATE_2, PG_private_2);
u |= kpf_copy_bit(k, KPF_OWNER_PRIVATE, PG_owner_priv_1);
u |= kpf_copy_bit(k, KPF_ARCH, PG_arch_1);
#ifdef CONFIG_ARCH_USES_PG_ARCH_2
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers
2026-07-02 11:06 [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
2026-07-02 11:06 ` [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
@ 2026-07-02 12:03 ` David Hildenbrand (Arm)
2026-07-03 3:00 ` Jinjiang Tu
2 siblings, 1 reply; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-02 12:03 UTC (permalink / raw)
To: Jinjiang Tu, akpm, ziy, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong
On 7/2/26 13:06, Jinjiang Tu wrote:
> This series cleans up stable_page_flags(), removing the remaining direct
> flag manipulation and replacing with folio helpers.
>
> Patch 1 replaces the "1 << KPF_*" expressions with BIT_ULL() marco, to
> avoid -Wshift-count-overflow warning for KPF_* values larger than 32.
>
> Patch 2 replaces direct accesses to folio->flags.f with the standard
> folio_test_*() helper functions, which cleans up stable_page_flags() and
> hides internal implementation details.
>
> This series is based on [1].
>
> [1] https://lore.kernel.org/all/20260629033122.774318-1-tujinjiang@huawei.com/
You should explain the history a bit, and why we converted to the manual checks
in the first place.
Now that we take a folio+page snapshot, the values cannot change concurrently
anymore.
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
@ 2026-07-02 13:10 ` David Hildenbrand (Arm)
2026-07-02 14:32 ` [PATCH 1/2] " Zi Yan
1 sibling, 0 replies; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-02 13:10 UTC (permalink / raw)
To: Jinjiang Tu, akpm, ziy, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong
On 7/2/26 13:06, Jinjiang Tu wrote:
> The stable_page_flags() function currently sets page flag bits using
> "1 << KPF_xxx" for various KPF_* definitions. KPF_* may be larger than 32,
> which will trigger -Wshift-count-overflow warning. All KPF_* values
> currently used in "1 << KPF_xxx" are smaller than 33, so no warning is
> triggered with current code. However, the later patch will cleanup
> stable_page_flags() and "1 << KPF_xxx" will be used for KPF_* values larger
> than 32, such as KPF_MLOCKED.
>
> Replace all occurrences of "1 << KPF_*" with the BIT_ULL() macro to
> ensure all shifts are performed on a 64-bit unsigned type. This makes
> the code robust, and safe for future extension.
>
> No functional change is intended.
>
> Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
> ---
Yes, looks cleaner.
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] stable_page_flags(): use BIT_ULL() for KPF flags
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
2026-07-02 13:10 ` David Hildenbrand (Arm)
@ 2026-07-02 14:32 ` Zi Yan
1 sibling, 0 replies; 9+ messages in thread
From: Zi Yan @ 2026-07-02 14:32 UTC (permalink / raw)
To: Jinjiang Tu
Cc: akpm, david, luizcap, willy, linmiaohe, svetly.todorov, xu.xin16,
chengming.zhou, linux-fsdevel, linux-mm, wangkefeng.wang,
sunnanyong
On 2 Jul 2026, at 7:06, Jinjiang Tu wrote:
> The stable_page_flags() function currently sets page flag bits using
> "1 << KPF_xxx" for various KPF_* definitions. KPF_* may be larger than 32,
> which will trigger -Wshift-count-overflow warning. All KPF_* values
> currently used in "1 << KPF_xxx" are smaller than 33, so no warning is
> triggered with current code. However, the later patch will cleanup
> stable_page_flags() and "1 << KPF_xxx" will be used for KPF_* values larger
> than 32, such as KPF_MLOCKED.
>
> Replace all occurrences of "1 << KPF_*" with the BIT_ULL() macro to
> ensure all shifts are performed on a 64-bit unsigned type. This makes
> the code robust, and safe for future extension.
>
> No functional change is intended.
>
> Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
> ---
> fs/proc/page.c | 30 +++++++++++++++---------------
> 1 file changed, 15 insertions(+), 15 deletions(-)
>
LGTM. Thanks.
Acked-by: Zi Yan <ziy@nvidia.com>
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers
2026-07-02 12:03 ` [PATCH 0/2] " David Hildenbrand (Arm)
@ 2026-07-03 3:00 ` Jinjiang Tu
0 siblings, 0 replies; 9+ messages in thread
From: Jinjiang Tu @ 2026-07-03 3:00 UTC (permalink / raw)
To: David Hildenbrand (Arm), akpm, ziy, luizcap, willy, linmiaohe,
svetly.todorov, xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong
在 2026/7/2 20:03, David Hildenbrand (Arm) 写道:
> On 7/2/26 13:06, Jinjiang Tu wrote:
>> This series cleans up stable_page_flags(), removing the remaining direct
>> flag manipulation and replacing with folio helpers.
>>
>> Patch 1 replaces the "1 << KPF_*" expressions with BIT_ULL() marco, to
>> avoid -Wshift-count-overflow warning for KPF_* values larger than 32.
>>
>> Patch 2 replaces direct accesses to folio->flags.f with the standard
>> folio_test_*() helper functions, which cleans up stable_page_flags() and
>> hides internal implementation details.
>>
>> This series is based on [1].
>>
>> [1] https://lore.kernel.org/all/20260629033122.774318-1-tujinjiang@huawei.com/
> You should explain the history a bit, and why we converted to the manual checks
> in the first place.
>
> Now that we take a folio+page snapshot, the values cannot change concurrently
> anymore.
Yes, I only metioned commit 476d87d6a061 ("fs: stable_page_flags(): use snapshot_page()")
in patch2. I will update to explain the history in detail.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers
2026-07-02 11:06 ` [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
@ 2026-07-10 3:52 ` Jinjiang Tu
2026-07-10 11:29 ` David Hildenbrand (Arm)
1 sibling, 0 replies; 9+ messages in thread
From: Jinjiang Tu @ 2026-07-10 3:52 UTC (permalink / raw)
To: akpm, ziy, david, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong
在 2026/7/2 19:06, Jinjiang Tu 写道:
> stable_page_flags() currently accesses folio->flags.f directly. Since
> commit 476d87d6a061 ("fs: stable_page_flags(): use snapshot_page()"), we
> can replace these raw flag accesses with the existing folio_test_*()
> helpers, thereby cleaning up the open‑coded flag handling.
>
> For KPF_IDLE, set_ps_flags() already handles both 64‑bit and 32‑bit
> cases, so the duplicate code in stable_page_flags() that deals with
> CONFIG_PAGE_IDLE_FLAG for the 64‑bit case is removed.
>
> The flag bits that has no folio_test_*() helpers are left unchanged,
> including PG_owner_priv_1, PG_arch_*.
>
> No functional change is intended.
I update commit message to explain the history and motivation. The updated
commit message is as follows:
Since commit 304daa8132a9 ("maps4: add /proc/kpageflags interface"),
/proc/kpageflags directly operates on page->flags to determine page status.
Later, commit 177975495914 ("proc: export more page flags in
/proc/kpageflags") started using page helper functions when exposing new
flags, leading to a mix of both approaches.
For tail pages, the original code did not return corresponding status.
commit 0a71649cb724 ("/proc/kpageflags: return KPF_SLAB for slab tail
pages") and commit 832fc1de01ae ("/proc/kpageflags: return KPF_BUDDY for
"tail" buddy pages") made tail slab/buddy pages also return corresponding
status. Then commit dee3d0bef2b0 ("proc: rewrite stable_page_flags()")
made all tail pages return the same status as their head page, except for
hwpoison and mapped flags. It also cached the folio's flags and operate on
the flags directly to avoid concurrency issues if using folio_test_*()
helpers. At this point, folio helpers and direct flag operations are mixed
together in stable_page_flags().
Since commit 476d87d6a061 ("fs: stable_page_flags(): use snapshot_page()"),
the folio has already been snapshotted, we can now safely switch to
folio_test_*() helpers instead of directly operating on flags, which is
more readable and consistent with the rest of the kernel.
For KPF_IDLE, set_ps_flags() already handles both 64-bit and 32-bit cases,
so the duplicate code in stable_page_flags() that deals with
CONFIG_PAGE_IDLE_FLAG for the 64-bit case is removed.
The flag bits that have no folio_test_*() helpers are left unchanged,
including PG_owner_priv_1, PG_arch_*.
No functional change is intended.
> Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
> ---
> fs/proc/page.c | 94 ++++++++++++++++++++++++++------------------------
> 1 file changed, 49 insertions(+), 45 deletions(-)
>
> diff --git a/fs/proc/page.c b/fs/proc/page.c
> index 2717dbb0431b..0dbd46fa84ea 100644
> --- a/fs/proc/page.c
> +++ b/fs/proc/page.c
> @@ -148,8 +148,6 @@ u64 stable_page_flags(const struct page *page)
> const struct folio *folio;
> struct page_snapshot ps;
> unsigned long k;
> - unsigned long mapping;
> - bool is_anon;
> u64 u = 0;
>
> /*
> @@ -163,17 +161,14 @@ u64 stable_page_flags(const struct page *page)
> folio = &ps.folio_snapshot;
>
> k = folio->flags.f;
> - mapping = (unsigned long)folio->mapping;
> - is_anon = mapping & FOLIO_MAPPING_ANON;
> -
> /*
> * pseudo flags for the well known (anonymous) memory mapped pages
> */
> if (folio_mapped(folio))
> u |= BIT_ULL(KPF_MMAP);
> - if (is_anon) {
> + if (folio_test_anon(folio)) {
> u |= BIT_ULL(KPF_ANON);
> - if ((mapping & FOLIO_MAPPING_FLAGS) == FOLIO_MAPPING_KSM)
> + if (folio_test_ksm(folio))
> u |= BIT_ULL(KPF_KSM);
> }
>
> @@ -181,10 +176,12 @@ u64 stable_page_flags(const struct page *page)
> * compound pages: export both head/tail info
> * they together define a compound page's start/end pos and order
> */
> - if (ps.idx == 0)
> - u |= kpf_copy_bit(k, KPF_COMPOUND_HEAD, PG_head);
> - else
> + if (ps.idx == 0) {
> + if (folio_test_head(folio))
> + u |= BIT_ULL(KPF_COMPOUND_HEAD);
> + } else {
> u |= BIT_ULL(KPF_COMPOUND_TAIL);
> + }
> if (folio_test_hugetlb(folio))
> u |= BIT_ULL(KPF_HUGE);
> else if (folio_test_large(folio) &&
> @@ -201,6 +198,9 @@ u64 stable_page_flags(const struct page *page)
> if (ps.flags & PAGE_SNAPSHOT_PG_BUDDY)
> u |= BIT_ULL(KPF_BUDDY);
>
> + if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
> + u |= BIT_ULL(KPF_IDLE);
> +
> if (folio_test_offline(folio))
> u |= BIT_ULL(KPF_OFFLINE);
> if (folio_test_pgtable(folio))
> @@ -208,42 +208,46 @@ u64 stable_page_flags(const struct page *page)
> if (folio_test_slab(folio))
> u |= BIT_ULL(KPF_SLAB);
>
> -#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT)
> - u |= kpf_copy_bit(k, KPF_IDLE, PG_idle);
> -#else
> - if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
> - u |= BIT_ULL(KPF_IDLE);
> -#endif
> -
> - u |= kpf_copy_bit(k, KPF_LOCKED, PG_locked);
> - u |= kpf_copy_bit(k, KPF_DIRTY, PG_dirty);
> - u |= kpf_copy_bit(k, KPF_UPTODATE, PG_uptodate);
> - u |= kpf_copy_bit(k, KPF_WRITEBACK, PG_writeback);
> -
> - u |= kpf_copy_bit(k, KPF_LRU, PG_lru);
> - u |= kpf_copy_bit(k, KPF_REFERENCED, PG_referenced);
> - u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active);
> - u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim);
> -
> -#define SWAPCACHE ((1 << PG_swapbacked) | (1 << PG_swapcache))
> - if ((k & SWAPCACHE) == SWAPCACHE)
> - u |= 1 << KPF_SWAPCACHE;
> - u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked);
> -
> - u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable);
> - u |= kpf_copy_bit(k, KPF_MLOCKED, PG_mlocked);
> -
> -#ifdef CONFIG_MEMORY_FAILURE
> - if (u & (1 << KPF_HUGE))
> - u |= kpf_copy_bit(k, KPF_HWPOISON, PG_hwpoison);
> - else
> - u |= kpf_copy_bit(ps.page_snapshot.flags.f, KPF_HWPOISON, PG_hwpoison);
> -#endif
> + if (folio_test_locked(folio))
> + u |= BIT_ULL(KPF_LOCKED);
> + if (folio_test_dirty(folio))
> + u |= BIT_ULL(KPF_DIRTY);
> + if (folio_test_uptodate(folio))
> + u |= BIT_ULL(KPF_UPTODATE);
> + if (folio_test_writeback(folio))
> + u |= BIT_ULL(KPF_WRITEBACK);
> +
> + if (folio_test_lru(folio))
> + u |= BIT_ULL(KPF_LRU);
> + if (folio_test_referenced(folio))
> + u |= BIT_ULL(KPF_REFERENCED);
> + if (folio_test_active(folio))
> + u |= BIT_ULL(KPF_ACTIVE);
> + if (folio_test_reclaim(folio))
> + u |= BIT_ULL(KPF_RECLAIM);
> +
> + if (folio_test_swapcache(folio))
> + u |= BIT_ULL(KPF_SWAPCACHE);
> + if (folio_test_swapbacked(folio))
> + u |= BIT_ULL(KPF_SWAPBACKED);
> + if (folio_test_unevictable(folio))
> + u |= BIT_ULL(KPF_UNEVICTABLE);
> + if (folio_test_mlocked(folio))
> + u |= BIT_ULL(KPF_MLOCKED);
> +
> + if ((folio_test_hugetlb(folio) && folio_test_hwpoison(folio))
> + || PageHWPoison(&ps.page_snapshot))
> + u |= BIT_ULL(KPF_HWPOISON);
> +
> + if (folio_test_reserved(folio))
> + u |= BIT_ULL(KPF_RESERVED);
> + if (folio_test_owner_2(folio))
> + u |= BIT_ULL(KPF_OWNER_2);
> + if (folio_test_private(folio))
> + u |= BIT_ULL(KPF_PRIVATE);
> + if (folio_test_private_2(folio))
> + u |= BIT_ULL(KPF_PRIVATE_2);
>
> - u |= kpf_copy_bit(k, KPF_RESERVED, PG_reserved);
> - u |= kpf_copy_bit(k, KPF_OWNER_2, PG_owner_2);
> - u |= kpf_copy_bit(k, KPF_PRIVATE, PG_private);
> - u |= kpf_copy_bit(k, KPF_PRIVATE_2, PG_private_2);
> u |= kpf_copy_bit(k, KPF_OWNER_PRIVATE, PG_owner_priv_1);
> u |= kpf_copy_bit(k, KPF_ARCH, PG_arch_1);
> #ifdef CONFIG_ARCH_USES_PG_ARCH_2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers
2026-07-02 11:06 ` [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-10 3:52 ` Jinjiang Tu
@ 2026-07-10 11:29 ` David Hildenbrand (Arm)
1 sibling, 0 replies; 9+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-10 11:29 UTC (permalink / raw)
To: Jinjiang Tu, akpm, ziy, luizcap, willy, linmiaohe, svetly.todorov,
xu.xin16, chengming.zhou, linux-fsdevel, linux-mm
Cc: wangkefeng.wang, sunnanyong
On 7/2/26 13:06, Jinjiang Tu wrote:
> stable_page_flags() currently accesses folio->flags.f directly. Since
> commit 476d87d6a061 ("fs: stable_page_flags(): use snapshot_page()"), we
> can replace these raw flag accesses with the existing folio_test_*()
> helpers, thereby cleaning up the open‑coded flag handling.
>
> For KPF_IDLE, set_ps_flags() already handles both 64‑bit and 32‑bit
> cases, so the duplicate code in stable_page_flags() that deals with
> CONFIG_PAGE_IDLE_FLAG for the 64‑bit case is removed.
>
> The flag bits that has no folio_test_*() helpers are left unchanged,
> including PG_owner_priv_1, PG_arch_*.
>
> No functional change is intended.
>
> Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
> ---
> fs/proc/page.c | 94 ++++++++++++++++++++++++++------------------------
> 1 file changed, 49 insertions(+), 45 deletions(-)
>
> diff --git a/fs/proc/page.c b/fs/proc/page.c
> index 2717dbb0431b..0dbd46fa84ea 100644
> --- a/fs/proc/page.c
> +++ b/fs/proc/page.c
> @@ -148,8 +148,6 @@ u64 stable_page_flags(const struct page *page)
> const struct folio *folio;
> struct page_snapshot ps;
> unsigned long k;
> - unsigned long mapping;
> - bool is_anon;
> u64 u = 0;
>
> /*
> @@ -163,17 +161,14 @@ u64 stable_page_flags(const struct page *page)
> folio = &ps.folio_snapshot;
>
> k = folio->flags.f;
> - mapping = (unsigned long)folio->mapping;
> - is_anon = mapping & FOLIO_MAPPING_ANON;
> -
> /*
> * pseudo flags for the well known (anonymous) memory mapped pages
> */
> if (folio_mapped(folio))
> u |= BIT_ULL(KPF_MMAP);
> - if (is_anon) {
> + if (folio_test_anon(folio)) {
> u |= BIT_ULL(KPF_ANON);
> - if ((mapping & FOLIO_MAPPING_FLAGS) == FOLIO_MAPPING_KSM)
> + if (folio_test_ksm(folio))
> u |= BIT_ULL(KPF_KSM);
> }
These make sense.
>
> @@ -181,10 +176,12 @@ u64 stable_page_flags(const struct page *page)
> * compound pages: export both head/tail info
> * they together define a compound page's start/end pos and order
> */
> - if (ps.idx == 0)
> - u |= kpf_copy_bit(k, KPF_COMPOUND_HEAD, PG_head);
> - else
> + if (ps.idx == 0) {
> + if (folio_test_head(folio))
> + u |= BIT_ULL(KPF_COMPOUND_HEAD);
Once we decouple folios from pages, we will have compound pages that are not
folios. PG_head is not folio specific.
But then, some of the flags below are used in other context outside of folios.
I would focus here only on converting things to use folios that will actually be
folio-specific: like the folio_test_anon() above.
> + } else {
> u |= BIT_ULL(KPF_COMPOUND_TAIL);
> + }
> if (folio_test_hugetlb(folio))
> u |= BIT_ULL(KPF_HUGE);
> else if (folio_test_large(folio) &&
> @@ -201,6 +198,9 @@ u64 stable_page_flags(const struct page *page)
> if (ps.flags & PAGE_SNAPSHOT_PG_BUDDY)
> u |= BIT_ULL(KPF_BUDDY);
>
> + if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
> + u |= BIT_ULL(KPF_IDLE);
> +
That looks like an independent cleanup, right? Should probably go in a separate
patch then.
> if (folio_test_offline(folio))
> u |= BIT_ULL(KPF_OFFLINE);
> if (folio_test_pgtable(folio))
> @@ -208,42 +208,46 @@ u64 stable_page_flags(const struct page *page)
> if (folio_test_slab(folio))
> u |= BIT_ULL(KPF_SLAB);
>
> -#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT)
> - u |= kpf_copy_bit(k, KPF_IDLE, PG_idle);
> -#else
> - if (ps.flags & PAGE_SNAPSHOT_PG_IDLE)
> - u |= BIT_ULL(KPF_IDLE);
> -#endif
> -
> - u |= kpf_copy_bit(k, KPF_LOCKED, PG_locked);
> - u |= kpf_copy_bit(k, KPF_DIRTY, PG_dirty);
> - u |= kpf_copy_bit(k, KPF_UPTODATE, PG_uptodate);
> - u |= kpf_copy_bit(k, KPF_WRITEBACK, PG_writeback);
> -
> - u |= kpf_copy_bit(k, KPF_LRU, PG_lru);
> - u |= kpf_copy_bit(k, KPF_REFERENCED, PG_referenced);
> - u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active);
> - u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim);
> -
> -#define SWAPCACHE ((1 << PG_swapbacked) | (1 << PG_swapcache))
> - if ((k & SWAPCACHE) == SWAPCACHE)
> - u |= 1 << KPF_SWAPCACHE;
> - u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked);
> -
> - u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable);
> - u |= kpf_copy_bit(k, KPF_MLOCKED, PG_mlocked);
> -
> -#ifdef CONFIG_MEMORY_FAILURE
> - if (u & (1 << KPF_HUGE))
> - u |= kpf_copy_bit(k, KPF_HWPOISON, PG_hwpoison);
> - else
> - u |= kpf_copy_bit(ps.page_snapshot.flags.f, KPF_HWPOISON, PG_hwpoison);
> -#endif
> + if (folio_test_locked(folio))
> + u |= BIT_ULL(KPF_LOCKED);
> + if (folio_test_dirty(folio))
> + u |= BIT_ULL(KPF_DIRTY);
> + if (folio_test_uptodate(folio))
> + u |= BIT_ULL(KPF_UPTODATE);
> + if (folio_test_writeback(folio))
> + u |= BIT_ULL(KPF_WRITEBACK);
> +
> + if (folio_test_lru(folio))
> + u |= BIT_ULL(KPF_LRU);
> + if (folio_test_referenced(folio))
> + u |= BIT_ULL(KPF_REFERENCED);
> + if (folio_test_active(folio))
> + u |= BIT_ULL(KPF_ACTIVE);
> + if (folio_test_reclaim(folio))
> + u |= BIT_ULL(KPF_RECLAIM);
> +
> + if (folio_test_swapcache(folio))
> + u |= BIT_ULL(KPF_SWAPCACHE);
> + if (folio_test_swapbacked(folio))
> + u |= BIT_ULL(KPF_SWAPBACKED);
> + if (folio_test_unevictable(folio))
> + u |= BIT_ULL(KPF_UNEVICTABLE);
> + if (folio_test_mlocked(folio))
> + u |= BIT_ULL(KPF_MLOCKED);
> +
> + if ((folio_test_hugetlb(folio) && folio_test_hwpoison(folio))
> + || PageHWPoison(&ps.page_snapshot))
> + u |= BIT_ULL(KPF_HWPOISON);
> +
> + if (folio_test_reserved(folio))
> + u |= BIT_ULL(KPF_RESERVED);
That is not a pure folio flag.
> + if (folio_test_owner_2(folio))
> + u |= BIT_ULL(KPF_OWNER_2);
> + if (folio_test_private(folio))
> + u |= BIT_ULL(KPF_PRIVATE);
> + if (folio_test_private_2(folio))
> + u |= BIT_ULL(KPF_PRIVATE_2);
These as well.
So I'd probably leave the page bit checking alone for now and focus on the
mapping only.
--
Cheers,
David
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-10 11:29 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-02 11:06 [PATCH 0/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-02 11:06 ` [PATCH 1/2] fs: stable_page_flags(): use BIT_ULL() for KPF flags Jinjiang Tu
2026-07-02 13:10 ` David Hildenbrand (Arm)
2026-07-02 14:32 ` [PATCH 1/2] " Zi Yan
2026-07-02 11:06 ` [PATCH 2/2] fs: stable_page_flags(): use folio_test_*() helpers Jinjiang Tu
2026-07-10 3:52 ` Jinjiang Tu
2026-07-10 11:29 ` David Hildenbrand (Arm)
2026-07-02 12:03 ` [PATCH 0/2] " David Hildenbrand (Arm)
2026-07-03 3:00 ` Jinjiang Tu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox