aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.com>2017-02-22 18:45:58 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:43 -0500
commit710531320af876192d76b2c1f68190a1df941b02 (patch)
treecefd9265906ea0559a1530ec3226484bbc274381
parent8f6620e391a43d5da24fa09f98d9b51016545470 (diff)
mm, vmscan: cleanup lru size claculations
commit fd538803731e50367b7c59ce4ad3454426a3d671 upstream. lruvec_lru_size returns the full size of the LRU list while we sometimes need a value reduced only to eligible zones (e.g. for lowmem requests). inactive_list_is_low is one such user. Later patches will add more of them. Add a new parameter to lruvec_lru_size and allow it filter out zones which are not eligible for the given context. Link: http://lkml.kernel.org/r/20170117103702.28542-2-mhocko@kernel.org Signed-off-by: Michal Hocko <mhocko@suse.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com> Acked-by: Minchan Kim <minchan@kernel.org> Acked-by: Mel Gorman <mgorman@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--mm/vmscan.c81
-rw-r--r--mm/workingset.c2
3 files changed, 41 insertions, 44 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index f99c993dd500..7e273e243a13 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -779,7 +779,7 @@ static inline struct pglist_data *lruvec_pgdat(struct lruvec *lruvec)
779#endif 779#endif
780} 780}
781 781
782extern unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru); 782extern unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone_idx);
783 783
784#ifdef CONFIG_HAVE_MEMORY_PRESENT 784#ifdef CONFIG_HAVE_MEMORY_PRESENT
785void memory_present(int nid, unsigned long start, unsigned long end); 785void memory_present(int nid, unsigned long start, unsigned long end);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index fa30010a5277..cd516c632e8f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -234,22 +234,39 @@ bool pgdat_reclaimable(struct pglist_data *pgdat)
234 pgdat_reclaimable_pages(pgdat) * 6; 234 pgdat_reclaimable_pages(pgdat) * 6;
235} 235}
236 236
237unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru) 237/**
238 * lruvec_lru_size - Returns the number of pages on the given LRU list.
239 * @lruvec: lru vector
240 * @lru: lru to use
241 * @zone_idx: zones to consider (use MAX_NR_ZONES for the whole LRU list)
242 */
243unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone_idx)
238{ 244{
245 unsigned long lru_size;
246 int zid;
247
239 if (!mem_cgroup_disabled()) 248 if (!mem_cgroup_disabled())
240 return mem_cgroup_get_lru_size(lruvec, lru); 249 lru_size = mem_cgroup_get_lru_size(lruvec, lru);
250 else
251 lru_size = node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru);
241 252
242 return node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru); 253 for (zid = zone_idx + 1; zid < MAX_NR_ZONES; zid++) {
243} 254 struct zone *zone = &lruvec_pgdat(lruvec)->node_zones[zid];
255 unsigned long size;
244 256
245unsigned long lruvec_zone_lru_size(struct lruvec *lruvec, enum lru_list lru, 257 if (!managed_zone(zone))
246 int zone_idx) 258 continue;
247{ 259
248 if (!mem_cgroup_disabled()) 260 if (!mem_cgroup_disabled())
249 return mem_cgroup_get_zone_lru_size(lruvec, lru, zone_idx); 261 size = mem_cgroup_get_zone_lru_size(lruvec, lru, zid);
262 else
263 size = zone_page_state(&lruvec_pgdat(lruvec)->node_zones[zid],
264 NR_ZONE_LRU_BASE + lru);
265 lru_size -= min(size, lru_size);
266 }
267
268 return lru_size;
250 269
251 return zone_page_state(&lruvec_pgdat(lruvec)->node_zones[zone_idx],
252 NR_ZONE_LRU_BASE + lru);
253} 270}
254 271
255/* 272/*
@@ -2028,11 +2045,10 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
2028 struct scan_control *sc) 2045 struct scan_control *sc)
2029{ 2046{
2030 unsigned long inactive_ratio; 2047 unsigned long inactive_ratio;
2031 unsigned long inactive; 2048 unsigned long inactive, active;
2032 unsigned long active; 2049 enum lru_list inactive_lru = file * LRU_FILE;
2050 enum lru_list active_lru = file * LRU_FILE + LRU_ACTIVE;
2033 unsigned long gb; 2051 unsigned long gb;
2034 struct pglist_data *pgdat = lruvec_pgdat(lruvec);
2035 int zid;
2036 2052
2037 /* 2053 /*
2038 * If we don't have swap space, anonymous page deactivation 2054 * If we don't have swap space, anonymous page deactivation
@@ -2041,27 +2057,8 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
2041 if (!file && !total_swap_pages) 2057 if (!file && !total_swap_pages)
2042 return false; 2058 return false;
2043 2059
2044 inactive = lruvec_lru_size(lruvec, file * LRU_FILE); 2060 inactive = lruvec_lru_size(lruvec, inactive_lru, sc->reclaim_idx);
2045 active = lruvec_lru_size(lruvec, file * LRU_FILE + LRU_ACTIVE); 2061 active = lruvec_lru_size(lruvec, active_lru, sc->reclaim_idx);
2046
2047 /*
2048 * For zone-constrained allocations, it is necessary to check if
2049 * deactivations are required for lowmem to be reclaimed. This
2050 * calculates the inactive/active pages available in eligible zones.
2051 */
2052 for (zid = sc->reclaim_idx + 1; zid < MAX_NR_ZONES; zid++) {
2053 struct zone *zone = &pgdat->node_zones[zid];
2054 unsigned long inactive_zone, active_zone;
2055
2056 if (!managed_zone(zone))
2057 continue;
2058
2059 inactive_zone = lruvec_zone_lru_size(lruvec, file * LRU_FILE, zid);
2060 active_zone = lruvec_zone_lru_size(lruvec, (file * LRU_FILE) + LRU_ACTIVE, zid);
2061
2062 inactive -= min(inactive, inactive_zone);
2063 active -= min(active, active_zone);
2064 }
2065 2062
2066 gb = (inactive + active) >> (30 - PAGE_SHIFT); 2063 gb = (inactive + active) >> (30 - PAGE_SHIFT);
2067 if (gb) 2064 if (gb)
@@ -2208,7 +2205,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
2208 * system is under heavy pressure. 2205 * system is under heavy pressure.
2209 */ 2206 */
2210 if (!inactive_list_is_low(lruvec, true, sc) && 2207 if (!inactive_list_is_low(lruvec, true, sc) &&
2211 lruvec_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) { 2208 lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES) >> sc->priority) {
2212 scan_balance = SCAN_FILE; 2209 scan_balance = SCAN_FILE;
2213 goto out; 2210 goto out;
2214 } 2211 }
@@ -2234,10 +2231,10 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
2234 * anon in [0], file in [1] 2231 * anon in [0], file in [1]
2235 */ 2232 */
2236 2233
2237 anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON) + 2234 anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
2238 lruvec_lru_size(lruvec, LRU_INACTIVE_ANON); 2235 lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, MAX_NR_ZONES);
2239 file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE) + 2236 file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
2240 lruvec_lru_size(lruvec, LRU_INACTIVE_FILE); 2237 lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES);
2241 2238
2242 spin_lock_irq(&pgdat->lru_lock); 2239 spin_lock_irq(&pgdat->lru_lock);
2243 if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) { 2240 if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) {
@@ -2275,7 +2272,7 @@ out:
2275 unsigned long size; 2272 unsigned long size;
2276 unsigned long scan; 2273 unsigned long scan;
2277 2274
2278 size = lruvec_lru_size(lruvec, lru); 2275 size = lruvec_lru_size(lruvec, lru, MAX_NR_ZONES);
2279 scan = size >> sc->priority; 2276 scan = size >> sc->priority;
2280 2277
2281 if (!scan && pass && force_scan) 2278 if (!scan && pass && force_scan)
diff --git a/mm/workingset.c b/mm/workingset.c
index fb1f9183d89a..33f6f4db32fd 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -266,7 +266,7 @@ bool workingset_refault(void *shadow)
266 } 266 }
267 lruvec = mem_cgroup_lruvec(pgdat, memcg); 267 lruvec = mem_cgroup_lruvec(pgdat, memcg);
268 refault = atomic_long_read(&lruvec->inactive_age); 268 refault = atomic_long_read(&lruvec->inactive_age);
269 active_file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE); 269 active_file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES);
270 rcu_read_unlock(); 270 rcu_read_unlock();
271 271
272 /* 272 /*