diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/memcontrol.c | 26 | ||||
| -rw-r--r-- | mm/page-writeback.c | 15 | ||||
| -rw-r--r-- | mm/vmscan.c | 19 |
3 files changed, 20 insertions, 40 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 930de9437271..ebd1e86bef1c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -1841,29 +1841,23 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, | |||
| 1841 | */ | 1841 | */ |
| 1842 | static bool mem_cgroup_oom_lock(struct mem_cgroup *mem) | 1842 | static bool mem_cgroup_oom_lock(struct mem_cgroup *mem) |
| 1843 | { | 1843 | { |
| 1844 | int lock_count = -1; | ||
| 1845 | struct mem_cgroup *iter, *failed = NULL; | 1844 | struct mem_cgroup *iter, *failed = NULL; |
| 1846 | bool cond = true; | 1845 | bool cond = true; |
| 1847 | 1846 | ||
| 1848 | for_each_mem_cgroup_tree_cond(iter, mem, cond) { | 1847 | for_each_mem_cgroup_tree_cond(iter, mem, cond) { |
| 1849 | bool locked = iter->oom_lock; | 1848 | if (iter->oom_lock) { |
| 1850 | |||
| 1851 | iter->oom_lock = true; | ||
| 1852 | if (lock_count == -1) | ||
| 1853 | lock_count = iter->oom_lock; | ||
| 1854 | else if (lock_count != locked) { | ||
| 1855 | /* | 1849 | /* |
| 1856 | * this subtree of our hierarchy is already locked | 1850 | * this subtree of our hierarchy is already locked |
| 1857 | * so we cannot give a lock. | 1851 | * so we cannot give a lock. |
| 1858 | */ | 1852 | */ |
| 1859 | lock_count = 0; | ||
| 1860 | failed = iter; | 1853 | failed = iter; |
| 1861 | cond = false; | 1854 | cond = false; |
| 1862 | } | 1855 | } else |
| 1856 | iter->oom_lock = true; | ||
| 1863 | } | 1857 | } |
| 1864 | 1858 | ||
| 1865 | if (!failed) | 1859 | if (!failed) |
| 1866 | goto done; | 1860 | return true; |
| 1867 | 1861 | ||
| 1868 | /* | 1862 | /* |
| 1869 | * OK, we failed to lock the whole subtree so we have to clean up | 1863 | * OK, we failed to lock the whole subtree so we have to clean up |
| @@ -1877,8 +1871,7 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *mem) | |||
| 1877 | } | 1871 | } |
| 1878 | iter->oom_lock = false; | 1872 | iter->oom_lock = false; |
| 1879 | } | 1873 | } |
| 1880 | done: | 1874 | return false; |
| 1881 | return lock_count; | ||
| 1882 | } | 1875 | } |
| 1883 | 1876 | ||
| 1884 | /* | 1877 | /* |
| @@ -2169,13 +2162,7 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync) | |||
| 2169 | 2162 | ||
| 2170 | /* Notify other cpus that system-wide "drain" is running */ | 2163 | /* Notify other cpus that system-wide "drain" is running */ |
| 2171 | get_online_cpus(); | 2164 | get_online_cpus(); |
| 2172 | /* | 2165 | curcpu = get_cpu(); |
| 2173 | * Get a hint for avoiding draining charges on the current cpu, | ||
| 2174 | * which must be exhausted by our charging. It is not required that | ||
| 2175 | * this be a precise check, so we use raw_smp_processor_id() instead of | ||
| 2176 | * getcpu()/putcpu(). | ||
| 2177 | */ | ||
| 2178 | curcpu = raw_smp_processor_id(); | ||
| 2179 | for_each_online_cpu(cpu) { | 2166 | for_each_online_cpu(cpu) { |
| 2180 | struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); | 2167 | struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); |
| 2181 | struct mem_cgroup *mem; | 2168 | struct mem_cgroup *mem; |
| @@ -2192,6 +2179,7 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync) | |||
| 2192 | schedule_work_on(cpu, &stock->work); | 2179 | schedule_work_on(cpu, &stock->work); |
| 2193 | } | 2180 | } |
| 2194 | } | 2181 | } |
| 2182 | put_cpu(); | ||
| 2195 | 2183 | ||
| 2196 | if (!sync) | 2184 | if (!sync) |
| 2197 | goto out; | 2185 | goto out; |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index d1960744f881..0e309cd1b5b9 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
| @@ -754,21 +754,10 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
| 754 | * 200ms is typically more than enough to curb heavy dirtiers; | 754 | * 200ms is typically more than enough to curb heavy dirtiers; |
| 755 | * (b) the pause time limit makes the dirtiers more responsive. | 755 | * (b) the pause time limit makes the dirtiers more responsive. |
| 756 | */ | 756 | */ |
| 757 | if (nr_dirty < dirty_thresh + | 757 | if (nr_dirty < dirty_thresh && |
| 758 | dirty_thresh / DIRTY_MAXPAUSE_AREA && | 758 | bdi_dirty < (task_bdi_thresh + bdi_thresh) / 2 && |
| 759 | time_after(jiffies, start_time + MAX_PAUSE)) | 759 | time_after(jiffies, start_time + MAX_PAUSE)) |
| 760 | break; | 760 | break; |
| 761 | /* | ||
| 762 | * pass-good area. When some bdi gets blocked (eg. NFS server | ||
| 763 | * not responding), or write bandwidth dropped dramatically due | ||
| 764 | * to concurrent reads, or dirty threshold suddenly dropped and | ||
| 765 | * the dirty pages cannot be brought down anytime soon (eg. on | ||
| 766 | * slow USB stick), at least let go of the good bdi's. | ||
| 767 | */ | ||
| 768 | if (nr_dirty < dirty_thresh + | ||
| 769 | dirty_thresh / DIRTY_PASSGOOD_AREA && | ||
| 770 | bdi_dirty < bdi_thresh) | ||
| 771 | break; | ||
| 772 | 761 | ||
| 773 | /* | 762 | /* |
| 774 | * Increase the delay for each loop, up to our previous | 763 | * Increase the delay for each loop, up to our previous |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 7ef69124fa3e..b7719ec10dc5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -2283,7 +2283,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
| 2283 | .mem_cgroup = mem, | 2283 | .mem_cgroup = mem, |
| 2284 | .memcg_record = rec, | 2284 | .memcg_record = rec, |
| 2285 | }; | 2285 | }; |
| 2286 | unsigned long start, end; | 2286 | ktime_t start, end; |
| 2287 | 2287 | ||
| 2288 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | | 2288 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | |
| 2289 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); | 2289 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); |
| @@ -2292,7 +2292,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
| 2292 | sc.may_writepage, | 2292 | sc.may_writepage, |
| 2293 | sc.gfp_mask); | 2293 | sc.gfp_mask); |
| 2294 | 2294 | ||
| 2295 | start = sched_clock(); | 2295 | start = ktime_get(); |
| 2296 | /* | 2296 | /* |
| 2297 | * NOTE: Although we can get the priority field, using it | 2297 | * 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. | 2298 | * here is not a good idea, since it limits the pages we can scan. |
| @@ -2301,10 +2301,10 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
| 2301 | * the priority and make it zero. | 2301 | * the priority and make it zero. |
| 2302 | */ | 2302 | */ |
| 2303 | shrink_zone(0, zone, &sc); | 2303 | shrink_zone(0, zone, &sc); |
| 2304 | end = sched_clock(); | 2304 | end = ktime_get(); |
| 2305 | 2305 | ||
| 2306 | if (rec) | 2306 | if (rec) |
| 2307 | rec->elapsed += end - start; | 2307 | rec->elapsed += ktime_to_ns(ktime_sub(end, start)); |
| 2308 | *scanned = sc.nr_scanned; | 2308 | *scanned = sc.nr_scanned; |
| 2309 | 2309 | ||
| 2310 | trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed); | 2310 | trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed); |
| @@ -2319,7 +2319,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
| 2319 | { | 2319 | { |
| 2320 | struct zonelist *zonelist; | 2320 | struct zonelist *zonelist; |
| 2321 | unsigned long nr_reclaimed; | 2321 | unsigned long nr_reclaimed; |
| 2322 | unsigned long start, end; | 2322 | ktime_t start, end; |
| 2323 | int nid; | 2323 | int nid; |
| 2324 | struct scan_control sc = { | 2324 | struct scan_control sc = { |
| 2325 | .may_writepage = !laptop_mode, | 2325 | .may_writepage = !laptop_mode, |
| @@ -2337,7 +2337,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
| 2337 | .gfp_mask = sc.gfp_mask, | 2337 | .gfp_mask = sc.gfp_mask, |
| 2338 | }; | 2338 | }; |
| 2339 | 2339 | ||
| 2340 | start = sched_clock(); | 2340 | start = ktime_get(); |
| 2341 | /* | 2341 | /* |
| 2342 | * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't | 2342 | * 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 | 2343 | * take care of from where we get pages. So the node where we start the |
| @@ -2352,9 +2352,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
| 2352 | sc.gfp_mask); | 2352 | sc.gfp_mask); |
| 2353 | 2353 | ||
| 2354 | nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink); | 2354 | nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink); |
| 2355 | end = sched_clock(); | 2355 | end = ktime_get(); |
| 2356 | if (rec) | 2356 | if (rec) |
| 2357 | rec->elapsed += end - start; | 2357 | rec->elapsed += ktime_to_ns(ktime_sub(end, start)); |
| 2358 | 2358 | ||
| 2359 | trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed); | 2359 | trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed); |
| 2360 | 2360 | ||
| @@ -2529,6 +2529,9 @@ loop_again: | |||
| 2529 | high_wmark_pages(zone), 0, 0)) { | 2529 | high_wmark_pages(zone), 0, 0)) { |
| 2530 | end_zone = i; | 2530 | end_zone = i; |
| 2531 | break; | 2531 | break; |
| 2532 | } else { | ||
| 2533 | /* If balanced, clear the congested flag */ | ||
| 2534 | zone_clear_flag(zone, ZONE_CONGESTED); | ||
| 2532 | } | 2535 | } |
| 2533 | } | 2536 | } |
| 2534 | if (i < 0) | 2537 | if (i < 0) |
