diff options
author | Mel Gorman <mel@csn.ul.ie> | 2009-06-16 18:32:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:47:33 -0400 |
commit | 3dd2826698b6902aafd9441ce28ebb44735fd0d6 (patch) | |
tree | c9bda4a84a0545d4acf41123072fd018100e63f8 /mm/page_alloc.c | |
parent | 5117f45d11a9ee62d9b086f1312f3f31781ff155 (diff) |
page allocator: calculate the migratetype for allocation only once
GFP mask is converted into a migratetype when deciding which pagelist to
take a page from. However, it is happening multiple times per allocation,
at least once per zone traversed. Calculate it once.
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Dave Hansen <dave@linux.vnet.ibm.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8fc6d1f42f0b..d3be076ea9c5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1061,13 +1061,13 @@ void split_page(struct page *page, unsigned int order) | |||
1061 | * or two. | 1061 | * or two. |
1062 | */ | 1062 | */ |
1063 | static struct page *buffered_rmqueue(struct zone *preferred_zone, | 1063 | static struct page *buffered_rmqueue(struct zone *preferred_zone, |
1064 | struct zone *zone, int order, gfp_t gfp_flags) | 1064 | struct zone *zone, int order, gfp_t gfp_flags, |
1065 | int migratetype) | ||
1065 | { | 1066 | { |
1066 | unsigned long flags; | 1067 | unsigned long flags; |
1067 | struct page *page; | 1068 | struct page *page; |
1068 | int cold = !!(gfp_flags & __GFP_COLD); | 1069 | int cold = !!(gfp_flags & __GFP_COLD); |
1069 | int cpu; | 1070 | int cpu; |
1070 | int migratetype = allocflags_to_migratetype(gfp_flags); | ||
1071 | 1071 | ||
1072 | again: | 1072 | again: |
1073 | cpu = get_cpu(); | 1073 | cpu = get_cpu(); |
@@ -1389,7 +1389,7 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) | |||
1389 | static struct page * | 1389 | static struct page * |
1390 | get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, | 1390 | get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, |
1391 | struct zonelist *zonelist, int high_zoneidx, int alloc_flags, | 1391 | struct zonelist *zonelist, int high_zoneidx, int alloc_flags, |
1392 | struct zone *preferred_zone) | 1392 | struct zone *preferred_zone, int migratetype) |
1393 | { | 1393 | { |
1394 | struct zoneref *z; | 1394 | struct zoneref *z; |
1395 | struct page *page = NULL; | 1395 | struct page *page = NULL; |
@@ -1433,7 +1433,8 @@ zonelist_scan: | |||
1433 | } | 1433 | } |
1434 | } | 1434 | } |
1435 | 1435 | ||
1436 | page = buffered_rmqueue(preferred_zone, zone, order, gfp_mask); | 1436 | page = buffered_rmqueue(preferred_zone, zone, order, |
1437 | gfp_mask, migratetype); | ||
1437 | if (page) | 1438 | if (page) |
1438 | break; | 1439 | break; |
1439 | this_zone_full: | 1440 | this_zone_full: |
@@ -1495,7 +1496,8 @@ should_alloc_retry(gfp_t gfp_mask, unsigned int order, | |||
1495 | static inline struct page * | 1496 | static inline struct page * |
1496 | __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, | 1497 | __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, |
1497 | struct zonelist *zonelist, enum zone_type high_zoneidx, | 1498 | struct zonelist *zonelist, enum zone_type high_zoneidx, |
1498 | nodemask_t *nodemask, struct zone *preferred_zone) | 1499 | nodemask_t *nodemask, struct zone *preferred_zone, |
1500 | int migratetype) | ||
1499 | { | 1501 | { |
1500 | struct page *page; | 1502 | struct page *page; |
1501 | 1503 | ||
@@ -1513,7 +1515,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, | |||
1513 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, | 1515 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, |
1514 | order, zonelist, high_zoneidx, | 1516 | order, zonelist, high_zoneidx, |
1515 | ALLOC_WMARK_HIGH|ALLOC_CPUSET, | 1517 | ALLOC_WMARK_HIGH|ALLOC_CPUSET, |
1516 | preferred_zone); | 1518 | preferred_zone, migratetype); |
1517 | if (page) | 1519 | if (page) |
1518 | goto out; | 1520 | goto out; |
1519 | 1521 | ||
@@ -1534,7 +1536,7 @@ static inline struct page * | |||
1534 | __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, | 1536 | __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, |
1535 | struct zonelist *zonelist, enum zone_type high_zoneidx, | 1537 | struct zonelist *zonelist, enum zone_type high_zoneidx, |
1536 | nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, | 1538 | nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, |
1537 | unsigned long *did_some_progress) | 1539 | int migratetype, unsigned long *did_some_progress) |
1538 | { | 1540 | { |
1539 | struct page *page = NULL; | 1541 | struct page *page = NULL; |
1540 | struct reclaim_state reclaim_state; | 1542 | struct reclaim_state reclaim_state; |
@@ -1567,7 +1569,8 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, | |||
1567 | if (likely(*did_some_progress)) | 1569 | if (likely(*did_some_progress)) |
1568 | page = get_page_from_freelist(gfp_mask, nodemask, order, | 1570 | page = get_page_from_freelist(gfp_mask, nodemask, order, |
1569 | zonelist, high_zoneidx, | 1571 | zonelist, high_zoneidx, |
1570 | alloc_flags, preferred_zone); | 1572 | alloc_flags, preferred_zone, |
1573 | migratetype); | ||
1571 | return page; | 1574 | return page; |
1572 | } | 1575 | } |
1573 | 1576 | ||
@@ -1587,14 +1590,15 @@ is_allocation_high_priority(struct task_struct *p, gfp_t gfp_mask) | |||
1587 | static inline struct page * | 1590 | static inline struct page * |
1588 | __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, | 1591 | __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, |
1589 | struct zonelist *zonelist, enum zone_type high_zoneidx, | 1592 | struct zonelist *zonelist, enum zone_type high_zoneidx, |
1590 | nodemask_t *nodemask, struct zone *preferred_zone) | 1593 | nodemask_t *nodemask, struct zone *preferred_zone, |
1594 | int migratetype) | ||
1591 | { | 1595 | { |
1592 | struct page *page; | 1596 | struct page *page; |
1593 | 1597 | ||
1594 | do { | 1598 | do { |
1595 | page = get_page_from_freelist(gfp_mask, nodemask, order, | 1599 | page = get_page_from_freelist(gfp_mask, nodemask, order, |
1596 | zonelist, high_zoneidx, ALLOC_NO_WATERMARKS, | 1600 | zonelist, high_zoneidx, ALLOC_NO_WATERMARKS, |
1597 | preferred_zone); | 1601 | preferred_zone, migratetype); |
1598 | 1602 | ||
1599 | if (!page && gfp_mask & __GFP_NOFAIL) | 1603 | if (!page && gfp_mask & __GFP_NOFAIL) |
1600 | congestion_wait(WRITE, HZ/50); | 1604 | congestion_wait(WRITE, HZ/50); |
@@ -1617,7 +1621,8 @@ void wake_all_kswapd(unsigned int order, struct zonelist *zonelist, | |||
1617 | static inline struct page * | 1621 | static inline struct page * |
1618 | __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, | 1622 | __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, |
1619 | struct zonelist *zonelist, enum zone_type high_zoneidx, | 1623 | struct zonelist *zonelist, enum zone_type high_zoneidx, |
1620 | nodemask_t *nodemask, struct zone *preferred_zone) | 1624 | nodemask_t *nodemask, struct zone *preferred_zone, |
1625 | int migratetype) | ||
1621 | { | 1626 | { |
1622 | const gfp_t wait = gfp_mask & __GFP_WAIT; | 1627 | const gfp_t wait = gfp_mask & __GFP_WAIT; |
1623 | struct page *page = NULL; | 1628 | struct page *page = NULL; |
@@ -1668,7 +1673,8 @@ restart: | |||
1668 | */ | 1673 | */ |
1669 | page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, | 1674 | page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, |
1670 | high_zoneidx, alloc_flags, | 1675 | high_zoneidx, alloc_flags, |
1671 | preferred_zone); | 1676 | preferred_zone, |
1677 | migratetype); | ||
1672 | if (page) | 1678 | if (page) |
1673 | goto got_pg; | 1679 | goto got_pg; |
1674 | 1680 | ||
@@ -1678,7 +1684,8 @@ rebalance: | |||
1678 | /* Do not dip into emergency reserves if specified */ | 1684 | /* Do not dip into emergency reserves if specified */ |
1679 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { | 1685 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { |
1680 | page = __alloc_pages_high_priority(gfp_mask, order, | 1686 | page = __alloc_pages_high_priority(gfp_mask, order, |
1681 | zonelist, high_zoneidx, nodemask, preferred_zone); | 1687 | zonelist, high_zoneidx, nodemask, preferred_zone, |
1688 | migratetype); | ||
1682 | if (page) | 1689 | if (page) |
1683 | goto got_pg; | 1690 | goto got_pg; |
1684 | } | 1691 | } |
@@ -1696,7 +1703,7 @@ rebalance: | |||
1696 | zonelist, high_zoneidx, | 1703 | zonelist, high_zoneidx, |
1697 | nodemask, | 1704 | nodemask, |
1698 | alloc_flags, preferred_zone, | 1705 | alloc_flags, preferred_zone, |
1699 | &did_some_progress); | 1706 | migratetype, &did_some_progress); |
1700 | if (page) | 1707 | if (page) |
1701 | goto got_pg; | 1708 | goto got_pg; |
1702 | 1709 | ||
@@ -1708,7 +1715,8 @@ rebalance: | |||
1708 | if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { | 1715 | if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { |
1709 | page = __alloc_pages_may_oom(gfp_mask, order, | 1716 | page = __alloc_pages_may_oom(gfp_mask, order, |
1710 | zonelist, high_zoneidx, | 1717 | zonelist, high_zoneidx, |
1711 | nodemask, preferred_zone); | 1718 | nodemask, preferred_zone, |
1719 | migratetype); | ||
1712 | if (page) | 1720 | if (page) |
1713 | goto got_pg; | 1721 | goto got_pg; |
1714 | 1722 | ||
@@ -1755,6 +1763,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, | |||
1755 | enum zone_type high_zoneidx = gfp_zone(gfp_mask); | 1763 | enum zone_type high_zoneidx = gfp_zone(gfp_mask); |
1756 | struct zone *preferred_zone; | 1764 | struct zone *preferred_zone; |
1757 | struct page *page; | 1765 | struct page *page; |
1766 | int migratetype = allocflags_to_migratetype(gfp_mask); | ||
1758 | 1767 | ||
1759 | lockdep_trace_alloc(gfp_mask); | 1768 | lockdep_trace_alloc(gfp_mask); |
1760 | 1769 | ||
@@ -1779,11 +1788,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, | |||
1779 | /* First allocation attempt */ | 1788 | /* First allocation attempt */ |
1780 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, | 1789 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, |
1781 | zonelist, high_zoneidx, ALLOC_WMARK_LOW|ALLOC_CPUSET, | 1790 | zonelist, high_zoneidx, ALLOC_WMARK_LOW|ALLOC_CPUSET, |
1782 | preferred_zone); | 1791 | preferred_zone, migratetype); |
1783 | if (unlikely(!page)) | 1792 | if (unlikely(!page)) |
1784 | page = __alloc_pages_slowpath(gfp_mask, order, | 1793 | page = __alloc_pages_slowpath(gfp_mask, order, |
1785 | zonelist, high_zoneidx, nodemask, | 1794 | zonelist, high_zoneidx, nodemask, |
1786 | preferred_zone); | 1795 | preferred_zone, migratetype); |
1787 | 1796 | ||
1788 | return page; | 1797 | return page; |
1789 | } | 1798 | } |