Skip to contentSkip to conversation

mm/memblock: introduce a new helper memblock_estimated_nr_free_pages()

PATCH Superseded Wei Yang 2 participants 6 messages Jul 8, 2024 – Jul 9, 2024

Subsystems (5)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore

Wei Yang

author
#0 lore raw

PATCH v4 1/3 mm/memblock: introduce a new helper memblock_estimated_nr_free_pages()

During bootup, system may need the number of free pages in the whole system to do some calculation before all pages are freed to buddy system. Usually this number is get from totalram_pages(). Since we plan to move the free pages accounting in __free_pages_core(), this value may not represent total free pages at the early stage, especially when CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled.

Instead of using raw memblock api, let's introduce a new helper for user to get the estimated number of free pages from memblock point of view.

---
v4: adjust comment per david's suggestion

---
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+)
include/linux/memblock.h +1 -0
index 40c62aca36ec..7d1c32b3dc12 100644
@@ -486,6 +486,7 @@ static inline __init_memblock bool memblock_bottom_up(void)
 
 phys_addr_t memblock_phys_mem_size(void);
 phys_addr_t memblock_reserved_size(void);
+unsigned long memblock_estimated_nr_pages(void);
 phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
mm/memblock.c +20 -0
index e81fb68f7f88..26162902789f 100644
@@ -1729,6 +1729,26 @@ phys_addr_t __init_memblock memblock_reserved_size(void)
 	return memblock.reserved.total_size;
 }
 
+/**
+ * memblock_estimated_nr_free_pages - return estimated number of free pages
+ * from memblock point of view
+ *
+ * During bootup, subsystems might need a rough estimate of the number of free
+ * pages in the whole system, before precise numbers are available from the
+ * buddy. Especially with CONFIG_DEFERRED_STRUCT_PAGE_INIT, the numbers
+ * obtained from the buddy might be very imprecise during bootup.
+ *
+ * While we can get the estimated number of free pages from memblock, which is
+ * good enough for estimation.
+ *
+ * Return:
+ * An estimated number of free pages from memblock point of view.
+ */
+unsigned long __init memblock_estimated_nr_free_pages(void)
+{
+	return PHYS_PFN(memblock_phys_mem_size() - memblock_reserved_size());
+}
+
 /* lowest address */
 phys_addr_t __init_memblock memblock_start_of_DRAM(void)
 {
Signature · 1 line
2.34.1
author
#1 lore raw

PATCH v4 2/3 kernel/fork.c: get totalram_pages from memblock to calculate max_threads

Since we plan to move the accounting into __free_pages_core(), totalram_pages may not represent the total usable pages on system at this point when defer_init is enabled.

Instead we can get the total estimated pages from memblock directly.

CC Mike Rapoport (IBM) <[email protected]>
CC David Hildenbrand <[email protected]>
CC Oleg Nesterov <[email protected]>
---
 kernel/fork.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/fork.c +2 -1
index 99076dbe27d8..e80e889543f3 100644
@@ -44,6 +44,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/mm_inline.h>
+#include <linux/memblock.h>
 #include <linux/nsproxy.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
@@ -999,7 +1000,7 @@ void __init __weak arch_task_cache_init(void) { }
 static void set_max_threads(unsigned int max_threads_suggested)
 {
 	u64 threads;
-	unsigned long nr_pages = totalram_pages();
+	unsigned long nr_pages = memblock_estimated_nr_pages();
 
 	/*
 	 * The number of threads shall be limited such that the thread
Signature · 1 line
2.34.1
#2 lore raw

Re: [PATCH v4 2/3] kernel/fork.c: get totalram_pages from memblock to calculate max_threads

Quoted 27 lines · Wei Yang

Since we plan to move the accounting into __free_pages_core(), totalram_pages may not represent the total usable pages on system at this point when defer_init is enabled.

Instead we can get the total estimated pages from memblock directly.

CC Mike Rapoport (IBM) <[email protected]>
CC David Hildenbrand <[email protected]>
CC Oleg Nesterov <[email protected]>
---
  kernel/fork.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
kernel/fork.c +1 -0
index 99076dbe27d8..e80e889543f3 100644
@@ -44,6 +44,7 @@
  #include <linux/fs.h>
  #include <linux/mm.h>
  #include <linux/mm_inline.h>
+#include <linux/memblock.h>
  #include <linux/nsproxy.h>
  #include <linux/capability.h>
  #include <linux/cpu.h>

kernel/fork.c void __init __weak arch_task_cache_init(void) { } · line 1003

Quoted 5 lines
kernel/fork.c +1 -1
@@ -999,7 +1000,7 @@ void __init __weak arch_task_cache_init(void) { }
  static void set_max_threads(unsigned int max_threads_suggested)
  {
  	u64 threads;
-	unsigned long nr_pages = totalram_pages();
+	unsigned long nr_pages = memblock_estimated_nr_pages();

Stale name

Signature · 3 lines
Cheers,

David / dhildenb
author
#3 lore raw

PATCH v4 3/3 kernel/fork.c: put set_max_threads()/task_struct_whitelist() in __init section

In reply to Wei Yang

Function set_max_threads()/task_struct_whitelist() is only used by fork_init() during bootup.

Let's add __init tag to them.

---
 kernel/fork.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/fork.c +2 -2
index e80e889543f3..da0b4545d380 100644
@@ -997,7 +997,7 @@ void __init __weak arch_task_cache_init(void) { }
 /*
  * set_max_threads
  */
-static void set_max_threads(unsigned int max_threads_suggested)
+static void __init set_max_threads(unsigned int max_threads_suggested)
 {
 	u64 threads;
 	unsigned long nr_pages = memblock_estimated_nr_pages();
@@ -1023,7 +1023,7 @@ static void set_max_threads(unsigned int max_threads_suggested)
 int arch_task_struct_size __read_mostly;
 #endif
 
-static void task_struct_whitelist(unsigned long *offset, unsigned long *size)
+static void __init task_struct_whitelist(unsigned long *offset, unsigned long *size)
 {
 	/* Fetch thread_struct whitelist for the architecture. */
 	arch_thread_struct_whitelist(offset, size);
Signature · 1 line
2.34.1
#4 lore raw
In reply to Wei Yang
Quoted 26 lines · Wei Yang

During bootup, system may need the number of free pages in the whole system to do some calculation before all pages are freed to buddy system. Usually this number is get from totalram_pages(). Since we plan to move the free pages accounting in __free_pages_core(), this value may not represent total free pages at the early stage, especially when CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled.

Instead of using raw memblock api, let's introduce a new helper for user to get the estimated number of free pages from memblock point of view.

---
v4: adjust comment per david's suggestion

---
  include/linux/memblock.h |  1 +
  mm/memblock.c            | 20 ++++++++++++++++++++
  2 files changed, 21 insertions(+)
include/linux/memblock.h +0 -0
index 40c62aca36ec..7d1c32b3dc12 100644

include/linux/memblock.h static inline __init_memblock bool memblock_bottom_up(void) · line 489

Quoted 4 lines
include/linux/memblock.h +1 -0
@@ -486,6 +486,7 @@ static inline __init_memblock bool memblock_bottom_up(void)
 
  phys_addr_t memblock_phys_mem_size(void);
  phys_addr_t memblock_reserved_size(void);
+unsigned long memblock_estimated_nr_pages(void);

^ stale name

Quoted 12 lines
include/linux/memblock.h +0 -0
  phys_addr_t memblock_start_of_DRAM(void);
  phys_addr_t memblock_end_of_DRAM(void);
  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
mm/memblock.c +1 -0
index e81fb68f7f88..26162902789f 100644
@@ -1729,6 +1729,26 @@ phys_addr_t __init_memblock memblock_reserved_size(void)
  	return memblock.reserved.total_size;
  }
 
+/**

mm/memblock.c phys_addr_t __init_memblock memblock_reserved_size(void) · line 1742

Quoted 10 lines
mm/memblock.c +10 -0
+ * memblock_estimated_nr_free_pages - return estimated number of free pages
+ * from memblock point of view
+ *
+ * During bootup, subsystems might need a rough estimate of the number of free
+ * pages in the whole system, before precise numbers are available from the
+ * buddy. Especially with CONFIG_DEFERRED_STRUCT_PAGE_INIT, the numbers
+ * obtained from the buddy might be very imprecise during bootup.
+ *
+ * While we can get the estimated number of free pages from memblock, which is
+ * good enough for estimation.

I'd drop that sentence.

Apart form that LGTM

Signature · 3 lines
Cheers,

David / dhildenb
author
#5 lore raw
Quoted 22 lines · David Hildenbrand
Quoted 21 lines · Wei Yang

During bootup, system may need the number of free pages in the whole system to do some calculation before all pages are freed to buddy system. Usually this number is get from totalram_pages(). Since we plan to move the free pages accounting in __free_pages_core(), this value may not represent total free pages at the early stage, especially when CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled.

Instead of using raw memblock api, let's introduce a new helper for user to get the estimated number of free pages from memblock point of view.

---
v4: adjust comment per david's suggestion

---
  include/linux/memblock.h |  1 +
  mm/memblock.c            | 20 ++++++++++++++++++++
  2 files changed, 21 insertions(+)
Quoted 10 lines

include/linux/memblock.h static inline __init_memblock bool memblock_bottom_up(void) · line 488

Quoted 8 lines
include/linux/memblock.h +1 -0
index 40c62aca36ec..7d1c32b3dc12 100644
@@ -486,6 +486,7 @@ static inline __init_memblock bool memblock_bottom_up(void)
  phys_addr_t memblock_phys_mem_size(void);
  phys_addr_t memblock_reserved_size(void);
+unsigned long memblock_estimated_nr_pages(void);

^ stale name

My bad.

Quoted 16 lines
Quoted 16 lines
include/linux/memblock.h +0 -0
  phys_addr_t memblock_start_of_DRAM(void);
  phys_addr_t memblock_end_of_DRAM(void);
  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
mm/memblock.c +5 -0
index e81fb68f7f88..26162902789f 100644
@@ -1729,6 +1729,26 @@ phys_addr_t __init_memblock memblock_reserved_size(void)
  	return memblock.reserved.total_size;
  }
+/**
+ * memblock_estimated_nr_free_pages - return estimated number of free pages
+ * from memblock point of view
+ *
+ * During bootup, subsystems might need a rough estimate of the number of free
Quoted 9 lines

mm/memblock.c phys_addr_t __init_memblock memblock_reserved_size(void) · line 1742

Quoted 6 lines
mm/memblock.c +6 -0
+ * pages in the whole system, before precise numbers are available from the
+ * buddy. Especially with CONFIG_DEFERRED_STRUCT_PAGE_INIT, the numbers
+ * obtained from the buddy might be very imprecise during bootup.
+ *
+ * While we can get the estimated number of free pages from memblock, which is
+ * good enough for estimation.

I'd drop that sentence.

Will update it.

Quoted 7 lines

Apart form that LGTM

Signature · 3 lines
Cheers,

David / dhildenb
Signature · 2 lines
Wei Yang
Help you, Help me