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 | |
| 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>
| -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 | } |
