From: Muchun Song <songmuchun@bytedance.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Oscar Salvador <osalvador@suse.de>,
David Hildenbrand <david@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>,
Vlastimil Babka <vbabka@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>, Michal Hocko <mhocko@suse.com>,
David Laight <david.laight.linux@gmail.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Muchun Song <songmuchun@bytedance.com>,
Muchun Song <muchun.song@linux.dev>
Subject: [PATCH v3 01/17] mm/sparse: relax struct mem_section size constraints
Date: Tue, 4 Aug 2026 11:55:19 +0800 [thread overview]
Message-ID: <20260804035535.2846016-2-songmuchun@bytedance.com> (raw)
In-Reply-To: <20260804035535.2846016-1-songmuchun@bytedance.com>
struct mem_section is currently forced to a power-of-2 size so the
section-to-root lookup can use a mask instead of a modulo.
That requirement makes future extensions harder than necessary: adding a
small field can require configuration-dependent padding or layout checks
just to preserve the lookup scheme. Keep the lookup correct for any
struct mem_section size by using a plain modulo instead.
Do not leave the layout entirely unconstrained, though. Keep struct
mem_section double-word aligned so modest size changes, such as adding
another word-sized field on 64-bit systems, still keep a compact and
efficient layout. If future fields grow the structure beyond that sweet
spot, the lookup remains correct; only the exact layout efficiency
changes.
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
v2:
- Align struct mem_section to power-of-2 where possible, but support
non-power-of-2 lookup (suggested by David Laight)
- Collect Acked-by from Mike Rapoport
---
include/linux/mmzone.h | 11 +++--------
mm/sparse.c | 2 --
scripts/gdb/linux/mm.py | 6 ++----
3 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index a26c8b855222..acf02c87900b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2028,13 +2028,9 @@ struct mem_section {
* section. (see page_ext.h about this.)
*/
struct page_ext *page_ext;
- unsigned long pad;
#endif
- /*
- * WARNING: mem_section must be a power-of-2 in size for the
- * calculation and use of SECTION_ROOT_MASK to make sense.
- */
-};
+/* Sacrifice minor padding space for efficient lookup. */
+} __aligned(2 * sizeof(unsigned long));
#ifdef CONFIG_SPARSEMEM_EXTREME
#define SECTIONS_PER_ROOT (PAGE_SIZE / sizeof (struct mem_section))
@@ -2044,7 +2040,6 @@ struct mem_section {
#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT)
#define NR_SECTION_ROOTS DIV_ROUND_UP(NR_MEM_SECTIONS, SECTIONS_PER_ROOT)
-#define SECTION_ROOT_MASK (SECTIONS_PER_ROOT - 1)
#ifdef CONFIG_SPARSEMEM_EXTREME
extern struct mem_section **mem_section;
@@ -2068,7 +2063,7 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
if (!mem_section || !mem_section[root])
return NULL;
#endif
- return &mem_section[root][nr & SECTION_ROOT_MASK];
+ return &mem_section[root][nr % SECTIONS_PER_ROOT];
}
extern size_t mem_section_usage_size(void);
diff --git a/mm/sparse.c b/mm/sparse.c
index 704a9dec2b9a..ca9875f568d3 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -332,8 +332,6 @@ void __init sparse_init(void)
unsigned long pnum_end, pnum_begin, map_count = 1;
int nid_begin;
- /* see include/linux/mmzone.h 'struct mem_section' definition */
- BUILD_BUG_ON(!is_power_of_2(sizeof(struct mem_section)));
memblocks_present();
if (compound_info_has_mask()) {
diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py
index dffadccbb01d..da4e8e9655a6 100644
--- a/scripts/gdb/linux/mm.py
+++ b/scripts/gdb/linux/mm.py
@@ -70,7 +70,6 @@ class x86_page_ops():
self.SECTIONS_PER_ROOT = 1
self.NR_SECTION_ROOTS = DIV_ROUND_UP(self.NR_MEM_SECTIONS, self.SECTIONS_PER_ROOT)
- self.SECTION_ROOT_MASK = self.SECTIONS_PER_ROOT - 1
try:
self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
@@ -100,7 +99,7 @@ class x86_page_ops():
def __nr_to_section(self, nr):
root = self.SECTION_NR_TO_ROOT(nr)
mem_section = gdb.parse_and_eval("mem_section")
- return mem_section[root][nr & self.SECTION_ROOT_MASK]
+ return mem_section[root][nr % self.SECTIONS_PER_ROOT]
def pfn_to_section_nr(self, pfn):
return pfn >> self.PFN_SECTION_SHIFT
@@ -249,7 +248,6 @@ class aarch64_page_ops():
self.SECTIONS_PER_ROOT = 1
self.NR_SECTION_ROOTS = DIV_ROUND_UP(self.NR_MEM_SECTIONS, self.SECTIONS_PER_ROOT)
- self.SECTION_ROOT_MASK = self.SECTIONS_PER_ROOT - 1
self.SUBSECTION_SHIFT = 21
self.SEBSECTION_SIZE = 1 << self.SUBSECTION_SHIFT
self.PFN_SUBSECTION_SHIFT = self.SUBSECTION_SHIFT - self.PAGE_SHIFT
@@ -304,7 +302,7 @@ class aarch64_page_ops():
def __nr_to_section(self, nr):
root = self.SECTION_NR_TO_ROOT(nr)
mem_section = gdb.parse_and_eval("mem_section")
- return mem_section[root][nr & self.SECTION_ROOT_MASK]
+ return mem_section[root][nr % self.SECTIONS_PER_ROOT]
def pfn_to_section_nr(self, pfn):
return pfn >> self.PFN_SECTION_SHIFT
--
2.54.0
next prev parent reply other threads:[~2026-08-04 3:55 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 3:55 [PATCH v3 00/17] mm: Introduce section-based vmemmap optimization for HugeTLB Muchun Song
2026-08-04 3:55 ` Muchun Song [this message]
2026-08-04 3:55 ` [PATCH v3 02/17] mm/sparse-vmemmap: rename HVO order macros Muchun Song
2026-08-04 3:55 ` [PATCH v3 03/17] mm/mm_init: skip initializing shared vmemmap tail pages Muchun Song
2026-08-04 3:55 ` [PATCH v3 04/17] mm/sparse-vmemmap: initialize shared tail vmemmap pages on allocation Muchun Song
2026-08-04 3:55 ` [PATCH v3 05/17] mm/sparse-vmemmap: support section-based vmemmap accounting Muchun Song
2026-08-04 3:55 ` [PATCH v3 06/17] mm/mm_init: factor out pfn_to_zone() Muchun Song
2026-08-04 3:55 ` [PATCH v3 07/17] mm/sparse-vmemmap: move vmemmap_get_tail() before PTE population Muchun Song
2026-08-04 3:55 ` [PATCH v3 08/17] mm/sparse-vmemmap: support section-based vmemmap optimization Muchun Song
2026-08-06 3:04 ` Muchun Song
2026-08-04 3:55 ` [PATCH v3 09/17] mm/sparse: initialize memory sections earlier Muchun Song
2026-08-04 3:55 ` [PATCH v3 10/17] mm/hugetlb: switch HugeTLB to section-based vmemmap optimization Muchun Song
2026-08-04 3:55 ` [PATCH v3 11/17] mm/sparse-vmemmap: remove SPARSEMEM_VMEMMAP_PREINIT support Muchun Song
2026-08-04 3:55 ` [PATCH v3 12/17] mm/sparse: inline usemap allocation into sparse_init_nid() Muchun Song
2026-08-04 3:55 ` [PATCH v3 13/17] mm/sparse: remove section_map_size() Muchun Song
2026-08-04 3:55 ` [PATCH v3 14/17] mm/hugetlb: remove HUGE_BOOTMEM_HVO Muchun Song
2026-08-04 3:55 ` [PATCH v3 15/17] mm/hugetlb: remove HUGE_BOOTMEM_CMA Muchun Song
2026-08-04 3:55 ` [PATCH v3 16/17] mm/hugetlb: localize struct huge_bootmem_page Muchun Song
2026-08-04 3:55 ` [PATCH v3 17/17] mm/hugetlb: localize HUGE_BOOTMEM_ZONES_VALID Muchun Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804035535.2846016-2-songmuchun@bytedance.com \
--to=songmuchun@bytedance.com \
--cc=akpm@linux-foundation.org \
--cc=david.laight.linux@gmail.com \
--cc=david@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=muchun.song@linux.dev \
--cc=osalvador@suse.de \
--cc=rppt@kernel.org \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox