ANDROID: vendor_hooks: account page-mapcount

Support five hooks as follows to account
the amount of multi-mapped pages in kernel:

- android_vh_show_mapcount_pages
- android_vh_do_traversal_lruvec
- android_vh_update_page_mapcount
- android_vh_add_page_to_lrulist
- android_vh_del_page_from_lrulist

Bug: 236578020
Signed-off-by: Peifeng Li <lipeifeng@oppo.com>
Change-Id: Ia2c7015aab442be7dbb496b8b630b9dff59ab935
This commit is contained in:
Peifeng Li
2022-06-23 14:15:35 +08:00
committed by Suren Baghdasaryan
parent bf19ba7dd0
commit efbe140e82
8 changed files with 128 additions and 23 deletions

View File

@@ -424,3 +424,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_thermal_stats);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_proc_transaction);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_new_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_del_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_show_mapcount_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_traversal_lruvec);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_update_page_mapcount);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_add_page_to_lrulist);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_del_page_from_lrulist);

View File

@@ -5,6 +5,10 @@
#include <linux/huge_mm.h>
#include <linux/swap.h>
#include <linux/string.h>
#ifndef __GENKSYMS__
#define PROTECT_TRACE_INCLUDE_PATH
#include <trace/hooks/mm.h>
#endif
/**
* page_is_file_lru - should the page be on a file LRU or anon LRU?
@@ -293,6 +297,7 @@ static __always_inline void add_page_to_lru_list(struct page *page,
if (lru_gen_add_page(lruvec, page, false))
return;
trace_android_vh_add_page_to_lrulist(page, false, lru);
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
list_add(&page->lru, &lruvec->lists[lru]);
}
@@ -305,6 +310,7 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page,
if (lru_gen_add_page(lruvec, page, true))
return;
trace_android_vh_add_page_to_lrulist(page, false, page_lru(page));
update_lru_size(lruvec, lru, page_zonenum(page), thp_nr_pages(page));
list_add_tail(&page->lru, &lruvec->lists[lru]);
}
@@ -315,6 +321,7 @@ static __always_inline void del_page_from_lru_list(struct page *page,
if (lru_gen_del_page(lruvec, page, false))
return;
trace_android_vh_del_page_from_lrulist(page, false, page_lru(page));
list_del(&page->lru);
update_lru_size(lruvec, page_lru(page), page_zonenum(page),
-thp_nr_pages(page));

View File

@@ -11,6 +11,10 @@
#include <linux/rwsem.h>
#include <linux/memcontrol.h>
#include <linux/highmem.h>
#ifndef __GENKSYMS__
#define PROTECT_TRACE_INCLUDE_PATH
#include <trace/hooks/mm.h>
#endif
/*
* The anon_vma heads a list of private "related" vmas, to scan if
@@ -182,7 +186,12 @@ void hugepage_add_new_anon_rmap(struct page *, struct vm_area_struct *,
static inline void page_dup_rmap(struct page *page, bool compound)
{
atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount);
bool success = false;
if (!compound)
trace_android_vh_update_page_mapcount(page, true, compound, NULL, &success);
if (!success)
atomic_inc(compound ? compound_mapcount_ptr(page) : &page->_mapcount);
}
/*

View File

@@ -91,6 +91,22 @@ 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_update_page_mapcount,
TP_PROTO(struct page *page, bool inc_size, bool compound,
bool *first_mapping, bool *success),
TP_ARGS(page, inc_size, compound, first_mapping, success));
DECLARE_HOOK(android_vh_add_page_to_lrulist,
TP_PROTO(struct page *page, bool compound, enum lru_list lru),
TP_ARGS(page, compound, lru));
DECLARE_HOOK(android_vh_del_page_from_lrulist,
TP_PROTO(struct page *page, bool compound, enum lru_list lru),
TP_ARGS(page, compound, lru));
DECLARE_HOOK(android_vh_show_mapcount_pages,
TP_PROTO(void *unused),
TP_ARGS(unused));
DECLARE_HOOK(android_vh_do_traversal_lruvec,
TP_PROTO(struct lruvec *lruvec),
TP_ARGS(lruvec));
#endif /* _TRACE_HOOK_MM_H */

