diff mbox series

[v6,10/10] mm/memory_hotplug: Cleanup __remove_pages()

Message ID 20191006085646.5768-11-david@redhat.com (mailing list archive)
State New, archived
Headers show
Series [v6,01/10] mm/memunmap: Don't access uninitialized memmap in memunmap_pages() | expand

Commit Message

David Hildenbrand Oct. 6, 2019, 8:56 a.m. UTC
Let's drop the basically unused section stuff and simplify.

Also, let's use a shorter variant to calculate the number of pages to
the next section boundary.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Wei Yang <richardw.yang@linux.intel.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 mm/memory_hotplug.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

Comments

Oscar Salvador Feb. 4, 2020, 9:46 a.m. UTC | #1
On Sun, Oct 06, 2019 at 10:56:46AM +0200, David Hildenbrand wrote:
> Let's drop the basically unused section stuff and simplify.
> 
> Also, let's use a shorter variant to calculate the number of pages to
> the next section boundary.
> 
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Oscar Salvador <osalvador@suse.de>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Wei Yang <richardw.yang@linux.intel.com>
> Signed-off-by: David Hildenbrand <david@redhat.com>

I have to confess that it took me while to wrap around my head
with the new min() change, but looks ok:

Reviewed-by: Oscar Salvador <osalvador@suse.de>

