Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 187228
b: refs/heads/master
c: 4ab7868
h: refs/heads/master
v: v3
  • Loading branch information
Kirill A. Shutemov authored and Linus Torvalds committed Mar 12, 2010
1 parent 4af0acb commit 5a47745
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: daaf1e68874c078a15ae6ae827751839c4d81739
refs/heads/master: 4ab78683c17d739c2a2077141dcf81a02b7fb57e
32 changes: 17 additions & 15 deletions trunk/kernel/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,28 +795,15 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
static int cgroup_call_pre_destroy(struct cgroup *cgrp)
{
struct cgroup_subsys *ss;
struct cgroup_event *event, *tmp;
int ret = 0;

for_each_subsys(cgrp->root, ss)
if (ss->pre_destroy) {
ret = ss->pre_destroy(ss, cgrp);
if (ret)
goto out;
break;
}

/*
* Unregister events and notify userspace.
*/
spin_lock(&cgrp->event_list_lock);
list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
list_del(&event->list);
eventfd_signal(event->eventfd, 1);
schedule_work(&event->remove);
}
spin_unlock(&cgrp->event_list_lock);

out:
return ret;
}

Expand Down Expand Up @@ -3006,7 +2993,6 @@ static void cgroup_event_remove(struct work_struct *work)
event->cft->unregister_event(cgrp, event->cft, event->eventfd);

eventfd_ctx_put(event->eventfd);
remove_wait_queue(event->wqh, &event->wait);
kfree(event);
}

Expand All @@ -3024,6 +3010,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
unsigned long flags = (unsigned long)key;

if (flags & POLLHUP) {
remove_wait_queue_locked(event->wqh, &event->wait);
spin_lock(&cgrp->event_list_lock);
list_del(&event->list);
spin_unlock(&cgrp->event_list_lock);
Expand Down Expand Up @@ -3472,6 +3459,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
struct dentry *d;
struct cgroup *parent;
DEFINE_WAIT(wait);
struct cgroup_event *event, *tmp;
int ret;

/* the vfs holds both inode->i_mutex already */
Expand Down Expand Up @@ -3555,6 +3543,20 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
set_bit(CGRP_RELEASABLE, &parent->flags);
check_for_release(parent);

/*
* Unregister events and notify userspace.
* Notify userspace about cgroup removing only after rmdir of cgroup
* directory to avoid race between userspace and kernelspace
*/
spin_lock(&cgrp->event_list_lock);
list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
list_del(&event->list);
remove_wait_queue(event->wqh, &event->wait);
eventfd_signal(event->eventfd, 1);
schedule_work(&event->remove);
}
spin_unlock(&cgrp->event_list_lock);

mutex_unlock(&cgroup_mutex);
return 0;
}
Expand Down

0 comments on commit 5a47745

Please sign in to comment.