diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-06-16 18:32:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:47:33 -0400 |
commit | 341ce06f69abfafa31b9468410a13dbd60e2b237 (patch) | |
tree | d7702157c9addb8e67e6dce883650e20b3ddcbfd | |
parent | 3dd2826698b6902aafd9441ce28ebb44735fd0d6 (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>
-rw-r--r-- | mm/page_alloc.c | 94 |
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 | ||
1577 | static inline int | ||
1578 | is_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 | ||
1612 | static inline int | ||
1613 | gfp_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 | |||
1621 | static inline struct page * | 1648 | static 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 | ||
1665 | restart: | 1681 | restart: |
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 | ||
1681 | rebalance: | 1689 | rebalance: |
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, |