Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1487455 > unrolled thread

[PATCH 0/1] memory offline issues with hugepage size > memory block size

Started byGerald Schaefer <gerald.schaefer@de.ibm.com>
First post2016-09-20 18:00 +0200
Last post2016-09-21 21:30 +0200
Articles 20 on this page of 24 — 7 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/1] memory offline issues with hugepage size > memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-20 18:00 +0200
    [PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-20 18:00 +0200
      Re: [PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2016-09-21 08:40 +0200
        [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size >  memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-21 14:40 +0200
          Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size  > memory block size Rui Teng <rui.teng@linux.vnet.ibm.com> - 2016-09-21 15:20 +0200
            Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage  size > memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-21 17:20 +0200
          Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2016-09-22 10:10 +0200
          Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size  > memory block size Michal Hocko <mhocko@kernel.org> - 2016-09-22 12:00 +0200
            Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage  size > memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-22 15:50 +0200
              [PATCH v3] mm/hugetlb: fix memory offline with hugepage size >  memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-22 18:40 +0200
                Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size >  memory block size Dave Hansen <dave.hansen@linux.intel.com> - 2016-09-22 20:20 +0200
                  Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size >  memory block size Mike Kravetz <mike.kravetz@oracle.com> - 2016-09-22 21:20 +0200
                  Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size >  memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-23 12:40 +0200
            Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size  > memory block size Rui Teng <rui.teng@linux.vnet.ibm.com> - 2016-09-23 08:50 +0200
              Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage  size > memory block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-23 13:10 +0200
                Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size  > memory block size Rui Teng <rui.teng@linux.vnet.ibm.com> - 2016-09-26 04:50 +0200
    Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Mike Kravetz <mike.kravetz@oracle.com> - 2016-09-20 19:40 +0200
      Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Dave Hansen <dave.hansen@linux.intel.com> - 2016-09-20 19:50 +0200
        Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Vlastimil Babka <vbabka@suse.cz> - 2016-09-21 11:50 +0200
        Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-21 12:40 +0200
      Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Gerald Schaefer <gerald.schaefer@de.ibm.com> - 2016-09-21 12:40 +0200
      Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Michal Hocko <mhocko@kernel.org> - 2016-09-21 20:30 +0200
        Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Dave Hansen <dave.hansen@linux.intel.com> - 2016-09-21 20:30 +0200
          Re: [PATCH 0/1] memory offline issues with hugepage size > memory  block size Michal Hocko <mhocko@kernel.org> - 2016-09-21 21:30 +0200

Page 1 of 2  [1] 2  Next page →


#1487455 — [PATCH 0/1] memory offline issues with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-20 18:00 +0200
Subject[PATCH 0/1] memory offline issues with hugepage size > memory block size
Message-ID<sjvCF-4Ws-1@gated-at.bofh.it>
dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
list corruption and addressing exception when trying to set a memory
block offline that is part (but not the first part) of a gigantic
hugetlb page with a size > memory block size.

When no other smaller hugepage sizes are present, the VM_BUG_ON() will
trigger directly. In the other case we will run into an addressing
exception later, because dissolve_free_huge_page() will not use the head
page of the compound hugetlb page which will result in a NULL hstate
from page_hstate(). list_del() would also not work well on a tail page.

To fix this, first remove the VM_BUG_ON() because it is wrong, and then
use the compound head page in dissolve_free_huge_page().

However, this all assumes that it is the desired behaviour to remove
a (gigantic) unused hugetlb page from the pool, just because a small
(in relation to the  hugepage size) memory block is going offline. Not
sure if this is the right thing, and it doesn't look very consistent
given that in this scenario it is _not_ possible to migrate
such a (gigantic) hugepage if it is in use. OTOH, has_unmovable_pages()
will return false in both cases, i.e. the memory block will be reported
as removable, no matter if the hugepage that it is part of is unused or
in use.

This patch is assuming that it would be OK to remove the hugepage,
i.e. memory offline beats pre-allocated unused (gigantic) hugepages.

Any thoughts?


Gerald Schaefer (1):
  mm/hugetlb: fix memory offline with hugepage size > memory block size

 mm/hugetlb.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

-- 
2.8.4

[toc] | [next] | [standalone]


#1487465 — [PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-20 18:00 +0200
Subject[PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sjvCG-4Ws-31@gated-at.bofh.it>
In reply to#1487455
dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
list corruption and addressing exception when trying to set a memory
block offline that is part (but not the first part) of a gigantic
hugetlb page with a size > memory block size.

When no other smaller hugepage sizes are present, the VM_BUG_ON() will
trigger directly. In the other case we will run into an addressing
exception later, because dissolve_free_huge_page() will not use the head
page of the compound hugetlb page which will result in a NULL hstate
from page_hstate(). list_del() would also not work well on a tail page.

To fix this, first remove the VM_BUG_ON() because it is wrong, and then
use the compound head page in dissolve_free_huge_page().

Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
---
 mm/hugetlb.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 87e11d8..65e723c 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1441,15 +1441,17 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
  */
 static void dissolve_free_huge_page(struct page *page)
 {
+	struct page *head = compound_head(page);
+
 	spin_lock(&hugetlb_lock);
-	if (PageHuge(page) && !page_count(page)) {
-		struct hstate *h = page_hstate(page);
-		int nid = page_to_nid(page);
-		list_del(&page->lru);
+	if (!page_count(head)) {
+		struct hstate *h = page_hstate(head);
+		int nid = page_to_nid(head);
+		list_del(&head->lru);
 		h->free_huge_pages--;
 		h->free_huge_pages_node[nid]--;
 		h->max_huge_pages--;
-		update_and_free_page(h, page);
+		update_and_free_page(h, head);
 	}
 	spin_unlock(&hugetlb_lock);
 }
@@ -1466,9 +1468,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 	if (!hugepages_supported())
 		return;
 
-	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));
+		if (PageHuge(pfn_to_page(pfn)))
+			dissolve_free_huge_page(pfn_to_page(pfn));
 }
 
 /*
-- 
2.8.4

[toc] | [prev] | [next] | [standalone]


#1487837 — Re: [PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

From"Hillf Danton" <hillf.zj@alibaba-inc.com>
Date2016-09-21 08:40 +0200
SubjectRe: [PATCH 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sjJmh-5vr-5@gated-at.bofh.it>
In reply to#1487465
> @@ -1466,9 +1468,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  	if (!hugepages_supported())
>  		return;
> 
> -	VM_BUG_ON(!IS_ALIGNED(start_pfn, 1 << minimum_order));

Then the relevant comment has to be updated.

Hillf
>  	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
> -		dissolve_free_huge_page(pfn_to_page(pfn));
> +		if (PageHuge(pfn_to_page(pfn)))
> +			dissolve_free_huge_page(pfn_to_page(pfn));
>  }
> 
>  /*
> --
> 2.8.4

[toc] | [prev] | [next] | [standalone]


#1488088 — [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-21 14:40 +0200
Subject[PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sjOYF-yH-15@gated-at.bofh.it>
In reply to#1487837
dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
list corruption and addressing exception when trying to set a memory
block offline that is part (but not the first part) of a hugetlb page
with a size > memory block size.

When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
will trigger directly. In the other case we will run into an addressing
exception later, because dissolve_free_huge_page() will not work on the
head page of the compound hugetlb page which will result in a NULL
hstate from page_hstate().

To fix this, first remove the VM_BUG_ON() because it is wrong, and then
use the compound head page in dissolve_free_huge_page().

Also change locking in dissolve_free_huge_page(), so that it only takes
the lock when actually removing a hugepage.

Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
---
Changes in v2:
- Update comment in dissolve_free_huge_pages()
- Change locking in dissolve_free_huge_page()

 mm/hugetlb.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 87e11d8..1522af8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1441,23 +1441,30 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
  */
 static void dissolve_free_huge_page(struct page *page)
 {
+	struct page *head = compound_head(page);
+	struct hstate *h;
+	int nid;
+
+	if (page_count(head))
+		return;
+
+	h = page_hstate(head);
+	nid = page_to_nid(head);
+
 	spin_lock(&hugetlb_lock);
-	if (PageHuge(page) && !page_count(page)) {
-		struct hstate *h = page_hstate(page);
-		int nid = page_to_nid(page);
-		list_del(&page->lru);
-		h->free_huge_pages--;
-		h->free_huge_pages_node[nid]--;
-		h->max_huge_pages--;
-		update_and_free_page(h, page);
-	}
+	list_del(&head->lru);
+	h->free_huge_pages--;
+	h->free_huge_pages_node[nid]--;
+	h->max_huge_pages--;
+	update_and_free_page(h, head);
 	spin_unlock(&hugetlb_lock);
 }
 
 /*
  * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
  * make specified memory blocks removable from the system.
- * Note that start_pfn should aligned with (minimum) hugepage size.
+ * Note that this will dissolve a free gigantic hugepage completely, if any
+ * part of it lies within the given range.
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -1466,9 +1473,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 	if (!hugepages_supported())
 		return;
 
-	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));
+		if (PageHuge(pfn_to_page(pfn)))
+			dissolve_free_huge_page(pfn_to_page(pfn));
 }
 
 /*

[toc] | [prev] | [next] | [standalone]


#1488117 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromRui Teng <rui.teng@linux.vnet.ibm.com>
Date2016-09-21 15:20 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sjPBn-10O-9@gated-at.bofh.it>
In reply to#1488088
On 9/21/16 8:35 PM, Gerald Schaefer wrote:
> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> list corruption and addressing exception when trying to set a memory
> block offline that is part (but not the first part) of a hugetlb page
> with a size > memory block size.
>
> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
> will trigger directly. In the other case we will run into an addressing
> exception later, because dissolve_free_huge_page() will not work on the
> head page of the compound hugetlb page which will result in a NULL
> hstate from page_hstate().
>
> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> use the compound head page in dissolve_free_huge_page().
>
> Also change locking in dissolve_free_huge_page(), so that it only takes
> the lock when actually removing a hugepage.
>
> Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
> ---
> Changes in v2:
> - Update comment in dissolve_free_huge_pages()
> - Change locking in dissolve_free_huge_page()
>
>  mm/hugetlb.c | 31 +++++++++++++++++++------------
>  1 file changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 87e11d8..1522af8 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1441,23 +1441,30 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
>   */
>  static void dissolve_free_huge_page(struct page *page)
>  {
> +	struct page *head = compound_head(page);
> +	struct hstate *h;
> +	int nid;
> +
> +	if (page_count(head))
> +		return;
> +
> +	h = page_hstate(head);
> +	nid = page_to_nid(head);
> +
>  	spin_lock(&hugetlb_lock);
> -	if (PageHuge(page) && !page_count(page)) {
> -		struct hstate *h = page_hstate(page);
> -		int nid = page_to_nid(page);
> -		list_del(&page->lru);
> -		h->free_huge_pages--;
> -		h->free_huge_pages_node[nid]--;
> -		h->max_huge_pages--;
> -		update_and_free_page(h, page);
> -	}
> +	list_del(&head->lru);
> +	h->free_huge_pages--;
> +	h->free_huge_pages_node[nid]--;
> +	h->max_huge_pages--;
> +	update_and_free_page(h, head);
>  	spin_unlock(&hugetlb_lock);
>  }
>
>  /*
>   * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
>   * make specified memory blocks removable from the system.
> - * Note that start_pfn should aligned with (minimum) hugepage size.
> + * Note that this will dissolve a free gigantic hugepage completely, if any
> + * part of it lies within the given range.
>   */
>  void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  {
> @@ -1466,9 +1473,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  	if (!hugepages_supported())
>  		return;
>
> -	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));
> +		if (PageHuge(pfn_to_page(pfn)))
> +			dissolve_free_huge_page(pfn_to_page(pfn));
How many times will dissolve_free_huge_page() be invoked in this loop?
For each pfn, it will be converted to the head page, and then the list
will be deleted repeatedly.
>  }
>
>  /*
>

[toc] | [prev] | [next] | [standalone]


#1488185 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-21 17:20 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sjRtw-2de-23@gated-at.bofh.it>
In reply to#1488117
On Wed, 21 Sep 2016 21:17:29 +0800
Rui Teng <rui.teng@linux.vnet.ibm.com> wrote:

> >  /*
> >   * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
> >   * make specified memory blocks removable from the system.
> > - * Note that start_pfn should aligned with (minimum) hugepage size.
> > + * Note that this will dissolve a free gigantic hugepage completely, if any
> > + * part of it lies within the given range.
> >   */
> >  void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
> >  {
> > @@ -1466,9 +1473,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
> >  	if (!hugepages_supported())
> >  		return;
> >
> > -	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));
> > +		if (pfn_to_page(pfn)))
> > +			pfn_to_page(pfn));
> How many times will dissolve_free_huge_page() be invoked in this loop?
> For each pfn, it will be converted to the head page, and then the list
> will be deleted repeatedly.

