From a6bb340da32f0abf76656be1619fb85150eef61b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 11 Jul 2007 14:53:28 +0200 Subject: debugfs: remove rmdir() non-empty complaint Hi, This patch kills the pointless debugfs rmdir() printk() when called on a non-empty directory. blktrace will sometimes have to call it a few times when forcefully ending a trace, which polutes the log with pointless warnings. Rationale: - It's more code to work-around this "problem" in the debugfs users, and you would have to add code to check for empty directories to do so (or assume that debugfs is using simple_ helpers, but that would be a layering violation). - Other rmdir() implementations don't complain about something this silly. Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'fs') diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 1d533a2ec3a..11be8a325e2 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -345,11 +345,6 @@ void debugfs_remove(struct dentry *dentry) switch (dentry->d_inode->i_mode & S_IFMT) { case S_IFDIR: ret = simple_rmdir(parent->d_inode, dentry); - if (ret) - printk(KERN_ERR - "DebugFS rmdir on %s failed : " - "directory not empty.\n", - dentry->d_name.name); break; case S_IFLNK: kfree(dentry->d_inode->i_private); -- cgit v1.2.3 From 01da2425f327d7ac673e594bee5655523115970b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 14 Jul 2007 11:03:35 +0900 Subject: sysfs: avoid kmem_cache_free(NULL) kmem_cache_free() with NULL is not allowed. But it may happen if out of memory error is triggered in sysfs_new_dirent(). This patch fixes that error handling. Signed-off-by: Akinobu Mita Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index aee966c44aa..2e6775a836f 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -361,20 +361,20 @@ static struct dentry_operations sysfs_dentry_ops = { struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) { char *dup_name = NULL; - struct sysfs_dirent *sd = NULL; + struct sysfs_dirent *sd; if (type & SYSFS_COPY_NAME) { name = dup_name = kstrdup(name, GFP_KERNEL); if (!name) - goto err_out; + return NULL; } sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); if (!sd) - goto err_out; + goto err_out1; if (sysfs_alloc_ino(&sd->s_ino)) - goto err_out; + goto err_out2; atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); @@ -386,9 +386,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) return sd; - err_out: - kfree(dup_name); + err_out2: kmem_cache_free(sysfs_dir_cachep, sd); + err_out1: + kfree(dup_name); return NULL; } -- cgit v1.2.3 From e080e436f605877e47e4950f5386ed843badbb1b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 14:29:06 +0900 Subject: sysfs: fix sysfs root inode nlink accounting While making sysfs indoes hashed, sysfs root inode was left out. Now that nlink accounting depends on the inode being on the hash, sysfs root inode nlink isn't adjusted properly. Put sysfs root inode on the inode hash by allocating it using sysfs_get_inode() like other sysfs inodes. While at it, massage comments a bit. Signed-off-by: Tejun Heo Acked-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/mount.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 402cc356203..60714d075c2 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -43,19 +43,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_time_gran = 1; sysfs_sb = sb; - inode = new_inode(sysfs_sb); + /* get root inode, initialize and unlock it */ + inode = sysfs_get_inode(&sysfs_root); if (!inode) { pr_debug("sysfs: could not get root inode\n"); return -ENOMEM; } - sysfs_init_inode(&sysfs_root, inode); - inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations; - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); + inc_nlink(inode); /* directory, account for "." */ + unlock_new_inode(inode); + /* instantiate and link root dentry */ root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__FUNCTION__); -- cgit v1.2.3 From bc37e2830339cbfa42ac8579a7bf62fc4cdd360d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 14:30:28 +0900 Subject: sysfs: make sysfs_init_inode() static With sysfs_fill_super() converted to use sysfs_get_inode(), there is no user of sysfs_init_inode() outside of fs/sysfs/inode.c. Make it static. Signed-off-by: Tejun Heo Acked-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/inode.c | 2 +- fs/sysfs/sysfs.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 3756e152285..10d1b52899f 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -133,7 +133,7 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) */ static struct lock_class_key sysfs_inode_imutex_key; -void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) +static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { inode->i_blocks = 0; inode->i_mapping->a_ops = &sysfs_aops; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6a37f2386a8..6b8c8d76d30 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -71,7 +71,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); extern void sysfs_delete_inode(struct inode *inode); -extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); -- cgit v1.2.3 From a1da4dfe35bc36c3bc9716d995c85b7983c38a76 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 16:14:45 +0900 Subject: sysfs: kill an extra put in sysfs_create_link() failure path There is a subtle bug in sysfs_create_link() failure path. When symlink creation fails because there's already a node with the same name, the target sysfs_dirent is put twice - once by failure path of sysfs_create_link() and once more when the symlink is released. Fix it by making only the symlink node responsible for putting target_sd. Signed-off-by: Tejun Heo Cc: Gabriel C Cc: Miles Lane Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/symlink.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 2f86e042229..d056e9695cd 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -86,7 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); if (!sd) goto out_put; + sd->s_elem.symlink.target_sd = target_sd; + target_sd = NULL; /* reference is now owned by the symlink */ sysfs_addrm_start(&acxt, parent_sd); -- cgit v1.2.3 From 967e35dcc9ac194b4a6fad69a5a51f93d69bb0d1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 18 Jul 2007 16:38:11 +0900 Subject: sysfs: cosmetic clean up on node creation failure paths Node addition failure is detected by testing return value of sysfs_addfm_finish() which returns the number of added and removed nodes. As the function is called as the last step of addition right on top of error handling block, the if blocks looked like the following. if (sysfs_addrm_finish(&acxt)) success handling, usually return; /* fall through to error handling */ This is the opposite of usual convention in sysfs and makes the code difficult to understand. This patch inverts the test and makes those blocks look more like others. Signed-off-by: Tejun Heo Cc: Gabriel C Cc: Miles Lane Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 12 +++++++----- fs/sysfs/file.c | 9 +++++---- fs/sysfs/symlink.c | 10 ++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 2e6775a836f..048e6054c2f 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -699,17 +699,19 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, /* link in */ sysfs_addrm_start(&acxt, parent_sd); + if (!sysfs_find_dirent(parent_sd, name)) { sysfs_add_one(&acxt, sd); sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) { - *p_sd = sd; - return 0; + + if (!sysfs_addrm_finish(&acxt)) { + sysfs_put(sd); + return -EEXIST; } - sysfs_put(sd); - return -EEXIST; + *p_sd = sd; + return 0; } int sysfs_create_subdir(struct kobject *kobj, const char *name, diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index cc497994b2a..3e1cc062a74 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -410,11 +410,12 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) - return 0; + if (!sysfs_addrm_finish(&acxt)) { + sysfs_put(sd); + return -EEXIST; + } - sysfs_put(sd); - return -EEXIST; + return 0; } diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d056e9695cd..4ce687f0b5d 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -97,11 +97,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char sysfs_link_sibling(sd); } - if (sysfs_addrm_finish(&acxt)) - return 0; + if (!sysfs_addrm_finish(&acxt)) { + error = -EEXIST; + goto out_put; + } + + return 0; - error = -EEXIST; - /* fall through */ out_put: sysfs_put(target_sd); sysfs_put(sd); -- cgit v1.2.3