@@ -1110,7 +1110,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
unsigned long address, int avoid_reserve,
long chg)
{
- struct page *page;
+ struct page *page = NULL;
struct mempolicy *mpol;
gfp_t gfp_mask;
nodemask_t *nodemask;
@@ -1131,7 +1131,15 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
gfp_mask = htlb_alloc_mask(h);
nid = huge_node(vma, address, gfp_mask, &mpol, &nodemask);
- page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask);
+ if (mpol->mode != MPOL_BIND && nodemask) { /* AKA MPOL_PREFERRED_MANY */
+ page = dequeue_huge_page_nodemask(h,
+ gfp_mask | __GFP_RETRY_MAYFAIL | __GFP_NOWARN,
+ nid, nodemask);
+ if (!page)
+ page = dequeue_huge_page_nodemask(h, gfp_mask, nid, NULL);
+ } else {
+ page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask);
+ }
if (page && !avoid_reserve && vma_has_reserves(vma, chg)) {
SetPagePrivate(page);
h->resv_huge_pages--;
@@ -1935,7 +1943,15 @@ struct page *alloc_buddy_huge_page_with_mpol(struct hstate *h,
nodemask_t *nodemask;
nid = huge_node(vma, addr, gfp_mask, &mpol, &nodemask);
- page = alloc_surplus_huge_page(h, gfp_mask, nid, nodemask);
+ if (mpol->mode != MPOL_BIND && nodemask) { /* AKA MPOL_PREFERRED_MANY */
+ page = alloc_surplus_huge_page(h,
+ gfp_mask | __GFP_RETRY_MAYFAIL | __GFP_NOWARN,
+ nid, nodemask);
+ if (!page)
+ alloc_surplus_huge_page(h, gfp_mask, nid, NULL);
+ } else {
+ page = alloc_surplus_huge_page(h, gfp_mask, nid, nodemask);
+ }
mpol_cond_put(mpol);
return page;
@@ -2075,7 +2075,8 @@ int huge_node(struct vm_area_struct *vma, unsigned long addr, gfp_t gfp_flags,
huge_page_shift(hstate_vma(vma)));
} else {
nid = policy_node(gfp_flags, *mpol, numa_node_id());
- if ((*mpol)->mode == MPOL_BIND)
+ if ((*mpol)->mode == MPOL_BIND ||
+ (*mpol)->mode == MPOL_PREFERRED_MANY)
*nodemask = &(*mpol)->nodes;
}
return nid;