cgroups: remove events before destroying subsystem state objects
Kirill A. Shutemov [Wed, 10 Mar 2010 23:22:34 +0000 (15:22 -0800)]
Events should be removed after rmdir of cgroup directory, but before
destroying subsystem state objects.  Let's take reference to cgroup
directory dentry to do that.

Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hioryu@jp.fujitsu.com>
Cc: Paul Menage <menage@google.com>
Acked-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Cc: Dan Malek <dan@embeddedalley.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

include/linux/cgroup.h
kernel/cgroup.c
mm/memcontrol.c

index b4f2201..b8ad1ea 100644 (file)
@@ -396,9 +396,6 @@ struct cftype {
         * closes the eventfd or on cgroup removing.
         * This callback must be implemented, if you want provide
         * notification functionality.
-        *
-        * Be careful. It can be called after destroy(), so you have
-        * to keep all nesessary data, until all events are removed.
         */
        int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
                        struct eventfd_ctx *eventfd);
index 87441fc..ef909a3 100644 (file)
@@ -2994,6 +2994,7 @@ static void cgroup_event_remove(struct work_struct *work)
 
        eventfd_ctx_put(event->eventfd);
        kfree(event);
+       dput(cgrp->dentry);
 }
 
 /*
@@ -3114,6 +3115,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
                goto fail;
        }
 
+       /*
+        * Events should be removed after rmdir of cgroup directory, but before
+        * destroying subsystem state objects. Let's take reference to cgroup
+        * directory dentry to do that.
+        */
+       dget(cgrp->dentry);
+
        spin_lock(&cgrp->event_list_lock);
        list_add(&event->list, &cgrp->event_list);
        spin_unlock(&cgrp->event_list_lock);
index f9ae4b4..f7b910f 100644 (file)
@@ -3361,12 +3361,6 @@ static int mem_cgroup_register_event(struct cgroup *cgrp, struct cftype *cft,
                }
        }
 
-       /*
-        * We need to increment refcnt to be sure that all thresholds
-        * will be unregistered before calling __mem_cgroup_free()
-        */
-       mem_cgroup_get(memcg);
-
        if (type == _MEM)
                rcu_assign_pointer(memcg->thresholds, thresholds_new);
        else
@@ -3460,9 +3454,6 @@ assign:
        /* To be sure that nobody uses thresholds before freeing it */
        synchronize_rcu();
 
-       for (i = 0; i < thresholds->size - size; i++)
-               mem_cgroup_put(memcg);
-
        kfree(thresholds);
 unlock:
        mutex_unlock(&memcg->thresholds_lock);