From: Ackerley Tng Separate __filemap_get_folio_mpol() call in kvm_gmem_get_folio() into two distinct steps: 1. Allocating a folio via filemap_alloc_folio() with the NUMA policy. 2. Inserting the allocated folio into the inode filemap. Handle -EEXIST from filemap_add_folio() by retrying filemap_lock_folio() safely to manage concurrent insertions. Decouple folio allocation from filemap insertion to prepare for supporting other memory providers. No functional change intended. Signed-off-by: Ackerley Tng --- virt/kvm/guest_memfd.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 93f3d29d5751a..f865fa0e46840 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -131,7 +131,9 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index) /* TODO: Support huge pages. */ struct mempolicy *policy; struct folio *folio; + int r; +retry: /* * Fast-path: See if folio is already present in mapping to avoid * policy_lookup. @@ -141,10 +143,19 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index) return folio; policy = mpol_shared_policy_lookup(&GMEM_I(inode)->policy, index); - folio = __filemap_get_folio_mpol(inode->i_mapping, index, - FGP_LOCK | FGP_CREAT, - mapping_gfp_mask(inode->i_mapping), policy); + folio = filemap_alloc_folio(mapping_gfp_mask(inode->i_mapping), 0, + policy); mpol_cond_put(policy); + if (!folio) + return ERR_PTR(-ENOMEM); + + r = filemap_add_folio(inode->i_mapping, folio, index, GFP_KERNEL); + if (r) { + folio_put(folio); + if (r == -EEXIST) + goto retry; + return ERR_PTR(r); + } /* * External interfaces like kvm_gmem_get_pfn() support dealing @@ -153,7 +164,7 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index) * to be updated for anything otherwise (e.g. page-clearing * operations). */ - WARN_ON_ONCE(!IS_ERR(folio) && folio_order(folio)); + WARN_ON_ONCE(folio_order(folio)); return folio; } -- 2.56.0.257.gf7497c7d27-goog