debugfs: fix automount d_fsdata usage
[linux-2.6-microblaze.git] / fs / debugfs / inode.c
index 83e57e9..dcde419 100644 (file)
@@ -236,17 +236,19 @@ static const struct super_operations debugfs_super_operations = {
 
 static void debugfs_release_dentry(struct dentry *dentry)
 {
-       void *fsd = dentry->d_fsdata;
+       struct debugfs_fsdata *fsd = dentry->d_fsdata;
 
-       if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
-               kfree(dentry->d_fsdata);
+       if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+               return;
+
+       kfree(fsd);
 }
 
 static struct vfsmount *debugfs_automount(struct path *path)
 {
-       debugfs_automount_t f;
-       f = (debugfs_automount_t)path->dentry->d_fsdata;
-       return f(path->dentry, d_inode(path->dentry)->i_private);
+       struct debugfs_fsdata *fsd = path->dentry->d_fsdata;
+
+       return fsd->automount(path->dentry, d_inode(path->dentry)->i_private);
 }
 
 static const struct dentry_operations debugfs_dops = {
@@ -634,13 +636,23 @@ struct dentry *debugfs_create_automount(const char *name,
                                        void *data)
 {
        struct dentry *dentry = start_creating(name, parent);
+       struct debugfs_fsdata *fsd;
        struct inode *inode;
 
        if (IS_ERR(dentry))
                return dentry;
 
+       fsd = kzalloc(sizeof(*fsd), GFP_KERNEL);
+       if (!fsd) {
+               failed_creating(dentry);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       fsd->automount = f;
+
        if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
                failed_creating(dentry);
+               kfree(fsd);
                return ERR_PTR(-EPERM);
        }
 
@@ -648,13 +660,14 @@ struct dentry *debugfs_create_automount(const char *name,
        if (unlikely(!inode)) {
                pr_err("out of free dentries, can not create automount '%s'\n",
                       name);
+               kfree(fsd);
                return failed_creating(dentry);
        }
 
        make_empty_dir_inode(inode);
        inode->i_flags |= S_AUTOMOUNT;
        inode->i_private = data;
-       dentry->d_fsdata = (void *)f;
+       dentry->d_fsdata = fsd;
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
        inc_nlink(inode);
        d_instantiate(dentry, inode);