Skip to content

Commit a259945

Browse files
x-y-zakpm00
authored andcommitted
mm/migrate: correct nr_failed in migrate_pages_sync()
nr_failed was missing the large folio splits from migrate_pages_batch() and can cause a mismatch between migrate_pages() return value and the number of not migrated pages, i.e., when the return value of migrate_pages() is 0, there are still pages left in the from page list. It will happen when a non-PMD THP large folio fails to migrate due to -ENOMEM and is split successfully but not all the split pages are not migrated, migrate_pages_batch() would return non-zero, but astats.nr_thp_split = 0. nr_failed would be 0 and returned to the caller of migrate_pages(), but the not migrated pages are left in the from page list without being added back to LRU lists. Fix it by adding a new nr_split counter for large folio splits and adding it to nr_failed in migrate_page_sync() after migrate_pages_batch() is done. Link: https://lkml.kernel.org/r/20231017163129.2025214-1-zi.yan@sent.com Fixes: 2ef7dbb ("migrate_pages: try migrate in batch asynchronously firstly") Signed-off-by: Zi Yan <ziy@nvidia.com> Acked-by: Huang Ying <ying.huang@intel.com> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: David Hildenbrand <david@redhat.com> Cc: Matthew Wilcox <willy@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 245245c commit a259945

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

mm/migrate.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,7 @@ struct migrate_pages_stats {
14951495
int nr_thp_succeeded; /* THP migrated successfully */
14961496
int nr_thp_failed; /* THP failed to be migrated */
14971497
int nr_thp_split; /* THP split before migrating */
1498+
int nr_split; /* Large folio (include THP) split before migrating */
14981499
};
14991500

15001501
/*
@@ -1614,6 +1615,7 @@ static int migrate_pages_batch(struct list_head *from,
16141615
int nr_retry_pages = 0;
16151616
int pass = 0;
16161617
bool is_thp = false;
1618+
bool is_large = false;
16171619
struct folio *folio, *folio2, *dst = NULL, *dst2;
16181620
int rc, rc_saved = 0, nr_pages;
16191621
LIST_HEAD(unmap_folios);
@@ -1629,7 +1631,8 @@ static int migrate_pages_batch(struct list_head *from,
16291631
nr_retry_pages = 0;
16301632

16311633
list_for_each_entry_safe(folio, folio2, from, lru) {
1632-
is_thp = folio_test_large(folio) && folio_test_pmd_mappable(folio);
1634+
is_large = folio_test_large(folio);
1635+
is_thp = is_large && folio_test_pmd_mappable(folio);
16331636
nr_pages = folio_nr_pages(folio);
16341637

16351638
cond_resched();
@@ -1649,6 +1652,7 @@ static int migrate_pages_batch(struct list_head *from,
16491652
stats->nr_thp_failed++;
16501653
if (!try_split_folio(folio, split_folios)) {
16511654
stats->nr_thp_split++;
1655+
stats->nr_split++;
16521656
continue;
16531657
}
16541658
stats->nr_failed_pages += nr_pages;
@@ -1677,11 +1681,12 @@ static int migrate_pages_batch(struct list_head *from,
16771681
nr_failed++;
16781682
stats->nr_thp_failed += is_thp;
16791683
/* Large folio NUMA faulting doesn't split to retry. */
1680-
if (folio_test_large(folio) && !nosplit) {
1684+
if (is_large && !nosplit) {
16811685
int ret = try_split_folio(folio, split_folios);
16821686

16831687
if (!ret) {
16841688
stats->nr_thp_split += is_thp;
1689+
stats->nr_split += is_large;
16851690
break;
16861691
} else if (reason == MR_LONGTERM_PIN &&
16871692
ret == -EAGAIN) {
@@ -1827,14 +1832,19 @@ static int migrate_pages_sync(struct list_head *from, new_folio_t get_new_folio,
18271832
stats->nr_succeeded += astats.nr_succeeded;
18281833
stats->nr_thp_succeeded += astats.nr_thp_succeeded;
18291834
stats->nr_thp_split += astats.nr_thp_split;
1835+
stats->nr_split += astats.nr_split;
18301836
if (rc < 0) {
18311837
stats->nr_failed_pages += astats.nr_failed_pages;
18321838
stats->nr_thp_failed += astats.nr_thp_failed;
18331839
list_splice_tail(&folios, ret_folios);
18341840
return rc;
18351841
}
18361842
stats->nr_thp_failed += astats.nr_thp_split;
1837-
nr_failed += astats.nr_thp_split;
1843+
/*
1844+
* Do not count rc, as pages will be retried below.
1845+
* Count nr_split only, since it includes nr_thp_split.
1846+
*/
1847+
nr_failed += astats.nr_split;
18381848
/*
18391849
* Fall back to migrate all failed folios one by one synchronously. All
18401850
* failed folios except split THPs will be retried, so their failure

0 commit comments

Comments
 (0)