> ---
>  mm/memory_hotplug.c | 17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 843481bd507d..2275240cfa10 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -490,25 +490,20 @@ static void __remove_section(unsigned long pfn, unsigned long nr_pages,
>  void __remove_pages(unsigned long pfn, unsigned long nr_pages,
>  		    struct vmem_altmap *altmap)
>  {
> +	const unsigned long end_pfn = pfn + nr_pages;
> +	unsigned long cur_nr_pages;
>  	unsigned long map_offset = 0;
> -	unsigned long nr, start_sec, end_sec;
>  
>  	map_offset = vmem_altmap_offset(altmap);
>  
>  	if (check_pfn_span(pfn, nr_pages, "remove"))
>  		return;
>  
> -	start_sec = pfn_to_section_nr(pfn);
> -	end_sec = pfn_to_section_nr(pfn + nr_pages - 1);
> -	for (nr = start_sec; nr <= end_sec; nr++) {
> -		unsigned long pfns;
> -
> +	for (; pfn < end_pfn; pfn += cur_nr_pages) {
>  		cond_resched();
> -		pfns = min(nr_pages, PAGES_PER_SECTION
> -				- (pfn & ~PAGE_SECTION_MASK));
> -		__remove_section(pfn, pfns, map_offset, altmap);
> -		pfn += pfns;
> -		nr_pages -= pfns;
> +		/* Select all remaining pages up to the next section boundary */
> +		cur_nr_pages = min(end_pfn - pfn, -(pfn | PAGE_SECTION_MASK));
> +		__remove_section(pfn, cur_nr_pages, map_offset, altmap);
>  		map_offset = 0;
>  	}
>  }
> -- 
> 2.21.0
> 
>
David Hildenbrand Feb. 4, 2020, 12:41 p.m. UTC | #2
On 04.02.20 10:46, Oscar Salvador wrote:
> On Sun, Oct 06, 2019 at 10:56:46AM +0200, David Hildenbrand wrote:
>> Let's drop the basically unused section stuff and simplify.
>>
>> Also, let's use a shorter variant to calculate the number of pages to
>> the next section boundary.
>>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Oscar Salvador <osalvador@suse.de>
>> Cc: Michal Hocko <mhocko@suse.com>
>> Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
>> Cc: Dan Williams <dan.j.williams@intel.com>
>> Cc: Wei Yang <richardw.yang@linux.intel.com>
>> Signed-off-by: David Hildenbrand <david@redhat.com>
> 
> I have to confess that it took me while to wrap around my head
> with the new min() change, but looks ok:

It's a pattern commonly used in compilers and emulators to calculate the
number of bytes to the next block/alignment. (we're missing a macro
(like we have ALIGN_UP/IS_ALIGNED) for that - but it's hard to come up
with a good name (e.g., SIZE_TO_NEXT_ALIGN) .
Segher Boessenkool Feb. 4, 2020, 1:13 p.m. UTC | #3
On Tue, Feb 04, 2020 at 01:41:06PM +0100, David Hildenbrand wrote:
> On 04.02.20 10:46, Oscar Salvador wrote:
> > I have to confess that it took me while to wrap around my head
> > with the new min() change, but looks ok:
> 
> It's a pattern commonly used in compilers and emulators to calculate the
> number of bytes to the next block/alignment. (we're missing a macro
> (like we have ALIGN_UP/IS_ALIGNED) for that - but it's hard to come up
> with a good name (e.g., SIZE_TO_NEXT_ALIGN) .

You can just write the easy to understand

  ...  ALIGN_UP(x) - x  ...

which is better *without* having a separate name.  Does that not
generate good machine code for you?


Segher
David Hildenbrand Feb. 4, 2020, 1:38 p.m. UTC | #4
On 04.02.20 14:13, Segher Boessenkool wrote:
> On Tue, Feb 04, 2020 at 01:41:06PM +0100, David Hildenbrand wrote:
>> On 04.02.20 10:46, Oscar Salvador wrote:
>>> I have to confess that it took me while to wrap around my head
>>> with the new min() change, but looks ok:
>>
>> It's a pattern commonly used in compilers and emulators to calculate the
>> number of bytes to the next block/alignment. (we're missing a macro
>> (like we have ALIGN_UP/IS_ALIGNED) for that - but it's hard to come up
>> with a good name (e.g., SIZE_TO_NEXT_ALIGN) .
> 
> You can just write the easy to understand
> 
>   ...  ALIGN_UP(x) - x  ...

you mean

ALIGN_UP(x, PAGES_PER_SECTION) - x

but ...

> 
> which is better *without* having a separate name.  Does that not
> generate good machine code for you?

1. There is no ALIGN_UP. "SECTION_ALIGN_UP(x) - x" would be possible
2. It would be wrong if x is already aligned.

e.g., let's use 4096 for simplicity as we all know that value by heart
(for both x and the block size).

a) -(4096 | -4096) -> 4096

b) #define ALIGN_UP(x, a) ((x + a - 1) & -(a))

ALIGN_UP(4096, 4096) - 4096 -> 0

Not as easy as it seems ...
Wei Yang Feb. 5, 2020, 11:48 a.m. UTC | #5
On Sun, Oct 06, 2019 at 10:56:46AM +0200, David Hildenbrand wrote:
>Let's drop the basically unused section stuff and simplify.
>
>Also, let's use a shorter variant to calculate the number of pages to
>the next section boundary.
>
>Cc: Andrew Morton <akpm@linux-foundation.org>
>Cc: Oscar Salvador <osalvador@suse.de>
>Cc: Michal Hocko <mhocko@suse.com>
>Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
>Cc: Dan Williams <dan.j.williams@intel.com>
>Cc: Wei Yang <richardw.yang@linux.intel.com>
>Signed-off-by: David Hildenbrand <david@redhat.com>

Finally understand the code.

Reviewed-by: Wei Yang <richardw.yang@linux.intel.com>
Segher Boessenkool Feb. 5, 2020, 12:51 p.m. UTC | #6
On Tue, Feb 04, 2020 at 02:38:51PM +0100, David Hildenbrand wrote:
> On 04.02.20 14:13, Segher Boessenkool wrote:
> > On Tue, Feb 04, 2020 at 01:41:06PM +0100, David Hildenbrand wrote:
> >> It's a pattern commonly used in compilers and emulators to calculate the
> >> number of bytes to the next block/alignment. (we're missing a macro
> >> (like we have ALIGN_UP/IS_ALIGNED) for that - but it's hard to come up
> >> with a good name (e.g., SIZE_TO_NEXT_ALIGN) .

> > You can just write the easy to understand
> > 
> >   ...  ALIGN_UP(x) - x  ...
> 
> you mean
> 
> ALIGN_UP(x, PAGES_PER_SECTION) - x
> 
> but ...
> 
> > which is better *without* having a separate name.  Does that not
> > generate good machine code for you?
> 
> 1. There is no ALIGN_UP. "SECTION_ALIGN_UP(x) - x" would be possible

Erm, you started it ;-)

> 2. It would be wrong if x is already aligned.
> 
> e.g., let's use 4096 for simplicity as we all know that value by heart
> (for both x and the block size).
> 
> a) -(4096 | -4096) -> 4096
> 
> b) #define ALIGN_UP(x, a) ((x + a - 1) & -(a))
> 
> ALIGN_UP(4096, 4096) - 4096 -> 0
> 
> Not as easy as it seems ...

If you always want to return a number >= 1, it it simply
  ALIGN_UP(x + 1) - x
(and replace 1 by any other minimum size required).  This *also* is
easy to read, without having to have any details (and quirks :-/ )
of those utility functions memorised.


Segher
David Hildenbrand Feb. 5, 2020, 1:17 p.m. UTC | #7
On 05.02.20 13:51, Segher Boessenkool wrote:
> On Tue, Feb 04, 2020 at 02:38:51PM +0100, David Hildenbrand wrote:
>> On 04.02.20 14:13, Segher Boessenkool wrote:
>>> On Tue, Feb 04, 2020 at 01:41:06PM +0100, David Hildenbrand wrote:
>>>> It's a pattern commonly used in compilers and emulators to calculate the
>>>> number of bytes to the next block/alignment. (we're missing a macro
>>>> (like we have ALIGN_UP/IS_ALIGNED) for that - but it's hard to come up
>>>> with a good name (e.g., SIZE_TO_NEXT_ALIGN) .
> 
>>> You can just write the easy to understand
>>>
>>>   ...  ALIGN_UP(x) - x  ...
>>
>> you mean
>>
>> ALIGN_UP(x, PAGES_PER_SECTION) - x
>>
>> but ...
>>
>>> which is better *without* having a separate name.  Does that not
>>> generate good machine code for you?
>>
>> 1. There is no ALIGN_UP. "SECTION_ALIGN_UP(x) - x" would be possible
> 
> Erm, you started it ;-)

Yeah, I was thinking in the wrong code base :)

