From: Al Viro Signed-off-by: Al Viro --- fs/debugfs/inode.c | 61 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index adaaa04448b3..100186c2bf0a 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -305,11 +305,9 @@ static struct file_system_type debug_fs_type = { }; MODULE_ALIAS_FS("debugfs"); -static struct dentry *__create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops) +static struct dentry *start_creating(const char *name, struct dentry *parent) { - struct dentry *dentry = NULL; + struct dentry *dentry; int error; pr_debug("debugfs: creating file '%s'\n",name); @@ -317,7 +315,7 @@ static struct dentry *__create_file(const char *name, umode_t mode, error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count); if (error) - goto exit; + return ERR_PTR(error); /* If the parent is not specified, we create it in the root. * We need the root dentry to do this, which is in the super @@ -329,32 +327,51 @@ static struct dentry *__create_file(const char *name, umode_t mode, mutex_lock(&parent->d_inode->i_mutex); dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(dentry)) { - switch (mode & S_IFMT) { - case S_IFDIR: - error = debugfs_mkdir(dentry, mode); - - break; - case S_IFLNK: - error = debugfs_link(dentry, mode, data); - break; - default: - error = debugfs_create(dentry, mode, data, fops); - break; - } + if (!IS_ERR(dentry) && dentry->d_inode) { dput(dentry); - } else - error = PTR_ERR(dentry); - mutex_unlock(&parent->d_inode->i_mutex); + dentry = ERR_PTR(-EEXIST); + } + if (IS_ERR(dentry)) + mutex_unlock(&parent->d_inode->i_mutex); + return dentry; +} + +static struct dentry *end_creating(struct dentry *dentry, int error) +{ + mutex_unlock(&dentry->d_parent->d_inode->i_mutex); + dput(dentry); if (error) { dentry = NULL; simple_release_fs(&debugfs_mount, &debugfs_mount_count); } -exit: return dentry; } +static struct dentry *__create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) +{ + struct dentry *dentry = start_creating(name, parent); + int error; + + if (IS_ERR(dentry)) + return NULL; + + switch (mode & S_IFMT) { + case S_IFDIR: + error = debugfs_mkdir(dentry, mode); + break; + case S_IFLNK: + error = debugfs_link(dentry, mode, data); + break; + default: + error = debugfs_create(dentry, mode, data, fops); + break; + } + return end_creating(dentry, error); +} + /** * debugfs_create_file - create a file in the debugfs filesystem * @name: a pointer to a string containing the name of the file to create. -- 2.1.4