Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/hugetlb: cleanup hugetlb_folio_init_tail_vmemmap()

We can now safely iterate over all pages in a folio, so no need for the
pfn_to_page().

Also, as we already force the refcount in __init_single_page() to 1
through init_page_count(), we can just set the refcount to 0 and avoid
page_ref_freeze() + VM_BUG_ON. Likely, in the future, we would just want
to tell __init_single_page() to which value to initialize the refcount.

Further, adjust the comments to highlight that we are dealing with an
open-coded prep_compound_page() variant, and add another comment
explaining why we really need the __init_single_page() only on the tail
pages.

Note that the current code was likely problematic, but we never ran into
it: prep_compound_tail() would have been called with an offset that might
exceed a memory section, and prep_compound_tail() would have simply added
that offset to the page pointer -- which would not have done the right
thing on sparsemem without vmemmap.

Link: https://lkml.kernel.org/r/20250901150359.867252-14-david@redhat.com
Signed-off-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Acked-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

David Hildenbrand and committed by
Andrew Morton
372c9b54 73b3294b

+12 -8
+12 -8
mm/hugetlb.c
··· 3237 3237 { 3238 3238 enum zone_type zone = zone_idx(folio_zone(folio)); 3239 3239 int nid = folio_nid(folio); 3240 + struct page *page = folio_page(folio, start_page_number); 3240 3241 unsigned long head_pfn = folio_pfn(folio); 3241 3242 unsigned long pfn, end_pfn = head_pfn + end_page_number; 3242 - int ret; 3243 3243 3244 - for (pfn = head_pfn + start_page_number; pfn < end_pfn; pfn++) { 3245 - struct page *page = pfn_to_page(pfn); 3246 - 3244 + /* 3245 + * As we marked all tail pages with memblock_reserved_mark_noinit(), 3246 + * we must initialize them ourselves here. 3247 + */ 3248 + for (pfn = head_pfn + start_page_number; pfn < end_pfn; page++, pfn++) { 3247 3249 __init_single_page(page, pfn, zone, nid); 3248 3250 prep_compound_tail((struct page *)folio, pfn - head_pfn); 3249 - ret = page_ref_freeze(page, 1); 3250 - VM_BUG_ON(!ret); 3251 + set_page_count(page, 0); 3251 3252 } 3252 3253 } 3253 3254 ··· 3258 3257 { 3259 3258 int ret; 3260 3259 3261 - /* Prepare folio head */ 3260 + /* 3261 + * This is an open-coded prep_compound_page() whereby we avoid 3262 + * walking pages twice by initializing/preparing+freezing them in the 3263 + * same go. 3264 + */ 3262 3265 __folio_clear_reserved(folio); 3263 3266 __folio_set_head(folio); 3264 3267 ret = folio_ref_freeze(folio, 1); 3265 3268 VM_BUG_ON(!ret); 3266 - /* Initialize the necessary tail struct pages */ 3267 3269 hugetlb_folio_init_tail_vmemmap(folio, 1, nr_pages); 3268 3270 prep_compound_head((struct page *)folio, huge_page_order(h)); 3269 3271 }