|
@@ -185,6 +185,11 @@ static const struct super_operations debugfs_super_operations = {
|
|
|
.evict_inode = debugfs_evict_inode,
|
|
|
};
|
|
|
|
|
|
+static void debugfs_release_dentry(struct dentry *dentry)
|
|
|
+{
|
|
|
+ kfree(dentry->d_fsdata);
|
|
|
+}
|
|
|
+
|
|
|
static struct vfsmount *debugfs_automount(struct path *path)
|
|
|
{
|
|
|
debugfs_automount_t f;
|
|
@@ -194,6 +199,7 @@ static struct vfsmount *debugfs_automount(struct path *path)
|
|
|
|
|
|
static const struct dentry_operations debugfs_dops = {
|
|
|
.d_delete = always_delete_dentry,
|
|
|
+ .d_release = debugfs_release_dentry,
|
|
|
.d_automount = debugfs_automount,
|
|
|
};
|
|
|
|
|
@@ -341,24 +347,34 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
|
|
|
{
|
|
|
struct dentry *dentry;
|
|
|
struct inode *inode;
|
|
|
+ struct debugfs_fsdata *fsd;
|
|
|
+
|
|
|
+ fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
|
|
|
+ if (!fsd)
|
|
|
+ return NULL;
|
|
|
|
|
|
if (!(mode & S_IFMT))
|
|
|
mode |= S_IFREG;
|
|
|
BUG_ON(!S_ISREG(mode));
|
|
|
dentry = start_creating(name, parent);
|
|
|
|
|
|
- if (IS_ERR(dentry))
|
|
|
+ if (IS_ERR(dentry)) {
|
|
|
+ kfree(fsd);
|
|
|
return NULL;
|
|
|
+ }
|
|
|
|
|
|
inode = debugfs_get_inode(dentry->d_sb);
|
|
|
- if (unlikely(!inode))
|
|
|
+ if (unlikely(!inode)) {
|
|
|
+ kfree(fsd);
|
|
|
return failed_creating(dentry);
|
|
|
+ }
|
|
|
|
|
|
inode->i_mode = mode;
|
|
|
inode->i_private = data;
|
|
|
|
|
|
inode->i_fop = proxy_fops;
|
|
|
- dentry->d_fsdata = (void *)real_fops;
|
|
|
+ fsd->real_fops = real_fops;
|
|
|
+ dentry->d_fsdata = fsd;
|
|
|
|
|
|
d_instantiate(dentry, inode);
|
|
|
fsnotify_create(d_inode(dentry->d_parent), dentry);
|