diff mbox series

[1/5] mm: remove find_subpage()

Message ID 20240817095122.2460977-2-wangkefeng.wang@huawei.com (mailing list archive)
State New
Headers show
Series mm: finish three more folio conversion | expand

Commit Message

Kefeng Wang Aug. 17, 2024, 9:51 a.m. UTC
After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
in filemap.c"), the find_subpage() should remove hugetlb case as the
folio_file_page(), furthermore, we could convert to use folio_file_page()
to remove find_subpage().

Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
 include/linux/pagemap.h | 13 -------------
 lib/iov_iter.c          | 24 +++++++++++++-----------
 2 files changed, 13 insertions(+), 24 deletions(-)

Comments

Kefeng Wang Aug. 19, 2024, 11:02 a.m. UTC | #1
On 2024/8/17 17:51, Kefeng Wang wrote:
> After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
> in filemap.c"), the find_subpage() should remove hugetlb case as the
> folio_file_page(), furthermore, we could convert to use folio_file_page()
> to remove find_subpage().

There are some comments from David to the non-public send(forget to cc 
list),
the problem of find_subpage() is not described , so adding some here,


see commit a08c7193e4f1,

--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -789,9 +789,6 @@ static inline pgoff_t folio_next_index(struct folio 
*folio)
   */
  static inline struct page *folio_file_page(struct folio *folio, 
pgoff_t index)
  {
-       /* HugeTLBfs indexes the page cache in units of hpage_size */
-       if (folio_test_hugetlb(folio))
-               return &folio->page;
         return folio_page(folio, index & (folio_nr_pages(folio) - 1));
  }

It changes the granularity of ->index to the base page size rather than
the huge page size, so for hugetlb, the special handling(return head
page) is removed from folio_file_page(), so we need remove special
hugetlb handling find_subpage() too, maybe this is a bugfix as a
separate patch.

And after removing hugetlb handling in find_subpage(), there is
another issue about "head + (index & (thp_nr_pages(head) - 1))", for
hugetlb without sparsemem vmemmap, struct page is not guaranteed to be
contiguous beyond a section, so we need to use

  nth_page(head, (index & (thp_nr_pages(head) - 1))

and in order to reduce code maintain between folio_file_page() and
find_subpage(), just use folio_file_page() in find_subpage() to
fix above two issue.

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index d9c7edb6422b..e2553e4ac3ef 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -866,11 +866,9 @@ static inline bool folio_contains(struct folio 
*folio, pgoff_t index)
   */
  static inline struct page *find_subpage(struct page *head, pgoff_t index)
  {
-       /* HugeTLBfs wants the head page regardless */
-       if (PageHuge(head))
-               return head;
+       struct folio *folio = (struct folio *)head;

-       return head + (index & (thp_nr_pages(head) - 1));
+       return folio_file_page(folio);
  }

And this will correctly handle head/tail page, correct me if I am wrong.

Thanks.
David Hildenbrand Aug. 19, 2024, 1:27 p.m. UTC | #2
On 19.08.24 13:02, Kefeng Wang wrote:
> 
> 
> On 2024/8/17 17:51, Kefeng Wang wrote:
>> After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
>> in filemap.c"), the find_subpage() should remove hugetlb case as the
>> folio_file_page(), furthermore, we could convert to use folio_file_page()
>> to remove find_subpage().
> 
> There are some comments from David to the non-public send(forget to cc
> list),
> the problem of find_subpage() is not described , so adding some here,
> 

Thanks!

> 
> see commit a08c7193e4f1,
> 
> --- a/include/linux/pagemap.h
> +++ b/include/linux/pagemap.h
> @@ -789,9 +789,6 @@ static inline pgoff_t folio_next_index(struct folio
> *folio)
>     */
>    static inline struct page *folio_file_page(struct folio *folio,
> pgoff_t index)
>    {
> -       /* HugeTLBfs indexes the page cache in units of hpage_size */
> -       if (folio_test_hugetlb(folio))
> -               return &folio->page;
>           return folio_page(folio, index & (folio_nr_pages(folio) - 1));
>    }
> 
> It changes the granularity of ->index to the base page size rather than
> the huge page size, so for hugetlb, the special handling(return head
> page) is removed from folio_file_page(), so we need remove special
> hugetlb handling find_subpage() too, maybe this is a bugfix as a
> separate patch.

That's the part I understand. Any caller of folio_file_page() is 
expected to be able to deal with a hugetlb tail page after this patch.

Now, your assumption is the callers of find_subpage() are find with a 
tail page as well. That's the part I am not sure about, but if you think 
all callers are fine, then please spell that out in the patch description.

Something like

"Note that find_subpage() would never return the tail page of a hugetlb 
folio, but folio_file_page() will return tail pages. This, however, is 
fine because XYZ".

But I am wondering if these functions here even get called for hugetlb 
ever ... :)

