Add a write-only module parameter 'flush' that triggers immediate
page reporting.  The value specifies approximately how many pages
(at page_reporting_order) to report.  The flush loops through
reporting cycles, each processing up to PAGE_REPORTING_CAPACITY
pages, until the budget is exhausted, all pages are reported, or
a signal is pending.

This is helpful when there is a lot of memory freed quickly,
and a single cycle may not process all free pages due to
internal budget limits.

  echo 512 > /sys/module/page_reporting/parameters/flush

Signed-off-by: Michael S. Tsirkin <[email protected]>
Assisted-by: Claude:claude-opus-4-6
---
 mm/page_reporting.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index 61f7f08d02d4..05bdcf89f3e3 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -358,6 +358,48 @@ static void page_reporting_process(struct work_struct 
*work)
 static DEFINE_MUTEX(page_reporting_mutex);
 DEFINE_STATIC_KEY_FALSE(page_reporting_enabled);
 
+static int page_reporting_flush_set(const char *val,
+                                   const struct kernel_param *kp)
+{
+       struct page_reporting_dev_info *prdev;
+       unsigned int budget;
+       int err;
+
+       err = kstrtouint(val, 0, &budget);
+       if (err)
+               return err;
+       if (!budget)
+               return 0;
+
+       mutex_lock(&page_reporting_mutex);
+       prdev = rcu_dereference_protected(pr_dev_info,
+                               lockdep_is_held(&page_reporting_mutex));
+       if (prdev) {
+               unsigned int reported;
+
+               for (reported = 0; reported < budget;
+                    reported += PAGE_REPORTING_CAPACITY) {
+                       flush_delayed_work(&prdev->work);
+                       __page_reporting_request(prdev);
+                       flush_delayed_work(&prdev->work);
+                       if (atomic_read(&prdev->state) == PAGE_REPORTING_IDLE)
+                               break;
+                       if (signal_pending(current))
+                               break;
+               }
+       }
+       mutex_unlock(&page_reporting_mutex);
+       return 0;
+}
+
+static const struct kernel_param_ops flush_ops = {
+       .set = page_reporting_flush_set,
+       .get = param_get_uint,
+};
+static unsigned int page_reporting_flush;
+module_param_cb(flush, &flush_ops, &page_reporting_flush, 0200);
+MODULE_PARM_DESC(flush, "Report up to N pages at page_reporting_order");
+
 int page_reporting_register(struct page_reporting_dev_info *prdev)
 {
        int err = 0;
-- 
MST


Reply via email to