diff options
-rw-r--r-- | mm/vmscan.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 04dca89c4f34..fa91c20fe4b7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2142,10 +2142,11 @@ static inline bool should_continue_reclaim(struct zone *zone, | |||
2142 | } | 2142 | } |
2143 | } | 2143 | } |
2144 | 2144 | ||
2145 | static void | 2145 | static int |
2146 | __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) | 2146 | __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) |
2147 | { | 2147 | { |
2148 | unsigned long nr_reclaimed, nr_scanned; | 2148 | unsigned long nr_reclaimed, nr_scanned; |
2149 | int groups_scanned = 0; | ||
2149 | 2150 | ||
2150 | do { | 2151 | do { |
2151 | struct mem_cgroup *root = sc->target_mem_cgroup; | 2152 | struct mem_cgroup *root = sc->target_mem_cgroup; |
@@ -2163,6 +2164,7 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) | |||
2163 | while ((memcg = mem_cgroup_iter_cond(root, memcg, &reclaim, filter))) { | 2164 | while ((memcg = mem_cgroup_iter_cond(root, memcg, &reclaim, filter))) { |
2164 | struct lruvec *lruvec; | 2165 | struct lruvec *lruvec; |
2165 | 2166 | ||
2167 | groups_scanned++; | ||
2166 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); | 2168 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); |
2167 | 2169 | ||
2168 | shrink_lruvec(lruvec, sc); | 2170 | shrink_lruvec(lruvec, sc); |
@@ -2190,6 +2192,8 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) | |||
2190 | 2192 | ||
2191 | } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed, | 2193 | } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed, |
2192 | sc->nr_scanned - nr_scanned, sc)); | 2194 | sc->nr_scanned - nr_scanned, sc)); |
2195 | |||
2196 | return groups_scanned; | ||
2193 | } | 2197 | } |
2194 | 2198 | ||
2195 | 2199 | ||
@@ -2197,8 +2201,19 @@ static void shrink_zone(struct zone *zone, struct scan_control *sc) | |||
2197 | { | 2201 | { |
2198 | bool do_soft_reclaim = mem_cgroup_should_soft_reclaim(sc); | 2202 | bool do_soft_reclaim = mem_cgroup_should_soft_reclaim(sc); |
2199 | unsigned long nr_scanned = sc->nr_scanned; | 2203 | unsigned long nr_scanned = sc->nr_scanned; |
2204 | int scanned_groups; | ||
2200 | 2205 | ||
2201 | __shrink_zone(zone, sc, do_soft_reclaim); | 2206 | scanned_groups = __shrink_zone(zone, sc, do_soft_reclaim); |
2207 | /* | ||
2208 | * memcg iterator might race with other reclaimer or start from | ||
2209 | * a incomplete tree walk so the tree walk in __shrink_zone | ||
2210 | * might have missed groups that are above the soft limit. Try | ||
2211 | * another loop to catch up with others. Do it just once to | ||
2212 | * prevent from reclaim latencies when other reclaimers always | ||
2213 | * preempt this one. | ||
2214 | */ | ||
2215 | if (do_soft_reclaim && !scanned_groups) | ||
2216 | __shrink_zone(zone, sc, do_soft_reclaim); | ||
2202 | 2217 | ||
2203 | /* | 2218 | /* |
2204 | * No group is over the soft limit or those that are do not have | 2219 | * No group is over the soft limit or those that are do not have |