diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 102 |
1 files changed, 33 insertions, 69 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 72f402cc9c9a..0f1d2b8a952b 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -93,7 +93,7 @@ static kmem_cache_t *sn_cache; | |||
93 | 93 | ||
94 | /* Highest zone. An specific allocation for a zone below that is not | 94 | /* Highest zone. An specific allocation for a zone below that is not |
95 | policied. */ | 95 | policied. */ |
96 | static int policy_zone; | 96 | int policy_zone = ZONE_DMA; |
97 | 97 | ||
98 | struct mempolicy default_policy = { | 98 | struct mempolicy default_policy = { |
99 | .refcnt = ATOMIC_INIT(1), /* never free it */ | 99 | .refcnt = ATOMIC_INIT(1), /* never free it */ |
@@ -131,17 +131,8 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) | |||
131 | if (!zl) | 131 | if (!zl) |
132 | return NULL; | 132 | return NULL; |
133 | num = 0; | 133 | num = 0; |
134 | for_each_node_mask(nd, *nodes) { | 134 | for_each_node_mask(nd, *nodes) |
135 | int k; | 135 | zl->zones[num++] = &NODE_DATA(nd)->node_zones[policy_zone]; |
136 | for (k = MAX_NR_ZONES-1; k >= 0; k--) { | ||
137 | struct zone *z = &NODE_DATA(nd)->node_zones[k]; | ||
138 | if (!z->present_pages) | ||
139 | continue; | ||
140 | zl->zones[num++] = z; | ||
141 | if (k > policy_zone) | ||
142 | policy_zone = k; | ||
143 | } | ||
144 | } | ||
145 | zl->zones[num] = NULL; | 136 | zl->zones[num] = NULL; |
146 | return zl; | 137 | return zl; |
147 | } | 138 | } |
@@ -785,6 +776,34 @@ static unsigned offset_il_node(struct mempolicy *pol, | |||
785 | return nid; | 776 | return nid; |
786 | } | 777 | } |
787 | 778 | ||
779 | /* Determine a node number for interleave */ | ||
780 | static inline unsigned interleave_nid(struct mempolicy *pol, | ||
781 | struct vm_area_struct *vma, unsigned long addr, int shift) | ||
782 | { | ||
783 | if (vma) { | ||
784 | unsigned long off; | ||
785 | |||
786 | off = vma->vm_pgoff; | ||
787 | off += (addr - vma->vm_start) >> shift; | ||
788 | return offset_il_node(pol, vma, off); | ||
789 | } else | ||
790 | return interleave_nodes(pol); | ||
791 | } | ||
792 | |||
793 | /* Return a zonelist suitable for a huge page allocation. */ | ||
794 | struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr) | ||
795 | { | ||
796 | struct mempolicy *pol = get_vma_policy(current, vma, addr); | ||
797 | |||
798 | if (pol->policy == MPOL_INTERLEAVE) { | ||
799 | unsigned nid; | ||
800 | |||
801 | nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); | ||
802 | return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER); | ||
803 | } | ||
804 | return zonelist_policy(GFP_HIGHUSER, pol); | ||
805 | } | ||
806 | |||
788 | /* Allocate a page in interleaved policy. | 807 | /* Allocate a page in interleaved policy. |
789 | Own path because it needs to do special accounting. */ | 808 | Own path because it needs to do special accounting. */ |
790 | static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, | 809 | static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, |
@@ -833,15 +852,8 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) | |||
833 | 852 | ||
834 | if (unlikely(pol->policy == MPOL_INTERLEAVE)) { | 853 | if (unlikely(pol->policy == MPOL_INTERLEAVE)) { |
835 | unsigned nid; | 854 | unsigned nid; |
836 | if (vma) { | 855 | |
837 | unsigned long off; | 856 | 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); | 857 | return alloc_page_interleave(gfp, 0, nid); |
846 | } | 858 | } |
847 | return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); | 859 | return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); |
@@ -940,54 +952,6 @@ void __mpol_free(struct mempolicy *p) | |||
940 | } | 952 | } |
941 | 953 | ||
942 | /* | 954 | /* |
943 | * Hugetlb policy. Same as above, just works with node numbers instead of | ||
944 | * zonelists. | ||
945 | */ | ||
946 | |||
947 | /* Find first node suitable for an allocation */ | ||
948 | int mpol_first_node(struct vm_area_struct *vma, unsigned long addr) | ||
949 | { | ||
950 | struct mempolicy *pol = get_vma_policy(current, vma, addr); | ||
951 | |||
952 | switch (pol->policy) { | ||
953 | case MPOL_DEFAULT: | ||
954 | return numa_node_id(); | ||
955 | case MPOL_BIND: | ||
956 | return pol->v.zonelist->zones[0]->zone_pgdat->node_id; | ||
957 | case MPOL_INTERLEAVE: | ||
958 | return interleave_nodes(pol); | ||
959 | case MPOL_PREFERRED: | ||
960 | return pol->v.preferred_node >= 0 ? | ||
961 | pol->v.preferred_node : numa_node_id(); | ||
962 | } | ||
963 | BUG(); | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | /* Find secondary valid nodes for an allocation */ | ||
968 | int mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long addr) | ||
969 | { | ||
970 | struct mempolicy *pol = get_vma_policy(current, vma, addr); | ||
971 | |||
972 | switch (pol->policy) { | ||
973 | case MPOL_PREFERRED: | ||
974 | case MPOL_DEFAULT: | ||
975 | case MPOL_INTERLEAVE: | ||
976 | return 1; | ||
977 | case MPOL_BIND: { | ||
978 | struct zone **z; | ||
979 | for (z = pol->v.zonelist->zones; *z; z++) | ||
980 | if ((*z)->zone_pgdat->node_id == nid) | ||
981 | return 1; | ||
982 | return 0; | ||
983 | } | ||
984 | default: | ||
985 | BUG(); | ||
986 | return 0; | ||
987 | } | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * Shared memory backing store policy support. | 955 | * Shared memory backing store policy support. |
992 | * | 956 | * |
993 | * Remember policies even when nobody has shared memory mapped. | 957 | * Remember policies even when nobody has shared memory mapped. |