Skip to content

Commit 5b85593

Browse files
yhuang-intelakpm00
authored andcommitted
migrate_pages: organize stats with struct migrate_pages_stats
Patch series "migrate_pages(): batch TLB flushing", v5. Now, migrate_pages() migrates folios one by one, like the fake code as follows, for each folio unmap flush TLB copy restore map If multiple folios are passed to migrate_pages(), there are opportunities to batch the TLB flushing and copying. That is, we can change the code to something as follows, for each folio unmap for each folio flush TLB for each folio copy for each folio restore map The total number of TLB flushing IPI can be reduced considerably. And we may use some hardware accelerator such as DSA to accelerate the folio copying. So in this patch, we refactor the migrate_pages() implementation and implement the TLB flushing batching. Base on this, hardware accelerated folio copying can be implemented. If too many folios are passed to migrate_pages(), in the naive batched implementation, we may unmap too many folios at the same time. The possibility for a task to wait for the migrated folios to be mapped again increases. So the latency may be hurt. To deal with this issue, the max number of folios be unmapped in batch is restricted to no more than HPAGE_PMD_NR in the unit of page. That is, the influence is at the same level of THP migration. We use the following test to measure the performance impact of the patchset, On a 2-socket Intel server, - Run pmbench memory accessing benchmark - Run `migratepages` to migrate pages of pmbench between node 0 and node 1 back and forth. With the patch, the TLB flushing IPI reduces 99.1% during the test and the number of pages migrated successfully per second increases 291.7%. Xin Hao helped to test the patchset on an ARM64 server with 128 cores, 2 NUMA nodes. Test results show that the page migration performance increases up to 78%. This patch (of 9): Define struct migrate_pages_stats to organize the various statistics in migrate_pages(). This makes it easier to collect and consume the statistics in multiple functions. This will be needed in the following patches in the series. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: "Huang, Ying" <[email protected]> Reviewed-by: Alistair Popple <[email protected]> Reviewed-by: Zi Yan <[email protected]> Reviewed-by: Baolin Wang <[email protected]> Reviewed-by: Xin Hao <[email protected]> Cc: Yang Shi <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Bharata B Rao <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Hyeonggon Yoo <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 0621d16 commit 5b85593

File tree

1 file changed

+34
-26
lines changed

1 file changed

+34
-26
lines changed

mm/migrate.c

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,16 @@ static inline int try_split_folio(struct folio *folio, struct list_head *split_f
14141414
return rc;
14151415
}
14161416

1417+
struct migrate_pages_stats {
1418+
int nr_succeeded; /* Normal and large folios migrated successfully, in
1419+
units of base pages */
1420+
int nr_failed_pages; /* Normal and large folios failed to be migrated, in
1421+
units of base pages. Untried folios aren't counted */
1422+
int nr_thp_succeeded; /* THP migrated successfully */
1423+
int nr_thp_failed; /* THP failed to be migrated */
1424+
int nr_thp_split; /* THP split before migrating */
1425+
};
1426+
14171427
/*
14181428
* migrate_pages - migrate the folios specified in a list, to the free folios
14191429
* supplied as the target for the page migration
@@ -1448,13 +1458,8 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
14481458
int large_retry = 1;
14491459
int thp_retry = 1;
14501460
int nr_failed = 0;
1451-
int nr_failed_pages = 0;
14521461
int nr_retry_pages = 0;
1453-
int nr_succeeded = 0;
1454-
int nr_thp_succeeded = 0;
14551462
int nr_large_failed = 0;
1456-
int nr_thp_failed = 0;
1457-
int nr_thp_split = 0;
14581463
int pass = 0;
14591464
bool is_large = false;
14601465
bool is_thp = false;
@@ -1464,9 +1469,11 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
14641469
LIST_HEAD(split_folios);
14651470
bool nosplit = (reason == MR_NUMA_MISPLACED);
14661471
bool no_split_folio_counting = false;
1472+
struct migrate_pages_stats stats;
14671473

14681474
trace_mm_migrate_pages_start(mode, reason);
14691475

1476+
memset(&stats, 0, sizeof(stats));
14701477
split_folio_migration:
14711478
for (pass = 0; pass < 10 && (retry || large_retry); pass++) {
14721479
retry = 0;
@@ -1520,17 +1527,17 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15201527
/* Large folio migration is unsupported */
15211528
if (is_large) {
15221529
nr_large_failed++;
1523-
nr_thp_failed += is_thp;
1530+
stats.nr_thp_failed += is_thp;
15241531
if (!try_split_folio(folio, &split_folios)) {
1525-
nr_thp_split += is_thp;
1532+
stats.nr_thp_split += is_thp;
15261533
break;
15271534
}
15281535
/* Hugetlb migration is unsupported */
15291536
} else if (!no_split_folio_counting) {
15301537
nr_failed++;
15311538
}
15321539

