Skip to contentSkip to conversation

mm: fix page_owner initializing issue for arm32

PATCH Superseded Zhenhua Huang 3 participants 8 messages Oct 16, 2020 – Oct 26, 2020

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mm: fix page_owner initializing issue for arm32

Page owner of pages used by page owner itself used is missing on arm32 targets. The reason is dummy_handle and failure_handle is not initialized correctly. Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that by initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).
2. invoke the init callback of page_ext_ops like page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid 1006, ts 67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +7 -1
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long index)
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Acked-by on v1 1/1
#1 lore raw
Quoted 24 lines · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32 targets. The reason is dummy_handle and failure_handle is not initialized correctly. Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that by initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).
2. invoke the init callback of page_ext_ops like page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid 1006, ts 67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

Quoted 4 lines
  init_page_owner+0x28/0x2f8
  invoke_init_callbacks_flatmem+0x24/0x34
  start_kernel+0x33c/0x5d8
    (null)

register_dummy_stack should also appear in the above. Either one too many is skipped in arm32 stack saving, or the noinline is not honoured. Could be investigated separately.

Quoted 2 lines

This should be safe, as the sparse variant page_ext_init() runs even later, so:

Nit below:

Quoted 52 lines
---
  include/linux/page_ext.h | 8 ++++++++
  init/main.c              | 2 ++
  mm/page_ext.c            | 8 +++++++-
  3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
  {
  }
  extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
  #else
  extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
  static inline void page_ext_init(void)
  {
  }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
  {
  }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
  static inline void page_ext_init_flatmem(void)
  {
  }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
  	init_debug_pagealloc();
  	report_meminit();
  	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
  	kmem_cache_init();
  	kmemleak_init();
  	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 102

Quoted 4 lines
mm/page_ext.c +1 -0
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
  	}
  }
 
+#if !defined(CONFIG_SPARSEMEM)

#ifndef is more common if you don't need boolean ops on multiple configs

Quoted 18 lines
mm/page_ext.c +6 -1
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
  static inline struct page_ext *get_entry(void *base, unsigned long index)
  {
  	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
  			goto fail;
  	}
  	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
  	return;
 
  fail:
#2 lore raw
Quoted 33 lines · Vlastimil Babka
Quoted 27 lines · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32 targets.
The reason is dummy_handle and failure_handle is not initialized correctly.
Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that by initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).
2. invoke the init callback of page_ext_ops like page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid 1006, ts
67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

Quoted 4 lines
 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
Quoted 4 lines

register_dummy_stack should also appear in the above. Either one too many is skipped in arm32 stack saving, or the noinline is not honoured. Could be investigated separately.

yes, it's another issue I need to investigate. Be noted, the printing is from 4.9 kernel and I will look into separately.

Quoted 65 lines
Quoted 2 lines

This should be safe, as the sparse variant page_ext_init() runs even later, so:

Nit below:

Quoted 55 lines
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}
 }
 
Quoted 4 lines

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 102

Quoted 1 line
mm/page_ext.c +1 -0
+#if !defined(CONFIG_SPARSEMEM)

#ifndef is more common if you don't need boolean ops on multiple configs

Thanks, I'll do the change in patchset v2

Quoted 21 lines
Quoted 19 lines
mm/page_ext.c +6 -0
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long
 index)
 {
mm/page_ext.c +0 -1
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
reviewer
#3 lore raw
In reply to Zhenhua Huang
Quoted 9 lines · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32 targets. The reason is dummy_handle and failure_handle is not initialized correctly. Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that by initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).

Is anything that requires a memblock allocation FLATMEM?
Any fundamental reason why wouldn't alloc_pages_exact_nid/vzalloc_node() work in this case?

It seems to me that for FLATMEM configuration we can allocate the page_ext using alloc_pages() with a fallback to vzalloc_node() and then we can unify lot's of page_ext code and entirely drop page_ext_init_flatmem().

Quoted 99 lines

2. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid 1006, ts 67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +7 -1
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long index)
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Signature · 2 lines
Sincerely yours,
Mike.
#4 lore raw

Hi Mike,

Quoted 14 lines · Mike Rapoport
Quoted 1 line · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32

targets.

Quoted 1 line

The reason is dummy_handle and failure_handle is not initialized

correctly.

Quoted 2 lines

Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that

by

Quoted 5 lines

initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).

Quoted 8 lines

Is anything that requires a memblock allocation FLATMEM?
Any fundamental reason why wouldn't alloc_pages_exact_nid/vzalloc_node() work in this case?