They only trigger for iov_iter_is_xarray()?

> 
> And after removing hugetlb handling in find_subpage(), there is
> another issue about "head + (index & (thp_nr_pages(head) - 1))", for
> hugetlb without sparsemem vmemmap, struct page is not guaranteed to be
> contiguous beyond a section, so we need to use
> 
>    nth_page(head, (index & (thp_nr_pages(head) - 1))

Agreed. So as soon as we would unlock that code for THP, we would run 
into that issue.

> 
> and in order to reduce code maintain between folio_file_page() and
> find_subpage(), just use folio_file_page() in find_subpage() to
> fix above two issue.
> 
> diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
> index d9c7edb6422b..e2553e4ac3ef 100644
> --- a/include/linux/pagemap.h
> +++ b/include/linux/pagemap.h
> @@ -866,11 +866,9 @@ static inline bool folio_contains(struct folio
> *folio, pgoff_t index)
>     */
>    static inline struct page *find_subpage(struct page *head, pgoff_t index)
>    {
> -       /* HugeTLBfs wants the head page regardless */
> -       if (PageHuge(head))
> -               return head;
> +       struct folio *folio = (struct folio *)head;
> 
> -       return head + (index & (thp_nr_pages(head) - 1));
> +       return folio_file_page(folio);

^ I assume you meant "folio_file_page(folio, index);"

>    }
> 
> And this will correctly handle head/tail page, correct me if I am wrong.

Right.

Is iov_iter_xarray() one of the things Willy mentioned is scheduled for 
removal? Then I agree that looking into removing that part completely 
does also sounds reasonable.
Kefeng Wang Aug. 20, 2024, 8:22 a.m. UTC | #3
On 2024/8/19 21:27, David Hildenbrand wrote:
> On 19.08.24 13:02, Kefeng Wang wrote:
>>
>>
>> On 2024/8/17 17:51, Kefeng Wang wrote:
>>> After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
>>> in filemap.c"), the find_subpage() should remove hugetlb case as the
>>> folio_file_page(), furthermore, we could convert to use 
>>> folio_file_page()
>>> to remove find_subpage().
>>
>> There are some comments from David to the non-public send(forget to cc
>> list),
>> the problem of find_subpage() is not described , so adding some here,
>>
> 
> Thanks!
> 
>>
>> see commit a08c7193e4f1,
>>
>> --- a/include/linux/pagemap.h
>> +++ b/include/linux/pagemap.h
>> @@ -789,9 +789,6 @@ static inline pgoff_t folio_next_index(struct folio
>> *folio)
>>     */
>>    static inline struct page *folio_file_page(struct folio *folio,
>> pgoff_t index)
>>    {
>> -       /* HugeTLBfs indexes the page cache in units of hpage_size */
>> -       if (folio_test_hugetlb(folio))
>> -               return &folio->page;
>>           return folio_page(folio, index & (folio_nr_pages(folio) - 1));
>>    }
>>
>> It changes the granularity of ->index to the base page size rather than
>> the huge page size, so for hugetlb, the special handling(return head
>> page) is removed from folio_file_page(), so we need remove special
>> hugetlb handling find_subpage() too, maybe this is a bugfix as a
>> separate patch.
> 
> That's the part I understand. Any caller of folio_file_page() is 
> expected to be able to deal with a hugetlb tail page after this patch.
> 
> Now, your assumption is the callers of find_subpage() are find with a 
> tail page as well. That's the part I am not sure about, but if you think 
> all callers are fine, then please spell that out in the patch description.
> 
> Something like
> 
> "Note that find_subpage() would never return the tail page of a hugetlb 
> folio, but folio_file_page() will return tail pages. This, however, is 
> fine because XYZ" >
> But I am wondering if these functions here even get called for hugetlb 
> ever ... :)
> 
> They only trigger for iov_iter_is_xarray()?

