[RFC 07/11] mm/memremap: Add folio_split support
Balbir Singh
balbirs at nvidia.com
Thu Mar 6 21:42:10 UTC 2025
On 3/6/25 19:16, Mika Penttilä wrote:
> Hi,
>
> On 3/6/25 06:42, Balbir Singh wrote:
>> When a zone device page is split (via huge pmd folio split). The
>> driver callback for folio_split is invoked to let the device driver
>> know that the folio size has been split into a smaller order.
>>
>> The HMM test driver has been updated to handle the split, since the
>> test driver uses backing pages, it requires a mechanism of reorganizing
>> the backing pages (backing pages are used to create a mirror device)
>> again into the right sized order pages. This is supported by exporting
>> prep_compound_page().
>>
>> Signed-off-by: Balbir Singh <balbirs at nvidia.com>
>> ---
>> include/linux/memremap.h | 7 +++++++
>> include/linux/mm.h | 1 +
>> lib/test_hmm.c | 35 +++++++++++++++++++++++++++++++++++
>> mm/huge_memory.c | 5 +++++
>> mm/page_alloc.c | 1 +
>> 5 files changed, 49 insertions(+)
>>
>> diff --git a/include/linux/memremap.h b/include/linux/memremap.h
>> index 11d586dd8ef1..2091b754f1da 100644
>> --- a/include/linux/memremap.h
>> +++ b/include/linux/memremap.h
>> @@ -100,6 +100,13 @@ struct dev_pagemap_ops {
>> */
>> int (*memory_failure)(struct dev_pagemap *pgmap, unsigned long pfn,
>> unsigned long nr_pages, int mf_flags);
>> +
>> + /*
>> + * Used for private (un-addressable) device memory only.
>> + * This callback is used when a folio is split into
>> + * a smaller folio
>> + */
>> + void (*folio_split)(struct folio *head, struct folio *tail);
>> };
>>
>> #define PGMAP_ALTMAP_VALID (1 << 0)
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 98a67488b5fe..3d0e91e0a923 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -1415,6 +1415,7 @@ static inline struct folio *virt_to_folio(const void *x)
>> void __folio_put(struct folio *folio);
>>
>> void split_page(struct page *page, unsigned int order);
>> +void prep_compound_page(struct page *page, unsigned int order);
>> void folio_copy(struct folio *dst, struct folio *src);
>> int folio_mc_copy(struct folio *dst, struct folio *src);
>>
>> diff --git a/lib/test_hmm.c b/lib/test_hmm.c
>> index a81d2f8a0426..18b6a7b061d7 100644
>> --- a/lib/test_hmm.c
>> +++ b/lib/test_hmm.c
>> @@ -1640,10 +1640,45 @@ static vm_fault_t dmirror_devmem_fault(struct vm_fault *vmf)
>> return ret;
>> }
>>
>> +
>> +static void dmirror_devmem_folio_split(struct folio *head, struct folio *tail)
>> +{
>> + struct page *rpage = BACKING_PAGE(folio_page(head, 0));
>> + struct folio *new_rfolio;
>> + struct folio *rfolio;
>> + unsigned long offset = 0;
>> +
>> + if (!rpage) {
>> + folio_page(tail, 0)->zone_device_data = NULL;
>> + return;
>> + }
>> +
>> + offset = folio_pfn(tail) - folio_pfn(head);
>> + rfolio = page_folio(rpage);
>> + new_rfolio = page_folio(folio_page(rfolio, offset));
>> +
>> + folio_page(tail, 0)->zone_device_data = folio_page(new_rfolio, 0);
>> +
>
>> + if (folio_pfn(tail) - folio_pfn(head) == 1) {
>> + if (folio_order(head))
>> + prep_compound_page(folio_page(rfolio, 0),
>> + folio_order(head));
>> + folio_set_count(rfolio, 1);
>> + }
>
> I think this might need at least a comment. Also, isn't the
> folio_order(head) always 0, tail and head are splitted folios and if pfn
> difference == 1?
> If the intention is to adjust the backing folio's head page to the new
> order, shouldn't there be clear_compound_head() also for backing head
> page if split to zero order?
>
I'll add some comments to clarify, I'll add clear_compound_head()
Thanks,
Balbir
More information about the dri-devel
mailing list