Re: [Patch -mm 2/5] driver core: Introduce device_move(): move adevice to a new parent.
From: Cornelia Huck
Date: Wed Nov 15 2006 - 05:11:26 EST
On Wed, 15 Nov 2006 10:31:59 +0100,
Kay Sievers <kay.sievers@xxxxxxxx> wrote:
> We need the old DEVPATH in the environment (or something similar),
> otherwise we can't connect the event with the new device location to the
> current device. :)
Duh. I've attached another completely untested patch below.
> > Wouldn't we need something similar for kobject_rename()
> > as well?
>
> Maybe kobject_rename() can go, if we have a move function which can be
> used. In any case, the events should look identical to userspace, yes.
I think kobject_move() and kobject_rename() are two different beasts.
kobject_move() changes the topology, kobject_rename() changes an
identifier. Shouldn't they be reported in two different ways to
userspace?
---
include/linux/kobject.h | 6 ++++++
lib/kobject.c | 13 +++++++++++++
lib/kobject_uevent.c | 38 ++++++++++++++++++++++++++++++--------
3 files changed, 49 insertions(+), 8 deletions(-)
--- linux-2.6-CH.orig/include/linux/kobject.h
+++ linux-2.6-CH/include/linux/kobject.h
@@ -47,6 +47,7 @@ enum kobject_action {
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */
+ KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */
};
struct kobject {
@@ -265,6 +266,8 @@ extern int __must_check subsys_create_fi
#if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
+void kobject_uevent_extended(struct kobject *kobj, enum kobject_action action,
+ const char *string);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
@@ -272,6 +275,9 @@ int add_uevent_var(char **envp, int num_
__attribute__((format (printf, 7, 8)));
#else
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
+static inline void kobject_uevent_extended(struct kobject *kobj,
+ enum kobject_action action,
+ const char *string) { }
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
--- linux-2.6-CH.orig/lib/kobject.c
+++ linux-2.6-CH/lib/kobject.c
@@ -364,6 +364,8 @@ int kobject_move(struct kobject *kobj, s
{
int error;
struct kobject *old_parent;
+ const char *devpath = NULL;
+ const char *devpath_string = NULL;
kobj = kobject_get(kobj);
if (!kobj)
@@ -373,14 +375,25 @@ int kobject_move(struct kobject *kobj, s
error = -EINVAL;
goto out;
}
+ /* old object path */
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath)
+ goto out;
+ devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
+ if (!devpath_string)
+ goto out;
+ sprintf(devpath_string, "OLD_DEVPATH=%s", devpath);
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_extended(kobj, KOBJ_MOVE, devpath);
out:
kobject_put(kobj);
+ kfree(devpath_string);
+ kfree(devpath);
return error;
}
--- linux-2.6-CH.orig/lib/kobject_uevent.c
+++ linux-2.6-CH/lib/kobject_uevent.c
@@ -55,13 +55,8 @@ static char *action_to_string(enum kobje
}
}
-/**
- * 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)
+static void do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
+ const char *string)
{
char **envp;
char *buffer;
@@ -134,7 +129,10 @@ void kobject_uevent(struct kobject *kobj
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
-
+ if (string != NULL) {
+ envp [i++] = scratch;
+ scratch += sprintf(scratch, "%s", string) + 1;
+ }
/* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
@@ -200,9 +198,33 @@ exit:
kfree(envp);
return;
}
+
+/**
+ * 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)
+{
+ do_kobject_uevent(kobj, action, NULL);
+}
EXPORT_SYMBOL_GPL(kobject_uevent);
/**
+ * kobject_uevent_extended - send an uevent with extended data
+ *
+ * @action: action that is happening (usually KOBJ_MOVE)
+ * @kobj: struct kobject that the action is happening to
+ * @string: string containing additional data
+ */
+void kobject_uevent_extended(struct kobject *kobj, enum kobject_action action,
+ const char *string)
+{
+ do_kobject_uevent(kobj, action, string);
+}
+
+/**
* add_uevent_var - helper for creating event variables
* @envp: Pointer to table of environment variables, as passed into
* uevent() method.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/