FAILED: patch "[PATCH] hugetlb: fix update_and_free_page contig page struct" failed to apply to 4.4-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From dbfee5aee7e54f83d96ceb8e3e80717fac62ad63 Mon Sep 17 00:00:00 2001
From: Mike Kravetz <[email protected]>
Date: Wed, 24 Feb 2021 12:07:50 -0800
Subject: [PATCH] hugetlb: fix update_and_free_page contig page struct
assumption
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
page structs are not guaranteed to be contiguous for gigantic pages. The routine update_and_free_page can encounter a gigantic page, yet it assumes page structs are contiguous when setting page flags in subpages.
If update_and_free_page encounters non-contiguous page structs, we can see “BUG: Bad page state in process …” errors.
Non-contiguous page structs are generally not an issue. However, they can exist with a specific kernel configuration and hotplug operations. For
example: Configure the kernel with CONFIG_SPARSEMEM and !CONFIG_SPARSEMEM_VMEMMAP. Then, hotplug add memory for the area where the gigantic page will be allocated. Zi Yan outlined steps to reproduce here [1].
[1] https://lore.kernel.org/linux-mm/[email protected]/
mm/hugetlb.c +4 -2
@@ -1321,14 +1321,16 @@ static inline void destroy_compound_gigantic_page(struct page *page,static void update_and_free_page (struct hstate *h,struct page *page) {int i; +struct page *subpage = page;if (hstate_is_gigantic (h) && !gigantic_page_runtime_supported ())return ; h->nr_huge_pages--; h->nr_huge_pages_node[page_to_nid (page)]--; -for (i =0 ; i <pages_per_huge_page (h); i++) { - page[i].flags &= ~(1 << PG_locked |1 << PG_error | +for (i =0 ; i <pages_per_huge_page (h); + i++, subpage =mem_map_next (subpage, page, i)) { + subpage->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced |1 << PG_dirty |1 << PG_active |1 << PG_private |1 << PG_writeback);
Quoted 5 lines · On 3/1/21 4:40 AM, [email protected] wrote:
The patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
From 291e3463b1b7e2f71cb5999f68d3aa2a80178570 Mon Sep 17 00:00:00 2001
From: Mike Kravetz <[email protected]>
Date: Mon, 1 Mar 2021 18:12:38 -0800
Subject: [PATCH] hugetlb: fix update_and_free_page contig page struct
assumption
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
commit dbfee5aee7e54f83d96ceb8e3e80717fac62ad63 upstream.
page structs are not guaranteed to be contiguous for gigantic pages. The routine update_and_free_page can encounter a gigantic page, yet it assumes page structs are contiguous when setting page flags in subpages.
If update_and_free_page encounters non-contiguous page structs, we can see “BUG: Bad page state in process …” errors.
Non-contiguous page structs are generally not an issue. However, they can exist with a specific kernel configuration and hotplug operations. For
example: Configure the kernel with CONFIG_SPARSEMEM and !CONFIG_SPARSEMEM_VMEMMAP. Then, hotplug add memory for the area where the gigantic page will be allocated.
Zi Yan outlined steps to reproduce here [1].
[1] https://lore.kernel.org/linux-mm/[email protected]/
--- mm/hugetlb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
mm/hugetlb.c +4 -2
@@ -1142,14 +1142,16 @@ static inline int alloc_fresh_gigantic_page(struct hstate *h,static void update_and_free_page (struct hstate *h,struct page *page) {int i; +struct page *subpage = page;if (hstate_is_gigantic (h) && !gigantic_page_supported ())return ; h->nr_huge_pages--; h->nr_huge_pages_node[page_to_nid (page)]--; -for (i =0 ; i <pages_per_huge_page (h); i++) { - page[i].flags &= ~(1 << PG_locked |1 << PG_error | +for (i =0 ; i <pages_per_huge_page (h); + i++, subpage =mem_map_next (subpage, page, i)) { + subpage->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced |1 << PG_dirty |1 << PG_active |1 << PG_private |1 << PG_writeback);
Signature · 1 line
2.29.2