diff options
Diffstat (limited to 'kernel')
-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 a7c9e6ddb979..c6e77ef2a0a6 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -3727,6 +3727,23 @@ static int cgroup_write_notify_on_release(struct cgroup *cgrp, | |||
3727 | } | 3727 | } |
3728 | 3728 | ||
3729 | /* | 3729 | /* |
3730 | * When dput() is called asynchronously, if umount has been done and | ||
3731 | * then deactivate_super() in cgroup_free_fn() kills the superblock, | ||
3732 | * there's a small window that vfs will see the root dentry with non-zero | ||
3733 | * refcnt and trigger BUG(). | ||
3734 | * | ||
3735 | * That's why we hold a reference before dput() and drop it right after. | ||
3736 | */ | ||
3737 | static void cgroup_dput(struct cgroup *cgrp) | ||
3738 | { | ||
3739 | struct super_block *sb = cgrp->root->sb; | ||
3740 | |||
3741 | atomic_inc(&sb->s_active); | ||
3742 | dput(cgrp->dentry); | ||
3743 | deactivate_super(sb); | ||
3744 | } | ||
3745 | |||
3746 | /* | ||
3730 | * Unregister event and free resources. | 3747 | * Unregister event and free resources. |
3731 | * | 3748 | * |
3732 | * Gets called from workqueue. | 3749 | * Gets called from workqueue. |
@@ -3746,7 +3763,7 @@ static void cgroup_event_remove(struct work_struct *work) | |||
3746 | 3763 | ||
3747 | eventfd_ctx_put(event->eventfd); | 3764 | eventfd_ctx_put(event->eventfd); |
3748 | kfree(event); | 3765 | kfree(event); |
3749 | dput(cgrp->dentry); | 3766 | cgroup_dput(cgrp); |
3750 | } | 3767 | } |
3751 | 3768 | ||
3752 | /* | 3769 | /* |
@@ -4031,12 +4048,8 @@ static void css_dput_fn(struct work_struct *work) | |||
4031 | { | 4048 | { |
4032 | struct cgroup_subsys_state *css = | 4049 | struct cgroup_subsys_state *css = |
4033 | container_of(work, struct cgroup_subsys_state, dput_work); | 4050 | container_of(work, struct cgroup_subsys_state, dput_work); |
4034 | struct dentry *dentry = css->cgroup->dentry; | ||
4035 | struct super_block *sb = dentry->d_sb; | ||
4036 | 4051 | ||
4037 | atomic_inc(&sb->s_active); | 4052 | cgroup_dput(css->cgroup); |
4038 | dput(dentry); | ||
4039 | deactivate_super(sb); | ||
4040 | } | 4053 | } |
4041 | 4054 | ||
4042 | static void init_cgroup_css(struct cgroup_subsys_state *css, | 4055 | static void init_cgroup_css(struct cgroup_subsys_state *css, |