hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IASFAM
--------------------------------
During page migration, if MIGRATE_SYNC_NO_COPY mode is used, the page content should not be migrated.
This patch fix it.
Fixes: 374fe8ea8082 ("fs: hugetlbfs: support poisoned recover from hugetlbfs_migrate_folio()") Fixes: 1d263184ba06 ("mm: migrate: support poisoned recover from migrate folio") Signed-off-by: Tong Tiangen tongtiangen@huawei.com --- fs/hugetlbfs/inode.c | 10 ++++++++++ include/linux/migrate.h | 7 +++++-- mm/migrate.c | 20 ++++++++------------ 3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 8386d78eabe5..d4fcfc03fac9 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -1145,6 +1145,16 @@ static int hugetlbfs_migrate_folio(struct address_space *mapping, enum migrate_mode mode) { int rc; + int expected_count = folio_expected_refs(mapping, src); + + if (folio_ref_count(src) != expected_count) + return -EAGAIN; + + if (mode != MIGRATE_SYNC_NO_COPY) { + rc = folio_mc_copy(dst, src); + if (unlikely(rc)) + return rc; + }
rc = migrate_huge_page_move_mapping(mapping, dst, src); if (rc != MIGRATEPAGE_SUCCESS) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 517f70b70620..832d711d381d 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -79,7 +79,7 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio); void folio_migrate_copy(struct folio *newfolio, struct folio *folio); int folio_migrate_mapping(struct address_space *mapping, struct folio *newfolio, struct folio *folio, int extra_count); - +int folio_expected_refs(struct address_space *mapping, struct folio *folio); #else
static inline void putback_movable_pages(struct list_head *l) {} @@ -98,7 +98,10 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping, { return -ENOSYS; } - +static inline int folio_expected_refs(struct address_space *mapping, struct folio *folio) +{ + return 0; +} #endif /* CONFIG_MIGRATION */
#ifdef CONFIG_COMPACTION diff --git a/mm/migrate.c b/mm/migrate.c index efcca5330568..50cf85d65cf3 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -376,7 +376,7 @@ void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd) } #endif
-static int folio_expected_refs(struct address_space *mapping, +int folio_expected_refs(struct address_space *mapping, struct folio *folio) { int refs = 1; @@ -552,16 +552,10 @@ int migrate_huge_page_move_mapping(struct address_space *mapping, struct folio *dst, struct folio *src) { XA_STATE(xas, &mapping->i_pages, folio_index(src)); - int rc, expected_count = folio_expected_refs(mapping, src); - - if (folio_ref_count(src) != expected_count) - return -EAGAIN; - - rc = folio_mc_copy(dst, src); - if (unlikely(rc)) - return rc; + int expected_count;
xas_lock_irq(&xas); + expected_count = folio_expected_refs(mapping, src); if (!folio_ref_freeze(src, expected_count)) { xas_unlock_irq(&xas); return -EAGAIN; @@ -695,9 +689,11 @@ static int __migrate_folio(struct address_space *mapping, struct folio *dst, if (folio_ref_count(src) != expected_count) return -EAGAIN;
- rc = folio_mc_copy(dst, src); - if (unlikely(rc)) - return rc; + if (mode != MIGRATE_SYNC_NO_COPY) { + rc = folio_mc_copy(dst, src); + if (unlikely(rc)) + return rc; + }
rc = __folio_migrate_mapping(mapping, dst, src, expected_count); if (rc != MIGRATEPAGE_SUCCESS)