diff options
-rw-r--r-- | include/linux/cgroup.h | 3 | ||||
-rw-r--r-- | kernel/cgroup.c | 8 | ||||
-rw-r--r-- | mm/memcontrol.c | 9 |
3 files changed, 8 insertions, 12 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index b4f2201321cd..b8ad1ea99586 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -396,9 +396,6 @@ struct cftype { | |||
396 | * closes the eventfd or on cgroup removing. | 396 | * closes the eventfd or on cgroup removing. |
397 | * This callback must be implemented, if you want provide | 397 | * This callback must be implemented, if you want provide |
398 | * notification functionality. | 398 | * notification functionality. |
399 | * | ||
400 | * Be careful. It can be called after destroy(), so you have | ||
401 | * to keep all nesessary data, until all events are removed. | ||
402 | */ | 399 | */ |
403 | int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft, | 400 | int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft, |
404 | struct eventfd_ctx *eventfd); | 401 | struct eventfd_ctx *eventfd); |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 87441fc75663..ef909a329750 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2994,6 +2994,7 @@ static void cgroup_event_remove(struct work_struct *work) | |||
2994 | 2994 | ||
2995 | eventfd_ctx_put(event->eventfd); | 2995 | eventfd_ctx_put(event->eventfd); |
2996 | kfree(event); | 2996 | kfree(event); |
2997 | dput(cgrp->dentry); | ||
2997 | } | 2998 | } |
2998 | 2999 | ||
2999 | /* | 3000 | /* |
@@ -3114,6 +3115,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, | |||
3114 | goto fail; | 3115 | goto fail; |
3115 | } | 3116 | } |
3116 | 3117 | ||
3118 | /* | ||
3119 | * Events should be removed after rmdir of cgroup directory, but before | ||
3120 | * destroying subsystem state objects. Let's take reference to cgroup | ||
3121 | * directory dentry to do that. | ||
3122 | */ | ||
3123 | dget(cgrp->dentry); | ||
3124 | |||
3117 | spin_lock(&cgrp->event_list_lock); | 3125 | spin_lock(&cgrp->event_list_lock); |
3118 | list_add(&event->list, &cgrp->event_list); | 3126 | list_add(&event->list, &cgrp->event_list); |
3119 | spin_unlock(&cgrp->event_list_lock); | 3127 | spin_unlock(&cgrp->event_list_lock); |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index f9ae4b4c36eb..f7b910fc14fb 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, | |||
3361 | } | 3361 | } |
3362 | } | 3362 | } |
3363 | 3363 | ||
3364 | /* | ||
3365 | * We need to increment refcnt to be sure that all thresholds | ||
3366 | * will be unregistered before calling __mem_cgroup_free() | ||
3367 | */ | ||
3368 | mem_cgroup_get(memcg); | ||
3369 | |||
3370 | if (type == _MEM) | 3364 | if (type == _MEM) |
3371 | rcu_assign_pointer(memcg->thresholds, thresholds_new); | 3365 | rcu_assign_pointer(memcg->thresholds, thresholds_new); |
3372 | else | 3366 | else |
@@ -3460,9 +3454,6 @@ assign: | |||
3460 | /* To be sure that nobody uses thresholds before freeing it */ | 3454 | /* To be sure that nobody uses thresholds before freeing it */ |
3461 | synchronize_rcu(); | 3455 | synchronize_rcu(); |
3462 | 3456 | ||
3463 | for (i = 0; i < thresholds->size - size; i++) | ||
3464 | mem_cgroup_put(memcg); | ||
3465 | |||
3466 | kfree(thresholds); | 3457 | kfree(thresholds); |
3467 | unlock: | 3458 | unlock: |
3468 | mutex_unlock(&memcg->thresholds_lock); | 3459 | mutex_unlock(&memcg->thresholds_lock); |