View File

@@ -34,7 +34,7 @@
#include <linux/oom.h>
#include <linux/numa.h>
#include <linux/page_owner.h>
#include <trace/hooks/mm.h>
#include <asm/tlb.h>
#include <asm/pgalloc.h>
#include "internal.h"
@@ -1965,6 +1965,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
bool young, write, soft_dirty, pmd_migration = false, uffd_wp = false;
unsigned long addr;
int i;
bool success = false;
VM_BUG_ON(haddr & ~HPAGE_PMD_MASK);
VM_BUG_ON_VMA(vma->vm_start > haddr, vma);
@@ -2101,8 +2102,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
pte = pte_offset_map(&_pmd, addr);
BUG_ON(!pte_none(*pte));
set_pte_at(mm, addr, pte, entry);
if (!pmd_migration)
atomic_inc(&page[i]._mapcount);
if (!pmd_migration) {
trace_android_vh_update_page_mapcount(&page[i], true,
false, NULL, &success);
if (!success)
atomic_inc(&page[i]._mapcount);
}
pte_unmap(pte);
}
@@ -2113,8 +2118,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
*/
if (compound_mapcount(page) > 1 &&
!TestSetPageDoubleMap(page)) {
for (i = 0; i < HPAGE_PMD_NR; i++)
atomic_inc(&page[i]._mapcount);
for (i = 0; i < HPAGE_PMD_NR; i++) {
trace_android_vh_update_page_mapcount(&page[i], true,
false, NULL, &success);
if (!success)
atomic_inc(&page[i]._mapcount);
}
}
lock_page_memcg(page);
@@ -2124,8 +2133,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
-HPAGE_PMD_NR);
if (TestClearPageDoubleMap(page)) {
/* No need in mapcount reference anymore */
for (i = 0; i < HPAGE_PMD_NR; i++)
atomic_dec(&page[i]._mapcount);
for (i = 0; i < HPAGE_PMD_NR; i++) {
trace_android_vh_update_page_mapcount(&page[i],
false, false, NULL, &success);
if (!success)
atomic_dec(&page[i]._mapcount);
}
}
}
unlock_page_memcg(page);

View File

