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.
The driver's report() callback is responsible for managing the
bitmap: zeroing it before sending pages to the host, then setting
bits for pages the host actually zeroed.

page_reporting_drain() checks the bitmap per-page in addition to the
global host_zeroes_pages flag.

No driver sets host_zeroes_pages yet, so the static key is
off and the bitmap is never read.  Behavior is unchanged.

Signed-off-by: Michael S. Tsirkin <[email protected]>
Assisted-by: Claude:claude-opus-4-6
Assisted-by: cursor-agent:GPT-5.4-xhigh
---
 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 c331c6b36687..e2e6a487ddab 100644
--- a/include/linux/page_reporting.h
+++ b/include/linux/page_reporting.h
@@ -17,6 +17,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 37e4fce9eb38..6c957a9daeef 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


Reply via email to