Re: [RFC 07/11] mm/memremap: Add folio_split support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
>> ---
>>  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



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux