summaryrefslogtreecommitdiffstats
path: root/fs/sysfs/symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/symlink.c')
-rw-r--r--fs/sysfs/symlink.c51
1 files changed, 26 insertions, 25 deletions
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index cbd95a4109d..683316f0aa9 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -44,20 +44,6 @@ static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
}
}
-static int sysfs_add_link(struct sysfs_dirent * parent_sd, const char * name,
- struct sysfs_dirent * target_sd)
-{
- struct sysfs_dirent * sd;
-
- sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
- if (!sd)
- return -ENOMEM;
-
- sd->s_elem.symlink.target_sd = target_sd;
- sysfs_attach_dirent(sd, parent_sd, NULL);
- return 0;
-}
-
/**
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
@@ -68,7 +54,8 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
{
struct sysfs_dirent *parent_sd = NULL;
struct sysfs_dirent *target_sd = NULL;
- int error = -EEXIST;
+ struct sysfs_dirent *sd = NULL;
+ int error;
BUG_ON(!name);
@@ -78,8 +65,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
} else
parent_sd = kobj->sd;
+ error = -EFAULT;
if (!parent_sd)
- return -EFAULT;
+ goto out_put;
/* target->sd can go away beneath us but is protected with
* sysfs_assoc_lock. Fetch target_sd from it.
@@ -89,17 +77,30 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
target_sd = sysfs_get(target->sd);
spin_unlock(&sysfs_assoc_lock);
+ error = -ENOENT;
if (!target_sd)
- return -ENOENT;
+ 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;
- mutex_lock(&parent_sd->s_dentry->d_inode->i_mutex);
- if (!sysfs_find_dirent(parent_sd, name))
- error = sysfs_add_link(parent_sd, name, target_sd);
- mutex_unlock(&parent_sd->s_dentry->d_inode->i_mutex);
+ mutex_lock(&sysfs_mutex);
+ error = -EEXIST;
+ if (sysfs_find_dirent(parent_sd, name))
+ goto out_unlock;
+ sysfs_attach_dirent(sd, parent_sd, NULL);
+ mutex_unlock(&sysfs_mutex);
- if (error)
- sysfs_put(target_sd);
+ return 0;
+ out_unlock:
+ mutex_unlock(&sysfs_mutex);
+ out_put:
+ sysfs_put(target_sd);
+ sysfs_put(sd);
return error;
}
@@ -144,9 +145,9 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
int error;
- down_read(&sysfs_rename_sem);
+ mutex_lock(&sysfs_mutex);
error = sysfs_get_target_path(parent_sd, target_sd, path);
- up_read(&sysfs_rename_sem);
+ mutex_unlock(&sysfs_mutex);
return error;
}