mm/page_owner: misc cleanups
Subsystems (6)
v3 cover mm/page_owner: misc cleanups
v3:
- Patch 2: add MR_NEVER directly to enum migrate_reason instead of using a local MIGRATE_REASON_NONE define (Zi Yan and Vlastimil Babka).
- Patch 3 (new): convert all 'int reason' parameters in the migration callchain to 'enum migrate_reason' so the type system reflects the actual semantics.
- Patch 7: make threshold_fops a single line.
- Link: https://lore.kernel.org/all/[email protected]/
v2:
- Add cover letter (no code changes).
- Link: https://lore.kernel.org/all/[email protected]/
This series collects a few cleanups for mm/page_owner.c that have been accumulated while reading through the file. There is no functional change -- the goal is to make the code easier to read and maintain.
Patch 1 consolidates three identical PageBuddy skip blocks into a single skip_buddy_pages() helper, eliminating the duplication and keeping the lockless-read comment in one place.
Patch 2 replaces the -1 magic number used for "never migrated" with a proper MR_NEVER member in enum migrate_reason, and adds the corresponding "never_migrated" string in the MIGRATE_REASON trace macro.
Patch 3 follows up by converting the remaining 'int reason' parameters throughout the migration and hugetlb callchains to 'enum migrate_reason', making the type explicit and gaining compiler checking. The 'short last_migrate_reason' struct field in page_owner is intentionally left as 'short' since it is per-page metadata where size matters.
Patch 4 hoists the CONFIG_MEMCG guard out of print_page_owner_memcg()'s body so that the real implementation and the empty stub are two clearly separate definitions, the common kernel idiom.
Patch 5 adds a missing \n to the count_threshold debugfs attribute format string so that cat(1) output is properly terminated.
Patch 6 moves free_ts_nsec from the allocation summary line to the free section in __dump_page_owner(), grouping it with free_pid and free_tgid where it logically belongs. This also makes the dump output consistent with print_page_owner().
Patch 7 drops the redundant page_owner_ prefix from file-scoped static symbols (stack_fops, threshold_fops, etc.). Since they cannot collide across translation units, the prefix carries no information.
The series is based on v6.17-rc1 and has been compile-tested with and without CONFIG_MEMCG.
Ye Liu (7):
mm/page_owner: extract skip_buddy_pages() helper to unify buddy page
skipping
mm/page_owner: add MR_NEVER to enum migrate_reason and use it for
last_migrate_reason
mm: use enum migrate_reason instead of int for migration reason
parameters
mm/page_owner: hoist CONFIG_MEMCG to function level for
print_page_owner_memcg()
mm/page_owner: add missing newline to count_threshold format string mm/page_owner: move free_ts_nsec output to free section in
__dump_page_owner()
mm/page_owner: drop redundant page_owner prefix from static symbols
include/linux/hugetlb.h | 9 +-- include/linux/migrate.h | 6 +- include/linux/migrate_mode.h | 1 + include/linux/page_owner.h | 7 +- include/trace/events/migrate.h | 11 ++-- mm/hugetlb.c | 3 +- mm/migrate.c | 12 ++-- mm/page_owner.c | 115 +++++++++++++++++---------------- 8 files changed, 88 insertions(+), 76 deletions(-)
--
2.43.0
PATCH v3 1/7 mm/page_owner: extract skip_buddy_pages() helper to unify buddy page skipping
Three places in page_owner.c duplicate the same pattern: check if a page is PageBuddy, read its order via buddy_order_unsafe(), advance the pfn past the buddy block if the order is valid, and continue.
Consolidate them into a single inline helper skip_buddy_pages(). The function returns true (skip) for any buddy page and advances @pfn past the block when the order is valid; returns false if the page is not a buddy page and should be processed normally.
The old init_pages_in_zone() variant used "order > 0" as an extra guard before advancing pfn, but the continue was unconditional and (1UL << 0) - 1 == 0, so the behaviour is identical. The comment about zone->lock is preserved in the helper's kernel-doc.
No functional change.
--- mm/page_owner.c | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
mm/page_owner.c +26 -26
@@ -422,6 +422,29 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old)rcu_read_unlock (); } +/* +* Check if a page is a buddy page and advance @pfn past the entire buddy block. +* This safely reads the buddy order without the zone lock, which may cause us +* to skip less than the full buddy block, but that is acceptable for page owner +* iteration purposes. +* +* Return: true if the page was skipped (caller should continue its loop), +* false if the page is not a buddy page and should be processed normally. +*/ +static inline bool skip_buddy_pages (unsigned long *pfn,struct page *page) +{ +unsigned long order; + +if (!PageBuddy (page)) +return false; + + order =buddy_order_unsafe (page); +if (order <=MAX_PAGE_ORDER ) + *pfn += (1UL << order) -1 ; + +return true; +} +void pagetypeinfo_showmixedcount_print (struct seq_file *m,pg_data_t *pgdat,struct zone *zone) {
@@ -461,14 +484,8 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,if (page_zone (page) != zone)continue ; -if (PageBuddy (page)) { -unsigned long freepage_order; - - freepage_order =buddy_order_unsafe (page); -if (freepage_order <=MAX_PAGE_ORDER ) - pfn += (1UL << freepage_order) -1 ; +if (skip_buddy_pages (&pfn, page))continue ; - }if (PageReserved (page))continue ;
@@ -697,13 +714,8 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) } page =pfn_to_page (pfn); -if (PageBuddy (page)) { -unsigned long freepage_order =buddy_order_unsafe (page); - -if (freepage_order <=MAX_PAGE_ORDER ) - pfn += (1UL << freepage_order) -1 ; +if (skip_buddy_pages (&pfn, page))continue ; - } page_ext =page_ext_get (page);if (unlikely (!page_ext))
@@ -798,20 +810,8 @@ static void init_pages_in_zone(struct zone *zone)if (page_zone (page) != zone)continue ; -/* -* To avoid having to grab zone->lock, be a little -* careful when reading buddy page order. The only -* danger is that we skip too much and potentially miss -* some early allocated pages, which is better than -* heavy lock contention. -*/ -if (PageBuddy (page)) { -unsigned long order =buddy_order_unsafe (page); - -if (order >0 && order <=MAX_PAGE_ORDER ) - pfn += (1UL << order) -1 ; +if (skip_buddy_pages (&pfn, page))continue ; - }if (PageReserved (page))continue ;
Signature · 1 line
2.43.0
PATCH v3 2/7 mm/page_owner: add MR_NEVER to enum migrate_reason and use it for last_migrate_reason
In reply to Ye LiuThe last_migrate_reason field uses -1 as a sentinel value to mean "no migration has happened". Replace the four bare -1 occurrences by adding a proper MR_NEVER member to enum migrate_reason, defining a corresponding "never_migrated" string in the MIGRATE_REASON trace macro, and removing the local MIGRATE_REASON_NONE define.
No functional change.
--- include/linux/migrate_mode.h | 1 + include/trace/events/migrate.h | 3 ++- mm/page_owner.c | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-)
include/linux/migrate_mode.h +1 -0
@@ -25,6 +25,7 @@ enum migrate_reason {MR_LONGTERM_PIN ,MR_DEMOTION ,MR_DAMON , +MR_NEVER ,/* page has never been migrated */ MR_TYPES };
include/trace/events/migrate.h +2 -1
@@ -23,7 +23,8 @@ EM( MR_CONTIG_RANGE, "contig_range") \ EM( MR_LONGTERM_PIN, "longterm_pin") \ EM( MR_DEMOTION, "demotion") \ -EMe (MR_DAMON ,"damon" ) + EM( MR_DAMON, "damon") \ +EMe (MR_NEVER ,"never_migrated" )/* * First define the enums in the above macros to be exported to userspace
mm/page_owner.c +4 -4
@@ -339,7 +339,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,depot_stack_handle_t handle; handle =save_stack (gfp_mask); -__update_page_owner_handle (page, handle, order, gfp_mask,-1 , +__update_page_owner_handle (page, handle, order, gfp_mask,MR_NEVER , ts_nsec, current->pid, current->tgid, current->comm);inc_stack_record_count (handle, gfp_mask,1 << order);
@@ -596,7 +596,7 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,if (ret >= count) goto err; -if (page_owner->last_migrate_reason !=-1 ) { +if (page_owner->last_migrate_reason !=MR_NEVER ) { ret +=scnprintf (kbuf + ret, count - ret,"Page has been migrated, last migrate reason: %s\n" , migrate_reason_names[page_owner->last_migrate_reason]);
@@ -667,7 +667,7 @@ void __dump_page_owner(const struct page *page)stack_depot_print (handle); } -if (page_owner->last_migrate_reason !=-1 ) +if (page_owner->last_migrate_reason !=MR_NEVER )pr_alert ("page has been migrated, last migrate reason: %s\n" , migrate_reason_names[page_owner->last_migrate_reason]);page_ext_put (page_ext);
@@ -826,7 +826,7 @@ static void init_pages_in_zone(struct zone *zone)/* Found early allocated page */ __update_page_owner_handle (page, early_handle,0 ,0 , --1 ,local_clock (), current->pid, +MR_NEVER ,local_clock (), current->pid, current->tgid, current->comm); count++; ext_put_continue:
Signature · 1 line
2.43.0
Re: [PATCH v3 2/7] mm/page_owner: add MR_NEVER to enum migrate_reason and use it for last_migrate_reason
Quoted 6 lines · Ye Liu
The
last_migrate_reasonfield uses -1 as a sentinel value to mean "no migration has happened". Replace the four bare -1 occurrences by adding a properMR_NEVERmember to enummigrate_reason, defining a corresponding "never_migrated" string in theMIGRATE_REASONtrace macro, and removing the localMIGRATE_REASON_NONEdefine.
Quoted 9 lines
No functional change.
Signed-off-by Ye Liu <[email protected]>--- include/linux/migrate_mode.h | 1 + include/trace/events/migrate.h | 3 ++- mm/page_owner.c | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-)
LGTM. Thanks.
Signature · 2 lines
Best Regards, Yan, Zi
Re: [PATCH v3 2/7] mm/page_owner: add MR_NEVER to enum migrate_reason and use it for last_migrate_reason
In reply to Ye LiuQuoted 9 lines · Ye Liu
The
last_migrate_reasonfield uses -1 as a sentinel value to mean "no migration has happened". Replace the four bare -1 occurrences by adding a properMR_NEVERmember to enummigrate_reason, defining a corresponding "never_migrated" string in theMIGRATE_REASONtrace macro, and removing the localMIGRATE_REASON_NONEdefine.No functional change.
Signed-off-by Ye Liu <[email protected]>
Quoted 72 lines
--- include/linux/migrate_mode.h | 1 + include/trace/events/migrate.h | 3 ++- mm/page_owner.c | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-)include/linux/migrate_mode.h +1
-0@@ -25,6 +25,7 @@ enum migrate_reason {MR_LONGTERM_PIN ,MR_DEMOTION ,MR_DAMON , +MR_NEVER ,/* page has never been migrated */ MR_TYPES };include/trace/events/migrate.h +2
-1@@ -23,7 +23,8 @@ EM( MR_CONTIG_RANGE, "contig_range") \ EM( MR_LONGTERM_PIN, "longterm_pin") \ EM( MR_DEMOTION, "demotion") \ -EMe (MR_DAMON ,"damon" ) + EM( MR_DAMON, "damon") \ +EMe (MR_NEVER ,"never_migrated" )/* * First define the enums in the above macros to be exported to userspace mm/page_owner.c +4
-4@@ -339,7 +339,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,depot_stack_handle_t handle; handle =save_stack (gfp_mask); -__update_page_owner_handle (page, handle, order, gfp_mask,-1 , +__update_page_owner_handle (page, handle, order, gfp_mask,MR_NEVER , ts_nsec, current->pid, current->tgid, current->comm);inc_stack_record_count (handle, gfp_mask,1 << order);@@ -596,7 +596,7 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,if (ret >= count) goto err; -if (page_owner->last_migrate_reason !=-1 ) { +if (page_owner->last_migrate_reason !=MR_NEVER ) { ret +=scnprintf (kbuf + ret, count - ret,"Page has been migrated, last migrate reason: %s\n" , migrate_reason_names[page_owner->last_migrate_reason]);@@ -667,7 +667,7 @@ void __dump_page_owner(const struct page *page)stack_depot_print (handle); } -if (page_owner->last_migrate_reason !=-1 ) +if (page_owner->last_migrate_reason !=MR_NEVER )pr_alert ("page has been migrated, last migrate reason: %s\n" , migrate_reason_names[page_owner->last_migrate_reason]);page_ext_put (page_ext);@@ -826,7 +826,7 @@ static void init_pages_in_zone(struct zone *zone)/* Found early allocated page */ __update_page_owner_handle (page, early_handle,0 ,0 , --1 ,local_clock (), current->pid, +MR_NEVER ,local_clock (), current->pid, current->tgid, current->comm); count++; ext_put_continue:
PATCH v3 3/7 mm: use enum migrate_reason instead of int for migration reason parameters
In reply to Ye LiuReplace all 'int reason' function parameters that carry migrate_reason values with the proper 'enum migrate_reason' type. This makes the intent explicit and leverages compiler type checking. The affected subsystems are:
- page_owner: __folio_set_owner_migrate_reason(), folio_set_owner_migrate_reason()
- migrate: migrate_pages(), migrate_pages_sync(), migrate_pages_batch(), migrate_folios_move(), migrate_hugetlbs(), unmap_and_move_huge_page()
- hugetlb: move_hugetlb_state(), htlb_allow_alloc_fallback()
- trace: mm_migrate_pages and mm_migrate_pages_start events
The 'short last_migrate_reason' struct field and internal helper parameter in page_owner are intentionally left as 'short' since they store per-page metadata where size matters.
No functional change.
--- include/linux/hugetlb.h | 9 +++++---- include/linux/migrate.h | 6 ++++-- include/linux/page_owner.h | 7 ++++--- include/trace/events/migrate.h | 8 ++++---- mm/hugetlb.c | 3 ++- mm/migrate.c | 12 ++++++------ mm/page_owner.c | 2 +- 7 files changed, 26 insertions(+), 21 deletions(-)
include/linux/hugetlb.h +5 -4
@@ -154,7 +154,8 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,bool folio_isolate_hugetlb (struct folio *folio,struct list_head *list);int get_hwpoison_hugetlb_folio (struct folio *folio,bool *hugetlb,bool unpoison);void folio_putback_hugetlb (struct folio *folio); -void move_hugetlb_state (struct folio *old_folio,struct folio *new_folio,int reason); +void move_hugetlb_state (struct folio *old_folio,struct folio *new_folio, +enum migrate_reason reason);void hugetlb_fix_reserve_counts (struct inode *inode);extern struct mutex *hugetlb_fault_mutex_table;u32 hugetlb_fault_mutex_hash (struct address_space *mapping,pgoff_t idx);
@@ -424,7 +425,7 @@ static inline void folio_putback_hugetlb(struct folio *folio) }static inline void move_hugetlb_state (struct folio *old_folio, -struct folio *new_folio,int reason) +struct folio *new_folio,enum migrate_reason reason) { }
@@ -956,7 +957,7 @@ static inline gfp_t htlb_modify_alloc_mask(struct hstate *h, gfp_t gfp_mask)return modified_mask; } -static inline bool htlb_allow_alloc_fallback (int reason) +static inline bool htlb_allow_alloc_fallback (enum migrate_reason reason) {bool allowed_fallback = false;
@@ -1238,7 +1239,7 @@ static inline gfp_t htlb_modify_alloc_mask(struct hstate *h, gfp_t gfp_mask)return 0 ; } -static inline bool htlb_allow_alloc_fallback (int reason) +static inline bool htlb_allow_alloc_fallback (enum migrate_reason reason) {return false; }
include/linux/migrate.h +4 -2
@@ -57,7 +57,8 @@ void putback_movable_pages(struct list_head *l);int migrate_folio (struct address_space *mapping,struct folio *dst,struct folio *src,enum migrate_mode mode);int migrate_pages (struct list_head *l,new_folio_t new,free_folio_t free, -unsigned long private,enum migrate_mode mode,int reason, +unsigned long private,enum migrate_mode mode, +enum migrate_reason reason,unsigned int *ret_succeeded);struct folio *alloc_migration_target (struct folio *src,unsigned long private);bool isolate_movable_ops_page (struct page *page,isolate_mode_t mode);
@@ -77,7 +78,8 @@ int set_movable_ops(const struct movable_operations *ops, enum pagetype type);static inline void putback_movable_pages (struct list_head *l) {}static inline int migrate_pages (struct list_head *l,new_folio_t new,free_folio_t free,unsigned long private, -enum migrate_mode mode,int reason,unsigned int *ret_succeeded) +enum migrate_mode mode,enum migrate_reason reason, +unsigned int *ret_succeeded) {return -ENOSYS ; }static inline struct folio *alloc_migration_target (struct folio *src,unsigned long private)
include/linux/page_owner.h +4 -3
@@ -3,6 +3,7 @@#define __LINUX_PAGE_OWNER_H#include <linux/jump_label.h> +#include <linux/migrate_mode.h> #ifdef CONFIG_PAGE_OWNER extern struct static_key_false page_owner_inited;
@@ -14,7 +15,7 @@ extern void __set_page_owner(struct page *page,extern void __split_page_owner (struct page *page,int old_order,int new_order);extern void __folio_copy_owner (struct folio *newfolio,struct folio *old); -extern void __folio_set_owner_migrate_reason (struct folio *folio,int reason); +extern void __folio_set_owner_migrate_reason (struct folio *folio,enum migrate_reason reason);extern void __dump_page_owner (const struct page *page);extern void pagetypeinfo_showmixedcount_print (struct seq_file *m,pg_data_t *pgdat,struct zone *zone);
@@ -43,7 +44,7 @@ static inline void folio_copy_owner(struct folio *newfolio, struct folio *old)if (static_branch_unlikely (&page_owner_inited))__folio_copy_owner (newfolio, old); } -static inline void folio_set_owner_migrate_reason (struct folio *folio,int reason) +static inline void folio_set_owner_migrate_reason (struct folio *folio,enum migrate_reason reason) {if (static_branch_unlikely (&page_owner_inited))__folio_set_owner_migrate_reason (folio, reason);
@@ -68,7 +69,7 @@ static inline void split_page_owner(struct page *page, int old_order,static inline void folio_copy_owner (struct folio *newfolio,struct folio *folio) { } -static inline void folio_set_owner_migrate_reason (struct folio *folio,int reason) +static inline void folio_set_owner_migrate_reason (struct folio *folio,enum migrate_reason reason) { }static inline void dump_page_owner (const struct page *page)
include/trace/events/migrate.h +4 -4
@@ -52,7 +52,7 @@ TRACE_EVENT(mm_migrate_pages, TP_PROTO(unsigned long succeeded, unsigned long failed, unsigned long thp_succeeded, unsigned long thp_failed, unsigned long thp_split, unsigned long large_folio_split, - enum migrate_mode mode, int reason), + enum migrate_mode mode, enum migrate_reason reason),TP_ARGS (succeeded, failed, thp_succeeded, thp_failed, thp_split, large_folio_split, mode, reason),
@@ -65,7 +65,7 @@ TRACE_EVENT(mm_migrate_pages, __field( unsigned long, thp_split) __field( unsigned long, large_folio_split) __field( enum migrate_mode, mode) - __field( int, reason) + __field( enum migrate_reason, reason) ), TP_fast_assign(
@@ -92,13 +92,13 @@ TRACE_EVENT(mm_migrate_pages, TRACE_EVENT(mm_migrate_pages_start, - TP_PROTO(enum migrate_mode mode, int reason), + TP_PROTO(enum migrate_mode mode, enum migrate_reason reason), TP_ARGS(mode, reason), TP_STRUCT__entry( __field(enum migrate_mode, mode) - __field(int, reason) + __field(enum migrate_reason, reason) ), TP_fast_assign(
mm/hugetlb.c +2 -1
@@ -7182,7 +7182,8 @@ void folio_putback_hugetlb(struct folio *folio)folio_put (folio); } -void move_hugetlb_state (struct folio *old_folio,struct folio *new_folio,int reason) +void move_hugetlb_state (struct folio *old_folio,struct folio *new_folio, +enum migrate_reason reason) {struct hstate *h =folio_hstate (old_folio);
mm/migrate.c +6 -6
@@ -1469,7 +1469,7 @@ static int migrate_folio_move(free_folio_t put_new_folio, unsigned long private,static int unmap_and_move_huge_page (new_folio_t get_new_folio,free_folio_t put_new_folio,unsigned long private,struct folio *src,int force,enum migrate_mode mode, -int reason,struct list_head *ret) +enum migrate_reason reason,struct list_head *ret) {struct folio *dst;int rc = -EAGAIN ;
@@ -1626,7 +1626,7 @@ struct migrate_pages_stats {*/ static int migrate_hugetlbs (struct list_head *from,new_folio_t get_new_folio,free_folio_t put_new_folio,unsigned long private, -enum migrate_mode mode,int reason, +enum migrate_mode mode,enum migrate_reason reason,struct migrate_pages_stats *stats,struct list_head *ret_folios) {
@@ -1716,7 +1716,7 @@ static int migrate_hugetlbs(struct list_head *from, new_folio_t get_new_folio, static void migrate_folios_move(struct list_head *src_folios, struct list_head *dst_folios, free_folio_t put_new_folio, unsigned long private, - enum migrate_mode mode, int reason, + enum migrate_mode mode, enum migrate_reason reason, struct list_head *ret_folios, struct migrate_pages_stats *stats, int *retry, int *thp_retry, int *nr_failed,
@@ -1799,7 +1799,7 @@ static void migrate_folios_undo(struct list_head *src_folios,*/ static int migrate_pages_batch (struct list_head *from,new_folio_t get_new_folio,free_folio_t put_new_folio, -unsigned long private,enum migrate_mode mode,int reason, +unsigned long private,enum migrate_mode mode,enum migrate_reason reason,struct list_head *ret_folios,struct list_head *split_folios,struct migrate_pages_stats *stats,int nr_pass) {
@@ -2011,7 +2011,7 @@ static int migrate_pages_batch(struct list_head *from,static int migrate_pages_sync (struct list_head *from,new_folio_t get_new_folio,free_folio_t put_new_folio,unsigned long private, -enum migrate_mode mode,int reason, +enum migrate_mode mode,enum migrate_reason reason,struct list_head *ret_folios,struct list_head *split_folios,struct migrate_pages_stats *stats) {
@@ -2088,7 +2088,7 @@ static int migrate_pages_sync(struct list_head *from, new_folio_t get_new_folio,*/ int migrate_pages (struct list_head *from,new_folio_t get_new_folio,free_folio_t put_new_folio,unsigned long private, -enum migrate_mode mode,int reason,unsigned int *ret_succeeded) +enum migrate_mode mode,enum migrate_reason reason,unsigned int *ret_succeeded) {int rc, rc_gather;int nr_pages;
mm/page_owner.c +1 -1
@@ -345,7 +345,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,inc_stack_record_count (handle, gfp_mask,1 << order); } -void __folio_set_owner_migrate_reason (struct folio *folio,int reason) +void __folio_set_owner_migrate_reason (struct folio *folio,enum migrate_reason reason) {struct page_ext *page_ext =page_ext_get (&folio->page);struct page_owner *page_owner;
Signature · 1 line
2.43.0
Re: [PATCH v3 3/7] mm: use enum migrate_reason instead of int for migration reason parameters
Quoted 20 lines · Ye Liu
Replace all 'int reason' function parameters that carry
migrate_reasonvalues with the proper 'enummigrate_reason' type. This makes the intent explicit and leverages compiler type checking. The affected subsystems are:-
page_owner:__folio_set_owner_migrate_reason(),folio_set_owner_migrate_reason()
- migrate:migrate_pages(),migrate_pages_sync(),migrate_pages_batch(),migrate_folios_move(),migrate_hugetlbs(),unmap_and_move_huge_page()
- hugetlb:move_hugetlb_state(),htlb_allow_alloc_fallback()
- trace:mm_migrate_pagesandmm_migrate_pages_starteventsThe 'short
last_migrate_reason' struct field and internal helper parameter inpage_ownerare intentionally left as 'short' since they store per-page metadata where size matters.No functional change.
Signed-off-by Ye Liu <[email protected]>
Quoted 10 lines
--- include/linux/hugetlb.h | 9 +++++---- include/linux/migrate.h | 6 ++++-- include/linux/page_owner.h | 7 ++++--- include/trace/events/migrate.h | 8 ++++---- mm/hugetlb.c | 3 ++- mm/migrate.c | 12 ++++++------ mm/page_owner.c | 2 +- 7 files changed, 26 insertions(+), 21 deletions(-)
LGTM. Thanks.
Signature · 2 lines
Best Regards, Yan, Zi
Re: [PATCH v3 3/7] mm: use enum migrate_reason instead of int for migration reason parameters
In reply to Ye LiuQuoted 13 lines · Ye Liu
Replace all 'int reason' function parameters that carry
migrate_reasonvalues with the proper 'enummigrate_reason' type. This makes the intent explicit and leverages compiler type checking. The affected subsystems are:-
page_owner:__folio_set_owner_migrate_reason(),folio_set_owner_migrate_reason()
- migrate:migrate_pages(),migrate_pages_sync(),migrate_pages_batch(),migrate_folios_move(),migrate_hugetlbs(),unmap_and_move_huge_page()
- hugetlb:move_hugetlb_state(),htlb_allow_alloc_fallback()
- trace:mm_migrate_pagesandmm_migrate_pages_startevents
Quoted 7 lines
The 'short
last_migrate_reason' struct field and internal helper parameter inpage_ownerare intentionally left as 'short' since they store per-page metadata where size matters.No functional change.
Signed-off-by Ye Liu <[email protected]>
PATCH v3 4/7 mm/page_owner: hoist CONFIG_MEMCG to function level for print_page_owner_memcg()
In reply to Ye LiuThe print_page_owner_memcg() function has CONFIG_MEMCG guarding its entire body via #ifdef inside the function, which leaves a no-op { return ret; } when the config is disabled. Hoist the #ifdef to the top level so the real implementation and the empty stub are two clearly separated definitions.
No functional change.
--- mm/page_owner.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
mm/page_owner.c +8 -2
@@ -522,13 +522,13 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,seq_putc (m,'\n' ); } +#ifdef CONFIG_MEMCG /* * Looking for memcg information and print it out */ static inline int print_page_owner_memcg (char *kbuf,size_t count,int ret,struct page *page) { -#ifdef CONFIG_MEMCG unsigned long memcg_data;struct mem_cgroup *memcg;bool online;
@@ -556,10 +556,16 @@ static inline int print_page_owner_memcg(char *kbuf, size_t count, int ret, name); out_unlock:rcu_read_unlock (); -#endif /* CONFIG_MEMCG */ return ret; } +#else +static inline int print_page_owner_memcg (char *kbuf,size_t count,int ret, +struct page *page) +{ +return ret; +} +#endif static ssize_t print_page_owner(char __user *buf, size_t count, unsigned long pfn,
Signature · 1 line
2.43.0
PATCH v3 5/7 mm/page_owner: add missing newline to count_threshold format string
In reply to Ye LiuThe DEFINE_SIMPLE_ATTRIBUTE format string for page_owner_threshold_fops is missing a trailing \n. simple_attr_read() uses scnprintf() with the format string, which does not append a newline, so reading /sys/kernel/debug/page_owner_stacks/count_threshold produces output without a terminating newline. Add the missing \n to match the standard debugfs attribute convention.
--- mm/page_owner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/page_owner.c +1 -1
@@ -974,7 +974,7 @@ static int page_owner_threshold_set(void *data, u64 val) }DEFINE_SIMPLE_ATTRIBUTE (page_owner_threshold_fops, &page_owner_threshold_get, - &page_owner_threshold_set,"%llu" ); + &page_owner_threshold_set,"%llu\n" );static int __init pageowner_init (void )
Signature · 1 line
2.43.0
PATCH v3 6/7 mm/page_owner: move free_ts_nsec output to free section in __dump_page_owner()
In reply to Ye LiuThe free_ts_nsec field is a free-event timestamp, but it was printed in the allocation summary line alongside ts_nsec (allocation time). Move it to the free section where it logically belongs, together with free_pid and free_tgid. This also makes __dump_page_owner() consistent with print_page_owner(), which only prints ts_nsec in the allocation summary.
The output now groups all free-related information (pid, tgid, timestamp, stack trace) in one place.
No functional change except output formatting.
--- mm/page_owner.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
mm/page_owner.c +5 -4
@@ -653,10 +653,10 @@ void __dump_page_owner(const struct page *page)else pr_alert ("page_owner tracks the page as freed\n" ); -pr_alert ("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, tgid %d (%s), ts %llu, free_ts %llu\n" , +pr_alert ("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, tgid %d (%s), ts %llu\n" , page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask, page_owner->pid, page_owner->tgid, page_owner->comm, - page_owner->ts_nsec, page_owner->free_ts_nsec); + page_owner->ts_nsec); handle =READ_ONCE (page_owner->handle);if (!handle)
@@ -668,8 +668,9 @@ void __dump_page_owner(const struct page *page)if (!handle) {pr_alert ("page_owner free stack trace missing\n" ); }else { -pr_alert ("page last free pid %d tgid %d stack trace:\n" , - page_owner->free_pid, page_owner->free_tgid); +pr_alert ("page last free pid %d tgid %d ts %llu stack trace:\n" , + page_owner->free_pid, page_owner->free_tgid, + page_owner->free_ts_nsec);stack_depot_print (handle); }
Signature · 1 line
2.43.0
PATCH v3 7/7 mm/page_owner: drop redundant page_owner prefix from static symbols
In reply to Ye LiuAll of these symbols are file-scoped (static) in page_owner.c, so the page_owner_ prefix is pure noise. Rename them to shorter, still-clear names:
page_owner_stack_op -> stack_op page_owner_stack_open -> stack_open page_owner_stack_fops -> stack_fops
page_owner_pages_threshold -> pages_threshold
page_owner_threshold_get -> threshold_get
page_owner_threshold_set -> threshold_set
page_owner_threshold_fops -> threshold_fops
No functional change.
--- mm/page_owner.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-)
mm/page_owner.c +16 -18
@@ -894,7 +894,7 @@ static void *stack_next(struct seq_file *m, void *v, loff_t *ppos)return stack; } -static unsigned long page_owner_pages_threshold; +static unsigned long pages_threshold;static int stack_print (struct seq_file *m,void *v) {
@@ -911,7 +911,7 @@ static int stack_print(struct seq_file *m, void *v) nr_base_pages =refcount_read (&stack_record->count) -1 ;if (ctx->flags &STACK_PRINT_FLAG_PAGES && - (nr_base_pages <1 || nr_base_pages < page_owner_pages_threshold)) + (nr_base_pages <1 || nr_base_pages < pages_threshold))return 0 ;if (ctx->flags &STACK_PRINT_FLAG_STACK ) {
@@ -933,16 +933,16 @@ static void stack_stop(struct seq_file *m, void *v) { } -static const struct seq_operations page_owner_stack_op = { +static const struct seq_operations stack_op = { .start = stack_start, .next = stack_next, .stop = stack_stop, .show = stack_print }; -static int page_owner_stack_open (struct inode *inode,struct file *file) +static int stack_open (struct inode *inode,struct file *file) { -int ret =seq_open_private (file, &page_owner_stack_op, +int ret =seq_open_private (file, &stack_op,sizeof (struct stack_print_ctx ));if (!ret) {
@@ -955,28 +955,26 @@ static int page_owner_stack_open(struct inode *inode, struct file *file)return ret; } -static const struct file_operations page_owner_stack_fops = { - .open = page_owner_stack_open, +static const struct file_operations stack_fops = { + .open = stack_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release_private, }; -static int page_owner_threshold_get (void *data,u64 *val) +static int threshold_get (void *data,u64 *val) { - *val =READ_ONCE (page_owner_pages_threshold); + *val =READ_ONCE (pages_threshold);return 0 ; } -static int page_owner_threshold_set (void *data,u64 val) +static int threshold_set (void *data,u64 val) { -WRITE_ONCE (page_owner_pages_threshold, val); +WRITE_ONCE (pages_threshold, val);return 0 ; } -DEFINE_SIMPLE_ATTRIBUTE (page_owner_threshold_fops, &page_owner_threshold_get, - &page_owner_threshold_set,"%llu\n" ); - +DEFINE_SIMPLE_ATTRIBUTE (threshold_fops, &threshold_get, &threshold_set,"%llu\n" );static int __init pageowner_init (void ) {
@@ -992,17 +990,17 @@ static int __init pageowner_init(void)debugfs_create_file ("show_stacks" ,0400 , dir, (void *)(STACK_PRINT_FLAG_STACK |STACK_PRINT_FLAG_PAGES ), - &page_owner_stack_fops); + &stack_fops);debugfs_create_file ("show_handles" ,0400 , dir, (void *)(STACK_PRINT_FLAG_HANDLE |STACK_PRINT_FLAG_PAGES ), - &page_owner_stack_fops); + &stack_fops);debugfs_create_file ("show_stacks_handles" ,0400 , dir, (void *)(STACK_PRINT_FLAG_STACK |STACK_PRINT_FLAG_HANDLE ), - &page_owner_stack_fops); + &stack_fops);debugfs_create_file ("count_threshold" ,0600 , dir,NULL , - &page_owner_threshold_fops); + &threshold_fops);return 0 ; }late_initcall (pageowner_init)
Signature · 1 line
2.43.0
Andrew Morton
maintainerQuoted 3 lines · On Tue, 30 Jun 2026 09:53:17 +0800 Ye Liu <[email protected]> wrote:
This series collects a few cleanups for
mm/page_owner.cthat have been accumulated while reading through the file. There is no functional change -- the goal is to make the code easier to read and maintain.
Updated, thanks.
AI review had some questions and suggestions:
https://sashiko.dev/#/patchset/[email protected]