diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 62f9fada4d6d..b1c314877334 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -454,14 +454,16 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, | |||
454 | struct vm_area_struct *vma, | 454 | struct vm_area_struct *vma, |
455 | unsigned long address, int avoid_reserve) | 455 | unsigned long address, int avoid_reserve) |
456 | { | 456 | { |
457 | struct page *page = NULL; | 457 | struct page *page; |
458 | struct mempolicy *mpol; | 458 | struct mempolicy *mpol; |
459 | nodemask_t *nodemask; | 459 | nodemask_t *nodemask; |
460 | struct zonelist *zonelist; | 460 | struct zonelist *zonelist; |
461 | struct zone *zone; | 461 | struct zone *zone; |
462 | struct zoneref *z; | 462 | struct zoneref *z; |
463 | unsigned int cpuset_mems_cookie; | ||
463 | 464 | ||
464 | get_mems_allowed(); | 465 | retry_cpuset: |
466 | cpuset_mems_cookie = get_mems_allowed(); | ||
465 | zonelist = huge_zonelist(vma, address, | 467 | zonelist = huge_zonelist(vma, address, |
466 | htlb_alloc_mask, &mpol, &nodemask); | 468 | htlb_alloc_mask, &mpol, &nodemask); |
467 | /* | 469 | /* |
@@ -488,10 +490,15 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, | |||
488 | } | 490 | } |
489 | } | 491 | } |
490 | } | 492 | } |
491 | err: | 493 | |
492 | mpol_cond_put(mpol); | 494 | mpol_cond_put(mpol); |
493 | put_mems_allowed(); | 495 | if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) |
496 | goto retry_cpuset; | ||
494 | return page; | 497 | return page; |
498 | |||
499 | err: | ||
500 | mpol_cond_put(mpol); | ||
501 | return NULL; | ||
495 | } | 502 | } |
496 | 503 | ||
497 | static void update_and_free_page(struct hstate *h, struct page *page) | 504 | static void update_and_free_page(struct hstate *h, struct page *page) |