Subject: Re: [PATCH v8 00/37] mm/virtio: skip redundant zeroing of host-zeroed pages

From: "Michael S. Tsirkin" <[email-masked]>
Date: Thu, 21 May 2026 10:09:11 -0400

On Wed, May 20, 2026 at 06:20:13PM -0400, Michael S. Tsirkin wrote:
> When a guest reports free pages to the hypervisor via virtio-balloon's
> free page reporting, the host typically zeros those pages when reclaiming
> their backing memory (e.g., via MADV_DONTNEED on anonymous mappings).
> When the guest later reallocates those pages, the kernel zeros them
> again, redundantly.

FYI Sashiko reported a couple of issues. Mostly false positives but
I tweaked commit log to make it clearer. But also a couple of
real issues. So far I have this diff on top:

--->

Changes from v8 to v9 candidate (code only):

1. mm/mempolicy.c (patch 1: mm: mempolicy: fix interleave index calculation)
   Combine vm_pgoff and VMA offset into a single expression before
   shifting, fixing carry loss for file-backed VMAs with unaligned
   vm_pgoff.

2. mm/memory-failure.c (patch 2: mm: memory-failure: serialize TestSetPageHWPoison with zone->lock)
   Wrap ClearPageHWPoison in retry path with zone->lock too.

3. mm/huge_memory.c (patch 19: mm: use __GFP_ZERO in vma_alloc_anon_folio_pmd)
   Fix stale comment: "folio_zero_user writes" -> "page zeroing".

4. mm/page_reporting.c (patch 4: mm: page_reporting: allow driver to set batch capacity)
   Drop rounddown_pow_of_two: compiler cannot optimize division
   by runtime variable anyway, and rounding halves batch size for
   non-power-of-2 capacity values.

Commit log improvements (no code change):
- Patch 1: rewritten to explain new single-expression formula (fixes patch 1)
- Patch 2: mention ClearPageHWPoison in retry path (fixes patch 2)
- Patch 4: drop "rounded down to a power of 2" (fixes patch 4)
- Patch 10: "stub" wording simplified (fixes patch 10)
- Patch 22: note PG_zeroed hint loss is harmless (fixes patch 22)
- Patch 23: add PowerPC note (fixes patch 23)
- Patch 28: explain DEVICE_INIT_ON_INFLATE is a follow-up (fixes patch 28)
- Patch 29: explain flush over-reporting is by design (fixes patch 29)
- Patch 33: note __SetPageZeroed is safe on frozen pages (fixes patch 33)
- Patch 36: note __SetPageZeroed is safe on balloon-owned pages (fixes patch 36)

---

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 9845c920c29c..4978d34532ea 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1358,7 +1358,7 @@ static struct folio *vma_alloc_anon_folio_pmd(struct vm_area_struct *vma,
 
 	/*
 	 * The memory barrier inside __folio_mark_uptodate makes sure that
-	 * folio_zero_user writes become visible before the set_pmd_at()
+	 * page zeroing becomes visible before the set_pmd_at()
 	 * write.
 	 */
 	__folio_mark_uptodate(folio);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index a6b61172dd13..d106f2c135c7 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2426,7 +2426,9 @@ int memory_failure(unsigned long pfn, int flags)
 			} else {
 				/* We lost the race, try again */
 				if (retry) {
+					spin_lock_irqsave(&zone->lock, mf_flags);
 					ClearPageHWPoison(p);
+					spin_unlock_irqrestore(&zone->lock, mf_flags);
 					retry = false;
 					goto try_again;
 				}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index ea3043e0075b..f573ff32e94d 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2048,9 +2048,9 @@ struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
 		pol = get_task_policy(current);
 	if (pol->mode == MPOL_INTERLEAVE ||
 	    pol->mode == MPOL_WEIGHTED_INTERLEAVE) {
-		*ilx += vma->vm_pgoff >> order;
-		*ilx += (addr >> (PAGE_SHIFT + order)) -
-			(vma->vm_start >> (PAGE_SHIFT + order));
+		*ilx += (vma->vm_pgoff +
+			(addr >> PAGE_SHIFT) -
+			(vma->vm_start >> PAGE_SHIFT)) >> order;
 	}
 	return pol;
 }
diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index 8b278a494ea5..3f584f538c68 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -443,9 +443,6 @@ int page_reporting_register(struct page_reporting_dev_info *prdev)
 	if (!prdev->capacity || prdev->capacity > PAGE_REPORTING_CAPACITY)
 		prdev->capacity = PAGE_REPORTING_CAPACITY;
 
-	/* Power of 2 so division by capacity in the budget calc is cheap */
-	prdev->capacity = rounddown_pow_of_two(prdev->capacity);
-
 	/* initialize state and work structures */
 	atomic_set(&prdev->state, PAGE_REPORTING_IDLE);
 	INIT_DELAYED_WORK(&prdev->work, &page_reporting_process);