Commit a0a4db54 authored by Kirill A. Shutemov's avatar Kirill A. Shutemov Committed by Linus Torvalds

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: default avatarKirill A. Shutemov <kirill@shutemov.name>
Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hioryu@jp.fujitsu.com>
Cc: Paul Menage <menage@google.com>
Acked-by: default avatarLi 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4ab78683
...@@ -396,9 +396,6 @@ struct cftype { ...@@ -396,9 +396,6 @@ struct cftype {
* closes the eventfd or on cgroup removing. * closes the eventfd or on cgroup removing.
* This callback must be implemented, if you want provide * This callback must be implemented, if you want provide
* notification functionality. * 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, int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
struct eventfd_ctx *eventfd); struct eventfd_ctx *eventfd);
......
...@@ -2994,6 +2994,7 @@ static void cgroup_event_remove(struct work_struct *work) ...@@ -2994,6 +2994,7 @@ static void cgroup_event_remove(struct work_struct *work)
eventfd_ctx_put(event->eventfd); eventfd_ctx_put(event->eventfd);
kfree(event); kfree(event);
dput(cgrp->dentry);
} }
/* /*
...@@ -3114,6 +3115,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, ...@@ -3114,6 +3115,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
goto fail; 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); spin_lock(&cgrp->event_list_lock);
list_add(&event->list, &cgrp->event_list); list_add(&event->list, &cgrp->event_list);
spin_unlock(&cgrp->event_list_lock); spin_unlock(&cgrp->event_list_lock);
......
...@@ -3361,12 +3361,6 @@ static int mem_cgroup_register_event(struct cgroup *cgrp, struct cftype *cft, ...@@ -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) if (type == _MEM)
rcu_assign_pointer(memcg->thresholds, thresholds_new); rcu_assign_pointer(memcg->thresholds, thresholds_new);
else else
...@@ -3460,9 +3454,6 @@ static int mem_cgroup_unregister_event(struct cgroup *cgrp, struct cftype *cft, ...@@ -3460,9 +3454,6 @@ static int mem_cgroup_unregister_event(struct cgroup *cgrp, struct cftype *cft,
/* To be sure that nobody uses thresholds before freeing it */ /* To be sure that nobody uses thresholds before freeing it */
synchronize_rcu(); synchronize_rcu();
for (i = 0; i < thresholds->size - size; i++)
mem_cgroup_put(memcg);
kfree(thresholds); kfree(thresholds);
unlock: unlock:
mutex_unlock(&memcg->thresholds_lock); mutex_unlock(&memcg->thresholds_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment