aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/dir.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 463c5e3ccf1f..da4bb66a610c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -845,56 +845,58 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
845 BUG_ON(!sd->s_parent); 845 BUG_ON(!sd->s_parent);
846 new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; 846 new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
847 847
848 error = 0;
849 if (sd->s_parent == new_parent_sd)
850 goto out; /* nothing to move */
851
848 /* get dentries */ 852 /* get dentries */
849 old_dentry = sysfs_get_dentry(sd); 853 old_dentry = sysfs_get_dentry(sd);
850 if (IS_ERR(old_dentry)) { 854 if (IS_ERR(old_dentry)) {
851 error = PTR_ERR(old_dentry); 855 error = PTR_ERR(old_dentry);
852 goto out_dput; 856 goto out;
853 } 857 }
854 old_parent = old_dentry->d_parent; 858 old_parent = old_dentry->d_parent;
855 859
856 new_parent = sysfs_get_dentry(new_parent_sd); 860 new_parent = sysfs_get_dentry(new_parent_sd);
857 if (IS_ERR(new_parent)) { 861 if (IS_ERR(new_parent)) {
858 error = PTR_ERR(new_parent); 862 error = PTR_ERR(new_parent);
859 goto out_dput; 863 goto out;
860 } 864 }
861 865
862 if (old_parent->d_inode == new_parent->d_inode) {
863 error = 0;
864 goto out_dput; /* nothing to move */
865 }
866again: 866again:
867 mutex_lock(&old_parent->d_inode->i_mutex); 867 mutex_lock(&old_parent->d_inode->i_mutex);
868 if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { 868 if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
869 mutex_unlock(&old_parent->d_inode->i_mutex); 869 mutex_unlock(&old_parent->d_inode->i_mutex);
870 goto again; 870 goto again;
871 } 871 }
872 mutex_lock(&sysfs_mutex);
872 873
873 new_dentry = lookup_one_len(kobject_name(kobj), new_parent, strlen(kobject_name(kobj))); 874 error = -EEXIST;
874 if (IS_ERR(new_dentry)) { 875 if (sysfs_find_dirent(new_parent_sd, sd->s_name))
875 error = PTR_ERR(new_dentry);
876 goto out_unlock; 876 goto out_unlock;
877 } else 877
878 error = 0; 878 error = -ENOMEM;
879 new_dentry = d_alloc_name(new_parent, sd->s_name);
880 if (!new_dentry)
881 goto out_unlock;
882
883 error = 0;
879 d_add(new_dentry, NULL); 884 d_add(new_dentry, NULL);
880 d_move(old_dentry, new_dentry); 885 d_move(old_dentry, new_dentry);
881 dput(new_dentry); 886 dput(new_dentry);
882 887
883 /* Remove from old parent's list and insert into new parent's list. */ 888 /* Remove from old parent's list and insert into new parent's list. */
884 mutex_lock(&sysfs_mutex);
885
886 sysfs_unlink_sibling(sd); 889 sysfs_unlink_sibling(sd);
887 sysfs_get(new_parent_sd); 890 sysfs_get(new_parent_sd);
888 sysfs_put(sd->s_parent); 891 sysfs_put(sd->s_parent);
889 sd->s_parent = new_parent_sd; 892 sd->s_parent = new_parent_sd;
890 sysfs_link_sibling(sd); 893 sysfs_link_sibling(sd);
891 894
892 mutex_unlock(&sysfs_mutex);
893
894 out_unlock: 895 out_unlock:
896 mutex_unlock(&sysfs_mutex);
895 mutex_unlock(&new_parent->d_inode->i_mutex); 897 mutex_unlock(&new_parent->d_inode->i_mutex);
896 mutex_unlock(&old_parent->d_inode->i_mutex); 898 mutex_unlock(&old_parent->d_inode->i_mutex);
897 out_dput: 899 out:
898 dput(new_parent); 900 dput(new_parent);
899 dput(old_dentry); 901 dput(old_dentry);
900 dput(new_dentry); 902 dput(new_dentry);