Skip to contentSkip to conversation

mm: memory-hotplug: enable memory hotplug to handle hugepage

PATCH In review Dan Carpenter 3 participants 13 messages May 11, 2015 – May 14, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Hello Naoya Horiguchi,

The patch c8721bbbdd36: "mm: memory-hotplug: enable memory hotplug to handle hugepage" from Sep 11, 2013, leads to the following static checker warning:

	mm/hugetlb.c:1203 dissolve_free_huge_pages()
	warn: potential right shift more than type allows '9,18,64'

mm/hugetlb.c
1189 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) 1190 {

  1191          unsigned int order = 8 * sizeof(void *);
                                     ^^^^^^^^^^^^^^^^^^

Let's say order is 64.

1192 unsigned long pfn;
1193 struct hstate *h;
1194
1195 if (!hugepages_supported())
1196 return;
1197
1198 /* Set scan step to minimum hugepage size */
1199 for_each_hstate(h)
1200 if (order > huge_page_order(h))
1201 order = huge_page_order(h);
1202 VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
1203 for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

                                                            ^^^^^^^^^^

1 << 64 is undefined but let's say it's zero because that's normal for GCC. This is an endless loop.

  1204                  dissolve_free_huge_page(pfn_to_page(pfn));
  1205  }

regards,
dan carpenter

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw
Quoted 9 lines · Dan Carpenter

Hello Naoya Horiguchi,

The patch c8721bbbdd36: "mm: memory-hotplug: enable memory hotplug to handle hugepage" from Sep 11, 2013, leads to the following static checker warning:

	mm/hugetlb.c:1203 dissolve_free_huge_pages()
	warn: potential right shift more than type allows '9,18,64'
Quoted 6 lines

