3.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michal Hocko <mho...@suse.cz>

commit ecc736fc3c71c411a9d201d8588c9e7e049e5d8c upstream.

Hugh has reported an endless loop when the hardlimit reclaim sees the
same group all the time.  This might happen when the reclaim races with
the memcg removal.

shrink_zone
                                                [rmdir root]
  mem_cgroup_iter(root, NULL, reclaim)
    // prev = NULL
    rcu_read_lock()
    mem_cgroup_iter_load
      last_visited = iter->last_visited   // gets root || NULL
      css_tryget(last_visited)            // failed
      last_visited = NULL                 [1]
    memcg = root = __mem_cgroup_iter_next(root, NULL)
    mem_cgroup_iter_update
      iter->last_visited = root;
    reclaim->generation = iter->generation

 mem_cgroup_iter(root, root, reclaim)
   // prev = root
   rcu_read_lock
    mem_cgroup_iter_load
      last_visited = iter->last_visited   // gets root
      css_tryget(last_visited)            // failed
    [1]

The issue seemed to be introduced by commit 5f5781619718 ("memcg: relax
memcg iter caching") which has replaced unconditional css_get/css_put by
css_tryget/css_put for the cached iterator.

This patch fixes the issue by skipping css_tryget on the root of the
tree walk in mem_cgroup_iter_load and symmetrically doesn't release it
in mem_cgroup_iter_update.

Signed-off-by: Michal Hocko <mho...@suse.cz>
Reported-by: Hugh Dickins <hu...@google.com>
Tested-by: Hugh Dickins <hu...@google.com>
Cc: Johannes Weiner <han...@cmpxchg.org>
Cc: Greg Thelen <gthe...@google.com>
Cc: <sta...@vger.kernel.org>    [3.10+]
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 mm/memcontrol.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1220,7 +1220,7 @@ struct mem_cgroup *mem_cgroup_iter(struc
                        if (dead_count == iter->last_dead_count) {
                                smp_rmb();
                                last_visited = iter->last_visited;
-                               if (last_visited &&
+                               if (last_visited && last_visited != root &&
                                    !css_tryget(&last_visited->css))
                                        last_visited = NULL;
                        }
@@ -1229,7 +1229,7 @@ struct mem_cgroup *mem_cgroup_iter(struc
                memcg = __mem_cgroup_iter_next(root, last_visited);
 
                if (reclaim) {
-                       if (last_visited)
+                       if (last_visited && last_visited != root)
                                css_put(&last_visited->css);
 
                        iter->last_visited = memcg;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to