| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Chris Goldsworthy <cgoldswo@codeaurora.org> |
| Date: Mon, 9 Nov 2020 22:26:47 -0800 |
| Subject: NOUPSTREAM: ANDROID: mm: Memory Managment related vendor hooks |
| |
| Create a vendor hook inside of gfp_zone() to modify which allocations |
| get to enter ZONE_MOVABLE, by zeroing out __GFP_HIGHMEM inside of the |
| trace hook based on certain conditions. |
| |
| Separately, create separate trace hooks in the swap-in and readahead |
| paths to affect the behavior of the tracehook in gfp_zone(). |
| |
| [CPNOTE: 03/06/21] Lee: Vendor related code - maintain forever |
| |
| Squash: |
| ANDROID: mm: vmscan: support equal reclaim for anon and file pages |
| ANDROID: syscall_check: add vendor hook for mmap syscall |
| |
| Bug: 175415908 |
| Bug: 158645321 |
| Bug: 191291287 |
| Change-Id: I4a4f0b724267ee120a1e5661f6da5d43d7ef6fc6 |
| Signed-off-by: Chris Goldsworthy <cgoldswo@codeaurora.org> |
| --- |
| drivers/android/vendor_hooks.c | 8 ++++++++ |
| include/linux/gfp.h | 11 +---------- |
| include/linux/pagemap.h | 5 +---- |
| include/trace/hooks/mm.h | 28 ++++++++++++++++++++++++++++ |
| include/trace/hooks/syscall_check.h | 22 ++++++++++++++++++++++ |
| include/trace/hooks/vmscan.h | 18 ++++++++++++++++++ |
| mm/memory.c | 7 +++++-- |
| mm/mmzone.c | 17 +++++++++++++++++ |
| mm/readahead.c | 10 ++++++++++ |
| mm/util.c | 4 ++++ |
| mm/vmscan.c | 12 ++++++++++-- |
| 11 files changed, 124 insertions(+), 18 deletions(-) |
| create mode 100644 include/trace/hooks/mm.h |
| create mode 100644 include/trace/hooks/syscall_check.h |
| create mode 100644 include/trace/hooks/vmscan.h |
| |
| diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c |
| --- a/drivers/android/vendor_hooks.c |
| +++ b/drivers/android/vendor_hooks.c |
| @@ -13,7 +13,10 @@ |
| #include <trace/hooks/dtask.h> |
| #include <trace/hooks/mpam.h> |
| #include <trace/hooks/debug.h> |
| +#include <trace/hooks/mm.h> |
| #include <trace/hooks/iommu.h> |
| +#include <trace/hooks/vmscan.h> |
| +#include <trace/hooks/syscall_check.h> |
| |
| /* |
| * Export tracepoints that act as a bare tracehook (ie: have no trace event |
| @@ -50,6 +53,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_sugov_sched_attr); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_iowait); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_sugov_update); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_sched_setaffinity); |
| +EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_skip_swapcache_flags); |
| +EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_gfp_zone_flags); |
| +EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_readahead_gfp_mask); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_task_cpu); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_try_to_wake_up); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_try_to_wake_up_success); |
| @@ -83,6 +89,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_build_sched_domains); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_sched_balance_rt); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_pick_next_entity); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_check_preempt_wakeup); |
| +EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_balance_anon_file_reclaim); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_task); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_after_enqueue_task); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_after_dequeue_task); |
| @@ -91,3 +98,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_dequeue_entity); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_entity_tick); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_enqueue_task_fair); |
| EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_dequeue_task_fair); |
| +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_mmap_file); |
| diff --git a/include/linux/gfp.h b/include/linux/gfp.h |
| --- a/include/linux/gfp.h |
| +++ b/include/linux/gfp.h |
| @@ -473,16 +473,7 @@ static inline bool gfpflags_normal_context(const gfp_t gfp_flags) |
| | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA | ___GFP_HIGHMEM) \ |
| ) |
| |
| -static inline enum zone_type gfp_zone(gfp_t flags) |
| -{ |
| - enum zone_type z; |
| - int bit = (__force int) (flags & GFP_ZONEMASK); |
| - |
| - z = (GFP_ZONE_TABLE >> (bit * GFP_ZONES_SHIFT)) & |
| - ((1 << GFP_ZONES_SHIFT) - 1); |
| - VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1); |
| - return z; |
| -} |
| +enum zone_type gfp_zone(gfp_t flags); |
| |
| /* |
| * There is only one page-allocator function, and two main namespaces to |
| diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h |
| --- a/include/linux/pagemap.h |
| +++ b/include/linux/pagemap.h |
| @@ -378,10 +378,7 @@ static inline struct page *page_cache_alloc(struct address_space *x) |
| return __page_cache_alloc(mapping_gfp_mask(x)); |
| } |
| |
| -static inline gfp_t readahead_gfp_mask(struct address_space *x) |
| -{ |
| - return mapping_gfp_mask(x) | __GFP_NORETRY | __GFP_NOWARN; |
| -} |
| +gfp_t readahead_gfp_mask(struct address_space *x); |
| |
| typedef int filler_t(void *, struct page *); |
| |
| diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h |
| new file mode 100644 |
| --- /dev/null |
| +++ b/include/trace/hooks/mm.h |
| @@ -0,0 +1,28 @@ |
| +/* SPDX-License-Identifier: GPL-2.0 */ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM mm |
| + |
| +#define TRACE_INCLUDE_PATH trace/hooks |
| + |
| +#if !defined(_TRACE_HOOK_MM_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_HOOK_MM_H |
| + |
| +#include <linux/types.h> |
| + |
| +#include <linux/tracepoint.h> |
| +#include <trace/hooks/vendor_hooks.h> |
| + |
| +DECLARE_RESTRICTED_HOOK(android_rvh_set_skip_swapcache_flags, |
| + TP_PROTO(gfp_t *flags), |
| + TP_ARGS(flags), 1); |
| +DECLARE_RESTRICTED_HOOK(android_rvh_set_gfp_zone_flags, |
| + TP_PROTO(gfp_t *flags), |
| + TP_ARGS(flags), 1); |
| +DECLARE_RESTRICTED_HOOK(android_rvh_set_readahead_gfp_mask, |
| + TP_PROTO(gfp_t *flags), |
| + TP_ARGS(flags), 1); |
| + |
| +#endif /* _TRACE_HOOK_MM_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include <trace/define_trace.h> |
| diff --git a/include/trace/hooks/syscall_check.h b/include/trace/hooks/syscall_check.h |
| new file mode 100644 |
| --- /dev/null |
| +++ b/include/trace/hooks/syscall_check.h |
| @@ -0,0 +1,22 @@ |
| +/* SPDX-License-Identifier: GPL-2.0 */ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM syscall_check |
| + |
| +#define TRACE_INCLUDE_PATH trace/hooks |
| +#if !defined(_TRACE_HOOK_SYSCALL_CHECK_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_HOOK_SYSCALL_CHECK_H |
| +#include <linux/tracepoint.h> |
| +#include <trace/hooks/vendor_hooks.h> |
| +/* |
| + * Following tracepoints are not exported in tracefs and provide a |
| + * mechanism for vendor modules to hook and extend functionality |
| + */ |
| +struct file; |
| +DECLARE_HOOK(android_vh_check_mmap_file, |
| + TP_PROTO(const struct file *file, unsigned long prot, |
| + unsigned long flag, unsigned long ret), |
| + TP_ARGS(file, prot, flag, ret)); |
| + |
| +#endif /* _TRACE_HOOK_SYSCALL_CHECK_H */ |
| +/* This part must be outside protection */ |
| +#include <trace/define_trace.h> |
| diff --git a/include/trace/hooks/vmscan.h b/include/trace/hooks/vmscan.h |
| new file mode 100644 |
| --- /dev/null |
| +++ b/include/trace/hooks/vmscan.h |
| @@ -0,0 +1,18 @@ |
| +/* SPDX-License-Identifier: GPL-2.0 */ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM vmscan |
| + |
| +#define TRACE_INCLUDE_PATH trace/hooks |
| + |
| +#if !defined(_TRACE_HOOK_VMSCAN_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_HOOK_VMSCAN_H |
| + |
| +#include <linux/tracepoint.h> |
| +#include <trace/hooks/vendor_hooks.h> |
| + |
| +DECLARE_RESTRICTED_HOOK(android_rvh_set_balance_anon_file_reclaim, |
| + TP_PROTO(bool *balance_anon_file_reclaim), |
| + TP_ARGS(balance_anon_file_reclaim), 1); |
| +#endif /* _TRACE_HOOK_VMSCAN_H */ |
| +/* This part must be outside protection */ |
| +#include <trace/define_trace.h> |
| diff --git a/mm/memory.c b/mm/memory.c |
| --- a/mm/memory.c |
| +++ b/mm/memory.c |
| @@ -73,6 +73,7 @@ |
| #include <linux/perf_event.h> |
| #include <linux/ptrace.h> |
| #include <linux/vmalloc.h> |
| +#include <trace/hooks/mm.h> |
| |
| #include <trace/events/kmem.h> |
| |
| @@ -3515,8 +3516,10 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) |
| if (data_race(si->flags & SWP_SYNCHRONOUS_IO) && |
| __swap_count(entry) == 1) { |
| /* skip swapcache */ |
| - page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, |
| - vmf->address); |
| + gfp_t flags = GFP_HIGHUSER_MOVABLE; |
| + |
| + trace_android_rvh_set_skip_swapcache_flags(&flags); |
| + page = alloc_page_vma(flags, vma, vmf->address); |
| if (page) { |
| __SetPageLocked(page); |
| __SetPageSwapBacked(page); |
| diff --git a/mm/mmzone.c b/mm/mmzone.c |
| --- a/mm/mmzone.c |
| +++ b/mm/mmzone.c |
| @@ -9,6 +9,7 @@ |
| #include <linux/stddef.h> |
| #include <linux/mm.h> |
| #include <linux/mmzone.h> |
| +#include <trace/hooks/mm.h> |
| |
| struct pglist_data *first_online_pgdat(void) |
| { |
| @@ -100,3 +101,19 @@ int page_cpupid_xchg_last(struct page *page, int cpupid) |
| return last_cpupid; |
| } |
| #endif |
| + |
| +enum zone_type gfp_zone(gfp_t flags) |
| +{ |
| + enum zone_type z; |
| + gfp_t local_flags = flags; |
| + int bit; |
| + |
| + trace_android_rvh_set_gfp_zone_flags(&local_flags); |
| + |
| + bit = (__force int) ((local_flags) & GFP_ZONEMASK); |
| + |
| + z = (GFP_ZONE_TABLE >> (bit * GFP_ZONES_SHIFT)) & |
| + ((1 << GFP_ZONES_SHIFT) - 1); |
| + VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1); |
| + return z; |
| +} |
| diff --git a/mm/readahead.c b/mm/readahead.c |
| --- a/mm/readahead.c |
| +++ b/mm/readahead.c |
| @@ -22,6 +22,7 @@ |
| #include <linux/blk-cgroup.h> |
| #include <linux/fadvise.h> |
| #include <linux/sched/mm.h> |
| +#include <trace/hooks/mm.h> |
| |
| #include "internal.h" |
| |
| @@ -113,6 +114,15 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages, |
| |
| EXPORT_SYMBOL(read_cache_pages); |
| |
| +gfp_t readahead_gfp_mask(struct address_space *x) |
| +{ |
| + gfp_t mask = mapping_gfp_mask(x) | __GFP_NORETRY | __GFP_NOWARN; |
| + |
| + trace_android_rvh_set_readahead_gfp_mask(&mask); |
| + return mask; |
| +} |
| +EXPORT_SYMBOL_GPL(readahead_gfp_mask); |
| + |
| static void read_pages(struct readahead_control *rac, struct list_head *pages, |
| bool skip_page) |
| { |
| diff --git a/mm/util.c b/mm/util.c |
| --- a/mm/util.c |
| +++ b/mm/util.c |
| @@ -27,6 +27,9 @@ |
| #include <linux/uaccess.h> |
| |
| #include "internal.h" |
| +#ifndef __GENSYMS__ |
| +#include <trace/hooks/syscall_check.h> |
| +#endif |
| |
| /** |
| * kfree_const - conditionally free memory |
| @@ -523,6 +526,7 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, |
| if (populate) |
| mm_populate(ret, populate); |
| } |
| + trace_android_vh_check_mmap_file(file, prot, flag, ret); |
| return ret; |
| } |
| |
| diff --git a/mm/vmscan.c b/mm/vmscan.c |
| --- a/mm/vmscan.c |
| +++ b/mm/vmscan.c |
| @@ -62,6 +62,9 @@ |
| #define CREATE_TRACE_POINTS |
| #include <trace/events/vmscan.h> |
| |
| +#undef CREATE_TRACE_POINTS |
| +#include <trace/hooks/vmscan.h> |
| + |
| struct scan_control { |
| /* How many pages shrink_list() should reclaim */ |
| unsigned long nr_to_reclaim; |
| @@ -2696,6 +2699,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, |
| enum scan_balance scan_balance; |
| unsigned long ap, fp; |
| enum lru_list lru; |
| + bool balance_anon_file_reclaim = false; |
| |
| /* If we have no swap space, do not bother scanning anon pages. */ |
| if (!sc->may_swap || !can_reclaim_anon_pages(memcg, pgdat->node_id, sc)) { |
| @@ -2733,11 +2737,15 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, |
| goto out; |
| } |
| |
| + trace_android_rvh_set_balance_anon_file_reclaim(&balance_anon_file_reclaim); |
| + |
| /* |
| * If there is enough inactive page cache, we do not reclaim |
| - * anything from the anonymous working right now. |
| + * anything from the anonymous working right now. But when balancing |
| + * anon and page cache files for reclaim, allow swapping of anon pages |
| + * even if there are a number of inactive file cache pages. |
| */ |
| - if (sc->cache_trim_mode) { |
| + if (!balance_anon_file_reclaim && sc->cache_trim_mode) { |
| scan_balance = SCAN_FILE; |
| goto out; |
| } |