In the case where the memory block [start_pfn, end_pfn] is part of a
gigantic hugepage, dissolve_free_huge_page() will only be invoked once.

If there is only one gigantic hugepage pool, 1 << minimum_order will be
larger than the memory block size, and the loop will stop after the first
invocation of dissolve_free_huge_page().

If there are additional hugepage pools, with hugepage sizes < memory
block size, then it will loop as many times as 1 << minimum_order fits
inside a memory block, e.g. 256 times with 1 MB minimum hugepage size
and 256 MB memory block size.

However, the PageHuge() check should always return false after the first
invocation of dissolve_free_huge_page(), since update_and_free_page()
will take care of resetting compound_dtor, and so there will also be
just one invocation.

The only case where there will be more than one invocation is the case
where we do not have any part of a gigantic hugepage inside the memory
block, but rather multiple "normal sized" hugepages. Then there will be
one invocation per hugepage, as opposed to one invocation per
"1 << minimum_order" range as it was before the patch. So it also
improves the behaviour in the case where there is no gigantic page
involved.

> >  }
> >
> >  /*
> >
> 

[toc] | [prev] | [next] | [standalone]


#1488610 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

From"Hillf Danton" <hillf.zj@alibaba-inc.com>
Date2016-09-22 10:10 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sk7eV-3OW-1@gated-at.bofh.it>
In reply to#1488088
> 
> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> list corruption and addressing exception when trying to set a memory
> block offline that is part (but not the first part) of a hugetlb page
> with a size > memory block size.
> 
> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
> will trigger directly. In the other case we will run into an addressing
> exception later, because dissolve_free_huge_page() will not work on the
> head page of the compound hugetlb page which will result in a NULL
> hstate from page_hstate().
> 
> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> use the compound head page in dissolve_free_huge_page().
> 
> Also change locking in dissolve_free_huge_page(), so that it only takes
> the lock when actually removing a hugepage.
> 
> Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
> ---
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>

[toc] | [prev] | [next] | [standalone]


#1488711 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromMichal Hocko <mhocko@kernel.org>
Date2016-09-22 12:00 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<sk8Xo-4DU-13@gated-at.bofh.it>
In reply to#1488088
On Wed 21-09-16 14:35:34, Gerald Schaefer wrote:
> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> list corruption and addressing exception when trying to set a memory
> block offline that is part (but not the first part) of a hugetlb page
> with a size > memory block size.
> 
> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
> will trigger directly. In the other case we will run into an addressing
> exception later, because dissolve_free_huge_page() will not work on the
> head page of the compound hugetlb page which will result in a NULL
> hstate from page_hstate().
> 
> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> use the compound head page in dissolve_free_huge_page().

OK so dissolve_free_huge_page will work also on tail pages now which
makes some sense. I would appreciate also few words why do we want to
sacrifice something as precious as gigantic page rather than fail the
page block offline. Dave pointed out dim offline usecase for example.

> Also change locking in dissolve_free_huge_page(), so that it only takes
> the lock when actually removing a hugepage.

From a quick look it seems this has been broken since introduced by
c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle
hugepage"). Do we want to have this backported to stable? In any way
Fixes: SHA1 would be really nice.

> Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>

Other than that looks good to me, although there is a room for
improvements here. See below

> ---
> Changes in v2:
> - Update comment in dissolve_free_huge_pages()
> - Change locking in dissolve_free_huge_page()
> 
>  mm/hugetlb.c | 31 +++++++++++++++++++------------
>  1 file changed, 19 insertions(+), 12 deletions(-)
> 
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 87e11d8..1522af8 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1441,23 +1441,30 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
>   */
>  static void dissolve_free_huge_page(struct page *page)
>  {
> +	struct page *head = compound_head(page);
> +	struct hstate *h;
> +	int nid;
> +
> +	if (page_count(head))
> +		return;
> +
> +	h = page_hstate(head);
> +	nid = page_to_nid(head);
> +
>  	spin_lock(&hugetlb_lock);
> -	if (PageHuge(page) && !page_count(page)) {
> -		struct hstate *h = page_hstate(page);
> -		int nid = page_to_nid(page);
> -		list_del(&page->lru);
> -		h->free_huge_pages--;
> -		h->free_huge_pages_node[nid]--;
> -		h->max_huge_pages--;
> -		update_and_free_page(h, page);
> -	}
> +	list_del(&head->lru);
> +	h->free_huge_pages--;
> +	h->free_huge_pages_node[nid]--;
> +	h->max_huge_pages--;
> +	update_and_free_page(h, head);
>  	spin_unlock(&hugetlb_lock);
>  }
>  
>  /*
>   * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
>   * make specified memory blocks removable from the system.
> - * Note that start_pfn should aligned with (minimum) hugepage size.
> + * Note that this will dissolve a free gigantic hugepage completely, if any
> + * part of it lies within the given range.
>   */
>  void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  {
> @@ -1466,9 +1473,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  	if (!hugepages_supported())
>  		return;
>  
> -	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));
> +		if (PageHuge(pfn_to_page(pfn)))
> +			dissolve_free_huge_page(pfn_to_page(pfn));
>  }

