* [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent.
@ 2006-11-14 10:32 Cornelia Huck
2006-11-15 6:50 ` Greg KH
0 siblings, 1 reply; 10+ messages in thread
From: Cornelia Huck @ 2006-11-14 10:32 UTC (permalink / raw)
To: linux-kernel; +Cc: Andrew Morton, Greg K-H, Martin Schwidefsky
From: Cornelia Huck <cornelia.huck@de.ibm.com>
Provide a function device_move() to move a device to a new parent device. Add
auxilliary functions kobject_move() and sysfs_move_dir().
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
drivers/base/core.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
fs/sysfs/dir.c | 45 +++++++++++++++++++++++
include/linux/device.h | 1
include/linux/kobject.h | 1
include/linux/sysfs.h | 3 +
lib/kobject.c | 30 +++++++++++++++
6 files changed, 172 insertions(+)
--- linux-2.6-CH.orig/drivers/base/core.c
+++ linux-2.6-CH/drivers/base/core.c
@@ -955,3 +955,95 @@ int device_rename(struct device *dev, ch
return error;
}
+
+
+static int device_move_class_links(struct device *dev,
+ struct device *old_parent,
+ struct device *new_parent)
+{
+#ifdef CONFIG_SYSFS_DEPRECATED
+ int error;
+ char *class_name;
+
+ class_name = make_class_name(dev->class->name, &dev->kobj);
+ if (!class_name) {
+ error = PTR_ERR(class_name);
+ class_name = NULL;
+ goto out;
+ }
+ if (old_parent) {
+ sysfs_remove_link(&dev->kobj, "device");
+ sysfs_remove_link(&old_parent->kobj, class_name);
+ }
+ error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
+ if (error)
+ goto out;
+ error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
+ if (error)
+ sysfs_remove_link(&dev->kobj, "device");
+out:
+ kfree(class_name);
+ return error;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * device_move - moves a device to a new parent
+ * @dev: the pointer to the struct device to be moved
+ * @new_parent: the new parent of the device
+ */
+int device_move(struct device *dev, struct device *new_parent)
+{
+ int error;
+ struct device *old_parent;
+
+ dev = get_device(dev);
+ if (!dev)
+ return -EINVAL;
+
+ if (!device_is_registered(dev)) {
+ error = -EINVAL;
+ goto out;
+ }
+ new_parent = get_device(new_parent);
+ if (!new_parent) {
+ error = -EINVAL;
+ goto out;
+ }
+ pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
+ new_parent->bus_id);
+ error = kobject_move(&dev->kobj, &new_parent->kobj);
+ if (error) {
+ put_device(new_parent);
+ goto out;
+ }
+ old_parent = dev->parent;
+ dev->parent = new_parent;
+ if (old_parent)
+ klist_del(&dev->knode_parent);
+ klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+ if (!dev->class)
+ goto out_put;
+ error = device_move_class_links(dev, old_parent, new_parent);
+ if (error) {
+ /* We ignore errors on cleanup since we're hosed anyway... */
+ device_move_class_links(dev, new_parent, old_parent);
+ if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
+ klist_del(&dev->knode_parent);
+ if (old_parent)
+ klist_add_tail(&dev->knode_parent,
+ &old_parent->klist_children);
+ }
+ put_device(new_parent);
+ goto out;
+ }
+out_put:
+ put_device(old_parent);
+out:
+ put_device(dev);
+ return error;
+}
+
+EXPORT_SYMBOL_GPL(device_move);
--- linux-2.6-CH.orig/fs/sysfs/dir.c
+++ linux-2.6-CH/fs/sysfs/dir.c
@@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * ko
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_path.dentry;
--- linux-2.6-CH.orig/include/linux/device.h
+++ linux-2.6-CH/include/linux/device.h
@@ -423,6 +423,7 @@ extern int device_for_each_child(struct
extern struct device *device_find_child(struct device *, void *data,
int (*match)(struct device *, void *));
extern int device_rename(struct device *dev, char *new_name);
+extern int device_move(struct device *dev, struct device *new_parent);
/*
* Manual binding of a device to driver. See drivers/base/bus.c
--- linux-2.6-CH.orig/include/linux/kobject.h
+++ linux-2.6-CH/include/linux/kobject.h
@@ -76,6 +76,7 @@ extern int __must_check kobject_add(stru
extern void kobject_del(struct kobject *);
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
+extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern int __must_check kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *);
--- linux-2.6-CH.orig/include/linux/sysfs.h
+++ linux-2.6-CH/include/linux/sysfs.h
@@ -97,6 +97,9 @@ extern int __must_check
sysfs_rename_dir(struct kobject *, const char *new_name);
extern int __must_check
+sysfs_move_dir(struct kobject *, struct kobject *);
+
+extern int __must_check
sysfs_create_file(struct kobject *, const struct attribute *);
extern int __must_check
--- linux-2.6-CH.orig/lib/kobject.c
+++ linux-2.6-CH/lib/kobject.c
@@ -355,6 +355,36 @@ int kobject_rename(struct kobject * kobj
}
/**
+ * 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;
+
+ kobj = kobject_get(kobj);
+ if (!kobj)
+ return -EINVAL;
+ new_parent = kobject_get(new_parent);
+ if (!new_parent) {
+ error = -EINVAL;
+ goto out;
+ }
+ error = sysfs_move_dir(kobj, new_parent);
+ if (error)
+ goto out;
+ old_parent = kobj->parent;
+ kobj->parent = new_parent;
+ kobject_put(old_parent);
+out:
+ kobject_put(kobj);
+ return error;
+}
+
+/**
* kobject_del - unlink kobject from hierarchy.
* @kobj: object.
*/
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-14 10:32 [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent Cornelia Huck @ 2006-11-15 6:50 ` Greg KH 2006-11-15 7:28 ` Cornelia Huck 0 siblings, 1 reply; 10+ messages in thread From: Greg KH @ 2006-11-15 6:50 UTC (permalink / raw) To: Cornelia Huck; +Cc: linux-kernel, Andrew Morton, Martin Schwidefsky On Tue, Nov 14, 2006 at 11:32:08AM +0100, Cornelia Huck wrote: > From: Cornelia Huck <cornelia.huck@de.ibm.com> > > Provide a function device_move() to move a device to a new parent device. Add > auxilliary functions kobject_move() and sysfs_move_dir(). At first glance, this looks sane, but for the kobject_move function, we are not notifying userspace that something has changed here. Is that ok? How will udev and HAL handle something like this without being told about it? When the device eventually goes away, I think they will be very confused. thanks, greg k-h ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 6:50 ` Greg KH @ 2006-11-15 7:28 ` Cornelia Huck 2006-11-15 8:44 ` Kay Sievers 0 siblings, 1 reply; 10+ messages in thread From: Cornelia Huck @ 2006-11-15 7:28 UTC (permalink / raw) To: Greg KH; +Cc: linux-kernel, Andrew Morton, Martin Schwidefsky On Tue, 14 Nov 2006 22:50:52 -0800, Greg KH <greg@kroah.com> wrote: > On Tue, Nov 14, 2006 at 11:32:08AM +0100, Cornelia Huck wrote: > > From: Cornelia Huck <cornelia.huck@de.ibm.com> > > > > Provide a function device_move() to move a device to a new parent device. Add > > auxilliary functions kobject_move() and sysfs_move_dir(). > > At first glance, this looks sane, but for the kobject_move function, we > are not notifying userspace that something has changed here. > > Is that ok? > > How will udev and HAL handle something like this without being told > about it? When the device eventually goes away, I think they will be > very confused. Hm. I don't think we want to trigger udev with some remove/add events (especially since it is still the same device, it just has been moved around). A change event doesn't sound quite right either. But I guess we need to do something, at least to make HAL happy since it remembers the path in sysfs (although I seem to remember a HAL patch that got rid of it?) -- Cornelia Huck Linux for zSeries Developer Tel.: +49-7031-16-4837, Mail: cornelia.huck@de.ibm.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 7:28 ` Cornelia Huck @ 2006-11-15 8:44 ` Kay Sievers 2006-11-15 9:24 ` Cornelia Huck 0 siblings, 1 reply; 10+ messages in thread From: Kay Sievers @ 2006-11-15 8:44 UTC (permalink / raw) To: Cornelia Huck; +Cc: Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On 11/15/06, Cornelia Huck <cornelia.huck@de.ibm.com> wrote: > On Tue, 14 Nov 2006 22:50:52 -0800, > Greg KH <greg@kroah.com> wrote: > > > On Tue, Nov 14, 2006 at 11:32:08AM +0100, Cornelia Huck wrote: > > > From: Cornelia Huck <cornelia.huck@de.ibm.com> > > > > > > Provide a function device_move() to move a device to a new parent device. Add > > > auxilliary functions kobject_move() and sysfs_move_dir(). > > > > At first glance, this looks sane, but for the kobject_move function, we > > are not notifying userspace that something has changed here. > > > > Is that ok? > > > > How will udev and HAL handle something like this without being told > > about it? When the device eventually goes away, I think they will be > > very confused. Yes, userspace will get confused, if we we don't get proper notification. We require to update the udev and HAL database with the new devpath, to find the current device context on device events, or for "remove". > Hm. I don't think we want to trigger udev with some remove/add events > (especially since it is still the same device, it just has been moved > around). A change event doesn't sound quite right either. But I guess > we need to do something, at least to make HAL happy since it remembers > the path in sysfs (although I seem to remember a HAL patch that got rid > of it?) Udev and HAL, both will need an event for the moving, with the old DEVPATH value in the environment. We want something like a "rename" or "move" event. Without that, weird things will happen in userspace, because the devpath is used as the key to the device during the whole device lifetime. The only weird exception today is the netif rename case, which is already handled by special code in udev. Thanks, Kay ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 8:44 ` Kay Sievers @ 2006-11-15 9:24 ` Cornelia Huck 2006-11-15 9:31 ` Kay Sievers 0 siblings, 1 reply; 10+ messages in thread From: Cornelia Huck @ 2006-11-15 9:24 UTC (permalink / raw) To: Kay Sievers; +Cc: Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On Wed, 15 Nov 2006 09:44:33 +0100, "Kay Sievers" <kay.sievers@vrfy.org> wrote: > Udev and HAL, both will need an event for the moving, with the old > DEVPATH value in the environment. We want something like a "rename" or > "move" event. Without that, weird things will happen in userspace, > because the devpath is used as the key to the device during the whole > device lifetime. The only weird exception today is the netif rename > case, which is already handled by special code in udev. Something like below (completely untested as my test box is currently inaccessible)? Wouldn't we need something similar for kobject_rename() as well? --- include/linux/kobject.h | 1 + lib/kobject.c | 1 + 2 files changed, 2 insertions(+) --- 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 { --- linux-2.6-CH.orig/lib/kobject.c +++ linux-2.6-CH/lib/kobject.c @@ -379,6 +379,7 @@ int kobject_move(struct kobject *kobj, s old_parent = kobj->parent; kobj->parent = new_parent; kobject_put(old_parent); + kobject_uevent(kobj, KOBJ_MOVE); out: kobject_put(kobj); return error; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 9:24 ` Cornelia Huck @ 2006-11-15 9:31 ` Kay Sievers 2006-11-15 10:11 ` Cornelia Huck 0 siblings, 1 reply; 10+ messages in thread From: Kay Sievers @ 2006-11-15 9:31 UTC (permalink / raw) To: Cornelia Huck; +Cc: Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On Wed, 2006-11-15 at 10:24 +0100, Cornelia Huck wrote: > On Wed, 15 Nov 2006 09:44:33 +0100, > "Kay Sievers" <kay.sievers@vrfy.org> wrote: > > > Udev and HAL, both will need an event for the moving, with the old > > DEVPATH value in the environment. We want something like a "rename" or > > "move" event. Without that, weird things will happen in userspace, > > because the devpath is used as the key to the device during the whole > > device lifetime. The only weird exception today is the netif rename > > case, which is already handled by special code in udev. > > Something like below (completely untested as my test box is currently > inaccessible)? 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. :) > 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. Thanks, Kay ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 9:31 ` Kay Sievers @ 2006-11-15 10:11 ` Cornelia Huck 2006-11-15 16:44 ` Dmitry Torokhov 2006-11-15 17:39 ` Cornelia Huck 0 siblings, 2 replies; 10+ messages in thread From: Cornelia Huck @ 2006-11-15 10:11 UTC (permalink / raw) To: Kay Sievers; +Cc: Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On Wed, 15 Nov 2006 10:31:59 +0100, Kay Sievers <kay.sievers@vrfy.org> 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. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 10:11 ` Cornelia Huck @ 2006-11-15 16:44 ` Dmitry Torokhov 2006-11-15 17:23 ` Cornelia Huck 2006-11-15 17:39 ` Cornelia Huck 1 sibling, 1 reply; 10+ messages in thread From: Dmitry Torokhov @ 2006-11-15 16:44 UTC (permalink / raw) To: Cornelia Huck Cc: Kay Sievers, Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On 11/15/06, Cornelia Huck <cornelia.huck@de.ibm.com> wrote: > On Wed, 15 Nov 2006 10:31:59 +0100, > Kay Sievers <kay.sievers@vrfy.org> 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? > Why do we need to have them at all? Devices should not "move" in the trees - it it moves we should just treat them as old devices going away and new devices appearing... Renames - they are only used to rename net devices, don't they? I wonder if we could have just a separate "alias" or "name" sysfs attribute for them and get away with renaming of devices. -- Dmitry ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 16:44 ` Dmitry Torokhov @ 2006-11-15 17:23 ` Cornelia Huck 0 siblings, 0 replies; 10+ messages in thread From: Cornelia Huck @ 2006-11-15 17:23 UTC (permalink / raw) To: Dmitry Torokhov Cc: Kay Sievers, Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On Wed, 15 Nov 2006 11:44:36 -0500, "Dmitry Torokhov" <dmitry.torokhov@gmail.com> wrote: > Why do we need to have them at all? Devices should not "move" in the > trees - it it moves we should just treat them as old devices going > away and new devices appearing... But unregistering and re-registering is exactly what we want to avoid in our case. We have still the same ccw device, it's only now operational via another subchannel (i. e. the topology changed, but not the device). If we unregistered the device, we would also kill the associated block device(s), and if it had been mounted, we go boom. (This is what currently happens without this patchset, and it may be triggered by a short hardware outage we'd otherwise survive without a problem.) -- Cornelia Huck Linux for zSeries Developer Tel.: +49-7031-16-4837, Mail: cornelia.huck@de.ibm.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent. 2006-11-15 10:11 ` Cornelia Huck 2006-11-15 16:44 ` Dmitry Torokhov @ 2006-11-15 17:39 ` Cornelia Huck 1 sibling, 0 replies; 10+ messages in thread From: Cornelia Huck @ 2006-11-15 17:39 UTC (permalink / raw) To: Kay Sievers; +Cc: Greg KH, linux-kernel, Andrew Morton, Martin Schwidefsky On Wed, 15 Nov 2006 11:11:36 +0100, Cornelia Huck <cornelia.huck@de.ibm.com> wrote: > On Wed, 15 Nov 2006 10:31:59 +0100, > Kay Sievers <kay.sievers@vrfy.org> 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. And this one may have an actual chance of doing something useful :/ --- include/linux/kobject.h | 6 ++++++ lib/kobject.c | 17 +++++++++++++++++ lib/kobject_uevent.c | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 55 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; + char *devpath_string = NULL; kobj = kobject_get(kobj); if (!kobj) @@ -373,14 +375,29 @@ int kobject_move(struct kobject *kobj, s 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, "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 @@ -50,18 +50,15 @@ static char *action_to_string(enum kobje return "offline"; case KOBJ_ONLINE: return "online"; + case KOBJ_MOVE: + return "move"; default: return NULL; } } -/** - * 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 +131,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 +200,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. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2006-11-15 17:38 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-11-14 10:32 [Patch -mm 2/5] driver core: Introduce device_move(): move a device to a new parent Cornelia Huck 2006-11-15 6:50 ` Greg KH 2006-11-15 7:28 ` Cornelia Huck 2006-11-15 8:44 ` Kay Sievers 2006-11-15 9:24 ` Cornelia Huck 2006-11-15 9:31 ` Kay Sievers 2006-11-15 10:11 ` Cornelia Huck 2006-11-15 16:44 ` Dmitry Torokhov 2006-11-15 17:23 ` Cornelia Huck 2006-11-15 17:39 ` Cornelia Huck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox