Re: [PATCH] mm/mempolicy: apply bind policies against the scoped allocation zone
From: Joshua Hahn
Date: Sun Oct 18 2026 - 17:02:53 EST
On Sat, Oct 17, 2026 at 10:33 PM Gregory Price (Meta) <gourry@xxxxxxxxxx> wrote:
>
> QEMU fails to start a guest with a VFIO device when guest RAM comes
> from a memory backend bound to a movable-only node:
>
> vfio_container_dma_map(0x55b1b1317800, 0x0, 0x10000000,
> 0x7f39a2200000)
> = -12 (Cannot allocate memory)
>
> VFIO pins guest RAM when the device is realized, and the pin faults
> the pages in. io_uring fixed buffers fail the same way. Faulting the
> range in before pinning lets the same pin succeed, since resident
> pages are migrated off the node instead.
>
> A long-term pin faults under memalloc_pin_save(). PF_MEMALLOC_PIN makes
> current_gfp_context() clear __GFP_MOVABLE, but policy_nodemask() tests
> apply_policy_zone() against the caller's gfp.
>
> The bind keeps its movable-only nodemask, and the allocation finds no
> usable zone:
>
> page allocation failure:
> order:0,
> mode:0x140dc2(GFP_HIGHUSER|__GFP_ZERO|__GFP_COMP),
> nodemask=1,cpuset=/,mems_allowed=0-1
>
> Call Trace:
> warn_alloc+0x136/0x150
> __alloc_frozen_pages_noprof+0xed8/0x1720
> alloc_pages_mpol+0xaa/0x170
> vma_alloc_folio_noprof+0x65/0xd0
> __handle_mm_fault+0x137b/0x1ac0
> handle_mm_fault+0xa0/0x270
> __get_user_pages+0x250/0xfd0
> __gup_longterm_locked+0x116/0x870
> gup_fast_fallback+0xcfc/0xdf0
> pin_user_pages_fast+0x47/0x60
> io_pin_pages+0x9a/0x110
>
> Base page faults fail with -ENOMEM.
> hugetlb faults fail with -EFAULT.
>
> Check the policy zone against current_gfp_context(gfp), so a pin-scoped
> fault falls back off the movable-only nodemask, like any other
> non-movable allocation under the same bind.
Hi Gregory,
LGTM, thank you for making it so easy to review!
I wonder if other places are missing current_gfp_context as well.
Reviewed-by: Joshua Hahn <joshua.hahnjy@xxxxxxxxx>
> Tested in qemu with a dax/kmem movable-only node 1. io_uring and VFIO
> pins of unfaulted base pages and 2MB hugetlb pages now succeed and land
> on node 0 (correct). QEMU now starts with the same backend binding.
>
> Fixes: 8e3560d963d2 ("mm: honor PF_MEMALLOC_PIN for all movable pages")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
> ---
> mm/mempolicy.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 70298fded1b4a..0884c629670dd 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2302,7 +2302,7 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *pol,
> break;
> case MPOL_BIND:
> /* Restrict to nodemask (but not on lower zones) */
> - if (apply_policy_zone(pol, gfp_zone(gfp)) &&
> + if (apply_policy_zone(pol, gfp_zone(current_gfp_context(gfp))) &&
> cpuset_nodemask_valid_mems_allowed(&pol->nodes))
> nodemask = &pol->nodes;
> if (pol->home_node != NUMA_NO_NODE)
> --
> 2.53.0-Meta
>