diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2013-02-22 19:32:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 20:50:09 -0500 |
commit | 9a2651140ef740b3b67ad47ea3d0af75581aacc6 (patch) | |
tree | f839527265f7076f05504efa4371a648b0d01e3a /mm | |
parent | 11d16c25bbf7a3b7a43d7472e175cdd52961757d (diff) |
mm: vmscan: clean up get_scan_count()
Reclaim pressure balance between anon and file pages is calculated
through a tuple of numerators and a shared denominator.
Exceptional cases that want to force-scan anon or file pages configure
the numerators and denominator such that one list is preferred, which is
not necessarily the most obvious way:
fraction[0] = 1;
fraction[1] = 0;
denominator = 1;
goto out;
Make this easier by making the force-scan cases explicit and use the
fractionals only in case they are calculated from reclaim history.
[akpm@linux-foundation.org: avoid using unintialized_var()]
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Rik van Riel <riel@redhat.com>
Acked-by: Mel Gorman <mgorman@suse.de>
Reviewed-by: Michal Hocko <mhocko@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
Cc: Satoru Moriya <satoru.moriya@hds.com>
Cc: Simon Jeons <simon.jeons@gmail.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/vmscan.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 259f8208a388..d4f37634194e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1638,6 +1638,13 @@ static int vmscan_swappiness(struct scan_control *sc) | |||
1638 | return mem_cgroup_swappiness(sc->target_mem_cgroup); | 1638 | return mem_cgroup_swappiness(sc->target_mem_cgroup); |
1639 | } | 1639 | } |
1640 | 1640 | ||
1641 | enum scan_balance { | ||
1642 | SCAN_EQUAL, | ||
1643 | SCAN_FRACT, | ||
1644 | SCAN_ANON, | ||
1645 | SCAN_FILE, | ||
1646 | }; | ||
1647 | |||
1641 | /* | 1648 | /* |
1642 | * Determine how aggressively the anon and file LRU lists should be | 1649 | * Determine how aggressively the anon and file LRU lists should be |
1643 | * scanned. The relative value of each set of LRU lists is determined | 1650 | * scanned. The relative value of each set of LRU lists is determined |
@@ -1650,14 +1657,16 @@ static int vmscan_swappiness(struct scan_control *sc) | |||
1650 | static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | 1657 | static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, |
1651 | unsigned long *nr) | 1658 | unsigned long *nr) |
1652 | { | 1659 | { |
1653 | unsigned long anon, file, free; | 1660 | struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat; |
1661 | u64 fraction[2]; | ||
1662 | u64 denominator = 0; /* gcc */ | ||
1663 | struct zone *zone = lruvec_zone(lruvec); | ||
1654 | unsigned long anon_prio, file_prio; | 1664 | unsigned long anon_prio, file_prio; |
1665 | enum scan_balance scan_balance; | ||
1666 | unsigned long anon, file, free; | ||
1667 | bool force_scan = false; | ||
1655 | unsigned long ap, fp; | 1668 | unsigned long ap, fp; |
1656 | struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat; | ||
1657 | u64 fraction[2], denominator; | ||
1658 | enum lru_list lru; | 1669 | enum lru_list lru; |
1659 | bool force_scan = false; | ||
1660 | struct zone *zone = lruvec_zone(lruvec); | ||
1661 | 1670 | ||
1662 | /* | 1671 | /* |
1663 | * If the zone or memcg is small, nr[l] can be 0. This | 1672 | * If the zone or memcg is small, nr[l] can be 0. This |
@@ -1676,9 +1685,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | |||
1676 | 1685 | ||
1677 | /* If we have no swap space, do not bother scanning anon pages. */ | 1686 | /* If we have no swap space, do not bother scanning anon pages. */ |
1678 | if (!sc->may_swap || (nr_swap_pages <= 0)) { | 1687 | if (!sc->may_swap || (nr_swap_pages <= 0)) { |
1679 | fraction[0] = 0; | 1688 | scan_balance = SCAN_FILE; |
1680 | fraction[1] = 1; | ||
1681 | denominator = 1; | ||
1682 | goto out; | 1689 | goto out; |
1683 | } | 1690 | } |
1684 | 1691 | ||
@@ -1690,9 +1697,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | |||
1690 | * too expensive. | 1697 | * too expensive. |
1691 | */ | 1698 | */ |
1692 | if (!global_reclaim(sc) && !vmscan_swappiness(sc)) { | 1699 | if (!global_reclaim(sc) && !vmscan_swappiness(sc)) { |
1693 | fraction[0] = 0; | 1700 | scan_balance = SCAN_FILE; |
1694 | fraction[1] = 1; | ||
1695 | denominator = 1; | ||
1696 | goto out; | 1701 | goto out; |
1697 | } | 1702 | } |
1698 | 1703 | ||
@@ -1702,9 +1707,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | |||
1702 | * (unless the swappiness setting disagrees with swapping). | 1707 | * (unless the swappiness setting disagrees with swapping). |
1703 | */ | 1708 | */ |
1704 | if (!sc->priority && vmscan_swappiness(sc)) { | 1709 | if (!sc->priority && vmscan_swappiness(sc)) { |
1705 | fraction[0] = 1; | 1710 | scan_balance = SCAN_EQUAL; |
1706 | fraction[1] = 1; | ||
1707 | denominator = 1; | ||
1708 | goto out; | 1711 | goto out; |
1709 | } | 1712 | } |
1710 | 1713 | ||
@@ -1722,9 +1725,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | |||
1722 | if (global_reclaim(sc)) { | 1725 | if (global_reclaim(sc)) { |
1723 | free = zone_page_state(zone, NR_FREE_PAGES); | 1726 | free = zone_page_state(zone, NR_FREE_PAGES); |
1724 | if (unlikely(file + free <= high_wmark_pages(zone))) { | 1727 | if (unlikely(file + free <= high_wmark_pages(zone))) { |
1725 | fraction[0] = 1; | 1728 | scan_balance = SCAN_ANON; |
1726 | fraction[1] = 0; | ||
1727 | denominator = 1; | ||
1728 | goto out; | 1729 | goto out; |
1729 | } | 1730 | } |
1730 | } | 1731 | } |
@@ -1734,12 +1735,12 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, | |||
1734 | * anything from the anonymous working set right now. | 1735 | * anything from the anonymous working set right now. |
1735 | */ | 1736 | */ |
1736 | if (!inactive_file_is_low(lruvec)) { | 1737 | if (!inactive_file_is_low(lruvec)) { |
1737 | fraction[0] = 0; | 1738 | scan_balance = SCAN_FILE; |
1738 | fraction[1] = 1; | ||
1739 | denominator = 1; | ||
1740 | goto out; | 1739 | goto out; |
1741 | } | 1740 | } |
1742 | 1741 | ||
1742 | scan_balance = SCAN_FRACT; | ||
1743 | |||
1743 | /* | 1744 | /* |
1744 | * With swappiness at 100, anonymous and file have the same priority. | 1745 | * With swappiness at 100, anonymous and file have the same priority. |
1745 | * This scanning priority is essentially the inverse of IO cost. | 1746 | * This scanning priority is essentially the inverse of IO cost. |
@@ -1792,9 +1793,31 @@ out: | |||
1792 | 1793 | ||
1793 | size = get_lru_size(lruvec, lru); | 1794 | size = get_lru_size(lruvec, lru); |
1794 | scan = size >> sc->priority; | 1795 | scan = size >> sc->priority; |
1796 | |||
1795 | if (!scan && force_scan) | 1797 | if (!scan && force_scan) |
1796 | scan = min(size, SWAP_CLUSTER_MAX); | 1798 | scan = min(size, SWAP_CLUSTER_MAX); |
1797 | scan = div64_u64(scan * fraction[file], denominator); | 1799 | |
1800 | switch (scan_balance) { | ||
1801 | case SCAN_EQUAL: | ||
1802 | /* Scan lists relative to size */ | ||
1803 | break; | ||
1804 | case SCAN_FRACT: | ||
1805 | /* | ||
1806 | * Scan types proportional to swappiness and | ||
1807 | * their relative recent reclaim efficiency. | ||
1808 | */ | ||
1809 | scan = div64_u64(scan * fraction[file], denominator); | ||
1810 | break; | ||
1811 | case SCAN_FILE: | ||
1812 | case SCAN_ANON: | ||
1813 | /* Scan one type exclusively */ | ||
1814 | if ((scan_balance == SCAN_FILE) != file) | ||
1815 | scan = 0; | ||
1816 | break; | ||
1817 | default: | ||
1818 | /* Look ma, no brain */ | ||
1819 | BUG(); | ||
1820 | } | ||
1798 | nr[lru] = scan; | 1821 | nr[lru] = scan; |
1799 | } | 1822 | } |
1800 | } | 1823 | } |