diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 34 |
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 | } | ||
866 | again: | 866 | again: |
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); |