1533-
nr_failed_pages += nr_pages;
1540+
stats.nr_failed_pages += nr_pages;
15341541
list_move_tail(&folio->lru, &ret_folios);
15351542
break;
15361543
case -ENOMEM:
@@ -1540,13 +1547,13 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15401547
*/
15411548
if (is_large) {
15421549
nr_large_failed++;
1543-
nr_thp_failed += is_thp;
1550+
stats.nr_thp_failed += is_thp;
15441551
/* Large folio NUMA faulting doesn't split to retry. */
15451552
if (!nosplit) {
15461553
int ret = try_split_folio(folio, &split_folios);
15471554

15481555
if (!ret) {
1549-
nr_thp_split += is_thp;
1556+
stats.nr_thp_split += is_thp;
15501557
break;
15511558
} else if (reason == MR_LONGTERM_PIN &&
15521559
ret == -EAGAIN) {
@@ -1564,7 +1571,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15641571
nr_failed++;
15651572
}
15661573

1567-
nr_failed_pages += nr_pages + nr_retry_pages;
1574+
stats.nr_failed_pages += nr_pages + nr_retry_pages;
15681575
/*
15691576
* There might be some split folios of fail-to-migrate large
15701577
* folios left in split_folios list. Move them back to migration
@@ -1574,7 +1581,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15741581
list_splice_init(&split_folios, from);
15751582
/* nr_failed isn't updated for not used */
15761583
nr_large_failed += large_retry;
1577-
nr_thp_failed += thp_retry;
1584+
stats.nr_thp_failed += thp_retry;
15781585
goto out;
15791586
case -EAGAIN:
15801587
if (is_large) {
@@ -1586,8 +1593,8 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15861593
nr_retry_pages += nr_pages;
15871594
break;
15881595
case MIGRATEPAGE_SUCCESS:
1589-
nr_succeeded += nr_pages;
1590-
nr_thp_succeeded += is_thp;
1596+
stats.nr_succeeded += nr_pages;
1597+
stats.nr_thp_succeeded += is_thp;
15911598
break;
15921599
default:
15931600
/*
@@ -1598,20 +1605,20 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
15981605
*/
15991606
if (is_large) {
16001607
nr_large_failed++;
1601-
nr_thp_failed += is_thp;
1608+
stats.nr_thp_failed += is_thp;
16021609
} else if (!no_split_folio_counting) {
16031610
nr_failed++;
16041611
}
16051612

1606-
nr_failed_pages += nr_pages;
1613+
stats.nr_failed_pages += nr_pages;
16071614
break;
16081615
}
16091616
}
16101617
}
16111618
nr_failed += retry;
16121619
nr_large_failed += large_retry;
1613-
nr_thp_failed += thp_retry;
1614-
nr_failed_pages += nr_retry_pages;
1620+
stats.nr_thp_failed += thp_retry;
1621+
stats.nr_failed_pages += nr_retry_pages;
16151622
/*
16161623
* Try to migrate split folios of fail-to-migrate large folios, no
16171624
* nr_failed counting in this round, since all split folios of a
@@ -1644,16 +1651,17 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
16441651
if (list_empty(from))
16451652
rc = 0;
16461653

1647-
count_vm_events(PGMIGRATE_SUCCESS, nr_succeeded);
1648-
count_vm_events(PGMIGRATE_FAIL, nr_failed_pages);
1649-
count_vm_events(THP_MIGRATION_SUCCESS, nr_thp_succeeded);
1650-
count_vm_events(THP_MIGRATION_FAIL, nr_thp_failed);
1651-
count_vm_events(THP_MIGRATION_SPLIT, nr_thp_split);
1652-
trace_mm_migrate_pages(nr_succeeded, nr_failed_pages, nr_thp_succeeded,
1653-
nr_thp_failed, nr_thp_split, mode, reason);
1654+
count_vm_events(PGMIGRATE_SUCCESS, stats.nr_succeeded);
1655+
count_vm_events(PGMIGRATE_FAIL, stats.nr_failed_pages);
1656+
count_vm_events(THP_MIGRATION_SUCCESS, stats.nr_thp_succeeded);
1657+
count_vm_events(THP_MIGRATION_FAIL, stats.nr_thp_failed);
1658+
count_vm_events(THP_MIGRATION_SPLIT, stats.nr_thp_split);
1659+
trace_mm_migrate_pages(stats.nr_succeeded, stats.nr_failed_pages,
1660+
stats.nr_thp_succeeded, stats.nr_thp_failed,
1661+
stats.nr_thp_split, mode, reason);
16541662

16551663
if (ret_succeeded)
1656-
*ret_succeeded = nr_succeeded;
1664+
*ret_succeeded = stats.nr_succeeded;
16571665

16581666
return rc;
16591667
}

0 commit comments

Comments
 (0)