diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 72f402cc9c9a..45c51ac63443 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -785,6 +785,34 @@ static unsigned offset_il_node(struct mempolicy *pol, | |||
785 | return nid; | 785 | return nid; |
786 | } | 786 | } |
787 | 787 | ||
788 | /* Determine a node number for interleave */ | ||
789 | static inline unsigned interleave_nid(struct mempolicy *pol, | ||
790 | struct vm_area_struct *vma, unsigned long addr, int shift) | ||
791 | { | ||
792 | if (vma) { | ||
793 | unsigned long off; | ||
794 | |||
795 | off = vma->vm_pgoff; | ||
796 | off += (addr - vma->vm_start) >> shift; | ||
797 | return offset_il_node(pol, vma, off); | ||
798 | } else | ||
799 | return interleave_nodes(pol); | ||
800 | } | ||
801 | |||
802 | /* Return a zonelist suitable for a huge page allocation. */ | ||
803 | struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr) | ||
804 | { | ||
805 | struct mempolicy *pol = get_vma_policy(current, vma, addr); | ||
806 | |||
807 | if (pol->policy == MPOL_INTERLEAVE) { | ||
808 | unsigned nid; | ||
809 | |||
810 | nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); | ||
811 | return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER); | ||
812 | } | ||
813 | return zonelist_policy(GFP_HIGHUSER, pol); | ||
814 | } | ||
815 | |||
788 | /* Allocate a page in interleaved policy. | 816 | /* Allocate a page in interleaved policy. |
789 | Own path because it needs to do special accounting. */ | 817 | Own path because it needs to do special accounting. */ |
790 | static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, | 818 | static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, |
@@ -833,15 +861,8 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) | |||
833 | 861 | ||
834 | if (unlikely(pol->policy == MPOL_INTERLEAVE)) { | 862 | if (unlikely(pol->policy == MPOL_INTERLEAVE)) { |
835 | unsigned nid; | 863 | unsigned nid; |
836 | if (vma) { | 864 | |
837 | unsigned long off; | 865 | nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); |
838 | off = vma->vm_pgoff; | ||
839 | off += (addr - vma->vm_start) >> PAGE_SHIFT; | ||
840 | nid = offset_il_node(pol, vma, off); | ||
841 | } else { | ||
842 | /* fall back to process interleaving */ | ||
843 | nid = interleave_nodes(pol); | ||
844 | } | ||
845 | return alloc_page_interleave(gfp, 0, nid); | 866 | return alloc_page_interleave(gfp, 0, nid); |
846 | } | 867 | } |
847 | return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); | 868 | return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); |