diff mbox series

[1/1] mm/mlock: implement folio_mlock_step() using folio_pte_batch()

Message ID 20240603033118.76457-1-ioworker0@gmail.com (mailing list archive)
State New
Headers show
Series [1/1] mm/mlock: implement folio_mlock_step() using folio_pte_batch() | expand

Commit Message

Lance Yang June 3, 2024, 3:31 a.m. UTC
Let's make folio_mlock_step() simply a wrapper around folio_pte_batch(),
which will greatly reduce the cost of ptep_get() when scanning a range of
contptes.

Signed-off-by: Lance Yang <ioworker0@gmail.com>
---
 mm/mlock.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)

Comments

Matthew Wilcox June 3, 2024, 3:36 a.m. UTC | #1
On Mon, Jun 03, 2024 at 11:31:17AM +0800, Lance Yang wrote:
>  {
> -	unsigned int count, i, nr = folio_nr_pages(folio);
> -	unsigned long pfn = folio_pfn(folio);
> -	pte_t ptent = ptep_get(pte);

Please don't move type declarations later in the function.  Just because
you can doesn't mean you should.

> -	if (!folio_test_large(folio))
> +	if (likely(!folio_test_large(folio)))
>  		return 1;

How likely is this now?  How likely will it be in two years time?
Does this actually make any difference in either code generation or
performance?
Lance Yang June 3, 2024, 4:13 a.m. UTC | #2
Hi Matthew,

Thanks for taking time to review!

On Mon, Jun 3, 2024 at 11:36 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Mon, Jun 03, 2024 at 11:31:17AM +0800, Lance Yang wrote:
> >  {
> > -     unsigned int count, i, nr = folio_nr_pages(folio);
> > -     unsigned long pfn = folio_pfn(folio);
> > -     pte_t ptent = ptep_get(pte);
>
> Please don't move type declarations later in the function.  Just because
> you can doesn't mean you should.

Thanks for pointing this out, I'll adjust as you suggested.

>
> > -     if (!folio_test_large(folio))
> > +     if (likely(!folio_test_large(folio)))
> >               return 1;
>
> How likely is this now?  How likely will it be in two years time?
> Does this actually make any difference in either code generation or
> performance?

IMO, this hint could impact code generation and performance :)
But it seems that 'likely' is not necessary here. I'll remove it.

Thanks again for your time!
Lance

>
Barry Song June 3, 2024, 4:14 a.m. UTC | #3
On Mon, Jun 3, 2024 at 3:31 PM Lance Yang <ioworker0@gmail.com> wrote:
>
> Let's make folio_mlock_step() simply a wrapper around folio_pte_batch(),
> which will greatly reduce the cost of ptep_get() when scanning a range of
> contptes.
>
> Signed-off-by: Lance Yang <ioworker0@gmail.com>
> ---
>  mm/mlock.c | 23 ++++++-----------------
>  1 file changed, 6 insertions(+), 17 deletions(-)
>
> diff --git a/mm/mlock.c b/mm/mlock.c
> index 30b51cdea89d..1ae6232d38cf 100644
> --- a/mm/mlock.c
> +++ b/mm/mlock.c
> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>  static inline unsigned int folio_mlock_step(struct folio *folio,
>                 pte_t *pte, unsigned long addr, unsigned long end)
>  {
> -       unsigned int count, i, nr = folio_nr_pages(folio);
> -       unsigned long pfn = folio_pfn(folio);
> -       pte_t ptent = ptep_get(pte);
> -
> -       if (!folio_test_large(folio))
> +       if (likely(!folio_test_large(folio)))
>                 return 1;
>
> -       count = pfn + nr - pte_pfn(ptent);
> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
> -
> -       for (i = 0; i < count; i++, pte++) {
> -               pte_t entry = ptep_get(pte);
> -
> -               if (!pte_present(entry))
> -                       break;
> -               if (pte_pfn(entry) - pfn >= nr)
> -                       break;
> -       }
> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
> +       int max_nr = (end - addr) / PAGE_SIZE;
> +       pte_t ptent = ptep_get(pte);
>
> -       return i;
> +       return folio_pte_batch(folio, addr, pte, ptent, max_nr, fpb_flags, NULL,
> +                              NULL, NULL);
>  }

what about a minimum change as below?
index 30b51cdea89d..e8b98f84fbd2 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
 static inline unsigned int folio_mlock_step(struct folio *folio,
                pte_t *pte, unsigned long addr, unsigned long end)
 {
-       unsigned int count, i, nr = folio_nr_pages(folio);
-       unsigned long pfn = folio_pfn(folio);
+       unsigned int count = (end - addr) >> PAGE_SHIFT;
        pte_t ptent = ptep_get(pte);
+       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;

        if (!folio_test_large(folio))
                return 1;

-       count = pfn + nr - pte_pfn(ptent);
-       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
-
-       for (i = 0; i < count; i++, pte++) {
-               pte_t entry = ptep_get(pte);
-
-               if (!pte_present(entry))
-                       break;
-               if (pte_pfn(entry) - pfn >= nr)
-                       break;
-       }
-
-       return i;
+       return folio_pte_batch(folio, addr, pte, ptent, count, fpb_flags, NULL,
+                              NULL, NULL);
 }



>
>  static inline bool allow_mlock_munlock(struct folio *folio,
> --
> 2.33.1
>
Lance Yang June 3, 2024, 4:27 a.m. UTC | #4
Hi Barry,

Thanks for taking time to review!

On Mon, Jun 3, 2024 at 12:14 PM Barry Song <21cnbao@gmail.com> wrote:
>
> On Mon, Jun 3, 2024 at 3:31 PM Lance Yang <ioworker0@gmail.com> wrote:
> >
> > Let's make folio_mlock_step() simply a wrapper around folio_pte_batch(),
> > which will greatly reduce the cost of ptep_get() when scanning a range of
> > contptes.
> >
> > Signed-off-by: Lance Yang <ioworker0@gmail.com>
> > ---
> >  mm/mlock.c | 23 ++++++-----------------
> >  1 file changed, 6 insertions(+), 17 deletions(-)
> >
> > diff --git a/mm/mlock.c b/mm/mlock.c
> > index 30b51cdea89d..1ae6232d38cf 100644
> > --- a/mm/mlock.c
> > +++ b/mm/mlock.c
> > @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
> >  static inline unsigned int folio_mlock_step(struct folio *folio,
> >                 pte_t *pte, unsigned long addr, unsigned long end)
> >  {
> > -       unsigned int count, i, nr = folio_nr_pages(folio);
> > -       unsigned long pfn = folio_pfn(folio);
> > -       pte_t ptent = ptep_get(pte);
> > -
> > -       if (!folio_test_large(folio))
> > +       if (likely(!folio_test_large(folio)))
> >                 return 1;
> >
> > -       count = pfn + nr - pte_pfn(ptent);
> > -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
> > -
> > -       for (i = 0; i < count; i++, pte++) {
> > -               pte_t entry = ptep_get(pte);
> > -
> > -               if (!pte_present(entry))
> > -                       break;
> > -               if (pte_pfn(entry) - pfn >= nr)
> > -                       break;
> > -       }
> > +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
> > +       int max_nr = (end - addr) / PAGE_SIZE;
> > +       pte_t ptent = ptep_get(pte);
> >
> > -       return i;
> > +       return folio_pte_batch(folio, addr, pte, ptent, max_nr, fpb_flags, NULL,
> > +                              NULL, NULL);
> >  }
>
> what about a minimum change as below?

Nice, that makes sense to me ;)
I'll adjust as you suggested.

Thanks again for your time!
Lance

> index 30b51cdea89d..e8b98f84fbd2 100644
> --- a/mm/mlock.c
> +++ b/mm/mlock.c
> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>  static inline unsigned int folio_mlock_step(struct folio *folio,
>                 pte_t *pte, unsigned long addr, unsigned long end)
>  {
> -       unsigned int count, i, nr = folio_nr_pages(folio);
> -       unsigned long pfn = folio_pfn(folio);
> +       unsigned int count = (end - addr) >> PAGE_SHIFT;
>         pte_t ptent = ptep_get(pte);
> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
>
>         if (!folio_test_large(folio))
>                 return 1;
>
> -       count = pfn + nr - pte_pfn(ptent);
> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
> -
> -       for (i = 0; i < count; i++, pte++) {
> -               pte_t entry = ptep_get(pte);
> -
> -               if (!pte_present(entry))
> -                       break;
> -               if (pte_pfn(entry) - pfn >= nr)
> -                       break;
> -       }
> -
> -       return i;
> +       return folio_pte_batch(folio, addr, pte, ptent, count, fpb_flags, NULL,
> +                              NULL, NULL);
>  }
>
>
>
> >
> >  static inline bool allow_mlock_munlock(struct folio *folio,
> > --
> > 2.33.1
> >
Baolin Wang June 3, 2024, 8:58 a.m. UTC | #5
On 2024/6/3 12:14, Barry Song wrote:
> On Mon, Jun 3, 2024 at 3:31 PM Lance Yang <ioworker0@gmail.com> wrote:
>>
>> Let's make folio_mlock_step() simply a wrapper around folio_pte_batch(),
>> which will greatly reduce the cost of ptep_get() when scanning a range of
>> contptes.
>>
>> Signed-off-by: Lance Yang <ioworker0@gmail.com>
>> ---
>>   mm/mlock.c | 23 ++++++-----------------
>>   1 file changed, 6 insertions(+), 17 deletions(-)
>>
>> diff --git a/mm/mlock.c b/mm/mlock.c
>> index 30b51cdea89d..1ae6232d38cf 100644
>> --- a/mm/mlock.c
>> +++ b/mm/mlock.c
>> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>>   static inline unsigned int folio_mlock_step(struct folio *folio,
>>                  pte_t *pte, unsigned long addr, unsigned long end)
>>   {
>> -       unsigned int count, i, nr = folio_nr_pages(folio);
>> -       unsigned long pfn = folio_pfn(folio);
>> -       pte_t ptent = ptep_get(pte);
>> -
>> -       if (!folio_test_large(folio))
>> +       if (likely(!folio_test_large(folio)))
>>                  return 1;
>>
>> -       count = pfn + nr - pte_pfn(ptent);
>> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
>> -
>> -       for (i = 0; i < count; i++, pte++) {
>> -               pte_t entry = ptep_get(pte);
>> -
>> -               if (!pte_present(entry))
>> -                       break;
>> -               if (pte_pfn(entry) - pfn >= nr)
>> -                       break;
>> -       }
>> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
>> +       int max_nr = (end - addr) / PAGE_SIZE;
>> +       pte_t ptent = ptep_get(pte);
>>
>> -       return i;
>> +       return folio_pte_batch(folio, addr, pte, ptent, max_nr, fpb_flags, NULL,
>> +                              NULL, NULL);
>>   }
> 
> what about a minimum change as below?
> index 30b51cdea89d..e8b98f84fbd2 100644
> --- a/mm/mlock.c
> +++ b/mm/mlock.c
> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>   static inline unsigned int folio_mlock_step(struct folio *folio,
>                  pte_t *pte, unsigned long addr, unsigned long end)
>   {
> -       unsigned int count, i, nr = folio_nr_pages(folio);
> -       unsigned long pfn = folio_pfn(folio);
> +       unsigned int count = (end - addr) >> PAGE_SHIFT;
>          pte_t ptent = ptep_get(pte);
> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
> 
>          if (!folio_test_large(folio))
>                  return 1;
> 
> -       count = pfn + nr - pte_pfn(ptent);
> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
> -
> -       for (i = 0; i < count; i++, pte++) {
> -               pte_t entry = ptep_get(pte);
> -
> -               if (!pte_present(entry))
> -                       break;
> -               if (pte_pfn(entry) - pfn >= nr)
> -                       break;
> -       }
> -
> -       return i;
> +       return folio_pte_batch(folio, addr, pte, ptent, count, fpb_flags, NULL,
> +                              NULL, NULL);
>   }

LGTM.
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
David Hildenbrand June 3, 2024, 9:03 a.m. UTC | #6
On 03.06.24 10:58, Baolin Wang wrote:
> 
> 
> On 2024/6/3 12:14, Barry Song wrote:
>> On Mon, Jun 3, 2024 at 3:31 PM Lance Yang <ioworker0@gmail.com> wrote:
>>>
>>> Let's make folio_mlock_step() simply a wrapper around folio_pte_batch(),
>>> which will greatly reduce the cost of ptep_get() when scanning a range of
>>> contptes.
>>>
>>> Signed-off-by: Lance Yang <ioworker0@gmail.com>
>>> ---
>>>    mm/mlock.c | 23 ++++++-----------------
>>>    1 file changed, 6 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/mm/mlock.c b/mm/mlock.c
>>> index 30b51cdea89d..1ae6232d38cf 100644
>>> --- a/mm/mlock.c
>>> +++ b/mm/mlock.c
>>> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>>>    static inline unsigned int folio_mlock_step(struct folio *folio,
>>>                   pte_t *pte, unsigned long addr, unsigned long end)
>>>    {
>>> -       unsigned int count, i, nr = folio_nr_pages(folio);
>>> -       unsigned long pfn = folio_pfn(folio);
>>> -       pte_t ptent = ptep_get(pte);
>>> -
>>> -       if (!folio_test_large(folio))
>>> +       if (likely(!folio_test_large(folio)))
>>>                   return 1;
>>>
>>> -       count = pfn + nr - pte_pfn(ptent);
>>> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
>>> -
>>> -       for (i = 0; i < count; i++, pte++) {
>>> -               pte_t entry = ptep_get(pte);
>>> -
>>> -               if (!pte_present(entry))
>>> -                       break;
>>> -               if (pte_pfn(entry) - pfn >= nr)
>>> -                       break;
>>> -       }
>>> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
>>> +       int max_nr = (end - addr) / PAGE_SIZE;
>>> +       pte_t ptent = ptep_get(pte);
>>>
>>> -       return i;
>>> +       return folio_pte_batch(folio, addr, pte, ptent, max_nr, fpb_flags, NULL,
>>> +                              NULL, NULL);
>>>    }
>>
>> what about a minimum change as below?
>> index 30b51cdea89d..e8b98f84fbd2 100644
>> --- a/mm/mlock.c
>> +++ b/mm/mlock.c
>> @@ -307,26 +307,15 @@ void munlock_folio(struct folio *folio)
>>    static inline unsigned int folio_mlock_step(struct folio *folio,
>>                   pte_t *pte, unsigned long addr, unsigned long end)
>>    {
>> -       unsigned int count, i, nr = folio_nr_pages(folio);
>> -       unsigned long pfn = folio_pfn(folio);
>> +       unsigned int count = (end - addr) >> PAGE_SHIFT;
>>           pte_t ptent = ptep_get(pte);
>> +       const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
>>
>>           if (!folio_test_large(folio))
>>                   return 1;
>>
>> -       count = pfn + nr - pte_pfn(ptent);
>> -       count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
>> -
>> -       for (i = 0; i < count; i++, pte++) {
>> -               pte_t entry = ptep_get(pte);
>> -
>> -               if (!pte_present(entry))
>> -                       break;
>> -               if (pte_pfn(entry) - pfn >= nr)
>> -                       break;
>> -       }
>> -
>> -       return i;
>> +       return folio_pte_batch(folio, addr, pte, ptent, count, fpb_flags, NULL,
>> +                              NULL, NULL);
>>    }
> 
> LGTM.
> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> 

Acked-by: David Hildenbrand <david@redhat.com>
diff mbox series

Patch

diff --git a/mm/mlock.c b/mm/mlock.c
index 30b51cdea89d..1ae6232d38cf 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -307,26 +307,15 @@  void munlock_folio(struct folio *folio)
 static inline unsigned int folio_mlock_step(struct folio *folio,
 		pte_t *pte, unsigned long addr, unsigned long end)
 {
-	unsigned int count, i, nr = folio_nr_pages(folio);
-	unsigned long pfn = folio_pfn(folio);
-	pte_t ptent = ptep_get(pte);
-
-	if (!folio_test_large(folio))
+	if (likely(!folio_test_large(folio)))
 		return 1;
 
-	count = pfn + nr - pte_pfn(ptent);
-	count = min_t(unsigned int, count, (end - addr) >> PAGE_SHIFT);
-
-	for (i = 0; i < count; i++, pte++) {
-		pte_t entry = ptep_get(pte);
-
-		if (!pte_present(entry))
-			break;
-		if (pte_pfn(entry) - pfn >= nr)
-			break;
-	}
+	const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
+	int max_nr = (end - addr) / PAGE_SIZE;
+	pte_t ptent = ptep_get(pte);
 
-	return i;
+	return folio_pte_batch(folio, addr, pte, ptent, max_nr, fpb_flags, NULL,
+			       NULL, NULL);
 }
 
 static inline bool allow_mlock_munlock(struct folio *folio,