diff options
author | Christoph Lameter <clameter@engr.sgi.com> | 2006-01-06 03:10:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:23 -0500 |
commit | 5da7ca86078964cbfe6c83efc1205904587706fe (patch) | |
tree | a64a7824e90b42d6fdd71e6cb652362beb8983a1 /mm/mempolicy.c | |
parent | 96df9333c94d7d5aeceb21f6c5e7ae8ff34753cf (diff) |
[PATCH] Add NUMA policy support for huge pages.
The huge_zonelist() function in the memory policy layer provides an list of
zones ordered by NUMA distance. The hugetlb layer will walk that list looking
for a zone that has available huge pages but is also in the nodeset of the
current cpuset.
This patch does not contain the folding of find_or_alloc_huge_page() that was
controversial in the earlier discussion.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Cc: Andi Kleen <ak@muc.de>
Acked-by: William Lee Irwin III <wli@holomorphy.com>
Cc: Adam Litke <agl@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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)); |