From e09ddf36dd986e91edd69a0355bdd44cb738b45e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 13:50:23 -0500 Subject: debugfs_{mkdir,create,link}(): get rid of redundant argument Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 05f2960..adaaa04 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -89,8 +89,9 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, return error; } -static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +static int debugfs_mkdir(struct dentry *dentry, umode_t mode) { + struct inode *dir = dentry->d_parent->d_inode; int res; mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; @@ -102,16 +103,18 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) return res; } -static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode, +static int debugfs_link(struct dentry *dentry, umode_t mode, void *data) { + struct inode *dir = dentry->d_parent->d_inode; mode = (mode & S_IALLUGO) | S_IFLNK; return debugfs_mknod(dir, dentry, mode, 0, data, NULL); } -static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, +static int debugfs_create(struct dentry *dentry, umode_t mode, void *data, const struct file_operations *fops) { + struct inode *dir = dentry->d_parent->d_inode; int res; mode = (mode & S_IALLUGO) | S_IFREG; @@ -329,16 +332,14 @@ static struct dentry *__create_file(const char *name, umode_t mode, if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case S_IFDIR: - error = debugfs_mkdir(parent->d_inode, dentry, mode); + error = debugfs_mkdir(dentry, mode); break; case S_IFLNK: - error = debugfs_link(parent->d_inode, dentry, mode, - data); + error = debugfs_link(dentry, mode, data); break; default: - error = debugfs_create(parent->d_inode, dentry, mode, - data, fops); + error = debugfs_create(dentry, mode, data, fops); break; } dput(dentry); -- cgit v0.10.2 From 190afd81e4a5f24d1db6c774ca7f18acde2fca30 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 13:55:55 -0500 Subject: debugfs: split the beginning and the end of __create_file() off Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index adaaa04..100186c 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. -- cgit v0.10.2 From ad5abd5ba8c66ea44e24d7b6996e85ab83b412fc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:02:31 -0500 Subject: debugfs: kill __create_file() Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 100186c..18564b0 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -348,30 +348,6 @@ static struct dentry *end_creating(struct dentry *dentry, int error) 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. @@ -402,15 +378,19 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) { - switch (mode & S_IFMT) { - case S_IFREG: - case 0: - break; - default: - BUG(); - } + struct dentry *dentry; + int error; + + if (!(mode & S_IFMT)) + mode |= S_IFREG; + BUG_ON(!S_ISREG(mode)); + dentry = start_creating(name, parent); + + if (IS_ERR(dentry)) + return NULL; - return __create_file(name, mode, parent, data, fops); + error = debugfs_create(dentry, mode, data, fops); + return end_creating(dentry, error); } EXPORT_SYMBOL_GPL(debugfs_create_file); @@ -434,8 +414,14 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); */ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { - return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, - parent, NULL, NULL); + struct dentry *dentry = start_creating(name, parent); + int error; + + if (IS_ERR(dentry)) + return NULL; + + error = debugfs_mkdir(dentry, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); + return end_creating(dentry, error); } EXPORT_SYMBOL_GPL(debugfs_create_dir); @@ -465,17 +451,26 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir); struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, const char *target) { - struct dentry *result; + struct dentry *dentry; char *link; + int error; link = kstrdup(target, GFP_KERNEL); if (!link) return NULL; - result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL); - if (!result) + dentry = start_creating(name, parent); + + if (IS_ERR(dentry)) { kfree(link); - return result; + return NULL; + } + + error = debugfs_link(dentry, S_IFLNK | S_IRWXUGO, link); + if (error) + kfree(link); + + return end_creating(dentry, error); } EXPORT_SYMBOL_GPL(debugfs_create_symlink); -- cgit v0.10.2 From 9b73fab01bcd62530e8c9a5da44d3ed8a753b3eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:05:55 -0500 Subject: fold debugfs_link() into caller Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 18564b0..c69e00d 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -103,14 +103,6 @@ static int debugfs_mkdir(struct dentry *dentry, umode_t mode) return res; } -static int debugfs_link(struct dentry *dentry, umode_t mode, - void *data) -{ - struct inode *dir = dentry->d_parent->d_inode; - mode = (mode & S_IALLUGO) | S_IFLNK; - return debugfs_mknod(dir, dentry, mode, 0, data, NULL); -} - static int debugfs_create(struct dentry *dentry, umode_t mode, void *data, const struct file_operations *fops) { @@ -466,7 +458,8 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, return NULL; } - error = debugfs_link(dentry, S_IFLNK | S_IRWXUGO, link); + error = debugfs_mknod(dentry->d_parent->d_inode, dentry, + S_IFLNK | S_IRWXUGO, 0, link, NULL); if (error) kfree(link); -- cgit v0.10.2 From 160f7592f2364b47c615cff96117f0877d58e427 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:09:49 -0500 Subject: debugfs_mknod(): get rid useless arguments dev is always zero, dir was only used to get its ->i_sb, which is equal to ->d_sb of dentry... Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index c69e00d..bc02e20 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -70,23 +70,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev } /* SMP-safe */ -static int debugfs_mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev, void *data, +static int debugfs_mknod(struct dentry *dentry, + umode_t mode, void *data, const struct file_operations *fops) { struct inode *inode; - int error = -EPERM; - if (dentry->d_inode) - return -EEXIST; - - inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops); - if (inode) { - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; + inode = debugfs_get_inode(dentry->d_sb, mode, 0, data, fops); + if (unlikely(!inode)) + return -EPERM; + d_instantiate(dentry, inode); + dget(dentry); + return 0; } static int debugfs_mkdir(struct dentry *dentry, umode_t mode) @@ -95,7 +90,7 @@ static int debugfs_mkdir(struct dentry *dentry, umode_t mode) int res; mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL); + res = debugfs_mknod(dentry, mode, NULL, NULL); if (!res) { inc_nlink(dir); fsnotify_mkdir(dir, dentry); @@ -110,7 +105,7 @@ static int debugfs_create(struct dentry *dentry, umode_t mode, int res; mode = (mode & S_IALLUGO) | S_IFREG; - res = debugfs_mknod(dir, dentry, mode, 0, data, fops); + res = debugfs_mknod(dentry, mode, data, fops); if (!res) fsnotify_create(dir, dentry); return res; @@ -458,8 +453,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, return NULL; } - error = debugfs_mknod(dentry->d_parent->d_inode, dentry, - S_IFLNK | S_IRWXUGO, 0, link, NULL); + error = debugfs_mknod(dentry, S_IFLNK | S_IRWXUGO, link, NULL); if (error) kfree(link); -- cgit v0.10.2 From 02538a75ba176d286a421d1e41a66061f407c3b3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:15:18 -0500 Subject: fold debugfs_mkdir() into caller Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index bc02e20..8d12935 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -84,20 +84,6 @@ static int debugfs_mknod(struct dentry *dentry, return 0; } -static int debugfs_mkdir(struct dentry *dentry, umode_t mode) -{ - struct inode *dir = dentry->d_parent->d_inode; - int res; - - mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = debugfs_mknod(dentry, mode, NULL, NULL); - if (!res) { - inc_nlink(dir); - fsnotify_mkdir(dir, dentry); - } - return res; -} - static int debugfs_create(struct dentry *dentry, umode_t mode, void *data, const struct file_operations *fops) { @@ -407,7 +393,12 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) if (IS_ERR(dentry)) return NULL; - error = debugfs_mkdir(dentry, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); + error = debugfs_mknod(dentry, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, + NULL, NULL); + if (!error) { + inc_nlink(dentry->d_parent->d_inode); + fsnotify_mkdir(dentry->d_parent->d_inode, dentry); + } return end_creating(dentry, error); } EXPORT_SYMBOL_GPL(debugfs_create_dir); -- cgit v0.10.2 From 3473cde5655cf4501cadb8ed11ab8aad1484b377 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:17:11 -0500 Subject: fold debugfs_create() into caller Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 8d12935..778c0e3 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -84,19 +84,6 @@ static int debugfs_mknod(struct dentry *dentry, return 0; } -static int debugfs_create(struct dentry *dentry, umode_t mode, - void *data, const struct file_operations *fops) -{ - struct inode *dir = dentry->d_parent->d_inode; - int res; - - mode = (mode & S_IALLUGO) | S_IFREG; - res = debugfs_mknod(dentry, mode, data, fops); - if (!res) - fsnotify_create(dir, dentry); - return res; -} - static inline int debugfs_positive(struct dentry *dentry) { return dentry->d_inode && !d_unhashed(dentry); @@ -362,7 +349,9 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, if (IS_ERR(dentry)) return NULL; - error = debugfs_create(dentry, mode, data, fops); + error = debugfs_mknod(dentry, mode, data, fops); + if (!error) + fsnotify_create(dentry->d_parent->d_inode, dentry); return end_creating(dentry, error); } EXPORT_SYMBOL_GPL(debugfs_create_file); -- cgit v0.10.2 From 680b302409cdc87c2000a31f2ceb2951bd642260 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:31:32 -0500 Subject: fold debugfs_mknod() into callers Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 778c0e3..b765c04 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -69,21 +69,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev return inode; } -/* SMP-safe */ -static int debugfs_mknod(struct dentry *dentry, - umode_t mode, void *data, - const struct file_operations *fops) -{ - struct inode *inode; - - inode = debugfs_get_inode(dentry->d_sb, mode, 0, data, fops); - if (unlikely(!inode)) - return -EPERM; - d_instantiate(dentry, inode); - dget(dentry); - return 0; -} - static inline int debugfs_positive(struct dentry *dentry) { return dentry->d_inode && !d_unhashed(dentry); @@ -339,7 +324,7 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, const struct file_operations *fops) { struct dentry *dentry; - int error; + struct inode *inode; if (!(mode & S_IFMT)) mode |= S_IFREG; @@ -349,10 +334,14 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, if (IS_ERR(dentry)) return NULL; - error = debugfs_mknod(dentry, mode, data, fops); - if (!error) - fsnotify_create(dentry->d_parent->d_inode, dentry); - return end_creating(dentry, error); + inode = debugfs_get_inode(dentry->d_sb, mode, 0, data, fops); + if (unlikely(!inode)) + return end_creating(dentry, -ENOMEM); + + d_instantiate(dentry, inode); + dget(dentry); + fsnotify_create(dentry->d_parent->d_inode, dentry); + return end_creating(dentry, 0); } EXPORT_SYMBOL_GPL(debugfs_create_file); @@ -377,18 +366,22 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { struct dentry *dentry = start_creating(name, parent); - int error; + struct inode *inode; if (IS_ERR(dentry)) return NULL; - error = debugfs_mknod(dentry, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, - NULL, NULL); - if (!error) { - inc_nlink(dentry->d_parent->d_inode); - fsnotify_mkdir(dentry->d_parent->d_inode, dentry); - } - return end_creating(dentry, error); + inode = debugfs_get_inode(dentry->d_sb, + S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, + 0, NULL, NULL); + if (unlikely(!inode)) + return end_creating(dentry, -ENOMEM); + + d_instantiate(dentry, inode); + dget(dentry); + inc_nlink(dentry->d_parent->d_inode); + fsnotify_mkdir(dentry->d_parent->d_inode, dentry); + return end_creating(dentry, 0); } EXPORT_SYMBOL_GPL(debugfs_create_dir); @@ -419,25 +412,26 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, const char *target) { struct dentry *dentry; - char *link; - int error; - - link = kstrdup(target, GFP_KERNEL); + struct inode *inode; + char *link = kstrdup(target, GFP_KERNEL); if (!link) return NULL; dentry = start_creating(name, parent); - if (IS_ERR(dentry)) { kfree(link); return NULL; } - error = debugfs_mknod(dentry, S_IFLNK | S_IRWXUGO, link, NULL); - if (error) + inode = debugfs_get_inode(dentry->d_sb, S_IFLNK | S_IRWXUGO, 0, + link, NULL); + if (unlikely(!inode)) { kfree(link); - - return end_creating(dentry, error); + return end_creating(dentry, -ENOMEM); + } + d_instantiate(dentry, inode); + dget(dentry); + return end_creating(dentry, 0); } EXPORT_SYMBOL_GPL(debugfs_create_symlink); -- cgit v0.10.2 From edac65eaf8d5c00b1d6004a44e76b9de6b038dc6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:36:18 -0500 Subject: debugfs: take mode-dependent parts of debugfs_get_inode() into callers ... and trim the arguments list Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b765c04..61e9a68 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -34,37 +34,12 @@ static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; -static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev_t dev, - void *data, const struct file_operations *fops) - +static struct inode *debugfs_get_inode(struct super_block *sb) { struct inode *inode = new_inode(sb); - if (inode) { inode->i_ino = get_next_ino(); - inode->i_mode = mode; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - default: - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - inode->i_fop = fops ? fops : &debugfs_file_operations; - inode->i_private = data; - break; - case S_IFLNK: - inode->i_op = &debugfs_link_operations; - inode->i_private = data; - break; - case S_IFDIR: - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 - * (for "." entry) */ - inc_nlink(inode); - break; - } } return inode; } @@ -334,10 +309,13 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, if (IS_ERR(dentry)) return NULL; - inode = debugfs_get_inode(dentry->d_sb, mode, 0, data, fops); + inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) return end_creating(dentry, -ENOMEM); + inode->i_mode = mode; + inode->i_fop = fops ? fops : &debugfs_file_operations; + inode->i_private = data; d_instantiate(dentry, inode); dget(dentry); fsnotify_create(dentry->d_parent->d_inode, dentry); @@ -371,12 +349,16 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) if (IS_ERR(dentry)) return NULL; - inode = debugfs_get_inode(dentry->d_sb, - S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, - 0, NULL, NULL); + inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) return end_creating(dentry, -ENOMEM); + inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; + inode->i_op = &simple_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); dget(dentry); inc_nlink(dentry->d_parent->d_inode); @@ -423,12 +405,14 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, return NULL; } - inode = debugfs_get_inode(dentry->d_sb, S_IFLNK | S_IRWXUGO, 0, - link, NULL); + inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) { kfree(link); return end_creating(dentry, -ENOMEM); } + inode->i_mode = S_IFLNK | S_IRWXUGO; + inode->i_op = &debugfs_link_operations; + inode->i_private = link; d_instantiate(dentry, inode); dget(dentry); return end_creating(dentry, 0); -- cgit v0.10.2 From 5233e31191af661389a4f5b060873bfcb155c828 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 14:39:49 -0500 Subject: debugfs: split end_creating() into success and failure cases ... and don't bother with dput(dentry) in the former and with dget(dentry) preceding all its calls. Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 61e9a68..1219dff 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -256,15 +256,17 @@ static struct dentry *start_creating(const char *name, struct dentry *parent) return dentry; } -static struct dentry *end_creating(struct dentry *dentry, int error) +static struct dentry *failed_creating(struct dentry *dentry) { mutex_unlock(&dentry->d_parent->d_inode->i_mutex); dput(dentry); + simple_release_fs(&debugfs_mount, &debugfs_mount_count); + return NULL; +} - if (error) { - dentry = NULL; - simple_release_fs(&debugfs_mount, &debugfs_mount_count); - } +static struct dentry *end_creating(struct dentry *dentry) +{ + mutex_unlock(&dentry->d_parent->d_inode->i_mutex); return dentry; } @@ -311,15 +313,14 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) - return end_creating(dentry, -ENOMEM); + return failed_creating(dentry); inode->i_mode = mode; inode->i_fop = fops ? fops : &debugfs_file_operations; inode->i_private = data; d_instantiate(dentry, inode); - dget(dentry); fsnotify_create(dentry->d_parent->d_inode, dentry); - return end_creating(dentry, 0); + return end_creating(dentry); } EXPORT_SYMBOL_GPL(debugfs_create_file); @@ -351,7 +352,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) - return end_creating(dentry, -ENOMEM); + return failed_creating(dentry); inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; inode->i_op = &simple_dir_inode_operations; @@ -360,10 +361,9 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) /* directory inodes start off with i_nlink == 2 (for "." entry) */ inc_nlink(inode); d_instantiate(dentry, inode); - dget(dentry); inc_nlink(dentry->d_parent->d_inode); fsnotify_mkdir(dentry->d_parent->d_inode, dentry); - return end_creating(dentry, 0); + return end_creating(dentry); } EXPORT_SYMBOL_GPL(debugfs_create_dir); @@ -408,14 +408,13 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) { kfree(link); - return end_creating(dentry, -ENOMEM); + return failed_creating(dentry); } inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_op = &debugfs_link_operations; inode->i_private = link; d_instantiate(dentry, inode); - dget(dentry); - return end_creating(dentry, 0); + return end_creating(dentry); } EXPORT_SYMBOL_GPL(debugfs_create_symlink); -- cgit v0.10.2 From 77b3da6e3232d3b4d4b8addb4b05799fe98f3bf8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Jan 2015 15:10:32 -0500 Subject: new primitive: debugfs_create_automount() Signed-off-by: Al Viro diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 1219dff..957c40c 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -175,6 +175,18 @@ static const struct super_operations debugfs_super_operations = { .show_options = debugfs_show_options, }; +static struct vfsmount *debugfs_automount(struct path *path) +{ + struct vfsmount *(*f)(void *); + f = (struct vfsmount *(*)(void *))path->dentry->d_fsdata; + return f(path->dentry->d_inode->i_private); +} + +static const struct dentry_operations debugfs_dops = { + .d_delete = always_delete_dentry, + .d_automount = debugfs_automount, +}; + static int debug_fill_super(struct super_block *sb, void *data, int silent) { static struct tree_descr debug_files[] = {{""}}; @@ -199,6 +211,7 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) goto fail; sb->s_op = &debugfs_super_operations; + sb->s_d_op = &debugfs_dops; debugfs_apply_options(sb); @@ -368,6 +381,41 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) EXPORT_SYMBOL_GPL(debugfs_create_dir); /** + * debugfs_create_automount - create automount point in the debugfs filesystem + * @name: a pointer to a string containing the name of the file to create. + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is NULL, then the + * file will be created in the root of the debugfs filesystem. + * @f: function to be called when pathname resolution steps on that one. + * @data: opaque argument to pass to f(). + * + * @f should return what ->d_automount() would. + */ +struct dentry *debugfs_create_automount(const char *name, + struct dentry *parent, + struct vfsmount *(*f)(void *), + void *data) +{ + struct dentry *dentry = start_creating(name, parent); + struct inode *inode; + + if (IS_ERR(dentry)) + return NULL; + + inode = debugfs_get_inode(dentry->d_sb); + if (unlikely(!inode)) + return failed_creating(dentry); + + inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; + inode->i_flags |= S_AUTOMOUNT; + inode->i_private = data; + dentry->d_fsdata = (void *)f; + d_instantiate(dentry, inode); + return end_creating(dentry); +} +EXPORT_SYMBOL(debugfs_create_automount); + +/** * debugfs_create_symlink- create a symbolic link in the debugfs filesystem * @name: a pointer to a string containing the name of the symbolic link to * create. diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index da4c498..ea149a2 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -56,6 +56,11 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, const char *dest); +struct dentry *debugfs_create_automount(const char *name, + struct dentry *parent, + struct vfsmount *(*f)(void *), + void *data); + void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); -- cgit v0.10.2 From e59b4e9187bd5175b9845dc10fedb0879b7efbfd Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 21 Jan 2015 20:03:40 +0000 Subject: debugfs: Provide a file creation function that also takes an initial size Provide a file creation function that also takes an initial size so that the caller doesn't have to set i_size, thus meaning that we don't have to call deal with ->d_inode in the callers. Signed-off-by: David Howells Signed-off-by: Al Viro diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index eb5df4e..391309a 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -700,37 +700,24 @@ static const struct file_operations ep_debugfs_fops = { static int setup_debugfs(struct c4iw_dev *devp) { - struct dentry *de; - if (!devp->debugfs_root) return -1; - de = debugfs_create_file("qps", S_IWUSR, devp->debugfs_root, - (void *)devp, &qp_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = 4096; + debugfs_create_file_size("qps", S_IWUSR, devp->debugfs_root, + (void *)devp, &qp_debugfs_fops, 4096); - de = debugfs_create_file("stags", S_IWUSR, devp->debugfs_root, - (void *)devp, &stag_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = 4096; + debugfs_create_file_size("stags", S_IWUSR, devp->debugfs_root, + (void *)devp, &stag_debugfs_fops, 4096); - de = debugfs_create_file("stats", S_IWUSR, devp->debugfs_root, - (void *)devp, &stats_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = 4096; + debugfs_create_file_size("stats", S_IWUSR, devp->debugfs_root, + (void *)devp, &stats_debugfs_fops, 4096); - de = debugfs_create_file("eps", S_IWUSR, devp->debugfs_root, - (void *)devp, &ep_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = 4096; + debugfs_create_file_size("eps", S_IWUSR, devp->debugfs_root, + (void *)devp, &ep_debugfs_fops, 4096); - if (c4iw_wr_log) { - de = debugfs_create_file("wr_log", S_IWUSR, devp->debugfs_root, - (void *)devp, &wr_log_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = 4096; - } + if (c4iw_wr_log) + debugfs_create_file_size("wr_log", S_IWUSR, devp->debugfs_root, + (void *)devp, &wr_log_debugfs_fops, 4096); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index c98a350..4c7fe44 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -91,12 +91,9 @@ static const struct file_operations mem_debugfs_fops = { static void add_debugfs_mem(struct adapter *adap, const char *name, unsigned int idx, unsigned int size_mb) { - struct dentry *de; - - de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root, - (void *)adap + idx, &mem_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = size_mb << 20; + debugfs_create_file_size(name, S_IRUSR, adap->debugfs_root, + (void *)adap + idx, &mem_debugfs_fops, + size_mb << 20); } /* Add an array of Debug FS files. diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index 34d20cc..2617f15 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -113,12 +113,9 @@ static const struct file_operations csio_mem_debugfs_fops = { void csio_add_debugfs_mem(struct csio_hw *hw, const char *name, unsigned int idx, unsigned int size_mb) { - struct dentry *de; - - de = debugfs_create_file(name, S_IRUSR, hw->debugfs_root, - (void *)hw + idx, &csio_mem_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = size_mb << 20; + debugfs_create_file_size(name, S_IRUSR, hw->debugfs_root, + (void *)hw + idx, &csio_mem_debugfs_fops, + size_mb << 20); } static int csio_setup_debugfs(struct csio_hw *hw) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 9f93bed..b2239a2 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -264,14 +264,17 @@ static void usba_init_debugfs(struct usba_udc *udc) goto err_root; udc->debugfs_root = root; - regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops); - if (!regs) - goto err_regs; - regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); - regs->d_inode->i_size = resource_size(regs_resource); - udc->debugfs_regs = regs; + + if (regs_resource) { + regs = debugfs_create_file_size("regs", 0400, root, udc, + ®s_dbg_fops, + resource_size(regs_resource)); + if (!regs) + goto err_regs; + udc->debugfs_regs = regs; + } usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 957c40c..45b18a5 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -338,6 +338,46 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, EXPORT_SYMBOL_GPL(debugfs_create_file); /** + * debugfs_create_file_size - create a file in the debugfs filesystem + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have. + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is NULL, then the + * file will be created in the root of the debugfs filesystem. + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + * @fops: a pointer to a struct file_operations that should be used for + * this file. + * @file_size: initial file size + * + * This is the basic "create a file" function for debugfs. It allows for a + * wide range of flexibility in creating a file, or a directory (if you want + * to create a directory, the debugfs_create_dir() function is + * recommended to be used instead.) + * + * This function will return a pointer to a dentry if it succeeds. This + * pointer must be passed to the debugfs_remove() function when the file is + * to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here.) If an error occurs, %NULL will be returned. + * + * If debugfs is not enabled in the kernel, the value -%ENODEV will be + * returned. + */ +struct dentry *debugfs_create_file_size(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + loff_t file_size) +{ + struct dentry *de = debugfs_create_file(name, mode, parent, data, fops); + + if (de) + de->d_inode->i_size = file_size; + return de; +} +EXPORT_SYMBOL_GPL(debugfs_create_file_size); + +/** * debugfs_create_dir - create a directory in the debugfs filesystem * @name: a pointer to a string containing the name of the directory to * create. diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index ea149a2..cb25af4 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -51,6 +51,11 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); +struct dentry *debugfs_create_file_size(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + loff_t file_size); + struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, @@ -129,6 +134,14 @@ static inline struct dentry *debugfs_create_file(const char *name, umode_t mode, return ERR_PTR(-ENODEV); } +static inline struct dentry *debugfs_create_file_size(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + loff_t file_size) +{ + return ERR_PTR(-ENODEV); +} + static inline struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { -- cgit v0.10.2