ANDROID: vendor_hook: Added hook for memory reclaim tuning

The following hooks are added for memory reclaim tuning:

android_vh_mm_isolate_priv_lru - This hook is used to properly handle certain
folios when they are reclaimed.

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.

android_vh_mm_customize_pgdat_balanced - When there are multiple zones, it is
not always reasonable to perform indirect reclaim 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_reclaim_idx - When there are multiple zones, vendors use
this hook to customize which zones can be reclaimed.

android_vh_mm_customize_zone_can_compact - When there are multiple zones, vendors
use this hook to customize which zones can be compacted.

Bug: 431672372
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 T.J. Mercier
parent 73c426b11f
commit 6c25b93a26
5 changed files with 81 additions and 2 deletions
+5
View File
@@ -599,3 +599,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_suitable_zone);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_wmark_ok);
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_isolate_priv_lru);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_file_is_tiny);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_pgdat_balanced);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_reclaim_idx);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_zone_can_compact);
+3
View File
@@ -19,6 +19,9 @@ enum compact_result;
DECLARE_HOOK(android_vh_compaction_try_to_compact_exit,
TP_PROTO(enum compact_result *compact_result),
TP_ARGS(compact_result));
DECLARE_HOOK(android_vh_mm_customize_zone_can_compact,
TP_PROTO(struct zone *zone, bool *can_compact),
TP_ARGS(zone, can_compact));
#endif /* _TRACE_HOOK_COMPACTION_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
+14
View File
@@ -111,6 +111,20 @@ DECLARE_HOOK(android_vh_shrink_node,
DECLARE_HOOK(android_vh_shrink_node_memcgs,
TP_PROTO(struct mem_cgroup *memcg, bool *skip),
TP_ARGS(memcg, skip));
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_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));
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_reclaim_idx,
TP_PROTO(int order, gfp_t gfp, s8 *reclaim_idx, enum zone_type *highest_zoneidx),
TP_ARGS(order, gfp, reclaim_idx, highest_zoneidx));
#endif /* _TRACE_HOOK_VMSCAN_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
+27
View File
@@ -2854,6 +2854,11 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
for_each_zone_zonelist_nodemask(zone, z, ac->zonelist,
ac->highest_zoneidx, ac->nodemask) {
enum compact_result status;
bool can_compact = true;
trace_android_vh_mm_customize_zone_can_compact(zone, &can_compact);
if (!can_compact)
continue;
if (cpusets_enabled() &&
(alloc_flags & ALLOC_CPUSET) &&
@@ -2921,10 +2926,16 @@ void compact_node_async(int nid)
};
for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
bool can_compact = true;
zone = &pgdat->node_zones[zoneid];
if (!populated_zone(zone))
continue;
trace_android_vh_mm_customize_zone_can_compact(zone, &can_compact);
if (!can_compact)
continue;
if (fatal_signal_pending(current))
break;
@@ -2960,10 +2971,16 @@ static int compact_node(pg_data_t *pgdat, bool proactive)
};
for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
bool can_compact = true;
zone = &pgdat->node_zones[zoneid];
if (!populated_zone(zone))
continue;
trace_android_vh_mm_customize_zone_can_compact(zone, &can_compact);
if (!can_compact)
continue;
if (fatal_signal_pending(current))
return -EINTR;
@@ -3090,11 +3107,16 @@ static bool kcompactd_node_suitable(pg_data_t *pgdat)
enum compact_result ret;
for (zoneid = 0; zoneid <= highest_zoneidx; zoneid++) {
bool can_compact = true;
zone = &pgdat->node_zones[zoneid];
if (!populated_zone(zone))
continue;
trace_android_vh_mm_customize_zone_can_compact(zone, &can_compact);
if (!can_compact)
continue;
ret = compaction_suit_allocation_order(zone,
pgdat->kcompactd_max_order,
highest_zoneidx, ALLOC_WMARK_MIN);
@@ -3129,11 +3151,16 @@ static void kcompactd_do_work(pg_data_t *pgdat)
for (zoneid = 0; zoneid <= cc.highest_zoneidx; zoneid++) {
int status;
bool can_compact = true;
zone = &pgdat->node_zones[zoneid];
if (!populated_zone(zone))
continue;
trace_android_vh_mm_customize_zone_can_compact(zone, &can_compact);
if (!can_compact)
continue;
if (compaction_deferred(zone, cc.order))
continue;
+32 -2
View File
@@ -1738,6 +1738,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;
@@ -1996,7 +2002,7 @@ static 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;
@@ -2117,7 +2123,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);
@@ -2352,6 +2358,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,
@@ -2465,6 +2480,8 @@ static void prepare_scan_control(pg_data_t *pgdat, struct scan_control *sc)
!(sc->may_deactivate & DEACTIVATE_ANON) &&
anon >> sc->priority;
}
customize_sc_file_is_tiny(sc);
}
/*
@@ -6309,6 +6326,9 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
sc->reclaim_idx = gfp_zone(sc->gfp_mask);
}
trace_android_vh_mm_customize_reclaim_idx(sc->order, sc->gfp_mask,
&sc->reclaim_idx, NULL);
for_each_zone_zonelist_nodemask(zone, z, zonelist,
sc->reclaim_idx, sc->nodemask) {
/*
@@ -6860,8 +6880,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.
@@ -7469,6 +7496,9 @@ void wakeup_kswapd(struct zone *zone, gfp_t gfp_flags, int order,
if (!cpuset_zone_allowed(zone, gfp_flags))
return;
trace_android_vh_mm_customize_reclaim_idx(order, gfp_flags, NULL,
&highest_zoneidx);
pgdat = zone->zone_pgdat;
curr_idx = READ_ONCE(pgdat->kswapd_highest_zoneidx);