we can return the number of freed pages from dissolve_free_huge_page and
move by the approapriate number of pfns. Nothing to really lose sleep
about but no rocket science either. An early break out if the page is
used would be nice as well. Something like the following, probably a
separate patch on top of yours.
---
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 029a80b90cea..d230900f571e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1434,17 +1434,17 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
 }
 
 /*
- * Dissolve a given free hugepage into free buddy pages. This function does
- * nothing for in-use (including surplus) hugepages.
+ * Dissolve a given free hugepage into free buddy pages. Returns number
+ * of freed pages or EBUSY if the page is in use.
  */
-static void dissolve_free_huge_page(struct page *page)
+static int dissolve_free_huge_page(struct page *page)
 {
 	struct page *head = compound_head(page);
 	struct hstate *h;
 	int nid;
 
 	if (page_count(head))
-		return;
+		return -EBUSY;
 
 	h = page_hstate(head);
 	nid = page_to_nid(head);
@@ -1456,6 +1456,8 @@ static void dissolve_free_huge_page(struct page *page)
 	h->max_huge_pages--;
 	update_and_free_page(h, head);
 	spin_unlock(&hugetlb_lock);
+
+	return 1 << h->order;
 }
 
 /*
@@ -1471,9 +1473,18 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 	if (!hugepages_supported())
 		return;
 
-	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
-		if (PageHuge(pfn_to_page(pfn)))
-			dissolve_free_huge_page(pfn_to_page(pfn));
+	for (pfn = start_pfn; pfn < end_pfn; )
+		int nr_pages;
+
+		if (!PageHuge(pfn_to_page(pfn))) {
+			pfn += 1 << minimum_order;
+			continue;
+		}
+
+		nr_pages = dissolve_free_huge_page(pfn_to_page(pfn));
+		if (IS_ERR(nr_pages))
+			break;
+		pfn += nr_pages;
 }
 
 /*
-- 
Michal Hocko
SUSE Labs

[toc] | [prev] | [next] | [standalone]


#1488890 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-22 15:50 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skcxY-71r-19@gated-at.bofh.it>
In reply to#1488711
On Thu, 22 Sep 2016 11:51:37 +0200
Michal Hocko <mhocko@kernel.org> wrote:

> On Wed 21-09-16 14:35:34, Gerald Schaefer wrote:
> > dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> > list corruption and addressing exception when trying to set a memory
> > block offline that is part (but not the first part) of a hugetlb page
> > with a size > memory block size.
> > 
> > When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
> > will trigger directly. In the other case we will run into an addressing
> > exception later, because dissolve_free_huge_page() will not work on the
> > head page of the compound hugetlb page which will result in a NULL
> > hstate from page_hstate().
> > 
> > To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> > use the compound head page in dissolve_free_huge_page().
> 
> OK so dissolve_free_huge_page will work also on tail pages now which
> makes some sense. I would appreciate also few words why do we want to
> sacrifice something as precious as gigantic page rather than fail the
> page block offline. Dave pointed out dim offline usecase for example.
> 
> > Also change locking in dissolve_free_huge_page(), so that it only takes
> > the lock when actually removing a hugepage.
> 
> From a quick look it seems this has been broken since introduced by
> c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle
> hugepage"). Do we want to have this backported to stable? In any way
> Fixes: SHA1 would be really nice.

That's true, I'll send a v3.

> 
> > Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
> 
> Other than that looks good to me, although there is a room for
> improvements here. See below
> 
> > ---
> > Changes in v2:
> > - Update comment in dissolve_free_huge_pages()
> > - Change locking in dissolve_free_huge_page()
> > 
> >  mm/hugetlb.c | 31 +++++++++++++++++++------------
> >  1 file changed, 19 insertions(+), 12 deletions(-)
> > 
> > diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> > index 87e11d8..1522af8 100644
> > --- a/mm/hugetlb.c
> > +++ b/mm/hugetlb.c
> > @@ -1441,23 +1441,30 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
> >   */
> >  static void dissolve_free_huge_page(struct page *page)
> >  {
> > +	struct page *head = compound_head(page);
> > +	struct hstate *h;
> > +	int nid;
> > +
> > +	if (page_count(head))
> > +		return;
> > +
> > +	h = page_hstate(head);
> > +	nid = page_to_nid(head);
> > +
> >  	spin_lock(&hugetlb_lock);
> > -	if (PageHuge(page) && !page_count(page)) {
> > -		struct hstate *h = page_hstate(page);
> > -		int nid = page_to_nid(page);
> > -		list_del(&page->lru);
> > -		h->free_huge_pages--;
> > -		h->free_huge_pages_node[nid]--;
> > -		h->max_huge_pages--;
> > -		update_and_free_page(h, page);
> > -	}
> > +	list_del(&head->lru);
> > +	h->free_huge_pages--;
> > +	h->free_huge_pages_node[nid]--;
> > +	h->max_huge_pages--;
> > +	update_and_free_page(h, head);
> >  	spin_unlock(&hugetlb_lock);
> >  }
> >  
> >  /*
> >   * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
> >   * make specified memory blocks removable from the system.
> > - * Note that start_pfn should aligned with (minimum) hugepage size.
> > + * Note that this will dissolve a free gigantic hugepage completely, if any
> > + * part of it lies within the given range.
> >   */
> >  void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
> >  {
> > @@ -1466,9 +1473,9 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
> >  	if (!hugepages_supported())
> >  		return;
> >  
> > -	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));
> > +		if (PageHuge(pfn_to_page(pfn)))
> > +			dissolve_free_huge_page(pfn_to_page(pfn));
> >  }
> 
> we can return the number of freed pages from dissolve_free_huge_page and
> move by the approapriate number of pfns. Nothing to really lose sleep
> about but no rocket science either. An early break out if the page is
> used would be nice as well. Something like the following, probably a
> separate patch on top of yours.