Yes, the find_subpage only used under iov_iter_is_xarray(),  and
only afs/erofs/netfs/orangefs/ceph/smb use ITER_XARRAY, no hugetlb
involved, so we could safety drop hugetlb part in find_subpage().

> 
>>
>> And after removing hugetlb handling in find_subpage(), there is
>> another issue about "head + (index & (thp_nr_pages(head) - 1))", for
>> hugetlb without sparsemem vmemmap, struct page is not guaranteed to be
>> contiguous beyond a section, so we need to use
>>
>>    nth_page(head, (index & (thp_nr_pages(head) - 1))
> 
> Agreed. So as soon as we would unlock that code for THP, we would run 
> into that issue.

Since no hugetlb involved, there is no issue even we drop hugetlb
handling.
> 
>>
>> and in order to reduce code maintain between folio_file_page() and
>> find_subpage(), just use folio_file_page() in find_subpage() to
>> fix above two issue.
>>
>> diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
>> index d9c7edb6422b..e2553e4ac3ef 100644
>> --- a/include/linux/pagemap.h
>> +++ b/include/linux/pagemap.h
>> @@ -866,11 +866,9 @@ static inline bool folio_contains(struct folio
>> *folio, pgoff_t index)
>>     */
>>    static inline struct page *find_subpage(struct page *head, pgoff_t 
>> index)
>>    {
>> -       /* HugeTLBfs wants the head page regardless */
>> -       if (PageHuge(head))
>> -               return head;
>> +       struct folio *folio = (struct folio *)head;
>>
>> -       return head + (index & (thp_nr_pages(head) - 1));
>> +       return folio_file_page(folio);
> 
> ^ I assume you meant "folio_file_page(folio, index);"

Right.

> 
>>    }
>>
>> And this will correctly handle head/tail page, correct me if I am wrong.
> 
> Right.
> 
> Is iov_iter_xarray() one of the things Willy mentioned is scheduled for 
> removal? Then I agree that looking into removing that part completely 
> does also sounds reasonable.
> 

I think Willy want to remove __readahead_batch() totally, not related
about iter xarray.
David Hildenbrand Aug. 20, 2024, 8:23 a.m. UTC | #4
On 20.08.24 10:22, Kefeng Wang wrote:
> 
> 
> On 2024/8/19 21:27, David Hildenbrand wrote:
>> On 19.08.24 13:02, Kefeng Wang wrote:
>>>
>>>
>>> On 2024/8/17 17:51, Kefeng Wang wrote:
>>>> After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
>>>> in filemap.c"), the find_subpage() should remove hugetlb case as the
>>>> folio_file_page(), furthermore, we could convert to use
>>>> folio_file_page()
>>>> to remove find_subpage().
>>>
>>> There are some comments from David to the non-public send(forget to cc
>>> list),
>>> the problem of find_subpage() is not described , so adding some here,
>>>
>>
>> Thanks!
>>
>>>
>>> see commit a08c7193e4f1,
>>>
>>> --- a/include/linux/pagemap.h
>>> +++ b/include/linux/pagemap.h
>>> @@ -789,9 +789,6 @@ static inline pgoff_t folio_next_index(struct folio
>>> *folio)
>>>      */
>>>     static inline struct page *folio_file_page(struct folio *folio,
>>> pgoff_t index)
>>>     {
>>> -       /* HugeTLBfs indexes the page cache in units of hpage_size */
>>> -       if (folio_test_hugetlb(folio))
>>> -               return &folio->page;
>>>            return folio_page(folio, index & (folio_nr_pages(folio) - 1));
>>>     }
>>>
>>> It changes the granularity of ->index to the base page size rather than
>>> the huge page size, so for hugetlb, the special handling(return head
>>> page) is removed from folio_file_page(), so we need remove special
>>> hugetlb handling find_subpage() too, maybe this is a bugfix as a
>>> separate patch.
>>
>> That's the part I understand. Any caller of folio_file_page() is
>> expected to be able to deal with a hugetlb tail page after this patch.
>>
>> Now, your assumption is the callers of find_subpage() are find with a
>> tail page as well. That's the part I am not sure about, but if you think
>> all callers are fine, then please spell that out in the patch description.
>>
>> Something like
>>
>> "Note that find_subpage() would never return the tail page of a hugetlb
>> folio, but folio_file_page() will return tail pages. This, however, is
>> fine because XYZ" >
>> But I am wondering if these functions here even get called for hugetlb
>> ever ... :)
>>
>> They only trigger for iov_iter_is_xarray()?
> 
> Yes, the find_subpage only used under iov_iter_is_xarray(),  and
> only afs/erofs/netfs/orangefs/ceph/smb use ITER_XARRAY, no hugetlb
> involved, so we could safety drop hugetlb part in find_subpage().

