mm: vmscan: clarify how swappiness, highest priority, memcg interact
A swappiness of 0 has a slightly different meaning for global reclaim (may swap if file cache really low) and memory cgroup reclaim (never swap, ever). In addition, global reclaim at highest priority will scan all LRU lists equal to their size and ignore other balancing heuristics. UNLESS swappiness forbids swapping, then the lists are balanced based on recent reclaim effectiveness. UNLESS file cache is running low, then anonymous pages are force-scanned. This (total mess of a) behaviour is implicit and not obvious from the way the code is organized. At least make it apparent in the code flow and document the conditions. It will be it easier to come up with sane semantics later. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Rik van Riel <riel@redhat.com> Reviewed-by: Satoru Moriya <satoru.moriya@hds.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Acked-by: Mel Gorman <mgorman@suse.de> Cc: Hugh Dickins <hughd@google.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>
This commit is contained in:
parent
d778df51c0
commit
10316b313c
1 changed files with 30 additions and 9 deletions
39
mm/vmscan.c
39
mm/vmscan.c
|
@ -1656,7 +1656,6 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
|
||||||
struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat;
|
struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat;
|
||||||
u64 fraction[2], denominator;
|
u64 fraction[2], denominator;
|
||||||
enum lru_list lru;
|
enum lru_list lru;
|
||||||
int noswap = 0;
|
|
||||||
bool force_scan = false;
|
bool force_scan = false;
|
||||||
struct zone *zone = lruvec_zone(lruvec);
|
struct zone *zone = lruvec_zone(lruvec);
|
||||||
|
|
||||||
|
@ -1677,13 +1676,38 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
|
||||||
|
|
||||||
/* If we have no swap space, do not bother scanning anon pages. */
|
/* If we have no swap space, do not bother scanning anon pages. */
|
||||||
if (!sc->may_swap || (nr_swap_pages <= 0)) {
|
if (!sc->may_swap || (nr_swap_pages <= 0)) {
|
||||||
noswap = 1;
|
|
||||||
fraction[0] = 0;
|
fraction[0] = 0;
|
||||||
fraction[1] = 1;
|
fraction[1] = 1;
|
||||||
denominator = 1;
|
denominator = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global reclaim will swap to prevent OOM even with no
|
||||||
|
* swappiness, but memcg users want to use this knob to
|
||||||
|
* disable swapping for individual groups completely when
|
||||||
|
* using the memory controller's swap limit feature would be
|
||||||
|
* too expensive.
|
||||||
|
*/
|
||||||
|
if (!global_reclaim(sc) && !vmscan_swappiness(sc)) {
|
||||||
|
fraction[0] = 0;
|
||||||
|
fraction[1] = 1;
|
||||||
|
denominator = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not apply any pressure balancing cleverness when the
|
||||||
|
* system is close to OOM, scan both anon and file equally
|
||||||
|
* (unless the swappiness setting disagrees with swapping).
|
||||||
|
*/
|
||||||
|
if (!sc->priority && vmscan_swappiness(sc)) {
|
||||||
|
fraction[0] = 1;
|
||||||
|
fraction[1] = 1;
|
||||||
|
denominator = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) +
|
anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) +
|
||||||
get_lru_size(lruvec, LRU_INACTIVE_ANON);
|
get_lru_size(lruvec, LRU_INACTIVE_ANON);
|
||||||
file = get_lru_size(lruvec, LRU_ACTIVE_FILE) +
|
file = get_lru_size(lruvec, LRU_ACTIVE_FILE) +
|
||||||
|
@ -1765,13 +1789,10 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
|
||||||
unsigned long scan;
|
unsigned long scan;
|
||||||
|
|
||||||
size = get_lru_size(lruvec, lru);
|
size = get_lru_size(lruvec, lru);
|
||||||
if (sc->priority || noswap || !vmscan_swappiness(sc)) {
|
scan = size >> sc->priority;
|
||||||
scan = size >> sc->priority;
|
if (!scan && force_scan)
|
||||||
if (!scan && force_scan)
|
scan = min(size, SWAP_CLUSTER_MAX);
|
||||||
scan = min(size, SWAP_CLUSTER_MAX);
|
scan = div64_u64(scan * fraction[file], denominator);
|
||||||
scan = div64_u64(scan * fraction[file], denominator);
|
|
||||||
} else
|
|
||||||
scan = size;
|
|
||||||
nr[lru] = scan;
|
nr[lru] = scan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue