summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill@shutemov.name>2010-03-10 23:22:34 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 23:52:37 (GMT)
commita0a4db548edcce067c1201ef25cf2bc29f32dca4 (patch)
tree6f8139a582179666cd248d978332ed0e32ad9f0f
parent4ab78683c17d739c2a2077141dcf81a02b7fb57e (diff)
downloadlinux-fsl-qoriq-a0a4db548edcce067c1201ef25cf2bc29f32dca4.tar.xz
cgroups: remove events before destroying subsystem state objects
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>
-rw-r--r--include/linux/cgroup.h3
-rw-r--r--kernel/cgroup.c8
-rw-r--r--mm/memcontrol.c9
3 files changed, 8 insertions, 12 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index b4f2201..b8ad1ea 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -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);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 87441fc..ef909a3 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -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);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f9ae4b4..f7b910f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -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);