From 8a82472f86bf693b8e91ed56c9ca4f62fbbdcfa3 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 20 Nov 2006 17:07:51 +0100 Subject: driver core: Introduce device_move(): move a device to a new parent. Provide a function device_move() to move a device to a new parent device. Add auxilliary functions kobject_move() and sysfs_move_dir(). kobject_move() generates a new uevent of type KOBJ_MOVE, containing the previous path (DEVPATH_OLD) in addition to the usual values. For this, a new interface kobject_uevent_env() is created that allows to add further environmental data to the uevent at the kobject layer. Signed-off-by: Cornelia Huck Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'fs/sysfs') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 3aa3434621c..a5782e8c7f0 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) return error; } +int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) +{ + struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry; + struct sysfs_dirent *new_parent_sd, *sd; + int error; + + if (!new_parent) + return -EINVAL; + + old_parent_dentry = kobj->parent ? + kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; + new_parent_dentry = new_parent->dentry; + +again: + mutex_lock(&old_parent_dentry->d_inode->i_mutex); + if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { + mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + goto again; + } + + new_parent_sd = new_parent_dentry->d_fsdata; + sd = kobj->dentry->d_fsdata; + + new_dentry = lookup_one_len(kobj->name, new_parent_dentry, + strlen(kobj->name)); + if (IS_ERR(new_dentry)) { + error = PTR_ERR(new_dentry); + goto out; + } else + error = 0; + d_add(new_dentry, NULL); + d_move(kobj->dentry, new_dentry); + dput(new_dentry); + + /* Remove from old parent's list and insert into new parent's list. */ + list_del_init(&sd->s_sibling); + list_add(&sd->s_sibling, &new_parent_sd->s_children); + +out: + mutex_unlock(&new_parent_dentry->d_inode->i_mutex); + mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + + return error; +} + static int sysfs_dir_open(struct inode *inode, struct file *file) { struct dentry * dentry = file->f_dentry; -- cgit v1.2.3