aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-06-16 18:32:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:47:33 -0400
commit341ce06f69abfafa31b9468410a13dbd60e2b237 (patch)
treed7702157c9addb8e67e6dce883650e20b3ddcbfd /mm
parent3dd2826698b6902aafd9441ce28ebb44735fd0d6 (diff)
page allocator: calculate the alloc_flags for allocation only once
Factor out the mapping between GFP and alloc_flags only once. Once factored out, it only needs to be calculated once but some care must be taken. [neilb@suse.de says] As the test: - if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) - && !in_interrupt()) { - if (!(gfp_mask & __GFP_NOMEMALLOC)) { has been replaced with a slightly weaker one: + if (alloc_flags & ALLOC_NO_WATERMARKS) { Without care, this would allow recursion into the allocator via direct reclaim. This patch ensures we do not recurse when PF_MEMALLOC is set but TF_MEMDIE callers are now allowed to directly reclaim where they would have been prevented in the past. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Mel Gorman <mel@csn.ul.ie> Cc: Neil Brown <neilb@suse.de> Cc: Christoph Lameter <cl@linux-foundation.org> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> 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')
-rw-r--r--mm/page_alloc.c94
1 files changed, 50 insertions, 44 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d3be076ea9c5..ef870fb92f74 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1574,15 +1574,6 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
1574 return page; 1574 return page;
1575} 1575}
1576 1576
1577static inline int
1578is_allocation_high_priority(struct task_struct *p, gfp_t gfp_mask)
1579{
1580 if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE)))
1581 && !in_interrupt())
1582 return 1;
1583 return 0;
1584}
1585
1586/* 1577/*
1587 * This is called in the allocator slow-path if the allocation request is of 1578 * This is called in the allocator slow-path if the allocation request is of
1588 * sufficient urgency to ignore watermarks and take other desperate measures 1579 * sufficient urgency to ignore watermarks and take other desperate measures
@@ -1618,6 +1609,42 @@ void wake_all_kswapd(unsigned int order, struct zonelist *zonelist,
1618 wakeup_kswapd(zone, order); 1609 wakeup_kswapd(zone, order);
1619} 1610}
1620 1611
1612static inline int
1613gfp_to_alloc_flags(gfp_t gfp_mask)
1614{
1615 struct task_struct *p = current;
1616 int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET;
1617 const gfp_t wait = gfp_mask & __GFP_WAIT;
1618
1619 /*
1620 * The caller may dip into page reserves a bit more if the caller
1621 * cannot run direct reclaim, or if the caller has realtime scheduling
1622 * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will
1623 * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH).
1624 */
1625 if (gfp_mask & __GFP_HIGH)
1626 alloc_flags |= ALLOC_HIGH;
1627
1628 if (!wait) {
1629 alloc_flags |= ALLOC_HARDER;
1630 /*
1631 * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
1632 * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
1633 */
1634 alloc_flags &= ~ALLOC_CPUSET;
1635 } else if (unlikely(rt_task(p)))
1636 alloc_flags |= ALLOC_HARDER;
1637
1638 if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {
1639 if (!in_interrupt() &&
1640 ((p->flags & PF_MEMALLOC) ||
1641 unlikely(test_thread_flag(TIF_MEMDIE))))
1642 alloc_flags |= ALLOC_NO_WATERMARKS;
1643 }
1644
1645 return alloc_flags;
1646}
1647
1621static inline struct page * 1648static inline struct page *
1622__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, 1649__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
1623 struct zonelist *zonelist, enum zone_type high_zoneidx, 1650 struct zonelist *zonelist, enum zone_type high_zoneidx,
@@ -1648,56 +1675,35 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
1648 * OK, we're below the kswapd watermark and have kicked background 1675 * OK, we're below the kswapd watermark and have kicked background
1649 * reclaim. Now things get more complex, so set up alloc_flags according 1676 * reclaim. Now things get more complex, so set up alloc_flags according
1650 * to how we want to proceed. 1677 * to how we want to proceed.
1651 *
1652 * The caller may dip into page reserves a bit more if the caller
1653 * cannot run direct reclaim, or if the caller has realtime scheduling
1654 * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will
1655 * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH).
1656 */ 1678 */
1657 alloc_flags = ALLOC_WMARK_MIN; 1679 alloc_flags = gfp_to_alloc_flags(gfp_mask);
1658 if ((unlikely(rt_task(p)) && !in_interrupt()) || !wait)
1659 alloc_flags |= ALLOC_HARDER;
1660 if (gfp_mask & __GFP_HIGH)
1661 alloc_flags |= ALLOC_HIGH;
1662 if (wait)
1663 alloc_flags |= ALLOC_CPUSET;
1664 1680
1665restart: 1681restart:
1666 /* 1682 /* This is the last chance, in general, before the goto nopage. */
1667 * Go through the zonelist again. Let __GFP_HIGH and allocations
1668 * coming from realtime tasks go deeper into reserves.
1669 *
1670 * This is the last chance, in general, before the goto nopage.
1671 * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
1672 * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
1673 */
1674 page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, 1683 page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist,
1675 high_zoneidx, alloc_flags, 1684 high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS,
1676 preferred_zone, 1685 preferred_zone, migratetype);
1677 migratetype);
1678 if (page) 1686 if (page)
1679 goto got_pg; 1687 goto got_pg;
1680 1688
1681rebalance: 1689rebalance:
1682 /* Allocate without watermarks if the context allows */ 1690 /* Allocate without watermarks if the context allows */
1683 if (is_allocation_high_priority(p, gfp_mask)) { 1691 if (alloc_flags & ALLOC_NO_WATERMARKS) {
1684 /* Do not dip into emergency reserves if specified */ 1692 page = __alloc_pages_high_priority(gfp_mask, order,
1685 if (!(gfp_mask & __GFP_NOMEMALLOC)) { 1693 zonelist, high_zoneidx, nodemask,
1686 page = __alloc_pages_high_priority(gfp_mask, order, 1694 preferred_zone, migratetype);
1687 zonelist, high_zoneidx, nodemask, preferred_zone, 1695 if (page)
1688 migratetype); 1696 goto got_pg;
1689 if (page)
1690 goto got_pg;
1691 }
1692
1693 /* Ensure no recursion into the allocator */
1694 goto nopage;
1695 } 1697 }
1696 1698
1697 /* Atomic allocations - we can't balance anything */ 1699 /* Atomic allocations - we can't balance anything */
1698 if (!wait) 1700 if (!wait)
1699 goto nopage; 1701 goto nopage;
1700 1702
1703 /* Avoid recursion of direct reclaim */
1704 if (p->flags & PF_MEMALLOC)
1705 goto nopage;
1706
1701 /* Try direct reclaim and then allocating */ 1707 /* Try direct reclaim and then allocating */
1702 page = __alloc_pages_direct_reclaim(gfp_mask, order, 1708 page = __alloc_pages_direct_reclaim(gfp_mask, order,
1703 zonelist, high_zoneidx, 1709 zonelist, high_zoneidx,