[PATCH RFC v3 1/4] KVM: guest_memfd: Track amount of memory allocated on inode

From: Ackerley Tng

Date: Mon Mar 09 2026 - 05:56:19 EST


The guest memfd currently does not update the inode's i_blocks and i_bytes
count when memory is allocated or freed. Hence, st_blocks returned from
fstat() is always 0.

Introduce byte accounting for guest memfd inodes. When a new folio is
added to the filemap, add the folio's size. Use the .invalidate_folio()
callback to subtract the folio's size from inode fields when folios are
truncated and removed from the filemap.

Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
virt/kvm/guest_memfd.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 462c5c5cb602a..77219551056a7 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -136,6 +136,9 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
mapping_gfp_mask(inode->i_mapping), policy);
mpol_cond_put(policy);

+ if (!IS_ERR(folio))
+ inode_add_bytes(inode, folio_size(folio));
+
/*
* External interfaces like kvm_gmem_get_pfn() support dealing
* with hugepages to a degree, but internally, guest_memfd currently
@@ -532,10 +535,21 @@ static void kvm_gmem_free_folio(struct folio *folio)
}
#endif

+static void kvm_gmem_invalidate_folio(struct folio *folio, size_t offset, size_t len)
+{
+ size_t bytes = folio_size(folio);
+
+ WARN_ON_ONCE(offset);
+ WARN_ON_ONCE(len != bytes);
+
+ inode_sub_bytes(folio_inode(folio), bytes);
+}
+
static const struct address_space_operations kvm_gmem_aops = {
.dirty_folio = noop_dirty_folio,
.migrate_folio = kvm_gmem_migrate_folio,
.error_remove_folio = kvm_gmem_error_folio,
+ .invalidate_folio = kvm_gmem_invalidate_folio,
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
.free_folio = kvm_gmem_free_folio,
#endif

--
2.53.0.473.g4a7958ca14-goog