aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@engr.sgi.com>2006-01-06 03:10:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:23 -0500
commit5da7ca86078964cbfe6c83efc1205904587706fe (patch)
treea64a7824e90b42d6fdd71e6cb652362beb8983a1 /mm/mempolicy.c
parent96df9333c94d7d5aeceb21f6c5e7ae8ff34753cf (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.c39
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 */
789static 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. */
803struct 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. */
790static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, 818static 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));