Re: [PATCH RFC 18/19] mm/page_alloc: implement __GFP_UNMAPPED|__GFP_ZERO allocations

From: Brendan Jackman

Date: Fri Feb 27 2026 - 06:04:51 EST


On Wed Feb 25, 2026 at 4:34 PM UTC, Brendan Jackman wrote:

> +static inline void clear_page_mermap(struct page *page, unsigned int numpages)
> +{
> + void *mermap;
> +
> + BUILD_BUG_ON(IS_ENABLED(CONFIG_HIGHMEM));
> +
> + /* Fast path: single mapping (may fail under preemption). */
> + mermap = mermap_get(page, numpages << PAGE_SHIFT, PAGE_KERNEL_NOGLOBAL);
> + if (mermap) {
> + void *buf = kasan_reset_tag(mermap_addr(mermap));
> +
> + for (int i = 0; i < numpages; i++)
> + clear_page(buf + (i << PAGE_SHIFT));
> + mermap_put(mermap);
> + return;
> + }
> +
> + /* Slow path, map each page individually (always succeeds). */
> + for (int i = 0; i < numpages; i++) {
> + unsigned long flags;
> +
> + local_irq_save(flags);
> + mermap = mermap_get_reserved(page + i, PAGE_KERNEL);

Oh, that should be PAGE_KERNEL_NONGLOBAL. I think this means I never
tested this path as this will crash - mermap_get_reserved() will WARN()
and return NULL and then we'll dereference that below.

Maybe that's a bad idea, maybe it should WARN() but serve the request
anyway.

Anyway maybe I need to support failure injection to test the fallback path.

> + clear_page(kasan_reset_tag(mermap_addr(mermap)));
> + mermap_put(mermap);
> + local_irq_restore(flags);
> + }
> +}
> +#else
> +static inline bool pageblock_unmapped(struct page *page)
> +{
> + return false;
> +}
> +
> +static inline void clear_page_mermap(struct page *page, unsigned int numpages)
> +{
> + BUG();
> +}
> +#endif
> +
> +static void kernel_init_pages(struct page *page, unsigned int numpages)
> +{
> + int num_blocks = DIV_ROUND_UP(numpages, pageblock_nr_pages);
> +
> + for (int block = 0; block < num_blocks; block++) {
> + struct page *block_page = page + (block << pageblock_order);
> + bool unmapped = pageblock_unmapped(block_page);
> +
> + /* s390's use of memset() could override KASAN redzones. */
> + kasan_disable_current();
> + if (unmapped) {
> + clear_page_mermap(page, numpages);

That should be clearing block_page.

> + } else {
> + for (int i = 0; i < min(numpages, pageblock_nr_pages); i++)
> + clear_highpage_kasan_tagged(block_page + i);
> + }
> + kasan_enable_current();
> +
> + numpages -= pageblock_nr_pages;
> + }
> }