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:
committed by
Suren Baghdasaryan
parent
bf19ba7dd0
commit
efbe140e82
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
83
mm/rmap.c
83
mm/rmap.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user