@@ -6045,6 +6045,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
free_pcp,
global_zone_page_state(NR_FREE_CMA_PAGES));
trace_android_vh_show_mapcount_pages(NULL);
for_each_online_pgdat(pgdat) {
if (show_mem_node_skip(filter, pgdat->node_id, nodemask))
continue;

View File

@@ -1132,6 +1132,7 @@ void do_page_add_anon_rmap(struct page *page,
{
bool compound = flags & RMAP_COMPOUND;
bool first;
bool success = false;
if (unlikely(PageKsm(page)))
lock_page_memcg(page);
@@ -1145,7 +1146,10 @@ void do_page_add_anon_rmap(struct page *page,
mapcount = compound_mapcount_ptr(page);
first = atomic_inc_and_test(mapcount);
} else {
first = atomic_inc_and_test(&page->_mapcount);
trace_android_vh_update_page_mapcount(page, true, compound,
&first, &success);
if (!success)
first = atomic_inc_and_test(&page->_mapcount);
}
if (first) {
@@ -1220,6 +1224,8 @@ void page_add_new_anon_rmap(struct page *page,
void page_add_file_rmap(struct page *page, bool compound)
{
int i, nr = 1;
bool first_mapping;
bool success = false;
VM_BUG_ON_PAGE(compound && !PageTransHuge(page), page);
lock_page_memcg(page);
@@ -1227,8 +1233,15 @@ void page_add_file_rmap(struct page *page, bool compound)
int nr_pages = thp_nr_pages(page);
for (i = 0, nr = 0; i < nr_pages; i++) {
if (atomic_inc_and_test(&page[i]._mapcount))
nr++;
trace_android_vh_update_page_mapcount(&page[i], true,
compound, &first_mapping, &success);
if ((success)) {
if (first_mapping)
nr++;
} else {
if (atomic_inc_and_test(&page[i]._mapcount))
nr++;
}
}
if (!atomic_inc_and_test(compound_mapcount_ptr(page)))
goto out;
@@ -1248,8 +1261,15 @@ void page_add_file_rmap(struct page *page, bool compound)
if (PageMlocked(page))
clear_page_mlock(head);
}
if (!atomic_inc_and_test(&page->_mapcount))
goto out;
trace_android_vh_update_page_mapcount(page, true,
compound, &first_mapping, &success);
if (success) {
if (!first_mapping)
goto out;
} else {
if (!atomic_inc_and_test(&page->_mapcount))
goto out;
}
}
__mod_lruvec_page_state(page, NR_FILE_MAPPED, nr);
out:
@@ -1259,6 +1279,8 @@ out:
static void page_remove_file_rmap(struct page *page, bool compound)
{
int i, nr = 1;
bool first_mapping;
bool success = false;
VM_BUG_ON_PAGE(compound && !PageHead(page), page);
@@ -1274,8 +1296,15 @@ static void page_remove_file_rmap(struct page *page, bool compound)
int nr_pages = thp_nr_pages(page);
for (i = 0, nr = 0; i < nr_pages; i++) {
if (atomic_add_negative(-1, &page[i]._mapcount))
nr++;
trace_android_vh_update_page_mapcount(&page[i], false,
compound, &first_mapping, &success);
if (success) {
if (first_mapping)
nr++;
} else {
if (atomic_add_negative(-1, &page[i]._mapcount))
nr++;
}
}
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
return;
@@ -1286,8 +1315,15 @@ static void page_remove_file_rmap(struct page *page, bool compound)
__mod_lruvec_page_state(page, NR_FILE_PMDMAPPED,
-nr_pages);
} else {
if (!atomic_add_negative(-1, &page->_mapcount))
return;
trace_android_vh_update_page_mapcount(page, false,
compound, &first_mapping, &success);
if (success) {
if (!first_mapping)
return;
} else {
if (!atomic_add_negative(-1, &page->_mapcount))
return;
}
}
/*
@@ -1304,6 +1340,8 @@ static void page_remove_file_rmap(struct page *page, bool compound)
static void page_remove_anon_compound_rmap(struct page *page)
{
int i, nr;
bool first_mapping;
bool success = false;
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
return;
@@ -1323,8 +1361,15 @@ static void page_remove_anon_compound_rmap(struct page *page)
* them are still mapped.
*/
for (i = 0, nr = 0; i < thp_nr_pages(page); i++) {
if (atomic_add_negative(-1, &page[i]._mapcount))
nr++;
trace_android_vh_update_page_mapcount(&page[i], false,
false, &first_mapping, &success);
if (success) {
if (first_mapping)
nr++;
} else {
if (atomic_add_negative(-1, &page[i]._mapcount))
nr++;
}
}
/*
@@ -1354,6 +1399,8 @@ static void page_remove_anon_compound_rmap(struct page *page)
*/
void page_remove_rmap(struct page *page, bool compound)
{
bool first_mapping;
bool success = false;
lock_page_memcg(page);
if (!PageAnon(page)) {
@@ -1366,10 +1413,16 @@ void page_remove_rmap(struct page *page, bool compound)
goto out;
}
/* page still mapped by someone else? */
if (!atomic_add_negative(-1, &page->_mapcount))
goto out;
trace_android_vh_update_page_mapcount(page, false,
compound, &first_mapping, &success);
if (success) {
if (!first_mapping)
goto out;
} else {
/* page still mapped by someone else? */
if (!atomic_add_negative(-1, &page->_mapcount))
goto out;
}
/*
* We use the irq-unsafe __{inc|mod}_zone_page_stat because
* these counters are not modified in interrupt context, and

View File

@@ -2063,6 +2063,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
nr_taken += nr_pages;
nr_zone_taken[page_zonenum(page)] += nr_pages;
list_move(&page->lru, dst);
trace_android_vh_del_page_from_lrulist(page, false, lru);
}
/*