Skip to content

Commit

Permalink
mm/migrate: Add folio_migrate_copy()
Browse files Browse the repository at this point in the history
Combine the THP, hugetlb and base page routines together into a simple
loop.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
  • Loading branch information
Matthew Wilcox (Oracle) authored and intel-lab-lkp committed Jul 12, 2021
1 parent 44a2ba0 commit 77c6876
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 56 deletions.
1 change: 1 addition & 0 deletions include/linux/migrate.h
Expand Up @@ -53,6 +53,7 @@ extern int migrate_page_move_mapping(struct address_space *mapping,
struct page *newpage, struct page *page, int extra_count);
extern void copy_huge_page(struct page *dst, struct page *src);
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);
#else
Expand Down
6 changes: 6 additions & 0 deletions mm/folio-compat.c
Expand Up @@ -64,4 +64,10 @@ void migrate_page_states(struct page *newpage, struct page *page)
folio_migrate_flags(page_folio(newpage), page_folio(page));
}
EXPORT_SYMBOL(migrate_page_states);

void migrate_page_copy(struct page *newpage, struct page *page)
{
folio_migrate_copy(page_folio(newpage), page_folio(page));
}
EXPORT_SYMBOL(migrate_page_copy);
#endif
67 changes: 11 additions & 56 deletions mm/migrate.c
Expand Up @@ -537,54 +537,6 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
return MIGRATEPAGE_SUCCESS;
}

/*
* Gigantic pages are so large that we do not guarantee that page++ pointer
* arithmetic will work across the entire page. We need something more
* specialized.
*/
static void __copy_gigantic_page(struct page *dst, struct page *src,
int nr_pages)
{
int i;
struct page *dst_base = dst;
struct page *src_base = src;

for (i = 0; i < nr_pages; ) {
cond_resched();
copy_highpage(dst, src);

i++;
dst = mem_map_next(dst, dst_base, i);
src = mem_map_next(src, src_base, i);
}
}

void copy_huge_page(struct page *dst, struct page *src)
{
int i;
int nr_pages;

if (PageHuge(src)) {
/* hugetlbfs page */
struct hstate *h = page_hstate(src);
nr_pages = pages_per_huge_page(h);

if (unlikely(nr_pages > MAX_ORDER_NR_PAGES)) {
__copy_gigantic_page(dst, src, nr_pages);
return;
}
} else {
/* thp page */
BUG_ON(!PageTransHuge(src));
nr_pages = thp_nr_pages(src);
}

for (i = 0; i < nr_pages; i++) {
cond_resched();
copy_highpage(dst + i, src + i);
}
}

/*
* Copy the flags and some other ancillary information
*/
Expand Down Expand Up @@ -661,16 +613,19 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio)
}
EXPORT_SYMBOL(folio_migrate_flags);

void migrate_page_copy(struct page *newpage, struct page *page)
void folio_migrate_copy(struct folio *newfolio, struct folio *folio)
{
if (PageHuge(page) || PageTransHuge(page))
copy_huge_page(newpage, page);
else
copy_highpage(newpage, page);
unsigned int i, nr = folio_nr_pages(folio);

migrate_page_states(newpage, page);
for (i = 0; i < nr; i++) {
/* folio_page() handles discontinuities in memmap */
copy_highpage(folio_page(newfolio, i), folio_page(folio, i));
cond_resched();
}

folio_migrate_flags(newfolio, folio);
}
EXPORT_SYMBOL(migrate_page_copy);
EXPORT_SYMBOL(folio_migrate_copy);

/************************************************************
* Migration functions
Expand Down Expand Up @@ -698,7 +653,7 @@ int migrate_page(struct address_space *mapping,
return rc;

if (mode != MIGRATE_SYNC_NO_COPY)
migrate_page_copy(newpage, page);
folio_migrate_copy(newfolio, folio);
else
folio_migrate_flags(newfolio, folio);
return MIGRATEPAGE_SUCCESS;
Expand Down

0 comments on commit 77c6876

Please sign in to comment.