mm/hugetlb.c
1189 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) 1190 {

  1191          unsigned int order = 8 * sizeof(void *);
                                     ^^^^^^^^^^^^^^^^^^

Let's say order is 64.

Actually, the 64 here is just chosen to be an impossibly high number isn't it? It's a bit complicated to understand that at first glance.

regards,
dan carpenter

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw
Quoted 17 lines · Dan Carpenter
Quoted 9 lines · Dan Carpenter

Hello Naoya Horiguchi,

The patch c8721bbbdd36: "mm: memory-hotplug: enable memory hotplug to handle hugepage" from Sep 11, 2013, leads to the following static checker warning:

	mm/hugetlb.c:1203 dissolve_free_huge_pages()
	warn: potential right shift more than type allows '9,18,64'
Quoted 6 lines

mm/hugetlb.c
1189 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) 1190 {

  1191          unsigned int order = 8 * sizeof(void *);
                                     ^^^^^^^^^^^^^^^^^^

Let's say order is 64.

Quoted 2 lines

Actually, the 64 here is just chosen to be an impossibly high number isn't it?

Right.

Quoted 1 line

It's a bit complicated to understand that at first glance.

OK, so I added oneline comment in the patch in another email.

Thanks,
Naoya Horiguchi
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
In reply to Dan Carpenter
Quoted 9 lines · Dan Carpenter

Hello Naoya Horiguchi,

The patch c8721bbbdd36: "mm: memory-hotplug: enable memory hotplug to handle hugepage" from Sep 11, 2013, leads to the following static checker warning:

	mm/hugetlb.c:1203 dissolve_free_huge_pages()
	warn: potential right shift more than type allows '9,18,64'
Quoted 6 lines

mm/hugetlb.c
1189 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) 1190 {

  1191          unsigned int order = 8 * sizeof(void *);
                                     ^^^^^^^^^^^^^^^^^^

Let's say order is 64.

Hi Dan, thank you for reporting.

order is supposed to be capped by running each hstates and finding the minimum hugepage order as done in below code, and I intended that this initialization gives potential maximum. I guess that keeping this to 64 doesn't solve the above warning, so we use 8 * sizeof(void *) - 1 or 63 ? I don't test on 32-bit system, so not sure that this code can be used by 32-bit system, but considering such case, keeping sizeof(void *) seems better.

Quoted 13 lines

1192 unsigned long pfn;
1193 struct hstate *h;
1194
1195 if (!hugepages_supported())
1196 return;
1197
1198 /* Set scan step to minimum hugepage size */
1199 for_each_hstate(h)
1200 if (order > huge_page_order(h))
1201 order = huge_page_order(h);
1202 VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
1203 for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

Quoted 3 lines
                                                            ^^^^^^^^^^

1 << 64 is undefined but let's say it's zero because that's normal for GCC. This is an endless loop.

That never happens if hstates is properly initialized, but we had better avoid the potential risk.

How about the following patch?

Thanks,
Naoya Horiguchi
---
From: Naoya Horiguchi <[email protected]>
Date: Tue, 12 May 2015 08:17:10 +0900
Subject: [PATCH] mm/hugetlb: decrement initial value of order in
dissolve_free_huge_pages

Currently the initial value of order in dissolve_free_huge_page is 64 or 32, which leads to the following warning in static checker:

mm/hugetlb.c:1203 dissolve_free_huge_pages()
warn: potential right shift more than type allows '9,18,64'

This is a potential risk of infinite loop, because 1 << order (== 0) is used in for-loop like this:

for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

      ...

So this patch simply avoids the risk by decrementing the initial value.

Fixes c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle hugepage")
---
 mm/hugetlb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
mm/hugetlb.c +2 -1
index c41b2a0ee273..74abfb44e4d0 100644
@@ -1086,7 +1086,8 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	/* Initialized to "high enough" value which is capped later */
+	unsigned int order = 8 * sizeof(void *) - 1;
 	unsigned long pfn;
 	struct hstate *h;
 
Signature · 7 lines
2.1.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#4 lore raw

mm/hugetlb.c static void dissolve_free_huge_page(struct page *page) · line 1090

Quoted 7 lines · Naoya Horiguchi
mm/hugetlb.c +2 -1
@@ -1086,7 +1086,8 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	/* Initialized to "high enough" value which is capped later */
+	unsigned int order = 8 * sizeof(void *) - 1;

Why not use UINT_MAX? It's more clear that it's not valid that way. Otherwise doing a complicated calculation it makes it seem like we will use the variable.

regards,
dan carpenter

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw
Quoted 10 lines · Dan Carpenter

Review static void dissolve_free_huge_page(struct page *page) · line 1090

Quoted 7 lines · Naoya Horiguchi
(quoted diff) +2 -1
@@ -1086,7 +1086,8 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	/* Initialized to "high enough" value which is capped later */
+	unsigned int order = 8 * sizeof(void *) - 1;

Why not use UINT_MAX? It's more clear that it's not valid that way.

It's OK if code checker doesn't show "too much right shift" warning. With UINT_MAX, inserting VM_BUG_ON(order == UINT_MAX) after for_each_hstate loop might be safer (1 << UINT_MAX is clearly wrong.)

Quoted 2 lines

Otherwise doing a complicated calculation it makes it seem like we will use the variable.

OK.

Is the below OK for you?
---

mm/hugetlb.c +2 -1
index 271e4432734c..804437505a84 100644
@@ -1188,7 +1188,7 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	unsigned int order = UINT_MAX;
 	unsigned long pfn;
 	struct hstate *h;
 
@@ -1200,6 +1200,7 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 		if (order > huge_page_order(h))
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw
Quoted 12 lines · Naoya Horiguchi
Quoted 10 lines · Dan Carpenter

mm/hugetlb.c static void dissolve_free_huge_page(struct page *page) · line 1090

Quoted 7 lines · Naoya Horiguchi
mm/hugetlb.c +2 -1
@@ -1086,7 +1086,8 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	/* Initialized to "high enough" value which is capped later */
+	unsigned int order = 8 * sizeof(void *) - 1;

Why not use UINT_MAX? It's more clear that it's not valid that way.

Quoted 1 line

It's OK if code checker doesn't show "too much right shift" warning.

It's a comlicated question to answer but with the new VM_BUG_ON() then it won't warn.

regards,
dan carpenter

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
Quoted 13 lines · Dan Carpenter
Quoted 12 lines · Naoya Horiguchi
Quoted 10 lines · Dan Carpenter

mm/hugetlb.c static void dissolve_free_huge_page(struct page *page) · line 1090

Quoted 7 lines · Naoya Horiguchi
mm/hugetlb.c +2 -1
@@ -1086,7 +1086,8 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	/* Initialized to "high enough" value which is capped later */
+	unsigned int order = 8 * sizeof(void *) - 1;

Why not use UINT_MAX? It's more clear that it's not valid that way.

Quoted 4 lines
Quoted 1 line

It's OK if code checker doesn't show "too much right shift" warning.

It's a comlicated question to answer but with the new VM_BUG_ON() then it won't warn.

Good, so I'll repost the patch soon later with revised description.

Thanks,
Naoya
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

PATCH 1/1 mm/hugetlb: initialize order with UINT_MAX in dissolve_free_huge_pages()

Currently the initial value of order in dissolve_free_huge_page is 64 or 32, which leads to the following warning in static checker:

mm/hugetlb.c:1203 dissolve_free_huge_pages()
warn: potential right shift more than type allows '9,18,64'

This is a potential risk of infinite loop, because 1 << order (== 0) is used in for-loop like this:

for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

      ...

So this patch simply avoids the risk by initializing with UINT_MAX.

Fixes c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle hugepage")
---
 mm/hugetlb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
mm/hugetlb.c +2 -1
index 271e4432734c..804437505a84 100644
@@ -1188,7 +1188,7 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	unsigned int order = UINT_MAX;
 	unsigned long pfn;
 	struct hstate *h;
 
@@ -1200,6 +1200,7 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 		if (order > huge_page_order(h))
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));
 }
