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/sysfs/symlink.c') diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 2f86e0422290..d056e9695cd6 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.2 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/symlink.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'fs/sysfs/symlink.c') diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d056e9695cd6..4ce687f0b5d0 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.2