aboutsummaryrefslogtreecommitdiffstats
path: root/mm/hugetlb.c
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2013-09-11 17:21:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:57:26 -0400
commitb2261026825ed34066b24069359d118098bb1876 (patch)
tree89e08899fcc8291414cf43ed1f4a99a364f836a0 /mm/hugetlb.c
parent81a6fcae3ff3f6af1c9d7e31499e68fda2b3f58d (diff)
mm, hugetlb: fix and clean-up node iteration code to alloc or free
Current node iteration code have a minor problem which do one more node rotation if we can't succeed to allocate. For example, if we start to allocate at node 0, we stop to iterate at node 0. Then we start to allocate at node 1 for next allocation. I introduce new macros "for_each_node_mask_to_[alloc|free]" and fix and clean-up node iteration code to alloc or free. This makes code more understandable. Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Acked-by: Hillf Danton <dhillf@gmail.com> Cc: Michal Hocko <mhocko@suse.cz> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Wanpeng Li <liwanp@linux.vnet.ibm.com> Cc: Rik van Riel <riel@redhat.com> Cc: Mel Gorman <mgorman@suse.de> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Hugh Dickins <hughd@google.com> Cc: Davidlohr Bueso <davidlohr.bueso@hp.com> Cc: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r--mm/hugetlb.c143
1 files changed, 61 insertions, 82 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index a698d40d1c3e..08b7595fe3c1 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -772,33 +772,6 @@ static int hstate_next_node_to_alloc(struct hstate *h,
772 return nid; 772 return nid;
773} 773}
774 774
775static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
776{
777 struct page *page;
778 int start_nid;
779 int next_nid;
780 int ret = 0;
781
782 start_nid = hstate_next_node_to_alloc(h, nodes_allowed);
783 next_nid = start_nid;
784
785 do {
786 page = alloc_fresh_huge_page_node(h, next_nid);
787 if (page) {
788 ret = 1;
789 break;
790 }
791 next_nid = hstate_next_node_to_alloc(h, nodes_allowed);
792 } while (next_nid != start_nid);
793
794 if (ret)
795 count_vm_event(HTLB_BUDDY_PGALLOC);
796 else
797 count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
798
799 return ret;
800}
801
802/* 775/*
803 * helper for free_pool_huge_page() - return the previously saved 776 * helper for free_pool_huge_page() - return the previously saved
804 * node ["this node"] from which to free a huge page. Advance the 777 * node ["this node"] from which to free a huge page. Advance the
@@ -817,6 +790,40 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
817 return nid; 790 return nid;
818} 791}
819 792
793#define for_each_node_mask_to_alloc(hs, nr_nodes, node, mask) \
794 for (nr_nodes = nodes_weight(*mask); \
795 nr_nodes > 0 && \
796 ((node = hstate_next_node_to_alloc(hs, mask)) || 1); \
797 nr_nodes--)
798
799#define for_each_node_mask_to_free(hs, nr_nodes, node, mask) \
800 for (nr_nodes = nodes_weight(*mask); \
801 nr_nodes > 0 && \
802 ((node = hstate_next_node_to_free(hs, mask)) || 1); \
803 nr_nodes--)
804
805static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
806{
807 struct page *page;
808 int nr_nodes, node;
809 int ret = 0;
810
811 for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
812 page = alloc_fresh_huge_page_node(h, node);
813 if (page) {
814 ret = 1;
815 break;
816 }
817 }
818
819 if (ret)
820 count_vm_event(HTLB_BUDDY_PGALLOC);
821 else
822 count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
823
824 return ret;
825}
826
820/* 827/*
821 * Free huge page from pool from next node to free. 828 * Free huge page from pool from next node to free.
822 * Attempt to keep persistent huge pages more or less 829 * Attempt to keep persistent huge pages more or less
@@ -826,36 +833,31 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
826static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed, 833static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
827 bool acct_surplus) 834 bool acct_surplus)
828{ 835{
829 int start_nid; 836 int nr_nodes, node;
830 int next_nid;
831 int ret = 0; 837 int ret = 0;
832 838
833 start_nid = hstate_next_node_to_free(h, nodes_allowed); 839 for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) {
834 next_nid = start_nid;
835
836 do {
837 /* 840 /*
838 * If we're returning unused surplus pages, only examine 841 * If we're returning unused surplus pages, only examine
839 * nodes with surplus pages. 842 * nodes with surplus pages.
840 */ 843 */
841 if ((!acct_surplus || h->surplus_huge_pages_node[next_nid]) && 844 if ((!acct_surplus || h->surplus_huge_pages_node[node]) &&
842 !list_empty(&h->hugepage_freelists[next_nid])) { 845 !list_empty(&h->hugepage_freelists[node])) {
843 struct page *page = 846 struct page *page =
844 list_entry(h->hugepage_freelists[next_nid].next, 847 list_entry(h->hugepage_freelists[node].next,
845 struct page, lru); 848 struct page, lru);
846 list_del(&page->lru); 849 list_del(&page->lru);
847 h->free_huge_pages--; 850 h->free_huge_pages--;
848 h->free_huge_pages_node[next_nid]--; 851 h->free_huge_pages_node[node]--;
849 if (acct_surplus) { 852 if (acct_surplus) {
850 h->surplus_huge_pages--; 853 h->surplus_huge_pages--;
851 h->surplus_huge_pages_node[next_nid]--; 854 h->surplus_huge_pages_node[node]--;
852 } 855 }
853 update_and_free_page(h, page); 856 update_and_free_page(h, page);
854 ret = 1; 857 ret = 1;
855 break; 858 break;
856 } 859 }
857 next_nid = hstate_next_node_to_free(h, nodes_allowed); 860 }
858 } while (next_nid != start_nid);
859 861
860 return ret; 862 return ret;
861} 863}
@@ -1192,14 +1194,12 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
1192int __weak alloc_bootmem_huge_page(struct hstate *h) 1194int __weak alloc_bootmem_huge_page(struct hstate *h)
1193{ 1195{
1194 struct huge_bootmem_page *m; 1196 struct huge_bootmem_page *m;
1195 int nr_nodes = nodes_weight(node_states[N_MEMORY]); 1197 int nr_nodes, node;
1196 1198
1197 while (nr_nodes) { 1199 for_each_node_mask_to_alloc(h, nr_nodes, node, &node_states[N_MEMORY]) {
1198 void *addr; 1200 void *addr;
1199 1201
1200 addr = __alloc_bootmem_node_nopanic( 1202 addr = __alloc_bootmem_node_nopanic(NODE_DATA(node),
1201 NODE_DATA(hstate_next_node_to_alloc(h,
1202 &node_states[N_MEMORY])),
1203 huge_page_size(h), huge_page_size(h), 0); 1203 huge_page_size(h), huge_page_size(h), 0);
1204 1204
1205 if (addr) { 1205 if (addr) {
@@ -1211,7 +1211,6 @@ int __weak alloc_bootmem_huge_page(struct hstate *h)
1211 m = addr; 1211 m = addr;
1212 goto found; 1212 goto found;
1213 } 1213 }
1214 nr_nodes--;
1215 } 1214 }
1216 return 0; 1215 return 0;
1217 1216
@@ -1350,48 +1349,28 @@ static inline void try_to_free_low(struct hstate *h, unsigned long count,
1350static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed, 1349static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed,
1351 int delta) 1350 int delta)
1352{ 1351{
1353 int start_nid, next_nid; 1352 int nr_nodes, node;
1354 int ret = 0;
1355 1353
1356 VM_BUG_ON(delta != -1 && delta != 1); 1354 VM_BUG_ON(delta != -1 && delta != 1);
1357 1355
1358 if (delta < 0) 1356 if (delta < 0) {
1359 start_nid = hstate_next_node_to_alloc(h, nodes_allowed); 1357 for_each_node_mask_to_alloc(h, nr_nodes, node, nodes_allowed) {
1360 else 1358 if (h->surplus_huge_pages_node[node])
1361 start_nid = hstate_next_node_to_free(h, nodes_allowed); 1359 goto found;
1362 next_nid = start_nid;
1363
1364 do {
1365 int nid = next_nid;
1366 if (delta < 0) {
1367 /*
1368 * To shrink on this node, there must be a surplus page
1369 */
1370 if (!h->surplus_huge_pages_node[nid]) {
1371 next_nid = hstate_next_node_to_alloc(h,
1372 nodes_allowed);
1373 continue;
1374 }
1375 } 1360 }
1376 if (delta > 0) { 1361 } else {
1377 /* 1362 for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) {
1378 * Surplus cannot exceed the total number of pages 1363 if (h->surplus_huge_pages_node[node] <
1379 */ 1364 h->nr_huge_pages_node[node])
1380 if (h->surplus_huge_pages_node[nid] >= 1365 goto found;
1381 h->nr_huge_pages_node[nid]) {
1382 next_nid = hstate_next_node_to_free(h,
1383 nodes_allowed);
1384 continue;
1385 }
1386 } 1366 }
1367 }
1368 return 0;
1387 1369
1388 h->surplus_huge_pages += delta; 1370found:
1389 h->surplus_huge_pages_node[nid] += delta; 1371 h->surplus_huge_pages += delta;
1390 ret = 1; 1372 h->surplus_huge_pages_node[node] += delta;
1391 break; 1373 return 1;
1392 } while (next_nid != start_nid);
1393
1394 return ret;
1395} 1374}
1396 1375
1397#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages) 1376#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)