patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / sysfs / dir.c
index add2045..d688117 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/kobject.h>
 #include "sysfs.h"
 
+DECLARE_RWSEM(sysfs_rename_sem);
+
 static int init_dir(struct inode * inode)
 {
        inode->i_op = &simple_dir_inode_operations;
@@ -134,8 +136,14 @@ restart:
                        /**
                         * Unlink and unhash.
                         */
+                       __d_drop(d);
                        spin_unlock(&dcache_lock);
-                       d_delete(d);
+                       /* release the target kobject in case of 
+                        * a symlink
+                        */
+                       if (S_ISLNK(d->d_inode->i_mode))
+                               kobject_put(d->d_fsdata);
+                       
                        simple_unlink(dentry->d_inode,d);
                        dput(d);
                        pr_debug(" done\n");
@@ -154,24 +162,35 @@ restart:
        dput(dentry);
 }
 
-void sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
 {
+       int error = 0;
        struct dentry * new_dentry, * parent;
 
        if (!strcmp(kobject_name(kobj), new_name))
-               return;
+               return -EINVAL;
 
        if (!kobj->parent)
-               return;
+               return -EINVAL;
 
+       down_write(&sysfs_rename_sem);
        parent = kobj->parent->dentry;
 
        down(&parent->d_inode->i_sem);
 
        new_dentry = sysfs_get_dentry(parent, new_name);
-       d_move(kobj->dentry, new_dentry);
-       kobject_set_name(kobj,new_name);
+       if (!IS_ERR(new_dentry)) {
+               if (!new_dentry->d_inode) {
+                       error = kobject_set_name(kobj,new_name);
+                       if (!error)
+                               d_move(kobj->dentry, new_dentry);
+               }
+               dput(new_dentry);
+       }
        up(&parent->d_inode->i_sem);    
+       up_write(&sysfs_rename_sem);
+
+       return error;
 }
 
 EXPORT_SYMBOL(sysfs_create_dir);