diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 69 |
1 files changed, 20 insertions, 49 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 7ef69124fa3e..b55699cd9067 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -105,7 +105,6 @@ struct scan_control { | |||
105 | 105 | ||
106 | /* Which cgroup do we reclaim from */ | 106 | /* Which cgroup do we reclaim from */ |
107 | struct mem_cgroup *mem_cgroup; | 107 | struct mem_cgroup *mem_cgroup; |
108 | struct memcg_scanrecord *memcg_record; | ||
109 | 108 | ||
110 | /* | 109 | /* |
111 | * Nodemask of nodes allowed by the caller. If NULL, all nodes | 110 | * Nodemask of nodes allowed by the caller. If NULL, all nodes |
@@ -1349,8 +1348,6 @@ putback_lru_pages(struct zone *zone, struct scan_control *sc, | |||
1349 | int file = is_file_lru(lru); | 1348 | int file = is_file_lru(lru); |
1350 | int numpages = hpage_nr_pages(page); | 1349 | int numpages = hpage_nr_pages(page); |
1351 | reclaim_stat->recent_rotated[file] += numpages; | 1350 | reclaim_stat->recent_rotated[file] += numpages; |
1352 | if (!scanning_global_lru(sc)) | ||
1353 | sc->memcg_record->nr_rotated[file] += numpages; | ||
1354 | } | 1351 | } |
1355 | if (!pagevec_add(&pvec, page)) { | 1352 | if (!pagevec_add(&pvec, page)) { |
1356 | spin_unlock_irq(&zone->lru_lock); | 1353 | spin_unlock_irq(&zone->lru_lock); |
@@ -1394,10 +1391,6 @@ static noinline_for_stack void update_isolated_counts(struct zone *zone, | |||
1394 | 1391 | ||
1395 | reclaim_stat->recent_scanned[0] += *nr_anon; | 1392 | reclaim_stat->recent_scanned[0] += *nr_anon; |
1396 | reclaim_stat->recent_scanned[1] += *nr_file; | 1393 | reclaim_stat->recent_scanned[1] += *nr_file; |
1397 | if (!scanning_global_lru(sc)) { | ||
1398 | sc->memcg_record->nr_scanned[0] += *nr_anon; | ||
1399 | sc->memcg_record->nr_scanned[1] += *nr_file; | ||
1400 | } | ||
1401 | } | 1394 | } |
1402 | 1395 | ||
1403 | /* | 1396 | /* |
@@ -1511,9 +1504,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1511 | nr_reclaimed += shrink_page_list(&page_list, zone, sc); | 1504 | nr_reclaimed += shrink_page_list(&page_list, zone, sc); |
1512 | } | 1505 | } |
1513 | 1506 | ||
1514 | if (!scanning_global_lru(sc)) | ||
1515 | sc->memcg_record->nr_freed[file] += nr_reclaimed; | ||
1516 | |||
1517 | local_irq_disable(); | 1507 | local_irq_disable(); |
1518 | if (current_is_kswapd()) | 1508 | if (current_is_kswapd()) |
1519 | __count_vm_events(KSWAPD_STEAL, nr_reclaimed); | 1509 | __count_vm_events(KSWAPD_STEAL, nr_reclaimed); |
@@ -1613,8 +1603,6 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1613 | } | 1603 | } |
1614 | 1604 | ||
1615 | reclaim_stat->recent_scanned[file] += nr_taken; | 1605 | reclaim_stat->recent_scanned[file] += nr_taken; |
1616 | if (!scanning_global_lru(sc)) | ||
1617 | sc->memcg_record->nr_scanned[file] += nr_taken; | ||
1618 | 1606 | ||
1619 | __count_zone_vm_events(PGREFILL, zone, pgscanned); | 1607 | __count_zone_vm_events(PGREFILL, zone, pgscanned); |
1620 | if (file) | 1608 | if (file) |
@@ -1666,8 +1654,6 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1666 | * get_scan_ratio. | 1654 | * get_scan_ratio. |
1667 | */ | 1655 | */ |
1668 | reclaim_stat->recent_rotated[file] += nr_rotated; | 1656 | reclaim_stat->recent_rotated[file] += nr_rotated; |
1669 | if (!scanning_global_lru(sc)) | ||
1670 | sc->memcg_record->nr_rotated[file] += nr_rotated; | ||
1671 | 1657 | ||
1672 | move_active_pages_to_lru(zone, &l_active, | 1658 | move_active_pages_to_lru(zone, &l_active, |
1673 | LRU_ACTIVE + file * LRU_FILE); | 1659 | LRU_ACTIVE + file * LRU_FILE); |
@@ -1808,23 +1794,15 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc, | |||
1808 | u64 fraction[2], denominator; | 1794 | u64 fraction[2], denominator; |
1809 | enum lru_list l; | 1795 | enum lru_list l; |
1810 | int noswap = 0; | 1796 | int noswap = 0; |
1811 | int force_scan = 0; | 1797 | bool force_scan = false; |
1812 | unsigned long nr_force_scan[2]; | 1798 | unsigned long nr_force_scan[2]; |
1813 | 1799 | ||
1814 | 1800 | /* kswapd does zone balancing and needs to scan this zone */ | |
1815 | anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) + | 1801 | if (scanning_global_lru(sc) && current_is_kswapd()) |
1816 | zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON); | 1802 | force_scan = true; |
1817 | file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) + | 1803 | /* memcg may have small limit and need to avoid priority drop */ |
1818 | zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); | 1804 | if (!scanning_global_lru(sc)) |
1819 | 1805 | force_scan = true; | |
1820 | if (((anon + file) >> priority) < SWAP_CLUSTER_MAX) { | ||
1821 | /* kswapd does zone balancing and need to scan this zone */ | ||
1822 | if (scanning_global_lru(sc) && current_is_kswapd()) | ||
1823 | force_scan = 1; | ||
1824 | /* memcg may have small limit and need to avoid priority drop */ | ||
1825 | if (!scanning_global_lru(sc)) | ||
1826 | force_scan = 1; | ||
1827 | } | ||
1828 | 1806 | ||
1829 | /* If we have no swap space, do not bother scanning anon pages. */ | 1807 | /* If we have no swap space, do not bother scanning anon pages. */ |
1830 | if (!sc->may_swap || (nr_swap_pages <= 0)) { | 1808 | if (!sc->may_swap || (nr_swap_pages <= 0)) { |
@@ -1837,6 +1815,11 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc, | |||
1837 | goto out; | 1815 | goto out; |
1838 | } | 1816 | } |
1839 | 1817 | ||
1818 | anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) + | ||
1819 | zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON); | ||
1820 | file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) + | ||
1821 | zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); | ||
1822 | |||
1840 | if (scanning_global_lru(sc)) { | 1823 | if (scanning_global_lru(sc)) { |
1841 | free = zone_page_state(zone, NR_FREE_PAGES); | 1824 | free = zone_page_state(zone, NR_FREE_PAGES); |
1842 | /* If we have very few page cache pages, | 1825 | /* If we have very few page cache pages, |
@@ -2268,10 +2251,9 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | |||
2268 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 2251 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
2269 | 2252 | ||
2270 | unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | 2253 | unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, |
2271 | gfp_t gfp_mask, bool noswap, | 2254 | gfp_t gfp_mask, bool noswap, |
2272 | struct zone *zone, | 2255 | struct zone *zone, |
2273 | struct memcg_scanrecord *rec, | 2256 | unsigned long *nr_scanned) |
2274 | unsigned long *scanned) | ||
2275 | { | 2257 | { |
2276 | struct scan_control sc = { | 2258 | struct scan_control sc = { |
2277 | .nr_scanned = 0, | 2259 | .nr_scanned = 0, |
@@ -2281,9 +2263,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
2281 | .may_swap = !noswap, | 2263 | .may_swap = !noswap, |
2282 | .order = 0, | 2264 | .order = 0, |
2283 | .mem_cgroup = mem, | 2265 | .mem_cgroup = mem, |
2284 | .memcg_record = rec, | ||
2285 | }; | 2266 | }; |
2286 | unsigned long start, end; | ||
2287 | 2267 | ||
2288 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | | 2268 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | |
2289 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); | 2269 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); |
@@ -2292,7 +2272,6 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
2292 | sc.may_writepage, | 2272 | sc.may_writepage, |
2293 | sc.gfp_mask); | 2273 | sc.gfp_mask); |
2294 | 2274 | ||
2295 | start = sched_clock(); | ||
2296 | /* | 2275 | /* |
2297 | * NOTE: Although we can get the priority field, using it | 2276 | * NOTE: Although we can get the priority field, using it |
2298 | * here is not a good idea, since it limits the pages we can scan. | 2277 | * here is not a good idea, since it limits the pages we can scan. |
@@ -2301,25 +2280,19 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
2301 | * the priority and make it zero. | 2280 | * the priority and make it zero. |
2302 | */ | 2281 | */ |
2303 | shrink_zone(0, zone, &sc); | 2282 | shrink_zone(0, zone, &sc); |
2304 | end = sched_clock(); | ||
2305 | |||
2306 | if (rec) | ||
2307 | rec->elapsed += end - start; | ||
2308 | *scanned = sc.nr_scanned; | ||
2309 | 2283 | ||
2310 | trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed); | 2284 | trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed); |
2311 | 2285 | ||
2286 | *nr_scanned = sc.nr_scanned; | ||
2312 | return sc.nr_reclaimed; | 2287 | return sc.nr_reclaimed; |
2313 | } | 2288 | } |
2314 | 2289 | ||
2315 | unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | 2290 | unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, |
2316 | gfp_t gfp_mask, | 2291 | gfp_t gfp_mask, |
2317 | bool noswap, | 2292 | bool noswap) |
2318 | struct memcg_scanrecord *rec) | ||
2319 | { | 2293 | { |
2320 | struct zonelist *zonelist; | 2294 | struct zonelist *zonelist; |
2321 | unsigned long nr_reclaimed; | 2295 | unsigned long nr_reclaimed; |
2322 | unsigned long start, end; | ||
2323 | int nid; | 2296 | int nid; |
2324 | struct scan_control sc = { | 2297 | struct scan_control sc = { |
2325 | .may_writepage = !laptop_mode, | 2298 | .may_writepage = !laptop_mode, |
@@ -2328,7 +2301,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
2328 | .nr_to_reclaim = SWAP_CLUSTER_MAX, | 2301 | .nr_to_reclaim = SWAP_CLUSTER_MAX, |
2329 | .order = 0, | 2302 | .order = 0, |
2330 | .mem_cgroup = mem_cont, | 2303 | .mem_cgroup = mem_cont, |
2331 | .memcg_record = rec, | ||
2332 | .nodemask = NULL, /* we don't care the placement */ | 2304 | .nodemask = NULL, /* we don't care the placement */ |
2333 | .gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | | 2305 | .gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | |
2334 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK), | 2306 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK), |
@@ -2337,7 +2309,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
2337 | .gfp_mask = sc.gfp_mask, | 2309 | .gfp_mask = sc.gfp_mask, |
2338 | }; | 2310 | }; |
2339 | 2311 | ||
2340 | start = sched_clock(); | ||
2341 | /* | 2312 | /* |
2342 | * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't | 2313 | * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't |
2343 | * take care of from where we get pages. So the node where we start the | 2314 | * take care of from where we get pages. So the node where we start the |
@@ -2352,9 +2323,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
2352 | sc.gfp_mask); | 2323 | sc.gfp_mask); |
2353 | 2324 | ||
2354 | nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink); | 2325 | nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink); |
2355 | end = sched_clock(); | ||
2356 | if (rec) | ||
2357 | rec->elapsed += end - start; | ||
2358 | 2326 | ||
2359 | trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed); | 2327 | trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed); |
2360 | 2328 | ||
@@ -2529,6 +2497,9 @@ loop_again: | |||
2529 | high_wmark_pages(zone), 0, 0)) { | 2497 | high_wmark_pages(zone), 0, 0)) { |
2530 | end_zone = i; | 2498 | end_zone = i; |
2531 | break; | 2499 | break; |
2500 | } else { | ||
2501 | /* If balanced, clear the congested flag */ | ||
2502 | zone_clear_flag(zone, ZONE_CONGESTED); | ||
2532 | } | 2503 | } |
2533 | } | 2504 | } |
2534 | if (i < 0) | 2505 | if (i < 0) |