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


Reply via email to