Signature · 7 lines
2.1.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#9 lore raw

Re: [PATCH] mm/hugetlb: initialize order with UINT_MAX in dissolve_free_huge_pages()

Quoted 28 lines · On Tue, 12 May 2015 09:20:35 +0000 Naoya Horiguchi <[email protected]>…

Currently the initial value of order in dissolve_free_huge_page is 64 or 32, which leads to the following warning in static checker:

mm/hugetlb.c:1203 dissolve_free_huge_pages()
warn: potential right shift more than type allows '9,18,64'

This is a potential risk of infinite loop, because 1 << order (== 0) is used in for-loop like this:

for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

      ...

So this patch simply avoids the risk by initializing with UINT_MAX.

..

mm/hugetlb.c +1 -1
@@ -1188,7 +1188,7 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	unsigned int order = UINT_MAX;
 	unsigned long pfn;
 	struct hstate *h;
 

mm/hugetlb.c void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) · line 1205

Quoted 6 lines
mm/hugetlb.c +1 -0
@@ -1200,6 +1200,7 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 		if (order > huge_page_order(h))
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));

Do we need to calculate this each time? Can it be done in hugetlb_init_hstates(), save the result in a global?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw

Re: [PATCH] mm/hugetlb: initialize order with UINT_MAX in dissolve_free_huge_pages()

Quoted 29 lines · Andrew Morton
Quoted 27 lines · On Tue, 12 May 2015 09:20:35 +0000 Naoya Horiguchi <[email protected]>…

Currently the initial value of order in dissolve_free_huge_page is 64 or 32, which leads to the following warning in static checker:

mm/hugetlb.c:1203 dissolve_free_huge_pages()
warn: potential right shift more than type allows '9,18,64'

This is a potential risk of infinite loop, because 1 << order (== 0) is used in for-loop like this:

for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

      ...

So this patch simply avoids the risk by initializing with UINT_MAX.

..

mm/hugetlb.c +1 -1
@@ -1188,7 +1188,7 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
+	unsigned int order = UINT_MAX;
 	unsigned long pfn;
 	struct hstate *h;
 
Quoted 10 lines

mm/hugetlb.c void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) · line 1205

Quoted 7 lines
mm/hugetlb.c +1 -0
@@ -1200,6 +1200,7 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 		if (order > huge_page_order(h))
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));

Do we need to calculate this each time? Can it be done in hugetlb_init_hstates(), save the result in a global?

Yes, it should work. How about the following?
This adds 4bytes to .data due to a new global variable, but reduces 47 bytes .text size of code reduces, so it's a win in total.

text data bss dec hex filename

  28313     469   84236  113018   1b97a mm/hugetlb.o (above patch)
  28266     473   84236  112975   1b94f mm/hugetlb.o (below patch)

---

mm/hugetlb.c +8 -8
index 271e4432734c..fecb8bbfe11e 100644
@@ -40,6 +40,7 @@ int hugepages_treat_as_movable;
 int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
 struct hstate hstates[HUGE_MAX_HSTATE];
+unsigned int minimum_order __read_mostly;
 
 __initdata LIST_HEAD(huge_boot_pages);
 
@@ -1188,19 +1189,13 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
 	unsigned long pfn;
-	struct hstate *h;
 
 	if (!hugepages_supported())
 		return;
 
