#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;
/**
* 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");
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);