Highlighting that in the patch description would likely be best. The 
hugetlb check is essentially dead code right now ... and confuses David :)
Kefeng Wang Aug. 20, 2024, 8:34 a.m. UTC | #5
On 2024/8/20 16:23, David Hildenbrand wrote:
> On 20.08.24 10:22, Kefeng Wang wrote:
>>
>>
>> On 2024/8/19 21:27, David Hildenbrand wrote:
>>> On 19.08.24 13:02, Kefeng Wang wrote:
>>>>
>>>>
>>>> On 2024/8/17 17:51, Kefeng Wang wrote:
>>>>> After commit a08c7193e4f1 ("mm/filemap: remove hugetlb special casing
>>>>> in filemap.c"), the find_subpage() should remove hugetlb case as the
>>>>> folio_file_page(), furthermore, we could convert to use
>>>>> folio_file_page()
>>>>> to remove find_subpage().
>>>>
>>>> There are some comments from David to the non-public send(forget to cc
>>>> list),
>>>> the problem of find_subpage() is not described , so adding some here,
>>>>
>>>
>>> Thanks!
>>>
>>>>
>>>> see commit a08c7193e4f1,
>>>>
>>>> --- a/include/linux/pagemap.h
>>>> +++ b/include/linux/pagemap.h
>>>> @@ -789,9 +789,6 @@ static inline pgoff_t folio_next_index(struct folio
>>>> *folio)
>>>>      */
>>>>     static inline struct page *folio_file_page(struct folio *folio,
>>>> pgoff_t index)
>>>>     {
>>>> -       /* HugeTLBfs indexes the page cache in units of hpage_size */
>>>> -       if (folio_test_hugetlb(folio))
>>>> -               return &folio->page;
>>>>            return folio_page(folio, index & (folio_nr_pages(folio) - 
>>>> 1));
>>>>     }
>>>>
>>>> It changes the granularity of ->index to the base page size rather than
>>>> the huge page size, so for hugetlb, the special handling(return head
>>>> page) is removed from folio_file_page(), so we need remove special
>>>> hugetlb handling find_subpage() too, maybe this is a bugfix as a
>>>> separate patch.
>>>
>>> That's the part I understand. Any caller of folio_file_page() is
>>> expected to be able to deal with a hugetlb tail page after this patch.
>>>
>>> Now, your assumption is the callers of find_subpage() are find with a
>>> tail page as well. That's the part I am not sure about, but if you think
>>> all callers are fine, then please spell that out in the patch 
>>> description.
>>>
>>> Something like
>>>
>>> "Note that find_subpage() would never return the tail page of a hugetlb
>>> folio, but folio_file_page() will return tail pages. This, however, is
>>> fine because XYZ" >
>>> But I am wondering if these functions here even get called for hugetlb
>>> ever ... :)
>>>
>>> They only trigger for iov_iter_is_xarray()?
>>
>> Yes, the find_subpage only used under iov_iter_is_xarray(),  and
>> only afs/erofs/netfs/orangefs/ceph/smb use ITER_XARRAY, no hugetlb
>> involved, so we could safety drop hugetlb part in find_subpage().
> 
> Highlighting that in the patch description would likely be best. The 
> hugetlb check is essentially dead code right now ... and confuses David :)

