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 <[email protected]> --- 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

