From 4a1101db032add7973656dbece51ced4e826205f Mon Sep 17 00:00:00 2001 From: Pengfei Li Date: Mon, 14 Jul 2025 16:05:00 +0800 Subject: [PATCH] ANDROID: vendor_hook: Added hook for memory reclaim tuning The following hooks are added for memory reclaim tuning: android_vh_mm_customize_lru_add_dst - We create private LRU lists for some folios used by specific processes, and these folios are managed separately. This hook is used to ensure that the aforementioned separately managed folios are also properly handled during split_huge_page. android_vh_mm_isolate_priv_lru - This hook is used to properly handle certain folios when they are reclaimed. android_vh_mm_customize_pgdat_balanced - When there are multiple zones, it is not always reasonable to perform indirect collection only when all zones do not meet the watermark. This hook allows vendors to customize pgdat_balanced to use their own strategy to determine whether to perform and stop indirect collection. android_vh_mm_customize_file_is_tiny - For a specific process, we want only anonymous pages to be reclaimed. This hook allows vendors to modify the value of file_is_tiny to affect the reclaim behavior. Bug: 431730501 Change-Id: I860c2665088753a5c3b6d6dfeeb25a82aeefc8af Signed-off-by: Pengfei Li --- drivers/android/vendor_hooks.c | 4 ++++ include/trace/hooks/mm.h | 3 +++ include/trace/hooks/vmscan.h | 11 +++++++++++ mm/huge_memory.c | 6 ++++++ mm/vmscan.c | 28 ++++++++++++++++++++++++++-- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 6a107980ac45..a3eb6a548023 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -687,3 +687,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_rmqueue); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_suitable_zone); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_zone_max_order); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_zone_pageset); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_lru_add_dst); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_isolate_priv_lru); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_pgdat_balanced); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_file_is_tiny); diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h index c692582c5f77..5b26dbb21445 100644 --- a/include/trace/hooks/mm.h +++ b/include/trace/hooks/mm.h @@ -634,6 +634,9 @@ DECLARE_HOOK(android_vh_mm_customize_zone_max_order, DECLARE_HOOK(android_vh_mm_customize_zone_pageset, TP_PROTO(struct zone *zone, int *new_high, int *new_batch), TP_ARGS(zone, new_high, new_batch)); +DECLARE_HOOK(android_vh_mm_customize_lru_add_dst, + TP_PROTO(struct lruvec *lruvec, struct folio *src, struct folio *dst, bool *added), + TP_ARGS(lruvec, src, dst, added)); #endif /* _TRACE_HOOK_MM_H */ /* This part must be outside protection */ diff --git a/include/trace/hooks/vmscan.h b/include/trace/hooks/vmscan.h index 4bdcfc29c2f4..8bba24542944 100644 --- a/include/trace/hooks/vmscan.h +++ b/include/trace/hooks/vmscan.h @@ -133,6 +133,17 @@ DECLARE_HOOK(android_vh_direct_reclaim_end, DECLARE_HOOK(android_vh_should_split_folio_to_list, TP_PROTO(struct folio *folio, bool *should_split_to_list), TP_ARGS(folio, should_split_to_list)); +DECLARE_HOOK(android_vh_mm_isolate_priv_lru, + TP_PROTO(unsigned long nr_to_scan, struct lruvec *lruvec, enum lru_list lru, + struct list_head *dst, int reclaim_idx, bool may_unmap, + unsigned long *nr_scanned, unsigned long *nr_taken), + TP_ARGS(nr_to_scan, lruvec, lru, dst, reclaim_idx, may_unmap, nr_scanned, nr_taken)); +DECLARE_HOOK(android_vh_mm_customize_pgdat_balanced, + TP_PROTO(int order, int highest_zoneidx, bool *balanced, bool *customized), + TP_ARGS(order, highest_zoneidx, balanced, customized)); +DECLARE_HOOK(android_vh_mm_customize_file_is_tiny, + TP_PROTO(unsigned int may_swap, int order, int highest_zoneidx, bool *file_is_tiny), + TP_ARGS(may_swap, order, highest_zoneidx, file_is_tiny)); #endif /* _TRACE_HOOK_VMSCAN_H */ /* This part must be outside protection */ #include diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 122f52c172c2..792193e57784 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3121,6 +3121,12 @@ static void reset_src_folio(struct folio *src) static bool lru_add_dst(struct lruvec *lruvec, struct folio *src, struct folio *dst) { + bool added = false; + + trace_android_vh_mm_customize_lru_add_dst(lruvec, src, dst, &added); + if (added) + return true; + if (folio_can_split(src)) return false; diff --git a/mm/vmscan.c b/mm/vmscan.c index 4c62b503788b..e2047aa24f5d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2390,6 +2390,12 @@ static unsigned long isolate_lru_folios(unsigned long nr_to_scan, unsigned long skipped = 0; unsigned long scan, total_scan, nr_pages; LIST_HEAD(folios_skipped); + unsigned long nr_scanned_before = *nr_scanned; + + trace_android_vh_mm_isolate_priv_lru(nr_to_scan, lruvec, lru, dst, sc->reclaim_idx, + sc->may_unmap, nr_scanned, &nr_taken); + if (*nr_scanned != nr_scanned_before) + return nr_taken; total_scan = 0; scan = 0; @@ -2647,7 +2653,7 @@ unsigned long shrink_inactive_list(unsigned long nr_to_scan, enum lru_list lru) { LIST_HEAD(folio_list); - unsigned long nr_scanned; + unsigned long nr_scanned = 0; unsigned int nr_reclaimed = 0; unsigned long nr_taken; struct reclaim_stat stat; @@ -2770,7 +2776,7 @@ static void shrink_active_list(unsigned long nr_to_scan, enum lru_list lru) { unsigned long nr_taken; - unsigned long nr_scanned; + unsigned long nr_scanned = 0; unsigned long vm_flags; LIST_HEAD(l_hold); /* The folios which were snipped off */ LIST_HEAD(l_active); @@ -3014,6 +3020,15 @@ static bool inactive_is_low(struct lruvec *lruvec, enum lru_list inactive_lru) return inactive * inactive_ratio < active; } +static void customize_sc_file_is_tiny(struct scan_control *sc) +{ + bool file_is_tiny = sc->file_is_tiny; + + trace_android_vh_mm_customize_file_is_tiny(sc->may_swap, sc->order, + sc->reclaim_idx, &file_is_tiny); + sc->file_is_tiny = file_is_tiny; +} + enum scan_balance { SCAN_EQUAL, SCAN_FRACT, @@ -3131,6 +3146,8 @@ static void prepare_scan_count(pg_data_t *pgdat, struct scan_control *sc) !(sc->may_deactivate & DEACTIVATE_ANON) && anon >> sc->priority; } + + customize_sc_file_is_tiny(sc); } /* @@ -7478,8 +7495,15 @@ static bool pgdat_balanced(pg_data_t *pgdat, int order, int highest_zoneidx) { int i; unsigned long mark = -1; + bool customized = false; + bool balanced = false; struct zone *zone; + trace_android_vh_mm_customize_pgdat_balanced(order, highest_zoneidx, + &balanced, &customized); + if (customized) + return balanced; + /* * Check watermarks bottom-up as lower zones are more likely to * meet watermarks.