Thanks for your kindly review and helper, David :)
>
diff mbox series

Patch

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index d9c7edb6422b..68f59cd7637d 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -860,19 +860,6 @@  static inline bool folio_contains(struct folio *folio, pgoff_t index)
 	return index - folio_index(folio) < folio_nr_pages(folio);
 }
 
-/*
- * Given the page we found in the page cache, return the page corresponding
- * to this index in the file
- */
-static inline struct page *find_subpage(struct page *head, pgoff_t index)
-{
-	/* HugeTLBfs wants the head page regardless */
-	if (PageHuge(head))
-		return head;
-
-	return head + (index & (thp_nr_pages(head) - 1));
-}
-
 unsigned filemap_get_folios(struct address_space *mapping, pgoff_t *start,
 		pgoff_t end, struct folio_batch *fbatch);
 unsigned filemap_get_folios_contig(struct address_space *mapping,
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 4a6a9f419bd7..b0bb1e5ff331 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -891,21 +891,21 @@  static ssize_t iter_xarray_populate_pages(struct page **pages, struct xarray *xa
 					  pgoff_t index, unsigned int nr_pages)
 {
 	XA_STATE(xas, xa, index);
-	struct page *page;
+	struct folio *folio;
 	unsigned int ret = 0;
 
 	rcu_read_lock();
-	for (page = xas_load(&xas); page; page = xas_next(&xas)) {
-		if (xas_retry(&xas, page))
+	for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) {
+		if (xas_retry(&xas, folio))
 			continue;
 
 		/* Has the page moved or been split? */
-		if (unlikely(page != xas_reload(&xas))) {
+		if (unlikely(folio != xas_reload(&xas))) {
 			xas_reset(&xas);
 			continue;
 		}
 
-		pages[ret] = find_subpage(page, xas.xa_index);
+		pages[ret] = folio_file_page(folio, xas.xa_index);
 		get_page(pages[ret]);
 		if (++ret == nr_pages)
 			break;
@@ -1408,7 +1408,8 @@  static ssize_t iov_iter_extract_xarray_pages(struct iov_iter *i,
 					     iov_iter_extraction_t extraction_flags,
 					     size_t *offset0)
 {
-	struct page *page, **p;
+	struct page **p;
+	struct folio *folio;
 	unsigned int nr = 0, offset;
 	loff_t pos = i->xarray_start + i->iov_offset;
 	pgoff_t index = pos >> PAGE_SHIFT;
@@ -1420,20 +1421,21 @@  static ssize_t iov_iter_extract_xarray_pages(struct iov_iter *i,
 	maxpages = want_pages_array(pages, maxsize, offset, maxpages);
 	if (!maxpages)
 		return -ENOMEM;
+
 	p = *pages;
 
 	rcu_read_lock();
-	for (page = xas_load(&xas); page; page = xas_next(&xas)) {
-		if (xas_retry(&xas, page))
+	for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) {
+		if (xas_retry(&xas, folio))
 			continue;
 
-		/* Has the page moved or been split? */
-		if (unlikely(page != xas_reload(&xas))) {
+		/* Has the folio moved or been split? */
+		if (unlikely(folio != xas_reload(&xas))) {
 			xas_reset(&xas);
 			continue;
 		}
 
-		p[nr++] = find_subpage(page, xas.xa_index);
+		p[nr++] = folio_file_page(folio, xas.xa_index);
 		if (nr == maxpages)
 			break;
 	}