You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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 <cornelia.huck@de.ibm.com> Acked-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
af9e076536
commit
8a82472f86
@@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_move - move object to another parent
|
||||
* @kobj: object in question.
|
||||
* @new_parent: object's new parent
|
||||
*/
|
||||
|
||||
int kobject_move(struct kobject *kobj, struct kobject *new_parent)
|
||||
{
|
||||
int error;
|
||||
struct kobject *old_parent;
|
||||
const char *devpath = NULL;
|
||||
char *devpath_string = NULL;
|
||||
char *envp[2];
|
||||
|
||||
kobj = kobject_get(kobj);
|
||||
if (!kobj)
|
||||
return -EINVAL;
|
||||
new_parent = kobject_get(new_parent);
|
||||
if (!new_parent) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* old object path */
|
||||
devpath = kobject_get_path(kobj, GFP_KERNEL);
|
||||
if (!devpath) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
|
||||
if (!devpath_string) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
|
||||
envp[0] = devpath_string;
|
||||
envp[1] = NULL;
|
||||
error = sysfs_move_dir(kobj, new_parent);
|
||||
if (error)
|
||||
goto out;
|
||||
old_parent = kobj->parent;
|
||||
kobj->parent = new_parent;
|
||||
kobject_put(old_parent);
|
||||
kobject_uevent_env(kobj, KOBJ_MOVE, envp);
|
||||
out:
|
||||
kobject_put(kobj);
|
||||
kfree(devpath_string);
|
||||
kfree(devpath);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_del - unlink kobject from hierarchy.
|
||||
* @kobj: object.
|
||||
|
||||
+24
-4
@@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action)
|
||||
return "offline";
|
||||
case KOBJ_ONLINE:
|
||||
return "online";
|
||||
case KOBJ_MOVE:
|
||||
return "move";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_uevent - notify userspace by ending an uevent
|
||||
* kobject_uevent_env - send an uevent with environmental data
|
||||
*
|
||||
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
|
||||
* @action: action that is happening (usually KOBJ_MOVE)
|
||||
* @kobj: struct kobject that the action is happening to
|
||||
* @envp_ext: pointer to environmental data
|
||||
*/
|
||||
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
||||
char *envp_ext[])
|
||||
{
|
||||
char **envp;
|
||||
char *buffer;
|
||||
@@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
char *seq_buff;
|
||||
int i = 0;
|
||||
int retval;
|
||||
int j;
|
||||
|
||||
pr_debug("%s\n", __FUNCTION__);
|
||||
|
||||
@@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
|
||||
envp [i++] = scratch;
|
||||
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
|
||||
|
||||
for (j = 0; envp_ext && envp_ext[j]; j++)
|
||||
envp[i++] = envp_ext[j];
|
||||
/* just reserve the space, overwrite it after kset call has returned */
|
||||
envp[i++] = seq_buff = scratch;
|
||||
scratch += strlen("SEQNUM=18446744073709551616") + 1;
|
||||
@@ -200,6 +206,20 @@ exit:
|
||||
kfree(envp);
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(kobject_uevent_env);
|
||||
|
||||
/**
|
||||
* kobject_uevent - notify userspace by ending an uevent
|
||||
*
|
||||
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
|
||||
* @kobj: struct kobject that the action is happening to
|
||||
*/
|
||||
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
{
|
||||
kobject_uevent_env(kobj, action, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(kobject_uevent);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user