@@ -138,6 +138,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
global_node_page_state(NR_FILE_THPS) * HPAGE_PMD_NR);
show_val_kb(m, "FilePmdMapped: ",
global_node_page_state(NR_FILE_PMDMAPPED) * HPAGE_PMD_NR);
+ show_val_kb(m, "PartFreePages: ",
+ global_node_page_state(NR_PARTIAL_THPS));
#endif
#ifdef CONFIG_CMA
@@ -194,6 +194,7 @@ enum node_stat_item {
NR_FILE_THPS,
NR_FILE_PMDMAPPED,
NR_ANON_THPS,
+ NR_PARTIAL_THPS, /* partial free pages of transhuge pages */
NR_VMSCAN_WRITE,
NR_VMSCAN_IMMEDIATE, /* Prioritise for reclaim when writeback ends */
NR_DIRTIED, /* page dirtyings since bootup */
@@ -2788,6 +2788,8 @@ void free_transhuge_page(struct page *page)
if (!list_empty(page_deferred_list(page))) {
ds_queue->split_queue_len--;
list_del(page_deferred_list(page));
+ __mod_node_page_state(page_pgdat(page), NR_PARTIAL_THPS,
+ -HPAGE_PMD_NR);
}
spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags);
free_compound_page(page);
@@ -2880,8 +2882,11 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
if (!trylock_page(page))
goto next;
/* split_huge_page() removes page from list on success */
- if (!split_huge_page(page))
+ if (!split_huge_page(page)) {
split++;
+ __mod_node_page_state(page_pgdat(page),
+ NR_PARTIAL_THPS, -HPAGE_PMD_NR);
+ }
unlock_page(page);
next:
put_page(page);
@@ -1309,8 +1309,11 @@ static void page_remove_anon_compound_rmap(struct page *page)
* page of the compound page is unmapped, but at least one
* small page is still mapped.
*/
- if (nr && nr < thp_nr_pages(page))
+ if (nr && nr < thp_nr_pages(page)) {
+ __mod_node_page_state(page_pgdat(page),
+ NR_PARTIAL_THPS, nr);
deferred_split_huge_page(page);
+ }
} else {
nr = thp_nr_pages(page);
}
@@ -1357,8 +1360,10 @@ void page_remove_rmap(struct page *page, bool compound)
if (unlikely(PageMlocked(page)))
clear_page_mlock(page);
- if (PageTransCompound(page))
+ if (PageTransCompound(page)) {
+ __inc_node_page_state(page, NR_PARTIAL_THPS);
deferred_split_huge_page(compound_head(page));
+ }
/*
* It would be tidy to reset the PageAnon mapping here,
@@ -1203,6 +1203,7 @@ const char * const vmstat_text[] = {
"nr_file_hugepages",
"nr_file_pmdmapped",
"nr_anon_transparent_hugepages",
+ "nr_partial_free_pages",
"nr_vmscan_write",
"nr_vmscan_immediate_reclaim",
"nr_dirtied",