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 <pengfei.kernel@vivo.corp-partner.google.com>
This commit is contained in:
Pengfei Li
2025-07-14 16:05:00 +08:00
committed by Treehugger Robot
parent 5f135711ba
commit 4a1101db03
5 changed files with 50 additions and 2 deletions

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 <trace/define_trace.h>

View File

@@ -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;

View File

@@ -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.