Commit 365f0e17 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup fix from Tejun Heo:
 "This fixes the possible premature superblock release on umount bug
  mentioned during v3.5-rc1 pull request.

  Originally, cgroup dentry destruction path assumed that cgroup dentry
  didn't have any reference left after cgroup removal thus put super
  during dentry removal.  Now that there can be lingering dentry
  references, this led to super being put with live dentries.  This
  patch fixes the problem by putting super ref on dentry release instead
  of removal."

* 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup: superblock can't be released with active dentries
parents 690efa08 fa980ca8
...@@ -896,10 +896,13 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) ...@@ -896,10 +896,13 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
/* /*
* Drop the active superblock reference that we took when we * We want to drop the active superblock reference from the
* created the cgroup * cgroup creation after all the dentry refs are gone -
* kill_sb gets mighty unhappy otherwise. Mark
* dentry->d_fsdata with cgroup_diput() to tell
* cgroup_d_release() to call deactivate_super().
*/ */
deactivate_super(cgrp->root->sb); dentry->d_fsdata = cgroup_diput;
/* /*
* if we're getting rid of the cgroup, refcount should ensure * if we're getting rid of the cgroup, refcount should ensure
...@@ -925,6 +928,13 @@ static int cgroup_delete(const struct dentry *d) ...@@ -925,6 +928,13 @@ static int cgroup_delete(const struct dentry *d)
return 1; return 1;
} }
static void cgroup_d_release(struct dentry *dentry)
{
/* did cgroup_diput() tell me to deactivate super? */
if (dentry->d_fsdata == cgroup_diput)
deactivate_super(dentry->d_sb);
}
static void remove_dir(struct dentry *d) static void remove_dir(struct dentry *d)
{ {
struct dentry *parent = dget(d->d_parent); struct dentry *parent = dget(d->d_parent);
...@@ -1532,6 +1542,7 @@ static int cgroup_get_rootdir(struct super_block *sb) ...@@ -1532,6 +1542,7 @@ static int cgroup_get_rootdir(struct super_block *sb)
static const struct dentry_operations cgroup_dops = { static const struct dentry_operations cgroup_dops = {
.d_iput = cgroup_diput, .d_iput = cgroup_diput,
.d_delete = cgroup_delete, .d_delete = cgroup_delete,
.d_release = cgroup_d_release,
}; };
struct inode *inode = struct inode *inode =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment