If __kvm_gmem_get_pfn() detects an hwpoisoned page, it returns -EHWPOISON but it does not put back the reference that kvm_gmem_get_folio() had grabbed. Move the whole check to kvm_gmem_get_folio(), via an __-prefixed function. This removes a "goto" and simplifies the code. Now even fallocate() is prevented from picking an hwpoisoned page successfully. This is temporary until the page allocation flow is cleaned up. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- virt/kvm/guest_memfd.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 9714add38852..53742ec34a31 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -49,7 +49,7 @@ static int kvm_gmem_prepare_folio(struct inode *inode, pgoff_t index, struct fol return 0; } -static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index, bool prepare) +static struct folio *__kvm_gmem_get_folio(struct inode *inode, pgoff_t index) { struct folio *folio; @@ -58,6 +58,19 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index, bool if (IS_ERR(folio)) return folio; + if (folio_test_hwpoison(folio)) { + folio_unlock(folio); + folio_put(folio); + folio = ERR_PTR(-EHWPOISON); + } + + return folio; +} + +static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index, bool prepare) +{ + struct folio *folio = __kvm_gmem_get_folio(inode, index); + /* * Use the up-to-date flag to track whether or not the memory has been * zeroed before being handed off to the guest. There is no backing @@ -549,7 +562,6 @@ static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, struct kvm_gmem *gmem = file->private_data; struct folio *folio; struct page *page; - int r; if (file != slot->gmem.file) { WARN_ON_ONCE(slot->gmem.file); @@ -566,23 +578,14 @@ static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, if (IS_ERR(folio)) return PTR_ERR(folio); - if (folio_test_hwpoison(folio)) { - r = -EHWPOISON; - goto out_unlock; - } - page = folio_file_page(folio, index); *pfn = page_to_pfn(page); if (max_order) *max_order = 0; - r = 0; - -out_unlock: folio_unlock(folio); - - return r; + return 0; } int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot, -- 2.43.0