aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/dir.c38
1 files changed, 16 insertions, 22 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 36b6c796d4d5..463c5e3ccf1f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -770,7 +770,7 @@ void sysfs_remove_dir(struct kobject * kobj)
770 770
771int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 771int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
772{ 772{
773 struct sysfs_dirent *sd; 773 struct sysfs_dirent *sd = kobj->sd;
774 struct dentry *parent = NULL; 774 struct dentry *parent = NULL;
775 struct dentry *old_dentry = NULL, *new_dentry = NULL; 775 struct dentry *old_dentry = NULL, *new_dentry = NULL;
776 const char *dup_name = NULL; 776 const char *dup_name = NULL;
@@ -778,63 +778,57 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
778 778
779 mutex_lock(&sysfs_rename_mutex); 779 mutex_lock(&sysfs_rename_mutex);
780 780
781 error = 0;
782 if (strcmp(sd->s_name, new_name) == 0)
783 goto out; /* nothing to rename */
784
781 /* get the original dentry */ 785 /* get the original dentry */
782 sd = kobj->sd;
783 old_dentry = sysfs_get_dentry(sd); 786 old_dentry = sysfs_get_dentry(sd);
784 if (IS_ERR(old_dentry)) { 787 if (IS_ERR(old_dentry)) {
785 error = PTR_ERR(old_dentry); 788 error = PTR_ERR(old_dentry);
786 goto out_dput; 789 goto out;
787 } 790 }
788 791
789 parent = old_dentry->d_parent; 792 parent = old_dentry->d_parent;
790 793
791 /* lock parent and get dentry for new name */ 794 /* lock parent and get dentry for new name */
792 mutex_lock(&parent->d_inode->i_mutex); 795 mutex_lock(&parent->d_inode->i_mutex);
796 mutex_lock(&sysfs_mutex);
793 797
794 new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); 798 error = -EEXIST;
795 if (IS_ERR(new_dentry)) { 799 if (sysfs_find_dirent(sd->s_parent, new_name))
796 error = PTR_ERR(new_dentry);
797 goto out_unlock;
798 }
799
800 error = -EINVAL;
801 if (old_dentry == new_dentry)
802 goto out_unlock; 800 goto out_unlock;
803 801
804 error = -EEXIST; 802 error = -ENOMEM;
805 if (new_dentry->d_inode) 803 new_dentry = d_alloc_name(parent, new_name);
804 if (!new_dentry)
806 goto out_unlock; 805 goto out_unlock;
807 806
808 /* rename kobject and sysfs_dirent */ 807 /* rename kobject and sysfs_dirent */
809 error = -ENOMEM; 808 error = -ENOMEM;
810 new_name = dup_name = kstrdup(new_name, GFP_KERNEL); 809 new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
811 if (!new_name) 810 if (!new_name)
812 goto out_drop; 811 goto out_unlock;
813 812
814 error = kobject_set_name(kobj, "%s", new_name); 813 error = kobject_set_name(kobj, "%s", new_name);
815 if (error) 814 if (error)
816 goto out_drop; 815 goto out_unlock;
817 816
818 mutex_lock(&sysfs_mutex);
819 dup_name = sd->s_name; 817 dup_name = sd->s_name;
820 sd->s_name = new_name; 818 sd->s_name = new_name;
821 mutex_unlock(&sysfs_mutex);
822 819
823 /* rename */ 820 /* rename */
824 d_add(new_dentry, NULL); 821 d_add(new_dentry, NULL);
825 d_move(old_dentry, new_dentry); 822 d_move(old_dentry, new_dentry);
826 823
827 error = 0; 824 error = 0;
828 goto out_unlock;
829
830 out_drop:
831 d_drop(new_dentry);
832 out_unlock: 825 out_unlock:
826 mutex_unlock(&sysfs_mutex);
833 mutex_unlock(&parent->d_inode->i_mutex); 827 mutex_unlock(&parent->d_inode->i_mutex);
834 out_dput:
835 kfree(dup_name); 828 kfree(dup_name);
836 dput(old_dentry); 829 dput(old_dentry);
837 dput(new_dentry); 830 dput(new_dentry);
831 out:
838 mutex_unlock(&sysfs_rename_mutex); 832 mutex_unlock(&sysfs_rename_mutex);
839 return error; 833 return error;
840} 834}