From: Feng Tang <feng.tang(a)intel.com>
ANBZ: #80
cherry-picked from
https://git.kernel.org/pub/scm/linux/kernel/git/vishal/tiering.git/commit/?…
page migration is a key function in mm core, used by memory compaction,
cma, large order page allocation and PMEM promotion/demotion. And it
could fail due to many reasons, like no enough memory in target node,
page refcount being abnormal etc.
Adding counters into /proc/vmstat will give the detailed info
about why and where it fails, which will help debugging and analyzing.
Reviewed-by: Dave Hansen <dave.hansen(a)intel.com>
Signed-off-by: Feng Tang <feng.tang(a)intel.com>
Signed-off-by: Baolin Wang <baolin.wang(a)linux.alibaba.com>
---
include/linux/vm_event_item.h | 4 ++++
mm/migrate.c | 22 +++++++++++++++++++---
mm/vmstat.c | 4 ++++
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index d5419b3..ab9c658 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -59,6 +59,10 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
#endif
#ifdef CONFIG_MIGRATION
PGMIGRATE_SUCCESS, PGMIGRATE_FAIL,
+ PGMIGRATE_DST_NODE_FULL_FAIL,
+ PGMIGRATE_NUMA_ISOLATE_FAIL,
+ PGMIGRATE_NOMEM_FAIL,
+ PGMIGRATE_REFCOUNT_FAIL,
#endif
#ifdef CONFIG_COMPACTION
COMPACTMIGRATE_SCANNED, COMPACTFREE_SCANNED,
diff --git a/mm/migrate.c b/mm/migrate.c
index e9c022e..7e6dcef 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -457,6 +457,9 @@ int migrate_page_move_mapping(struct address_space *mapping,
expected_count += is_device_private_page(page);
expected_count += is_device_public_page(page);
+ if (page_count(page) != expected_count)
+ count_vm_events(PGMIGRATE_REFCOUNT_FAIL, hpage_nr_pages(page));
+
if (!mapping) {
/* Anonymous page without mapping */
if (page_count(page) != expected_count)
@@ -1508,6 +1511,9 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
}
}
nr_failed++;
+
+ count_vm_events(PGMIGRATE_NOMEM_FAIL,
+ hpage_nr_pages(page));
goto out;
case -EAGAIN:
retry++;
@@ -1995,6 +2001,9 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page
*page)
if (!migrate_balanced_pgdat(pgdat, order)) {
int z;
+ count_vm_events(PGMIGRATE_DST_NODE_FULL_FAIL,
+ hpage_nr_pages(page));
+
if (!(sysctl_numa_balancing_mode & NUMA_BALANCING_MEMORY_TIERING) ||
!numa_demotion_enabled)
return 0;
@@ -2065,8 +2074,11 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct
*vma,
goto out;
isolated = numamigrate_isolate_page(pgdat, page);
- if (!isolated)
+ if (!isolated) {
+ count_vm_events(PGMIGRATE_NUMA_ISOLATE_FAIL,
+ hpage_nr_pages(page));
goto out;
+ }
list_add(&page->lru, &migratepages);
nr_remaining = migrate_pages(&migratepages, alloc_misplaced_dst_page,
@@ -2117,14 +2129,18 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
isolated = numamigrate_isolate_page(pgdat, page);
- if (!isolated)
+ if (!isolated) {
+ count_vm_events(PGMIGRATE_NUMA_ISOLATE_FAIL, HPAGE_PMD_NR);
goto out_fail;
+ }
new_page = alloc_pages_node(node,
(GFP_TRANSHUGE_LIGHT | __GFP_THISNODE),
HPAGE_PMD_ORDER);
- if (!new_page)
+ if (!new_page) {
+ count_vm_events(PGMIGRATE_NOMEM_FAIL, HPAGE_PMD_NR);
goto out_fail;
+ }
prep_transhuge_page(new_page);
/* Prepare a page as a migration target */
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 3ca0d88..5651e09 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1257,6 +1257,10 @@ int fragmentation_index(struct zone *zone, unsigned int order)
#ifdef CONFIG_MIGRATION
"pgmigrate_success",
"pgmigrate_fail",
+ "pgmigrate_fail_dst_node_fail",
+ "pgmigrate_fail_numa_isolate_fail",
+ "pgmigrate_fail_nomem_fail",
+ "pgmigrate_fail_refcount_fail",
#endif
#ifdef CONFIG_COMPACTION
"compact_migrate_scanned",
--
1.8.3.1