The only difference, compared to the pre-existing code, is that symlink creation now triggers fsnotify_create. This was a bug in the debugfs code, since for example vfs_symlink does call fsnotify_create. Signed-off-by: Emanuele Giuseppe Esposito <eesposit@xxxxxxxxxx> --- fs/debugfs/inode.c | 144 +++++---------------------------------------- 1 file changed, 15 insertions(+), 129 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 834b5872ca0d..7a2369373b85 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -294,68 +294,6 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent) } EXPORT_SYMBOL_GPL(debugfs_lookup); -static struct dentry *start_creating(const char *name, struct dentry *parent) -{ - struct dentry *dentry; - int error; - - pr_debug("creating file '%s'\n", name); - - if (IS_ERR(parent)) - return parent; - - error = simple_pin_fs(&debugfs, &debug_fs_type); - if (error) { - pr_err("Unable to pin filesystem for file '%s'\n", name); - 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 - * block. A pointer to that is in the struct vfsmount that we - * have around. - */ - if (!parent) - parent = debugfs.mount->mnt_root; - - inode_lock(d_inode(parent)); - if (unlikely(IS_DEADDIR(d_inode(parent)))) - dentry = ERR_PTR(-ENOENT); - else - dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(dentry) && d_really_is_positive(dentry)) { - if (d_is_dir(dentry)) - pr_err("Directory '%s' with parent '%s' already present!\n", - name, parent->d_name.name); - else - pr_err("File '%s' in directory '%s' already present!\n", - name, parent->d_name.name); - dput(dentry); - dentry = ERR_PTR(-EEXIST); - } - - if (IS_ERR(dentry)) { - inode_unlock(d_inode(parent)); - simple_release_fs(&debugfs); - } - - return dentry; -} - -static struct dentry *failed_creating(struct dentry *dentry) -{ - inode_unlock(d_inode(dentry->d_parent)); - dput(dentry); - simple_release_fs(&debugfs); - return ERR_PTR(-ENOMEM); -} - -static struct dentry *end_creating(struct dentry *dentry) -{ - inode_unlock(d_inode(dentry->d_parent)); - return dentry; -} - static struct dentry *__debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *proxy_fops, @@ -364,32 +302,17 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, struct dentry *dentry; struct inode *inode; - if (!(mode & S_IFMT)) - mode |= S_IFREG; - BUG_ON(!S_ISREG(mode)); - dentry = start_creating(name, parent); - + dentry = simplefs_create_file(&debugfs, &debug_fs_type, + name, mode, parent, data, &inode); if (IS_ERR(dentry)) return dentry; - inode = simple_new_inode(dentry->d_sb); - if (unlikely(!inode)) { - pr_err("out of free dentries, can not create file '%s'\n", - name); - return failed_creating(dentry); - } - - inode->i_mode = mode; - inode->i_private = data; - inode->i_op = &debugfs_file_inode_operations; inode->i_fop = proxy_fops; dentry->d_fsdata = (void *)((unsigned long)real_fops | DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); - d_instantiate(dentry, inode); - fsnotify_create(d_inode(dentry->d_parent), dentry); - return end_creating(dentry); + return simplefs_finish_dentry(dentry, inode); } /** @@ -522,29 +445,16 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size); */ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { - struct dentry *dentry = start_creating(name, parent); + struct dentry *dentry; struct inode *inode; + dentry = simplefs_create_dir(&debugfs, &debug_fs_type, + name, 0755, parent, &inode); if (IS_ERR(dentry)) return dentry; - inode = simple_new_inode(dentry->d_sb); - if (unlikely(!inode)) { - pr_err("out of free dentries, can not create directory '%s'\n", - name); - return failed_creating(dentry); - } - - inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; inode->i_op = &debugfs_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); - d_instantiate(dentry, inode); - inc_nlink(d_inode(dentry->d_parent)); - fsnotify_mkdir(d_inode(dentry->d_parent), dentry); - return end_creating(dentry); + return simplefs_finish_dentry(dentry, inode); } EXPORT_SYMBOL_GPL(debugfs_create_dir); @@ -564,29 +474,19 @@ struct dentry *debugfs_create_automount(const char *name, debugfs_automount_t f, void *data) { - struct dentry *dentry = start_creating(name, parent); + struct dentry *dentry; struct inode *inode; + dentry = simplefs_create_dentry(&debugfs, &debug_fs_type, name, parent, + &inode); if (IS_ERR(dentry)) return dentry; - inode = simple_new_inode(dentry->d_sb); - if (unlikely(!inode)) { - pr_err("out of free dentries, can not create automount '%s'\n", - name); - return failed_creating(dentry); - } - make_empty_dir_inode(inode); inode->i_flags |= S_AUTOMOUNT; inode->i_private = data; dentry->d_fsdata = (void *)f; - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); - d_instantiate(dentry, inode); - inc_nlink(d_inode(dentry->d_parent)); - fsnotify_mkdir(d_inode(dentry->d_parent), dentry); - return end_creating(dentry); + return simplefs_finish_dentry(dentry, inode); } EXPORT_SYMBOL(debugfs_create_automount); @@ -618,28 +518,14 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, { struct dentry *dentry; struct inode *inode; - char *link = kstrdup(target, GFP_KERNEL); - if (!link) - return ERR_PTR(-ENOMEM); - dentry = start_creating(name, parent); - if (IS_ERR(dentry)) { - kfree(link); + dentry = simplefs_create_symlink(&debugfs, &debug_fs_type, + name, parent, target, &inode); + if (IS_ERR(dentry)) return dentry; - } - inode = simple_new_inode(dentry->d_sb); - if (unlikely(!inode)) { - pr_err("out of free dentries, can not create symlink '%s'\n", - name); - kfree(link); - return failed_creating(dentry); - } - inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_op = &debugfs_symlink_inode_operations; - inode->i_link = link; - d_instantiate(dentry, inode); - return end_creating(dentry); + return simplefs_finish_dentry(dentry, inode); } EXPORT_SYMBOL_GPL(debugfs_create_symlink); -- 2.25.2