__filemap_get_folio_mpol() is parametrized by a bunch of GFP flags, which
adds complexity for the reader. Since guest_memfd doesn't meaningfully use
any of the other FGP flags, undo that complexity by directly calling
filemap_alloc_folio().

Directly calling filemap_alloc_folio() also allows the order of 0 to be
explicitly specified, which is the only order guest_memfd supports. This is
easier to understand, and removes the chance of anything else being able to
unintentionally influence allocated folio size.

Signed-off-by: Ackerley Tng <[email protected]>
---
 virt/kvm/guest_memfd.c | 51 +++++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 2df27b6443115..2488d7b8f2b0d 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -107,6 +107,39 @@ static int kvm_gmem_prepare_folio(struct kvm *kvm, struct 
kvm_memory_slot *slot,
        return __kvm_gmem_prepare_folio(kvm, slot, index, folio);
 }
 
+static struct folio *__kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
+{
+       /* TODO: Support huge pages. */
+       struct mempolicy *policy;
+       struct folio *folio;
+       gfp_t gfp;
+       int ret;
+
+       /*
+        * Fast-path: See if folio is already present in mapping to avoid
+        * policy_lookup.
+        */
+       folio = filemap_lock_folio(inode->i_mapping, index);
+       if (!IS_ERR(folio))
+               return folio;
+
+       gfp = mapping_gfp_mask(inode->i_mapping);
+
+       policy = mpol_shared_policy_lookup(&GMEM_I(inode)->policy, index);
+       folio = filemap_alloc_folio(gfp, 0, policy);
+       mpol_cond_put(policy);
+       if (!folio)
+               return ERR_PTR(-ENOMEM);
+
+       ret = filemap_add_folio(inode->i_mapping, folio, index, gfp);
+       if (ret) {
+               folio_put(folio);
+               return ERR_PTR(ret);
+       }
+
+       return folio;
+}
+
 /*
  * Returns a locked folio on success.  The caller is responsible for
  * setting the up-to-date flag before the memory is mapped into the guest.
@@ -118,23 +151,11 @@ static int kvm_gmem_prepare_folio(struct kvm *kvm, struct 
kvm_memory_slot *slot,
  */
 static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
 {
-       /* TODO: Support huge pages. */
-       struct mempolicy *policy;
        struct folio *folio;
 
-       /*
-        * Fast-path: See if folio is already present in mapping to avoid
-        * policy_lookup.
-        */
-       folio = filemap_lock_folio(inode->i_mapping, index);
-       if (!IS_ERR(folio))
-               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);
-       mpol_cond_put(policy);
+       do {
+               folio = __kvm_gmem_get_folio(inode, index);
+       } while (PTR_ERR(folio) == -EEXIST);
 
        /*
         * External interfaces like kvm_gmem_get_pfn() support dealing
-- 
2.53.0.345.g96ddfc5eaa-goog


Reply via email to