Message ID | 20250411221111.493193-5-gourry@gourry.net (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Promotion of Unmapped Page Cache Folios. | expand |
On Fri, 11 Apr 2025 18:11:09 -0400 Gregory Price <gourry@gourry.net> wrote: > A common operation in tiering is to migrate multiple pages at once. > The migrate_misplaced_folio function requires one call for each > individual folio. Expose a batch-variant of the same call for use > when doing batch migrations. > > Signed-off-by: Gregory Price <gourry@gourry.net> > --- > include/linux/migrate.h | 6 ++++++ > mm/migrate.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 37 insertions(+) > > diff --git a/include/linux/migrate.h b/include/linux/migrate.h > index 61899ec7a9a3..2df756128316 100644 > --- a/include/linux/migrate.h > +++ b/include/linux/migrate.h > @@ -145,6 +145,7 @@ const struct movable_operations *page_movable_ops(struct page *page) > int migrate_misplaced_folio_prepare(struct folio *folio, > struct vm_area_struct *vma, int node); > int migrate_misplaced_folio(struct folio *folio, int node); > +int migrate_misplaced_folio_batch(struct list_head *foliolist, int node); Nit. s/foliolist/folio_list/ ? The none-inline-definition of the function below calls the parameter folio_list, and I show more treewide usage of folio_list than foliolist. linux$ git grep foliolist | wc -l 4 linux$ git grep folio_list | wc -l 142 I wouldn't argue folio_list is the only one right name, but at least using same name on the declaration and the definition[s] would be nice in terms of consistency. > #else > static inline int migrate_misplaced_folio_prepare(struct folio *folio, > struct vm_area_struct *vma, int node) > @@ -155,6 +156,11 @@ static inline int migrate_misplaced_folio(struct folio *folio, int node) > { > return -EAGAIN; /* can't migrate now */ > } > +static inline int migrate_misplaced_folio_batch(struct list_head *foliolist, Ditto. > + int node) > +{ > + return -EAGAIN; /* can't migrate now */ > +} > #endif /* CONFIG_NUMA_BALANCING */ > > #ifdef CONFIG_MIGRATION > diff --git a/mm/migrate.c b/mm/migrate.c > index 047131f6c839..7e1ba6001596 100644 > --- a/mm/migrate.c > +++ b/mm/migrate.c > @@ -2731,5 +2731,36 @@ int migrate_misplaced_folio(struct folio *folio, int node) > BUG_ON(!list_empty(&migratepages)); > return nr_remaining ? -EAGAIN : 0; > } > + > +/* > + * Batch variant of migrate_misplaced_folio. Attempts to migrate > + * a folio list to the specified destination. > + * > + * Caller is expected to have isolated the folios by calling > + * migrate_misplaced_folio_prepare(), which will result in an > + * elevated reference count on the folio. > + * > + * This function will un-isolate the folios, dereference them, and > + * remove them from the list before returning. > + */ > +int migrate_misplaced_folio_batch(struct list_head *folio_list, int node) > +{ > + pg_data_t *pgdat = NODE_DATA(node); > + unsigned int nr_succeeded; > + int nr_remaining; > + > + nr_remaining = migrate_pages(folio_list, alloc_misplaced_dst_folio, > + NULL, node, MIGRATE_ASYNC, > + MR_NUMA_MISPLACED, &nr_succeeded); > + if (nr_remaining) > + putback_movable_pages(folio_list); > + > + if (nr_succeeded) { > + count_vm_numa_events(NUMA_PAGE_MIGRATE, nr_succeeded); migrate_misplaced_folio() also counts memcg events and call mod_lruvec_state(), but this variant doesn't. Is this an intended difference? If so, could you please clarify the reason? > + mod_node_page_state(pgdat, PGPROMOTE_SUCCESS, nr_succeeded); > + } > + BUG_ON(!list_empty(folio_list)); > + return nr_remaining ? -EAGAIN : 0; > +} I feel some code here is duplicated from a part of migrate_misplaced_folio(). Can we deduplicate those? Maybe migrate_misplaced_folio() could be a wrapper of migrate_mispalced_folio_batch()? Thanks, SJ [...]
diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 61899ec7a9a3..2df756128316 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -145,6 +145,7 @@ const struct movable_operations *page_movable_ops(struct page *page) int migrate_misplaced_folio_prepare(struct folio *folio, struct vm_area_struct *vma, int node); int migrate_misplaced_folio(struct folio *folio, int node); +int migrate_misplaced_folio_batch(struct list_head *foliolist, int node); #else static inline int migrate_misplaced_folio_prepare(struct folio *folio, struct vm_area_struct *vma, int node) @@ -155,6 +156,11 @@ static inline int migrate_misplaced_folio(struct folio *folio, int node) { return -EAGAIN; /* can't migrate now */ } +static inline int migrate_misplaced_folio_batch(struct list_head *foliolist, + int node) +{ + return -EAGAIN; /* can't migrate now */ +} #endif /* CONFIG_NUMA_BALANCING */ #ifdef CONFIG_MIGRATION diff --git a/mm/migrate.c b/mm/migrate.c index 047131f6c839..7e1ba6001596 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -2731,5 +2731,36 @@ int migrate_misplaced_folio(struct folio *folio, int node) BUG_ON(!list_empty(&migratepages)); return nr_remaining ? -EAGAIN : 0; } + +/* + * Batch variant of migrate_misplaced_folio. Attempts to migrate + * a folio list to the specified destination. + * + * Caller is expected to have isolated the folios by calling + * migrate_misplaced_folio_prepare(), which will result in an + * elevated reference count on the folio. + * + * This function will un-isolate the folios, dereference them, and + * remove them from the list before returning. + */ +int migrate_misplaced_folio_batch(struct list_head *folio_list, int node) +{ + pg_data_t *pgdat = NODE_DATA(node); + unsigned int nr_succeeded; + int nr_remaining; + + nr_remaining = migrate_pages(folio_list, alloc_misplaced_dst_folio, + NULL, node, MIGRATE_ASYNC, + MR_NUMA_MISPLACED, &nr_succeeded); + if (nr_remaining) + putback_movable_pages(folio_list); + + if (nr_succeeded) { + count_vm_numa_events(NUMA_PAGE_MIGRATE, nr_succeeded); + mod_node_page_state(pgdat, PGPROMOTE_SUCCESS, nr_succeeded); + } + BUG_ON(!list_empty(folio_list)); + return nr_remaining ? -EAGAIN : 0; +} #endif /* CONFIG_NUMA_BALANCING */ #endif /* CONFIG_NUMA */
A common operation in tiering is to migrate multiple pages at once. The migrate_misplaced_folio function requires one call for each individual folio. Expose a batch-variant of the same call for use when doing batch migrations. Signed-off-by: Gregory Price <gourry@gourry.net> --- include/linux/migrate.h | 6 ++++++ mm/migrate.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+)