> 
>> 2. It would be wrong if x is already aligned.
>>
>> e.g., let's use 4096 for simplicity as we all know that value by heart
>> (for both x and the block size).
>>
>> a) -(4096 | -4096) -> 4096
>>
>> b) #define ALIGN_UP(x, a) ((x + a - 1) & -(a))
>>
>> ALIGN_UP(4096, 4096) - 4096 -> 0
>>
>> Not as easy as it seems ...
> 
> If you always want to return a number >= 1, it it simply
>   ALIGN_UP(x + 1) - x


I'm sorry to have to correct you again for some corner cases:

ALIGN_UP(1, 4096) - 4096 = 0

Again, not as easy as it seems ...
David Hildenbrand Feb. 5, 2020, 1:18 p.m. UTC | #8
> I'm sorry to have to correct you again for some corner cases:
> 
> ALIGN_UP(1, 4096) - 4096 = 0
> 
> Again, not as easy as it seems ...
> 

Eh, wait, I'm messing up things. Will double check :)
David Hildenbrand Feb. 5, 2020, 1:23 p.m. UTC | #9
On 05.02.20 14:18, David Hildenbrand wrote:
>> I'm sorry to have to correct you again for some corner cases:
>>
>> ALIGN_UP(1, 4096) - 4096 = 0
>>
>> Again, not as easy as it seems ...
>>
> 
> Eh, wait, I'm messing up things. Will double check :)
> 

Yes, makes sense, will send a patch and cc you. Thanks!
diff mbox series

Patch

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 843481bd507d..2275240cfa10 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -490,25 +490,20 @@  static void __remove_section(unsigned long pfn, unsigned long nr_pages,
 void __remove_pages(unsigned long pfn, unsigned long nr_pages,
 		    struct vmem_altmap *altmap)
 {
+	const unsigned long end_pfn = pfn + nr_pages;
+	unsigned long cur_nr_pages;
 	unsigned long map_offset = 0;
-	unsigned long nr, start_sec, end_sec;
 
 	map_offset = vmem_altmap_offset(altmap);
 
 	if (check_pfn_span(pfn, nr_pages, "remove"))
 		return;
 
-	start_sec = pfn_to_section_nr(pfn);
-	end_sec = pfn_to_section_nr(pfn + nr_pages - 1);
-	for (nr = start_sec; nr <= end_sec; nr++) {
-		unsigned long pfns;
-
+	for (; pfn < end_pfn; pfn += cur_nr_pages) {
 		cond_resched();
-		pfns = min(nr_pages, PAGES_PER_SECTION
-				- (pfn & ~PAGE_SECTION_MASK));
-		__remove_section(pfn, pfns, map_offset, altmap);
-		pfn += pfns;
-		nr_pages -= pfns;
+		/* Select all remaining pages up to the next section boundary */
+		cur_nr_pages = min(end_pfn - pfn, -(pfn | PAGE_SECTION_MASK));
+		__remove_section(pfn, cur_nr_pages, map_offset, altmap);
 		map_offset = 0;
 	}
 }