On Sat 10-07-21 16:11:38, Chao Yu wrote: > On 2021/7/7 17:57, Mel Gorman wrote: > > I think it would work but it would be preferable to find out why the > > tail page has an order set in the first place. I've looked over > > Agreed. > > > mm/page_alloc.c and mm/compaction.c a few times and did not spot where > > set_private_page(page, 0) is missed when it should be covered by > > clear_page_guard or del_page_from_free_list :( > > I didn't enable CONFIG_DEBUG_PAGEALLOC, so we will expect page private > should be cleared by del_page_from_free_list(), but I guess it only clears > the buddy's private field rather than original page's, so I added below > diff and check the dmesg, it looks stall private value in original page > will be left commonly... Let me know if I missed something? Page private should be cleared when the page is freed to the allocator. Have a look at PAGE_FLAGS_CHECK_AT_FREE. > --- > mm/page_alloc.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index a06bcfe6f786..1e7031ff548e 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1029,6 +1029,7 @@ static inline void __free_one_page(struct page *page, > unsigned long combined_pfn; > unsigned int max_order; > struct page *buddy; > + struct page *orig_page = page; > bool to_tail; > > max_order = min_t(unsigned int, MAX_ORDER - 1, pageblock_order); > @@ -1097,6 +1098,10 @@ static inline void __free_one_page(struct page *page, > > done_merging: > set_buddy_order(page, order); > + if (orig_page != page) { > + if (WARN_ON_ONCE(orig_page->private)) > + pr_info("2order:%x, origpage.private:%x", order, orig_page->private); > + } Why is this expected? Buddy allocator uses page private to store order. Whether we are merging to the freed page or coalesce it to a different page is not all that important. -- Michal Hocko SUSE Labs