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 <[email protected]> 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

