> +static struct folio *__kvm_gmem_get_folio(struct address_space *mapping,
> + pgoff_t index,
> + struct mempolicy *policy)
> +{
> + const gfp_t gfp = mapping_gfp_mask(mapping);
> + struct folio *folio;
> + int err;
> +
> + folio = filemap_lock_folio(mapping, index);
> + if (!IS_ERR(folio))
> + return folio;
> +
> + folio = filemap_alloc_folio(gfp, 0, policy);
> + if (!folio)
> + return ERR_PTR(-ENOMEM);
> +
> + err = mem_cgroup_charge(folio, NULL, gfp);
> + if (err)
> + goto err_put;
> +
> + __folio_set_locked(folio);
> +
> + err = __filemap_add_folio(mapping, folio, index, gfp, NULL);
> + if (err) {
mem_cgroup_uncharge(folio);
> + __folio_clear_locked(folio);
> + goto err_put;
> + }
> +
> + return folio;
> +
> +err_put:
> + folio_put(folio);
> + return ERR_PTR(err);
> +}
> +
> /*
> * 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.
> @@ -160,6 +195,7 @@ static struct mempolicy *kvm_gmem_get_folio_policy(struct
> gmem_inode *gi,
> static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
> {
> /* TODO: Support huge pages. */
> + struct address_space *mapping = inode->i_mapping;
> struct mempolicy *policy;
> struct folio *folio;
>
> @@ -167,16 +203,17 @@ static struct folio *kvm_gmem_get_folio(struct inode
> *inode, pgoff_t index)
> * Fast-path: See if folio is already present in mapping to avoid
> * policy_lookup.
> */
> - folio = filemap_lock_folio(inode->i_mapping, index);
> + folio = filemap_lock_folio(mapping, index);
> if (!IS_ERR(folio))
> return folio;
>
> policy = kvm_gmem_get_folio_policy(GMEM_I(inode), 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(mapping, index, policy);
> + } while (IS_ERR(folio) && PTR_ERR(folio) == -EEXIST);
Why not just return ERR_PTR(-EEXIST) up to kvm_gmem_get_pfn() and have a higher
level retry?
> + mpol_cond_put(policy);
> return folio;
> }