Hmm, not sure if this is really worth the effort and the (small) added
complexity. It would surely be worth it for the current code, where we
also have the spinlock involved even for non-huge pages. After this patch
however, dissolve_free_huge_page() will only be called for hugepages,
and the early break-out is also there, although the page_count() check
could probably be moved out from dissolve_free_huge_page() and into the
loop, I'll try this for v3.

The loop count will also not be greatly reduced, at least when there
are only hugepages of minimum_order in the memory block, or no hugepages
at all, it will not improve anything. In any other case the PageHuge()
check in the loop will already prevent unnecessary calls to
dissolve_free_huge_page().

> ---
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 029a80b90cea..d230900f571e 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1434,17 +1434,17 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
>  }
> 
>  /*
> - * Dissolve a given free hugepage into free buddy pages. This function does
> - * nothing for in-use (including surplus) hugepages.
> + * Dissolve a given free hugepage into free buddy pages. Returns number
> + * of freed pages or EBUSY if the page is in use.
>   */
> -static void dissolve_free_huge_page(struct page *page)
> +static int dissolve_free_huge_page(struct page *page)
>  {
>  	struct page *head = compound_head(page);
>  	struct hstate *h;
>  	int nid;
> 
>  	if (page_count(head))
> -		return;
> +		return -EBUSY;
> 
>  	h = page_hstate(head);
>  	nid = page_to_nid(head);
> @@ -1456,6 +1456,8 @@ static void dissolve_free_huge_page(struct page *page)
>  	h->max_huge_pages--;
>  	update_and_free_page(h, head);
>  	spin_unlock(&hugetlb_lock);
> +
> +	return 1 << h->order;
>  }
> 
>  /*
> @@ -1471,9 +1473,18 @@ void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>  	if (!hugepages_supported())
>  		return;
> 
> -	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order)
> -		if (PageHuge(pfn_to_page(pfn)))
> -			dissolve_free_huge_page(pfn_to_page(pfn));
> +	for (pfn = start_pfn; pfn < end_pfn; )
> +		int nr_pages;
> +
> +		if (!PageHuge(pfn_to_page(pfn))) {
> +			pfn += 1 << minimum_order;
> +			continue;
> +		}
> +
> +		nr_pages = dissolve_free_huge_page(pfn_to_page(pfn));
> +		if (IS_ERR(nr_pages))
> +			break;
> +		pfn += nr_pages;
>  }
> 
>  /*

[toc] | [prev] | [next] | [standalone]


#1489080 — [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-22 18:40 +0200
Subject[PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skfct-hW-11@gated-at.bofh.it>
In reply to#1488890
dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
list corruption and addressing exception when trying to set a memory
block offline that is part (but not the first part) of a "gigantic"
hugetlb page with a size > memory block size.

When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
will trigger directly. In the other case we will run into an addressing
exception later, because dissolve_free_huge_page() will not work on the
head page of the compound hugetlb page which will result in a NULL
hstate from page_hstate().

To fix this, first remove the VM_BUG_ON() because it is wrong, and then
use the compound head page in dissolve_free_huge_page(). This means that
an unused pre-allocated gigantic page that has any part of itself inside
the memory block that is going offline will be dissolved completely.
Losing the gigantic hugepage is preferable to failing the memory offline,
for example in the situation where a (possibly faulty) memory DIMM needs
to go offline.

Also move the PageHuge() and page_count() checks out of
dissolve_free_huge_page() in order to only take the spin_lock when
actually removing a hugepage.

Fixes: c8721bbb ("mm: memory-hotplug: enable memory hotplug to handle hugepage")
Cc: <stable@vger.kernel.org>
Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
---
Changes in v3:
- Add Fixes: c8721bbb
- Add Cc: stable
- Elaborate on losing the gigantic page vs. failing memory offline
- Move page_count() check out of dissolve_free_huge_page()

Changes in v2:
- Update comment in dissolve_free_huge_pages()
- Change locking in dissolve_free_huge_page()

 mm/hugetlb.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 87e11d8..29e10a2 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1436,39 +1436,43 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
 }
 
 /*
- * Dissolve a given free hugepage into free buddy pages. This function does
- * nothing for in-use (including surplus) hugepages.
+ * Dissolve a given free hugepage into free buddy pages.
  */
 static void dissolve_free_huge_page(struct page *page)
 {
+	struct page *head = compound_head(page);
+	struct hstate *h = page_hstate(head);
+	int nid = page_to_nid(head);
+
 	spin_lock(&hugetlb_lock);
-	if (PageHuge(page) && !page_count(page)) {
-		struct hstate *h = page_hstate(page);
-		int nid = page_to_nid(page);
-		list_del(&page->lru);
-		h->free_huge_pages--;
-		h->free_huge_pages_node[nid]--;
-		h->max_huge_pages--;
-		update_and_free_page(h, page);
-	}
+	list_del(&head->lru);
+	h->free_huge_pages--;
+	h->free_huge_pages_node[nid]--;
+	h->max_huge_pages--;
+	update_and_free_page(h, head);
 	spin_unlock(&hugetlb_lock);
 }
 
 /*
  * Dissolve free hugepages in a given pfn range. Used by memory hotplug to
  * make specified memory blocks removable from the system.
- * Note that start_pfn should aligned with (minimum) hugepage size.
+ * Note that this will dissolve a free gigantic hugepage completely, if any
+ * part of it lies within the given range.
+ * This function does nothing for in-use (including surplus) hugepages.
  */
 void dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
 	unsigned long pfn;
