ANDROID: vendor_hook: Add hook to not be stuck ro rmap lock in kswapd or direct_reclaim

Add hooks to support trylock in rmaplock when reclaiming in kswapd or
direct_reclaim, in order to avoid wait lock for a long time.

- android_vh_handle_failed_page_trylock
- android_vh_page_trylock_set
- android_vh_page_trylock_clear
- android_vh_page_trylock_get_result
- android_vh_do_page_trylock

Bug: 240003372

Signed-off-by: Peifeng Li <lipeifeng@oppo.com>
Change-Id: I0f605b35ae41f15b3ca7bc72cd5f003175c318a5
This commit is contained in:
Peifeng Li
2022-07-24 13:47:14 +08:00
parent 4f5025129f
commit 309a6bf81a
5 changed files with 53 additions and 7 deletions

View File

@@ -251,6 +251,11 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_freq_qos_update_request);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_freq_qos_remove_request);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_balance_anon_file_reclaim);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_show_max_freq);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_failed_page_trylock);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_set);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_clear);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_trylock_get_result);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_page_trylock);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_check_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_all_pages_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cma_drain_all_pages_bypass);

View File

@@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/oom.h>
#include <trace/hooks/vendor_hooks.h>
#include <linux/rwsem.h>
/* struct slabinfo */
#include <../mm/slab.h>
@@ -91,6 +92,10 @@ DECLARE_HOOK(android_vh_mem_cgroup_css_offline,
DECLARE_HOOK(android_vh_vmpressure,
TP_PROTO(struct mem_cgroup *memcg, bool *bypass),
TP_ARGS(memcg, bypass));
DECLARE_HOOK(android_vh_do_page_trylock,
TP_PROTO(struct page *page, struct rw_semaphore *sem,
bool *got_lock, bool *success),
TP_ARGS(page, sem, got_lock, success));
DECLARE_HOOK(android_vh_update_page_mapcount,
TP_PROTO(struct page *page, bool inc_size, bool compound,
bool *first_mapping, bool *success),

View File

@@ -18,7 +18,18 @@ DECLARE_HOOK(android_vh_kswapd_per_node,
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
TP_PROTO(struct page *page, unsigned long nr_to_scan, int lru, bool *bypass),
TP_ARGS(page, nr_to_scan, lru, bypass));
DECLARE_HOOK(android_vh_page_trylock_get_result,
TP_PROTO(struct page *page, bool *trylock_fail),
TP_ARGS(page, trylock_fail));
DECLARE_HOOK(android_vh_handle_failed_page_trylock,
TP_PROTO(struct list_head *page_list),
TP_ARGS(page_list));
DECLARE_HOOK(android_vh_page_trylock_set,
TP_PROTO(struct page *page),
TP_ARGS(page));
DECLARE_HOOK(android_vh_page_trylock_clear,
TP_PROTO(struct page *page),
TP_ARGS(page));
DECLARE_HOOK(android_vh_shrink_node_memcgs,
TP_PROTO(struct mem_cgroup *memcg, bool *skip),
TP_ARGS(memcg, skip));

View File

@@ -534,6 +534,7 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
struct anon_vma *anon_vma = NULL;
struct anon_vma *root_anon_vma;
unsigned long anon_mapping;
bool success = false;
rcu_read_lock();
anon_mapping = (unsigned long)READ_ONCE(page->mapping);
@@ -556,7 +557,11 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
}
goto out;
}
trace_android_vh_do_page_trylock(page, NULL, NULL, &success);
if (success) {
anon_vma = NULL;
goto out;
}
/* trylock failed, we got to sleep */
if (!atomic_inc_not_zero(&anon_vma->refcount)) {
anon_vma = NULL;
@@ -2409,6 +2414,7 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
struct address_space *mapping = page_mapping(page);
pgoff_t pgoff_start, pgoff_end;
struct vm_area_struct *vma;
bool got_lock = false, success = false;
/*
* The page lock not only makes sure that page->mapping cannot
@@ -2423,8 +2429,16 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
pgoff_start = page_to_pgoff(page);
pgoff_end = pgoff_start + thp_nr_pages(page) - 1;
if (!locked)
i_mmap_lock_read(mapping);
if (!locked) {
trace_android_vh_do_page_trylock(page,
&mapping->i_mmap_rwsem, &got_lock, &success);
if (success) {
if (!got_lock)
return;
} else {
i_mmap_lock_read(mapping);
}
}
vma_interval_tree_foreach(vma, &mapping->i_mmap,
pgoff_start, pgoff_end) {
unsigned long address = vma_address(page, vma);

View File

@@ -1257,15 +1257,19 @@ static enum page_references page_check_references(struct page *page,
int referenced_ptes, referenced_page;
unsigned long vm_flags;
bool should_protect = false;
bool trylock_fail = false;
trace_android_vh_page_should_be_protected(page, &should_protect);
if (unlikely(should_protect))
return PAGEREF_ACTIVATE;
trace_android_vh_page_trylock_set(page);
referenced_ptes = page_referenced(page, 1, sc->target_mem_cgroup,
&vm_flags);
referenced_page = TestClearPageReferenced(page);
trace_android_vh_page_trylock_get_result(page, &trylock_fail);
if (trylock_fail)
return PAGEREF_KEEP;
/*
* Mlock lost the isolation race with us. Let try_to_unmap()
* move the page to the unevictable list.
@@ -1645,6 +1649,7 @@ retry:
if (unlikely(PageTransHuge(page)))
flags |= TTU_SPLIT_HUGE_PMD;
trace_android_vh_page_trylock_set(page);
try_to_unmap(page, flags);
if (page_mapped(page)) {
stat->nr_unmap_fail += nr_pages;
@@ -1757,6 +1762,7 @@ retry:
* increment nr_reclaimed here (and
* leave it off the LRU).
*/
trace_android_vh_page_trylock_clear(page);
nr_reclaimed++;
continue;
}
@@ -1795,8 +1801,10 @@ free_it:
*/
if (unlikely(PageTransHuge(page)))
destroy_compound_page(page);
else
else {
trace_android_vh_page_trylock_clear(page);
list_add(&page->lru, &free_pages);
}
continue;
activate_locked_split:
@@ -2314,6 +2322,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
return 0;
nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, &stat, false);
trace_android_vh_handle_failed_page_trylock(&page_list);
spin_lock_irq(&lruvec->lru_lock);
move_pages_to_lru(lruvec, &page_list);
@@ -2437,7 +2446,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
trace_android_vh_page_referenced_check_bypass(page, nr_to_scan, lru, &bypass);
if (bypass)
goto skip_page_referenced;
trace_android_vh_page_trylock_set(page);
if (page_referenced(page, 0, sc->target_mem_cgroup,
&vm_flags)) {
/*
@@ -2450,11 +2459,13 @@ static void shrink_active_list(unsigned long nr_to_scan,
* so we ignore them here.
*/
if ((vm_flags & VM_EXEC) && page_is_file_lru(page)) {
trace_android_vh_page_trylock_clear(page);
nr_rotated += thp_nr_pages(page);
list_add(&page->lru, &l_active);
continue;
}
}
trace_android_vh_page_trylock_clear(page);
skip_page_referenced:
ClearPageActive(page); /* we are de-activating */
SetPageWorkingset(page);