|
@@ -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
|
|
|
|
- * created the cgroup
|
|
|
|
|
|
+ * We want to drop the active superblock reference from the
|
|
|
|
+ * 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)
|
|
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)
|
|
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 =
|