From: "Kiryl Shutsemau (Meta)" <[email protected]> The anonymous scan reports nothing, and its verdict decides everything after it: which orders selection may still try, and whether the table is refused outright. The only way to see it was to infer it from what the candidates did afterwards, or from their absence.
Add mm_collapse_scan: where the table was scanned, how many slots were holes or the zeropage, how many were swapped out, which orders survived the scan, and the verdict. The first two counts are why a table yields a smaller window than expected. The third is what a PMD candidate will have to read back. The order mask is the scan's whole output to selection in one number: a table refused as a unit shows an empty mask, which distinguishes it at a glance from one that merely lost the PMD order. The file scan already reported through mm_khugepaged_scan_file; this gives the anonymous side the same. Assisted-by: Claude-Code:claude-opus-5 Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]> --- include/trace/events/huge_memory.h | 34 ++++++++++++++++++++++++++++++ mm/collapse.c | 2 ++ 2 files changed, 36 insertions(+) diff --git a/include/trace/events/huge_memory.h b/include/trace/events/huge_memory.h index 86131845b761..573cf5428969 100644 --- a/include/trace/events/huge_memory.h +++ b/include/trace/events/huge_memory.h @@ -126,6 +126,40 @@ TRACE_EVENT(mm_collapse_huge_page, __entry->order) ); +TRACE_EVENT(mm_collapse_scan, + + TP_PROTO(struct mm_struct *mm, unsigned long addr, int none_or_zero, + int unmapped, unsigned long orders, int result), + + TP_ARGS(mm, addr, none_or_zero, unmapped, orders, result), + + TP_STRUCT__entry( + __field(struct mm_struct *, mm) + __field(unsigned long, addr) + __field(int, none_or_zero) + __field(int, unmapped) + __field(unsigned long, orders) + __field(int, result) + ), + + TP_fast_assign( + __entry->mm = mm; + __entry->addr = addr; + __entry->none_or_zero = none_or_zero; + __entry->unmapped = unmapped; + __entry->orders = orders; + __entry->result = result; + ), + + TP_printk("mm=%p, addr=0x%lx, none_or_zero=%d, unmapped=%d, orders=0x%lx, result=%s", + __entry->mm, + __entry->addr, + __entry->none_or_zero, + __entry->unmapped, + __entry->orders, + __print_symbolic(__entry->result, SCAN_STATUS)) +); + TRACE_EVENT(mm_collapse_candidate, TP_PROTO(struct mm_struct *mm, unsigned long addr, unsigned int order, diff --git a/mm/collapse.c b/mm/collapse.c index f0d80204c2bd..b750a1fc81a5 100644 --- a/mm/collapse.c +++ b/mm/collapse.c @@ -2097,6 +2097,8 @@ static enum scan_result collapse_scan_table(struct vm_area_struct *vma, cc->select_orders &= ~BIT(HPAGE_PMD_ORDER); cc->scan_unmapped = unmapped; + trace_mm_collapse_scan(vma->vm_mm, start, none_or_zero, unmapped, + cc->select_orders, result); return result; } -- 2.54.0
