Signed-off-by: Satyam Sharma --- fs/sysfs/symlink.c | 74 +++++++++++++++++++++++---------------------------- 1 files changed, 33 insertions(+), 41 deletions(-) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d056e96..bec477d 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -50,65 +50,57 @@ static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length) * @target: object we're pointing to. * @name: name of the symlink. */ -int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) +int sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name) { - struct sysfs_dirent *parent_sd = NULL; - struct sysfs_dirent *target_sd = NULL; - struct sysfs_dirent *sd = NULL; + struct sysfs_dirent *parent_sd; + struct sysfs_dirent *sd; struct sysfs_addrm_cxt acxt; - int error; + int error = 0; BUG_ON(!name); - if (!kobj) { - if (sysfs_mount && sysfs_mount->mnt_sb) - parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; - } else + if (kobj) parent_sd = kobj->sd; + else if (sysfs_mount && sysfs_mount->mnt_sb) + parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; + else { + error = -EFAULT; + goto out; + } - error = -EFAULT; - if (!parent_sd) - goto out_put; + if (sysfs_find_dirent(parent_sd, name)) { + error = -EEXIST; + goto out; + } + + sd = sysfs_new_dirent(name, S_IFLNK | S_IRWXUGO, SYSFS_KOBJ_LINK); + if (!sd) { + error = -ENOMEM; + goto out; + } /* target->sd can go away beneath us but is protected with - * sysfs_assoc_lock. Fetch target_sd from it. + * sysfs_assoc_lock. Grab us a reference on it. */ spin_lock(&sysfs_assoc_lock); if (target->sd) - target_sd = sysfs_get(target->sd); + sd->s_elem.symlink.target_sd = sysfs_get(target->sd); + else { + spin_unlock(&sysfs_assoc_lock); + sysfs_put(sd); + error = -ENOENT; + goto out; + } spin_unlock(&sysfs_assoc_lock); - error = -ENOENT; - if (!target_sd) - goto out_put; - - error = -ENOMEM; - 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); - - if (!sysfs_find_dirent(parent_sd, name)) { - sysfs_add_one(&acxt, sd); - sysfs_link_sibling(sd); - } - - if (sysfs_addrm_finish(&acxt)) - return 0; - - error = -EEXIST; - /* fall through */ - out_put: - sysfs_put(target_sd); - sysfs_put(sd); + sysfs_add_one(&acxt, sd); + sysfs_link_sibling(sd); + sysfs_addrm_finish(&acxt); +out: return error; } - /** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for.