diff options
-rw-r--r-- | kernel/cgroup.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c02b05560d10..589433f7a74b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4277,6 +4277,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4277 | DEFINE_WAIT(wait); | 4277 | DEFINE_WAIT(wait); |
4278 | struct cgroup_event *event, *tmp; | 4278 | struct cgroup_event *event, *tmp; |
4279 | struct cgroup_subsys *ss; | 4279 | struct cgroup_subsys *ss; |
4280 | LIST_HEAD(tmp_list); | ||
4280 | 4281 | ||
4281 | lockdep_assert_held(&d->d_inode->i_mutex); | 4282 | lockdep_assert_held(&d->d_inode->i_mutex); |
4282 | lockdep_assert_held(&cgroup_mutex); | 4283 | lockdep_assert_held(&cgroup_mutex); |
@@ -4331,16 +4332,20 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4331 | /* | 4332 | /* |
4332 | * Unregister events and notify userspace. | 4333 | * Unregister events and notify userspace. |
4333 | * Notify userspace about cgroup removing only after rmdir of cgroup | 4334 | * Notify userspace about cgroup removing only after rmdir of cgroup |
4334 | * directory to avoid race between userspace and kernelspace | 4335 | * directory to avoid race between userspace and kernelspace. Use |
4336 | * a temporary list to avoid a deadlock with cgroup_event_wake(). Since | ||
4337 | * cgroup_event_wake() is called with the wait queue head locked, | ||
4338 | * remove_wait_queue() cannot be called while holding event_list_lock. | ||
4335 | */ | 4339 | */ |
4336 | spin_lock(&cgrp->event_list_lock); | 4340 | spin_lock(&cgrp->event_list_lock); |
4337 | list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) { | 4341 | list_splice_init(&cgrp->event_list, &tmp_list); |
4342 | spin_unlock(&cgrp->event_list_lock); | ||
4343 | list_for_each_entry_safe(event, tmp, &tmp_list, list) { | ||
4338 | list_del(&event->list); | 4344 | list_del(&event->list); |
4339 | remove_wait_queue(event->wqh, &event->wait); | 4345 | remove_wait_queue(event->wqh, &event->wait); |
4340 | eventfd_signal(event->eventfd, 1); | 4346 | eventfd_signal(event->eventfd, 1); |
4341 | schedule_work(&event->remove); | 4347 | schedule_work(&event->remove); |
4342 | } | 4348 | } |
4343 | spin_unlock(&cgrp->event_list_lock); | ||
4344 | 4349 | ||
4345 | return 0; | 4350 | return 0; |
4346 | } | 4351 | } |