[PATCH RFC v4 17/22] mm: page_reporting: add per-page zeroed bitmap for host feedback
From: Michael S. Tsirkin
Date: Sun Apr 26 2026 - 17:51:05 EST
The host may skip zeroing some reported pages (e.g., due to alignment
constraints or bounce buffer fallback in QEMU). Currently, when
host_zeroes_pages is set, all reported pages are unconditionally
marked PG_zeroed -- even ones the host did not actually zero.
Add a zeroed_bitmap to page_reporting_dev_info that the report()
callback can use to indicate which pages were actually zeroed.
Before calling report(), the framework initializes the bitmap:
all bits set if host_zeroes_pages (optimistic default), all clear
otherwise. The driver's report() can then clear bits for pages
that were not zeroed.
page_reporting_drain() checks the bitmap per-page instead of the
global host_zeroes_pages flag.
No driver uses per-page feedback yet; the bitmap is pre-filled
based on host_zeroes_pages, so behavior is unchanged.
Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
Assisted-by: Claude:claude-opus-4-6
---
include/linux/page_reporting.h | 7 +++++++
mm/page_reporting.c | 8 ++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/include/linux/page_reporting.h b/include/linux/page_reporting.h
index 10faadfeb4fb..5b63de21949c 100644
--- a/include/linux/page_reporting.h
+++ b/include/linux/page_reporting.h
@@ -16,6 +16,13 @@ struct page_reporting_dev_info {
/* If true, host zeros reported pages on reclaim */
bool host_zeroes_pages;
+ /*
+ * Per-page zeroed status, indexed by scatterlist position.
+ * The driver's report() callback must clear the bitmap,
+ * then set bits for pages that were actually zeroed.
+ */
+ DECLARE_BITMAP(zeroed_bitmap, PAGE_REPORTING_CAPACITY);
+
/* work struct for processing reports */
struct delayed_work work;
diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index 6177d2413743..61f7f08d02d4 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -108,6 +108,7 @@ page_reporting_drain(struct page_reporting_dev_info *prdev,
struct scatterlist *sgl, unsigned int nents, bool reported)
{
struct scatterlist *sg = sgl;
+ unsigned int i = 0;
/*
* Drain the now reported pages back into their respective
@@ -122,7 +123,7 @@ page_reporting_drain(struct page_reporting_dev_info *prdev,
/* If the pages were not reported due to error skip flagging */
if (!reported)
- continue;
+ goto next;
/*
* If page was not commingled with another page we can
@@ -133,9 +134,12 @@ page_reporting_drain(struct page_reporting_dev_info *prdev,
*/
if (PageBuddy(page) && buddy_order(page) == order) {
__SetPageReported(page);
- if (page_reporting_host_zeroes_pages())
+ if (page_reporting_host_zeroes_pages() &&
+ test_bit(i, prdev->zeroed_bitmap))
__SetPageZeroed(page);
}
+next:
+ i++;
} while ((sg = sg_next(sg)));
/* reinitialize scatterlist now that it is empty */
--
MST