It seems to me that for FLATMEM configuration we can allocate the page_ext using alloc_pages() with a fallback to vzalloc_node() and then we can unify lot's of page_ext code and entirely drop page_ext_init_flatmem().

From comments in codes: "page_ext requires contiguous pages, bigger than MAX_ORDER unless SPARSEMEM."
The size of page_ext for FLATMEM(which used pgdat) should be much larger than the size for SPARSEMEM which used section.

Quoted 108 lines
Quoted 11 lines

2. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

Quoted 3 lines

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid

1006, ts

Quoted 61 lines

67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 109

Quoted 10 lines
mm/page_ext.c +7 -0
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long

index)

Quoted 12 lines
mm/page_ext.c +0 -1
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

Quoted 3 lines

a Linux Foundation Collaborative Project

Signature · 2 lines
Sincerely yours,
Mike.
reviewer
#5 lore raw
Quoted 26 lines · Zhenhua Huang

Hi Mike,

Quoted 14 lines · Mike Rapoport
Quoted 1 line · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32

targets.

Quoted 1 line

The reason is dummy_handle and failure_handle is not initialized

correctly.

Quoted 2 lines

Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that

by

Quoted 5 lines

initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).

Quoted 8 lines

Is anything that requires a memblock allocation FLATMEM?
Any fundamental reason why wouldn't alloc_pages_exact_nid/vzalloc_node() work in this case?

It seems to me that for FLATMEM configuration we can allocate the page_ext using alloc_pages() with a fallback to vzalloc_node() and then we can unify lot's of page_ext code and entirely drop page_ext_init_flatmem().

Quoted 4 lines

From comments in codes: "page_ext requires contiguous pages, bigger than MAX_ORDER unless SPARSEMEM."
The size of page_ext for FLATMEM(which used pgdat) should be much larger than the size for SPARSEMEM which used section.

Well, the vzalloc_node() fallback in alloc_page_ext() for SPARSEMEM case implies that using pages that are not physically contiguous should be fine. So, it seems to me that the comment is stale and vzalloc_node() would work just fine for FLATMEM case if the allocation of page_ext would exceed MAX_ORDER.

Quoted 107 lines
Quoted 107 lines
Quoted 10 lines

2. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

Quoted 3 lines

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid

1006, ts

Quoted 61 lines

67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 109

Quoted 10 lines
mm/page_ext.c +7 -0
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long

index)

Quoted 12 lines
mm/page_ext.c +0 -1
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

Quoted 3 lines

a Linux Foundation Collaborative Project

Signature · 2 lines
Sincerely yours,
Mike.
Signature · 2 lines
Sincerely yours,
Mike.
#6 lore raw
Quoted 35 lines · Mike Rapoport
Quoted 5 lines · Zhenhua Huang

Hi Mike,

Quoted 2 lines · Mike Rapoport
Quoted 1 line · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on

arm32

Quoted 4 lines
Quoted 4 lines

targets.

Quoted 1 line

The reason is dummy_handle and failure_handle is not initialized

correctly.

Quoted 1 line

Buddy allocator is used to initialize these two handles. However,

buddy

Quoted 1 line
Quoted 1 line
Quoted 1 line

allocator is not ready when page owner calls it. This change fixed

that

Quoted 9 lines
Quoted 9 lines

by

Quoted 5 lines

initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).

Is anything that requires a memblock allocation FLATMEM? Any fundamental reason why wouldn't

alloc_pages_exact_nid/vzalloc_node()

Quoted 4 lines
Quoted 4 lines

work in this case?

It seems to me that for FLATMEM configuration we can allocate the page_ext using alloc_pages() with a fallback to vzalloc_node() and

then

Quoted 6 lines
Quoted 2 lines

we can unify lot's of page_ext code and entirely drop page_ext_init_flatmem().

From comments in codes: "page_ext requires contiguous pages, bigger than MAX_ORDER unless SPARSEMEM."
The size of page_ext for FLATMEM(which used pgdat) should be much larger

Quoted 9 lines

than

Quoted 1 line

the size for SPARSEMEM which used section.

Well, the vzalloc_node() fallback in alloc_page_ext() for SPARSEMEM case implies that using pages that are not physically contiguous should be fine. So, it seems to me that the comment is stale and vzalloc_node() would work just fine for FLATMEM case if the allocation of page_ext would exceed MAX_ORDER.

Thanks Mike, got it. I agree with you for this point. I also haven't got why it needs physical continuous... and haven't found detailed commit message explained it.

Quoted 113 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

2. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN),

pid

Quoted 94 lines
Quoted 94 lines

1006, ts

Quoted 61 lines

67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 109

Quoted 10 lines
mm/page_ext.c +7 -0
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long

