Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6.git] / mm / memcontrol.c
index 00d4fa2..d87aa35 100644 (file)
@@ -381,16 +381,25 @@ static void mem_cgroup_put(struct mem_cgroup *memcg);
 static bool mem_cgroup_is_root(struct mem_cgroup *memcg);
 void sock_update_memcg(struct sock *sk)
 {
-       /* A socket spends its whole life in the same cgroup */
-       if (sk->sk_cgrp) {
-               WARN_ON(1);
-               return;
-       }
        if (static_branch(&memcg_socket_limit_enabled)) {
                struct mem_cgroup *memcg;
 
                BUG_ON(!sk->sk_prot->proto_cgroup);
 
+               /* Socket cloning can throw us here with sk_cgrp already
+                * filled. It won't however, necessarily happen from
+                * process context. So the test for root memcg given
+                * the current task's memcg won't help us in this case.
+                *
+                * Respecting the original socket's memcg is a better
+                * decision in this case.
+                */
+               if (sk->sk_cgrp) {
+                       BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg));
+                       mem_cgroup_get(sk->sk_cgrp->memcg);
+                       return;
+               }
+
                rcu_read_lock();
                memcg = mem_cgroup_from_task(current);
                if (!mem_cgroup_is_root(memcg)) {