-	/* Set scan step to minimum hugepage size */
-	for_each_hstate(h)
-		if (order > huge_page_order(h))
-			order = huge_page_order(h);
-	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
-	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
+	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << minimum_order));
+	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
 		dissolve_free_huge_page(pfn_to_page(pfn));
 }
 
@@ -1626,11 +1621,16 @@ static void __init hugetlb_init_hstates(void)
 {
 	struct hstate *h;
 
+	minimum_order = UINT_MAX;
 	for_each_hstate(h) {
+		if (minimum_order > huge_page_order(h))
+			minimum_order = huge_page_order(h);
+
 		/* oversize hugepages were init'ed in early boot */
 		if (!hstate_is_gigantic(h))
 			hugetlb_hstate_alloc_pages(h);
 	}
+	VM_BUG_ON(minimum_order == UINT_MAX);
 }
 
 static char * __init memfmt(char *buf, unsigned long n)
Signature · 7 lines
2.1.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#11 lore raw

Re: [PATCH] mm/hugetlb: initialize order with UINT_MAX in dissolve_free_huge_pages()

Quoted 9 lines · On Wed, 13 May 2015 01:44:22 +0000 Naoya Horiguchi <[email protected]>…
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +1 -0
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));

Do we need to calculate this each time? Can it be done in hugetlb_init_hstates(), save the result in a global?

Quoted 7 lines

Yes, it should work. How about the following?
This adds 4bytes to .data due to a new global variable, but reduces 47 bytes .text size of code reduces, so it's a win in total.

text data bss dec hex filename

  28313     469   84236  113018   1b97a mm/hugetlb.o (above patch)
  28266     473   84236  112975   1b94f mm/hugetlb.o (below patch)

Looks good. Please turn it into a real patch and send it over when convenient?

mm/hugetlb.c int hugepages_treat_as_movable; · line 43

Quoted 7 lines
mm/hugetlb.c +1 -0
@@ -40,6 +40,7 @@ int hugepages_treat_as_movable;
 int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
 struct hstate hstates[HUGE_MAX_HSTATE];
+unsigned int minimum_order __read_mostly;

static.

And a comment would be nice ;)

mm/hugetlb.c static void __init hugetlb_init_hstates(void) · line 1624

Quoted 8 lines

...

mm/hugetlb.c +1 -0
@@ -1626,11 +1621,16 @@ static void __init hugetlb_init_hstates(void)
 {
 	struct hstate *h;
 
+	minimum_order = UINT_MAX;

Do this at compile time.

mm/hugetlb.c static void __init hugetlb_init_hstates(void) · line 1633

Quoted 9 lines
mm/hugetlb.c +4 -0
 	for_each_hstate(h) {
+		if (minimum_order > huge_page_order(h))
+			minimum_order = huge_page_order(h);
+
 		/* oversize hugepages were init'ed in early boot */
 		if (!hstate_is_gigantic(h))
 			hugetlb_hstate_alloc_pages(h);
 	}
+	VM_BUG_ON(minimum_order == UINT_MAX);

Is the system hopelessly screwed up when this happens, or will it still be able to boot up and do useful things?

If the system is hopelessly broken then BUG_ON or, better, panic should be used here. But if there's still potential to do useful things then I guess VM_BUG_ON is appropriate.

mm/hugetlb.c static void __init hugetlb_init_hstates(void) · line 1634

Quoted 1 line
mm/hugetlb.c +0 -0
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw

PATCH 1/1 mm/hugetlb: introduce minimum hugepage order

Quoted 15 lines · Andrew Morton
Quoted 13 lines · On Wed, 13 May 2015 01:44:22 +0000 Naoya Horiguchi <[email protected]>…
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +1 -0
 			order = huge_page_order(h);
 	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
+	VM_BUG_ON(order == UINT_MAX);
 	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
 		dissolve_free_huge_page(pfn_to_page(pfn));

Do we need to calculate this each time? Can it be done in hugetlb_init_hstates(), save the result in a global?

Yes, it should work. How about the following?
This adds 4bytes to .data due to a new global variable, but reduces 47 bytes .text size of code reduces, so it's a win in total.

Quoted 6 lines
Quoted 3 lines

text data bss dec hex filename

  28313     469   84236  113018   1b97a mm/hugetlb.o (above patch)
  28266     473   84236  112975   1b94f mm/hugetlb.o (below patch)

Looks good. Please turn it into a real patch and send it over when convenient?

Yes, the patch is attached below.

Quoted 11 lines

mm/hugetlb.c int hugepages_treat_as_movable; · line 43

Quoted 7 lines
mm/hugetlb.c +1 -0
@@ -40,6 +40,7 @@ int hugepages_treat_as_movable;
 int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
 struct hstate hstates[HUGE_MAX_HSTATE];
+unsigned int minimum_order __read_mostly;

static.

And a comment would be nice ;)