index)

Quoted 12 lines
mm/page_ext.c +0 -1
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

Quoted 3 lines

a Linux Foundation Collaborative Project

Signature · 2 lines
Sincerely yours,
Mike.
Signature · 2 lines
Sincerely yours,
Mike.
#7 lore raw
In reply to Mike Rapoport

Hi Mike,

Quoted 14 lines · Mike Rapoport
Quoted 1 line · Zhenhua Huang

Page owner of pages used by page owner itself used is missing on arm32

targets.

Quoted 1 line

The reason is dummy_handle and failure_handle is not initialized

correctly.

Quoted 2 lines

Buddy allocator is used to initialize these two handles. However, buddy allocator is not ready when page owner calls it. This change fixed that

by

Quoted 5 lines

initializing page owner after buddy initialization.

The working flow before and after this change are:
original logic:
1. allocated memory for page_ext(using memblock).

Quoted 9 lines

Is anything that requires a memblock allocation FLATMEM?
Any fundamental reason why wouldn't alloc_pages_exact_nid/vzalloc_node() work in this case?

It seems to me that for FLATMEM configuration we can allocate the page_ext using alloc_pages() with a fallback to vzalloc_node() and then we can unify lot's of page_ext code and entirely drop page_ext_init_flatmem().

From comments in codes: "page_ext requires contiguous pages, bigger than MAX_ORDER unless SPARSEMEM."
The size of page_ext for FLATMEM(which used pgdat) should be much larger than the size for SPARSEMEM which used section.

Quoted 107 lines
Quoted 10 lines

2. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).
3. initialize buddy.

after this change:
1. allocated memory for page_ext(using memblock).
2. initialize buddy.
3. invoke the init callback of page_ext_ops like
page_owner(using buddy allocator).

Quoted 3 lines

with the change, failure/dummy_handle can get its correct value and page owner output for example has the one for page owner itself:
Page allocated via order 2, mask 0x6202c0(GFP_USER|__GFP_NOWARN), pid

1006, ts

Quoted 61 lines

67278156558 ns
PFN 543776 type Unmovable Block 531 type Unmovable Flags 0x0()

 init_page_owner+0x28/0x2f8
 invoke_init_callbacks_flatmem+0x24/0x34
 start_kernel+0x33c/0x5d8
   (null)
---
 include/linux/page_ext.h | 8 ++++++++
 init/main.c              | 2 ++
 mm/page_ext.c            | 8 +++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)
include/linux/page_ext.h +8 -0
index cfce186..aff81ba 100644
@@ -44,8 +44,12 @@ static inline void page_ext_init_flatmem(void)
 {
 }
 extern void page_ext_init(void);
+static inline void page_ext_init_flatmem_late(void)
+{
+}
 #else
 extern void page_ext_init_flatmem(void);
+extern void page_ext_init_flatmem_late(void);
 static inline void page_ext_init(void)
 {
 }
@@ -76,6 +80,10 @@ static inline void page_ext_init(void)
 {
 }
 
+static inline void page_ext_init_flatmem_late(void)
+{
+}
+
 static inline void page_ext_init_flatmem(void)
 {
 }
init/main.c +2 -0
index 130376e..b34c475 100644
@@ -818,6 +818,8 @@ static void __init mm_init(void)
 	init_debug_pagealloc();
 	report_meminit();
 	mem_init();
+	/* page_owner must be initialized after buddy is ready */
+	page_ext_init_flatmem_late();
 	kmem_cache_init();
 	kmemleak_init();
 	pgtable_init();
mm/page_ext.c +0 -0
index a3616f7..373f7a1 100644
@@ -99,6 +99,13 @@ static void __init invoke_init_callbacks(void)
 	}

mm/page_ext.c static void __init invoke_init_callbacks(void) · line 109

Quoted 10 lines
mm/page_ext.c +7 -0
 }
 
+#if !defined(CONFIG_SPARSEMEM)
+void __init page_ext_init_flatmem_late(void)
+{
+	invoke_init_callbacks();
+}
+#endif
+
 static inline struct page_ext *get_entry(void *base, unsigned long

index)

Quoted 12 lines
mm/page_ext.c +0 -1
 {
 	return base + page_ext_size * index;
@@ -177,7 +184,6 @@ void __init page_ext_init_flatmem(void)
 			goto fail;
 	}
 	pr_info("allocated %ld bytes of page_ext\n", total_usage);
-	invoke_init_callbacks();
 	return;
 
 fail:
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

Quoted 3 lines

a Linux Foundation Collaborative Project

Signature · 2 lines
Sincerely yours,
Mike.