blob: acbf4bfc41252e2a11de94cd36b241886a84b88d [file] [log] [blame]
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;
}