OK, fixed.

Quoted 11 lines

mm/hugetlb.c static void __init hugetlb_init_hstates(void) · line 1624

Quoted 9 lines

...

mm/hugetlb.c +1 -0
@@ -1626,11 +1621,16 @@ static void __init hugetlb_init_hstates(void)
 {
 	struct hstate *h;
 
+	minimum_order = UINT_MAX;

Do this at compile time.

OK.

Quoted 13 lines

mm/hugetlb.c static void __init hugetlb_init_hstates(void) · line 1633

Quoted 9 lines
mm/hugetlb.c +4 -0
 	for_each_hstate(h) {
+		if (minimum_order > huge_page_order(h))
+			minimum_order = huge_page_order(h);
+
 		/* oversize hugepages were init'ed in early boot */
 		if (!hstate_is_gigantic(h))
 			hugetlb_hstate_alloc_pages(h);
 	}
+	VM_BUG_ON(minimum_order == UINT_MAX);

Is the system hopelessly screwed up when this happens, or will it still be able to boot up and do useful things?

Quoted 3 lines

If the system is hopelessly broken then BUG_ON or, better, panic should be used here. But if there's still potential to do useful things then I guess VM_BUG_ON is appropriate.

When this happens, hugetlb subsystem is broken but the system can run as usual, so this is not critical. So I think VM_BUG_ON is OK.

Thanks,
Naoya Horiguchi
---
From: Naoya Horiguchi <[email protected]>
Subject: [PATCH] mm/hugetlb: introduce minimum hugepage order

Currently the initial value of order in dissolve_free_huge_page is 64 or 32, which leads to the following warning in static checker:

mm/hugetlb.c:1203 dissolve_free_huge_pages()
warn: potential right shift more than type allows '9,18,64'

This is a potential risk of infinite loop, because 1 << order (== 0) is used in for-loop like this:

for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)

      ...

So this patch fixes it by using global minimum_order calculated at boot time.

text data bss dec hex filename

   28313     469   84236  113018   1b97a mm/hugetlb.o
   28256     473   84236  112965   1b945 mm/hugetlb.o (patched)
Fixes c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle hugepage")
---
 mm/hugetlb.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)
mm/hugetlb.c +11 -8
index 271e4432734c..8c4c1f9f9a9a 100644
@@ -40,6 +40,11 @@ int hugepages_treat_as_movable;
 int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
 struct hstate hstates[HUGE_MAX_HSTATE];
+/*
+ * Minimum page order among possible hugepage sizes, set to a proper value
+ * at boot time.
+ */
+static unsigned int minimum_order __read_mostly = UINT_MAX;
 
 __initdata LIST_HEAD(huge_boot_pages);
 
@@ -1188,19 +1193,13 @@ static void dissolve_free_huge_page(struct page *page)
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned int order = 8 * sizeof(void *);
 	unsigned long pfn;
-	struct hstate *h;
 
 	if (!hugepages_supported())
 		return;
 
-	/* Set scan step to minimum hugepage size */
-	for_each_hstate(h)
-		if (order > huge_page_order(h))
-			order = huge_page_order(h);
-	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << order));
-	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << order)
+	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << minimum_order));
+	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
 		dissolve_free_huge_page(pfn_to_page(pfn));
 }
 
@@ -1627,10 +1626,14 @@ static void __init hugetlb_init_hstates(void)
 	struct hstate *h;
 
 	for_each_hstate(h) {
+		if (minimum_order > huge_page_order(h))
+			minimum_order = huge_page_order(h);
+
 		/* oversize hugepages were init'ed in early boot */
 		if (!hstate_is_gigantic(h))
 			hugetlb_hstate_alloc_pages(h);
 	}
+	VM_BUG_ON(minimum_order == UINT_MAX);
 }
 
 static char * __init memfmt(char *buf, unsigned long n)
Signature · 7 lines
2.1.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>