[PATCH RFC v2 47/50] samples/kvm: Implement put_pfn_range provider operation
From: Ackerley Tng via B4 Relay
Date: Thu Oct 22 2026 - 19:46:43 EST
From: Ackerley Tng <ackerleytng@xxxxxxxxxx>
When guest_memfd hole punches or destroys an instance backed by a PFN
provider, it invokes .put_pfn_range to release the physical memory back
to the provider.
Implement the .put_pfn_range callback in mps_gmem_provider_ops to clear
the CMA pages across the released range via clear_highpage(). This
ensures that subsequent accesses to punched ranges observe zeroed memory,
matching POSIX fallocate hole-punching semantics and preventing stale data
from being observed when pages are reused.
Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
samples/kvm/mem_provider_sample.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/samples/kvm/mem_provider_sample.c b/samples/kvm/mem_provider_sample.c
index a43c76d2259e7..dee15179959b2 100644
--- a/samples/kvm/mem_provider_sample.c
+++ b/samples/kvm/mem_provider_sample.c
@@ -17,6 +17,7 @@
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/gfp.h>
+#include <linux/highmem.h>
#include <linux/guest_memfd.h>
#include <linux/io.h>
#include <linux/miscdevice.h>
@@ -40,6 +41,21 @@ struct mps_info {
unsigned long *absent; /* taken away by MPS_SET_PRESENT */
};
+static void mps_gmem_put_pfn_range(void *provider, pgoff_t index,
+ size_t nr_pages)
+{
+ struct file *resource_file = provider;
+ struct mps_info *info = resource_file->private_data;
+ size_t i;
+
+ if (index >= info->npages)
+ return;
+
+ nr_pages = min_t(size_t, nr_pages, info->npages - index);
+ for (i = 0; i < nr_pages; i++)
+ clear_highpage(info->cma_pages + index + i);
+}
+
/* Byte range [offset, offset + len) of @info as page indices. */
static int mps_range(struct mps_info *info, u64 offset, u64 len,
unsigned long *start, unsigned long *end)
@@ -155,6 +171,7 @@ static const struct guest_memfd_provider_operations mps_gmem_provider_ops = {
.attach = mps_gmem_attach,
.release = mps_gmem_release,
.get_pfn = mps_gmem_get_pfn,
+ .put_pfn_range = mps_gmem_put_pfn_range,
};
static const struct file_operations mps_file_fops = {
--
2.56.0.257.gf7497c7d27-goog