Browse files

mm: setup pageblock_order before it's used by sparsemem

commit ca57df7 upstream.

On architectures with CONFIG_HUGETLB_PAGE_SIZE_VARIABLE set, such as
Itanium, pageblock_order is a variable with default value of 0.  It's set
to the right value by set_pageblock_order() in function

But pageblock_order may be used by sparse_init() before free_area_init_core()
is called along path:
		->((1UL << (PFN_SECTION_SHIFT - pageblock_order)) *

The uninitialized pageblock_size will cause memory wasting because
usemap_size() returns a much bigger value then it's really needed.

For example, on an Itanium platform,
sparse_init() pageblock_order=0 usemap_size=24576
free_area_init_core() before pageblock_order=0, usemap_size=24576
free_area_init_core() after pageblock_order=12, usemap_size=8

That means 24K memory has been wasted for each section, so fix it by calling
set_pageblock_order() from sparse_init().

Signed-off-by: Xishi Qiu <>
Signed-off-by: Jiang Liu <>
Cc: Tony Luck <>
Cc: Yinghai Lu <>
Cc: KAMEZAWA Hiroyuki <>
Cc: Benjamin Herrenschmidt <>
Cc: KOSAKI Motohiro <>
Cc: David Rientjes <>
Cc: Keping Chen <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <>
  • Loading branch information...
Xishi Qiu authored and bwhacks committed Jul 31, 2012
1 parent 27c4b68 commit 3927df7e5035769cea8c6646ebd28d9fdab86057
Showing with 7 additions and 2 deletions.
  1. +2 −0 mm/internal.h
  2. +2 −2 mm/page_alloc.c
  3. +3 −0 mm/sparse.c
@@ -309,3 +309,5 @@ extern u64 hwpoison_filter_flags_mask;
extern u64 hwpoison_filter_flags_value;
extern u64 hwpoison_filter_memcg;
extern u32 hwpoison_filter_enable;
+extern void set_pageblock_order(void);
@@ -4282,7 +4282,7 @@ static inline void setup_usemap(struct pglist_data *pgdat,
/* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */
-static inline void __init set_pageblock_order(void)
+void __init set_pageblock_order(void)
unsigned int order;
@@ -4310,7 +4310,7 @@ static inline void __init set_pageblock_order(void)
* include/linux/pageblock-flags.h for the values of pageblock_order based on
* the kernel config
-static inline void set_pageblock_order(void)
+void __init set_pageblock_order(void)
@@ -486,6 +486,9 @@ void __init sparse_init(void)
struct page **map_map;
+ /* Setup pageblock_order for HUGETLB_PAGE_SIZE_VARIABLE */
+ set_pageblock_order();
* map is using big page (aka 2M in x86 64 bit)
* usemap is less one page (aka 24 bytes)

0 comments on commit 3927df7

Please sign in to comment.