diff options
-rw-r--r-- | kernel/cgroup.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0224f6b3103e..7db2940bfc77 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -3822,6 +3822,23 @@ static int cgroup_write_notify_on_release(struct cgroup *cgrp, | |||
3822 | } | 3822 | } |
3823 | 3823 | ||
3824 | /* | 3824 | /* |
3825 | * When dput() is called asynchronously, if umount has been done and | ||
3826 | * then deactivate_super() in cgroup_free_fn() kills the superblock, | ||
3827 | * there's a small window that vfs will see the root dentry with non-zero | ||
3828 | * refcnt and trigger BUG(). | ||
3829 | * | ||
3830 | * That's why we hold a reference before dput() and drop it right after. | ||
3831 | */ | ||
3832 | static void cgroup_dput(struct cgroup *cgrp) | ||
3833 | { | ||
3834 | struct super_block *sb = cgrp->root->sb; | ||
3835 | |||
3836 | atomic_inc(&sb->s_active); | ||
3837 | dput(cgrp->dentry); | ||
3838 | deactivate_super(sb); | ||
3839 | } | ||
3840 | |||
3841 | /* | ||
3825 | * Unregister event and free resources. | 3842 | * Unregister event and free resources. |
3826 | * | 3843 | * |
3827 | * Gets called from workqueue. | 3844 | * Gets called from workqueue. |
@@ -3841,7 +3858,7 @@ static void cgroup_event_remove(struct work_struct *work) | |||
3841 | 3858 | ||
3842 | eventfd_ctx_put(event->eventfd); | 3859 | eventfd_ctx_put(event->eventfd); |
3843 | kfree(event); | 3860 | kfree(event); |
3844 | dput(cgrp->dentry); | 3861 | cgroup_dput(cgrp); |
3845 | } | 3862 | } |
3846 | 3863 | ||
3847 | /* | 3864 | /* |
@@ -4129,12 +4146,8 @@ static void css_dput_fn(struct work_struct *work) | |||
4129 | { | 4146 | { |
4130 | struct cgroup_subsys_state *css = | 4147 | struct cgroup_subsys_state *css = |
4131 | container_of(work, struct cgroup_subsys_state, dput_work); | 4148 | container_of(work, struct cgroup_subsys_state, dput_work); |
4132 | struct dentry *dentry = css->cgroup->dentry; | ||
4133 | struct super_block *sb = dentry->d_sb; | ||
4134 | 4149 | ||
4135 | atomic_inc(&sb->s_active); | 4150 | cgroup_dput(css->cgroup); |
4136 | dput(dentry); | ||
4137 | deactivate_super(sb); | ||
4138 | } | 4151 | } |
4139 | 4152 | ||
4140 | static void css_release(struct percpu_ref *ref) | 4153 | static void css_release(struct percpu_ref *ref) |