+	struct page *page;
 
 	if (!hugepages_supported())
 		return;
 
-	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));
+	for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) {
+		page = pfn_to_page(pfn);
+		if (PageHuge(page) && !page_count(page))
+			dissolve_free_huge_page(page);
+	}
 }
 
 /*

[toc] | [prev] | [next] | [standalone]


#1489285 — Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromDave Hansen <dave.hansen@linux.intel.com>
Date2016-09-22 20:20 +0200
SubjectRe: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skgLg-1mw-53@gated-at.bofh.it>
In reply to#1489080
On 09/22/2016 09:29 AM, Gerald Schaefer wrote:
>  static void dissolve_free_huge_page(struct page *page)
>  {
> +	struct page *head = compound_head(page);
> +	struct hstate *h = page_hstate(head);
> +	int nid = page_to_nid(head);
> +
>  	spin_lock(&hugetlb_lock);
> -	if (PageHuge(page) && !page_count(page)) {
> -		struct hstate *h = page_hstate(page);
> -		int nid = page_to_nid(page);
> -		list_del(&page->lru);
> -		h->free_huge_pages--;
> -		h->free_huge_pages_node[nid]--;
> -		h->max_huge_pages--;
> -		update_and_free_page(h, page);
> -	}
> +	list_del(&head->lru);
> +	h->free_huge_pages--;
> +	h->free_huge_pages_node[nid]--;
> +	h->max_huge_pages--;
> +	update_and_free_page(h, head);
>  	spin_unlock(&hugetlb_lock);
>  }

Do you need to revalidate anything once you acquire the lock?  Can this,
for instance, race with another thread doing vm.nr_hugepages=0?  Or a
thread faulting in and allocating the large page that's being dissolved?

[toc] | [prev] | [next] | [standalone]


#1489462 — Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromMike Kravetz <mike.kravetz@oracle.com>
Date2016-09-22 21:20 +0200
SubjectRe: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skhHl-1Xw-27@gated-at.bofh.it>
In reply to#1489285
On 09/22/2016 11:12 AM, Dave Hansen wrote:
> On 09/22/2016 09:29 AM, Gerald Schaefer wrote:
>>  static void dissolve_free_huge_page(struct page *page)
>>  {
>> +	struct page *head = compound_head(page);
>> +	struct hstate *h = page_hstate(head);
>> +	int nid = page_to_nid(head);
>> +
>>  	spin_lock(&hugetlb_lock);
>> -	if (PageHuge(page) && !page_count(page)) {
>> -		struct hstate *h = page_hstate(page);
>> -		int nid = page_to_nid(page);
>> -		list_del(&page->lru);
>> -		h->free_huge_pages--;
>> -		h->free_huge_pages_node[nid]--;
>> -		h->max_huge_pages--;
>> -		update_and_free_page(h, page);
>> -	}
>> +	list_del(&head->lru);
>> +	h->free_huge_pages--;
>> +	h->free_huge_pages_node[nid]--;
>> +	h->max_huge_pages--;
>> +	update_and_free_page(h, head);
>>  	spin_unlock(&hugetlb_lock);
>>  }
> 
> Do you need to revalidate anything once you acquire the lock?  Can this,
> for instance, race with another thread doing vm.nr_hugepages=0?  Or a
> thread faulting in and allocating the large page that's being dissolved?

I originally suggested the locking change, but this is not quite right.
The page count for huge pages is adjusted while holding hugetlb_lock.
So, that check or a revalidation needs to be done while holding the lock.

That question made me think about huge page reservations.  I don't think
the offline code takes this into account.  But, you would not want your
huge page count to drop below the reserved huge page count
(resv_huge_pages).
So, shouldn't this be another condition to check before allowing the huge
page to be dissolved?

-- 
Mike Kravetz

[toc] | [prev] | [next] | [standalone]


#1489933 — Re: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-23 12:40 +0200
SubjectRe: [PATCH v3] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skw3D-2sP-25@gated-at.bofh.it>
In reply to#1489285
On Thu, 22 Sep 2016 11:12:06 -0700
Dave Hansen <dave.hansen@linux.intel.com> wrote:

> On 09/22/2016 09:29 AM, Gerald Schaefer wrote:
> >  static void dissolve_free_huge_page(struct page *page)
> >  {
> > +	struct page *head = compound_head(page);
> > +	struct hstate *h = page_hstate(head);
> > +	int nid = page_to_nid(head);
> > +
> >  	spin_lock(&hugetlb_lock);
> > -	if (PageHuge(page) && !page_count(page)) {
> > -		struct hstate *h = page_hstate(page);
> > -		int nid = page_to_nid(page);
> > -		list_del(&page->lru);
> > -		h->free_huge_pages--;
> > -		h->free_huge_pages_node[nid]--;
> > -		h->max_huge_pages--;
> > -		update_and_free_page(h, page);
> > -	}
> > +	list_del(&head->lru);
> > +	h->free_huge_pages--;
> > +	h->free_huge_pages_node[nid]--;
> > +	h->max_huge_pages--;
> > +	update_and_free_page(h, head);
> >  	spin_unlock(&hugetlb_lock);
> >  }
> 
> Do you need to revalidate anything once you acquire the lock?  Can this,
> for instance, race with another thread doing vm.nr_hugepages=0?  Or a
> thread faulting in and allocating the large page that's being dissolved?
> 

Yes, good point. I was relying on the range being isolated, but that only
seems to be checked in dequeue_huge_page_node(), as introduced with the
original commit. So this would only protect against anyone allocating the
hugepage at this point. This is also somehow expected, since we already
are beyond the "point of no return" in offline_pages().

vm.nr_hugepages=0 seems to be an issue though, as set_max_hugepages()
will not care about isolation, and so I guess we could have a race here
and double-free the hugepage. Revalidation of at least PageHuge() after
taking the lock should protect from that, not sure about page_count(),
but I think I'll just check both which will give the same behaviour as
before.

Will send v4, after thinking a bit more on the page reservation point
brought up by Mike.

[toc] | [prev] | [next] | [standalone]


#1489790 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromRui Teng <rui.teng@linux.vnet.ibm.com>
Date2016-09-23 08:50 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skst4-eu-13@gated-at.bofh.it>
In reply to#1488711
On 9/22/16 5:51 PM, Michal Hocko wrote:
> On Wed 21-09-16 14:35:34, Gerald Schaefer wrote:
>> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
>> list corruption and addressing exception when trying to set a memory
>> block offline that is part (but not the first part) of a hugetlb page
>> with a size > memory block size.
>>
>> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
>> will trigger directly. In the other case we will run into an addressing
>> exception later, because dissolve_free_huge_page() will not work on the
>> head page of the compound hugetlb page which will result in a NULL
>> hstate from page_hstate().
>>
>> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
>> use the compound head page in dissolve_free_huge_page().
>
> OK so dissolve_free_huge_page will work also on tail pages now which
> makes some sense. I would appreciate also few words why do we want to
> sacrifice something as precious as gigantic page rather than fail the
> page block offline. Dave pointed out dim offline usecase for example.
>
>> Also change locking in dissolve_free_huge_page(), so that it only takes
>> the lock when actually removing a hugepage.
>
> From a quick look it seems this has been broken since introduced by
> c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle
> hugepage"). Do we want to have this backported to stable? In any way
> Fixes: SHA1 would be really nice.
>

If the huge page hot-plug function was introduced by c8721bbbdd36, and
it has already indicated that the gigantic page is not supported:

	"As for larger hugepages (1GB for x86_64), it's not easy to do
	hotremove over them because it's larger than memory block.  So
	we now simply leave it to fail as it is."

Is it possible that the gigantic page hot-plugin has never been
supported?

I made another patch for this problem, and also tried to apply the
first version of this patch on my system too. But they only postpone
the error happened. The HugePages_Free will be changed from 2 to 1, if I 
offline a huge page. I think it does not have a correct roll back.

# cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
HugePages_Total:       2
HugePages_Free:        1
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:   16777216 kB

I will make more test on it, but can any one confirm that this function 
has been implemented and tested before?

[toc] | [prev] | [next] | [standalone]


#1489949 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-23 13:10 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<skwwF-2RT-11@gated-at.bofh.it>
In reply to#1489790
On Fri, 23 Sep 2016 14:40:33 +0800
Rui Teng <rui.teng@linux.vnet.ibm.com> wrote:

> On 9/22/16 5:51 PM, Michal Hocko wrote:
> > On Wed 21-09-16 14:35:34, Gerald Schaefer wrote:
> >> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> >> list corruption and addressing exception when trying to set a memory
> >> block offline that is part (but not the first part) of a hugetlb page
> >> with a size > memory block size.
> >>
> >> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
> >> will trigger directly. In the other case we will run into an addressing
> >> exception later, because dissolve_free_huge_page() will not work on the
> >> head page of the compound hugetlb page which will result in a NULL
> >> hstate from page_hstate().
> >>
> >> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> >> use the compound head page in dissolve_free_huge_page().
> >
> > OK so dissolve_free_huge_page will work also on tail pages now which
> > makes some sense. I would appreciate also few words why do we want to
> > sacrifice something as precious as gigantic page rather than fail the
> > page block offline. Dave pointed out dim offline usecase for example.
> >
> >> Also change locking in dissolve_free_huge_page(), so that it only takes
> >> the lock when actually removing a hugepage.
> >
> > From a quick look it seems this has been broken since introduced by
> > c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle
> > hugepage"). Do we want to have this backported to stable? In any way
> > Fixes: SHA1 would be really nice.
> >
> 
> If the huge page hot-plug function was introduced by c8721bbbdd36, and
> it has already indicated that the gigantic page is not supported:
> 
> 	"As for larger hugepages (1GB for x86_64), it's not easy to do
> 	hotremove over them because it's larger than memory block.  So
> 	we now simply leave it to fail as it is."
> 
> Is it possible that the gigantic page hot-plugin has never been
> supported?

Offlining blocks with gigantic pages only fails when they are in-use,
I guess that was meant by the description. Maybe it was also meant to
fail in any case, but that was not was the patch did.

With free gigantic pages, it looks like it only ever worked when
offlining the first block of a gigantic page. And as long as you only
have gigantic pages, the VM_BUG_ON() would actually have triggered on
every block that is not gigantic-page-aligned, even if the block is not
part of any gigantic page at all.

Given the age of the patch it is a little bit surprising that it never
struck anyone, and that we now have found it on two architectures at
once :-)

> 
> I made another patch for this problem, and also tried to apply the
> first version of this patch on my system too. But they only postpone
> the error happened. The HugePages_Free will be changed from 2 to 1, if I 
> offline a huge page. I think it does not have a correct roll back.
> 
> # cat /proc/meminfo | grep -i huge
> AnonHugePages:         0 kB
> HugePages_Total:       2
> HugePages_Free:        1
> HugePages_Rsvd:        0
> HugePages_Surp:        0
> Hugepagesize:   16777216 kB

HugePages_Free is supposed to be reduced when offlining a block, but
then HugePages_Total should also be reduced, so that is strange. On my
system both were reduced. Does this happen with any version of my patch?

What do you mean with postpone the error? Can you reproduce the BUG_ON
or the addressing exception with my patch?

> 
> I will make more test on it, but can any one confirm that this function 
> has been implemented and tested before?

[toc] | [prev] | [next] | [standalone]


#1491051 — Re: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size

FromRui Teng <rui.teng@linux.vnet.ibm.com>
Date2016-09-26 04:50 +0200
SubjectRe: [PATCH v2 1/1] mm/hugetlb: fix memory offline with hugepage size > memory block size
Message-ID<slu9r-6r0-3@gated-at.bofh.it>
In reply to#1489949
On 9/23/16 7:03 PM, Gerald Schaefer wrote:
> On Fri, 23 Sep 2016 14:40:33 +0800
> Rui Teng <rui.teng@linux.vnet.ibm.com> wrote:
>
>> On 9/22/16 5:51 PM, Michal Hocko wrote:
>>> On Wed 21-09-16 14:35:34, Gerald Schaefer wrote:
>>>> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
>>>> list corruption and addressing exception when trying to set a memory
>>>> block offline that is part (but not the first part) of a hugetlb page
>>>> with a size > memory block size.
>>>>
>>>> When no other smaller hugetlb page sizes are present, the VM_BUG_ON()
>>>> will trigger directly. In the other case we will run into an addressing
>>>> exception later, because dissolve_free_huge_page() will not work on the
>>>> head page of the compound hugetlb page which will result in a NULL
>>>> hstate from page_hstate().
>>>>
>>>> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
>>>> use the compound head page in dissolve_free_huge_page().
>>>
>>> OK so dissolve_free_huge_page will work also on tail pages now which
>>> makes some sense. I would appreciate also few words why do we want to
>>> sacrifice something as precious as gigantic page rather than fail the
>>> page block offline. Dave pointed out dim offline usecase for example.
>>>
>>>> Also change locking in dissolve_free_huge_page(), so that it only takes
>>>> the lock when actually removing a hugepage.
>>>
>>> From a quick look it seems this has been broken since introduced by
>>> c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle
>>> hugepage"). Do we want to have this backported to stable? In any way
>>> Fixes: SHA1 would be really nice.
>>>
>>
>> If the huge page hot-plug function was introduced by c8721bbbdd36, and
>> it has already indicated that the gigantic page is not supported:
>>
>> 	"As for larger hugepages (1GB for x86_64), it's not easy to do
>> 	hotremove over them because it's larger than memory block.  So
>> 	we now simply leave it to fail as it is."
>>
>> Is it possible that the gigantic page hot-plugin has never been
>> supported?
>
> Offlining blocks with gigantic pages only fails when they are in-use,
> I guess that was meant by the description. Maybe it was also meant to
> fail in any case, but that was not was the patch did.
>
> With free gigantic pages, it looks like it only ever worked when
> offlining the first block of a gigantic page. And as long as you only
> have gigantic pages, the VM_BUG_ON() would actually have triggered on
> every block that is not gigantic-page-aligned, even if the block is not
> part of any gigantic page at all.

I have not met the VM_BUG_ON() issue on my powerpc architecture. Seems
it does not always have the align issue on other architectures.

>
> Given the age of the patch it is a little bit surprising that it never
> struck anyone, and that we now have found it on two architectures at
> once :-)
>
>>
>> I made another patch for this problem, and also tried to apply the
>> first version of this patch on my system too. But they only postpone
>> the error happened. The HugePages_Free will be changed from 2 to 1, if I
>> offline a huge page. I think it does not have a correct roll back.
>>
>> # cat /proc/meminfo | grep -i huge
>> AnonHugePages:         0 kB
>> HugePages_Total:       2
>> HugePages_Free:        1
>> HugePages_Rsvd:        0
>> HugePages_Surp:        0
>> Hugepagesize:   16777216 kB
>
> HugePages_Free is supposed to be reduced when offlining a block, but
> then HugePages_Total should also be reduced, so that is strange. On my
> system both were reduced. Does this happen with any version of my patch?

No, I only tested your first version. I do not have any question on
your patch, because the error was not introduced by your patch.

>
> What do you mean with postpone the error? Can you reproduce the BUG_ON
> or the addressing exception with my patch?

I mean the gigantic offlining function does not work at all on my
environment, even if the correct head page has been found. My method is
to filter all the tail pages out, and your method is to find head page
from tail pages.

Since you can offline gigantic page successful, I think such function
is supported now. I will debug the problem on my environment.

>
>>
>> I will make more test on it, but can any one confirm that this function
>> has been implemented and tested before?

[toc] | [prev] | [next] | [standalone]


#1487540 — Re: [PATCH 0/1] memory offline issues with hugepage size > memory block size

FromMike Kravetz <mike.kravetz@oracle.com>
Date2016-09-20 19:40 +0200
SubjectRe: [PATCH 0/1] memory offline issues with hugepage size > memory block size
Message-ID<sjxbr-61r-5@gated-at.bofh.it>
In reply to#1487455
On 09/20/2016 08:53 AM, Gerald Schaefer wrote:
> dissolve_free_huge_pages() will either run into the VM_BUG_ON() or a
> list corruption and addressing exception when trying to set a memory
> block offline that is part (but not the first part) of a gigantic
> hugetlb page with a size > memory block size.
> 
> When no other smaller hugepage sizes are present, the VM_BUG_ON() will
> trigger directly. In the other case we will run into an addressing
> exception later, because dissolve_free_huge_page() will not use the head
> page of the compound hugetlb page which will result in a NULL hstate
> from page_hstate(). list_del() would also not work well on a tail page.
> 
> To fix this, first remove the VM_BUG_ON() because it is wrong, and then
> use the compound head page in dissolve_free_huge_page().
> 
> However, this all assumes that it is the desired behaviour to remove
> a (gigantic) unused hugetlb page from the pool, just because a small
> (in relation to the  hugepage size) memory block is going offline. Not
> sure if this is the right thing, and it doesn't look very consistent
> given that in this scenario it is _not_ possible to migrate
> such a (gigantic) hugepage if it is in use. OTOH, has_unmovable_pages()
> will return false in both cases, i.e. the memory block will be reported
> as removable, no matter if the hugepage that it is part of is unused or
> in use.
> 
> This patch is assuming that it would be OK to remove the hugepage,
> i.e. memory offline beats pre-allocated unused (gigantic) hugepages.
> 
> Any thoughts?

Cc'ed Rui Teng and Dave Hansen as they were discussing the issue in
this thread:
https://lkml.org/lkml/2016/9/13/146

Their approach (I believe) would be to fail the offline operation in
this case.  However, I could argue that failing the operation, or
dissolving the unused huge page containing the area to be offlined is
the right thing to do.

I never thought too much about the VM_BUG_ON(), but you are correct in
that it should be removed in either case.

The other thing that needs to be changed is the locking in
dissolve_free_huge_page().  I believe the lock only needs to be held if
we are removing the huge page from the pool.  It is not a correctness
but performance issue.

-- 
Mike Kravetz

> 
> 
> Gerald Schaefer (1):
>   mm/hugetlb: fix memory offline with hugepage size > memory block size
> 
>  mm/hugetlb.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
> 

[toc] | [prev] | [next] | [standalone]


#1487549 — Re: [PATCH 0/1] memory offline issues with hugepage size > memory block size

FromDave Hansen <dave.hansen@linux.intel.com>
Date2016-09-20 19:50 +0200
SubjectRe: [PATCH 0/1] memory offline issues with hugepage size > memory block size
Message-ID<sjxl8-64Q-19@gated-at.bofh.it>
In reply to#1487540
On 09/20/2016 10:37 AM, Mike Kravetz wrote:
> 
> Their approach (I believe) would be to fail the offline operation in
> this case.  However, I could argue that failing the operation, or
> dissolving the unused huge page containing the area to be offlined is
> the right thing to do.

I think the right thing to do is dissolve the whole huge page if even a
part of it is offlined.  The only question is what to do with the
gigantic remnants.

[toc] | [prev] | [next] | [standalone]


#1487964 — Re: [PATCH 0/1] memory offline issues with hugepage size > memory block size

FromVlastimil Babka <vbabka@suse.cz>
Date2016-09-21 11:50 +0200
SubjectRe: [PATCH 0/1] memory offline issues with hugepage size > memory block size
Message-ID<sjMka-7il-17@gated-at.bofh.it>
In reply to#1487549
On 09/20/2016 07:45 PM, Dave Hansen wrote:
> On 09/20/2016 10:37 AM, Mike Kravetz wrote:
>>
>> Their approach (I believe) would be to fail the offline operation in
>> this case.  However, I could argue that failing the operation, or
>> dissolving the unused huge page containing the area to be offlined is
>> the right thing to do.
>
> I think the right thing to do is dissolve the whole huge page if even a
> part of it is offlined.  The only question is what to do with the
> gigantic remnants.

Just free them into the buddy system? Or what are the alternatives? 
Creating smaller huge pages (if supported)? That doesn't make much 
sense. Offline it completely? That's probably not what the user requested.

Vlastimil

[toc] | [prev] | [next] | [standalone]


#1488036 — Re: [PATCH 0/1] memory offline issues with hugepage size > memory block size

FromGerald Schaefer <gerald.schaefer@de.ibm.com>
Date2016-09-21 12:40 +0200
SubjectRe: [PATCH 0/1] memory offline issues with hugepage size > memory block size
Message-ID<sjN6y-7Tm-27@gated-at.bofh.it>
In reply to#1487549
On Tue, 20 Sep 2016 10:45:23 -0700
Dave Hansen <dave.hansen@linux.intel.com> wrote:

> On 09/20/2016 10:37 AM, Mike Kravetz wrote:
> > 
> > Their approach (I believe) would be to fail the offline operation in
> > this case.  However, I could argue that failing the operation, or
> > dissolving the unused huge page containing the area to be offlined is
> > the right thing to do.
> 
> I think the right thing to do is dissolve the whole huge page if even a
> part of it is offlined.  The only question is what to do with the
> gigantic remnants.
> 

Hmm, not sure if I got this right, but I thought that by calling
update_and_free_page() on the head page (even if it is not part of the
memory block to be removed) all parts of the gigantic hugepage should be
properly freed and there should not be any remnants left.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web