LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Greg KH <greg@kroah.com>
To: linux-kernel@vger.kernel.org
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>,
	Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 6/28] driver core: Allow device_move(dev, NULL).
Date: Wed,  7 Feb 2007 16:29:54 -0800	[thread overview]
Message-ID: <11708946391465-git-send-email-greg@kroah.com> (raw)
In-Reply-To: <11708946362677-git-send-email-greg@kroah.com>

From: Cornelia Huck <cornelia.huck@de.ibm.com>

If we allow NULL as the new parent in device_move(), we need to make sure
that the device is placed into the same place as it would if it was
newly registered:

- Consider the device virtual tree. In order to be able to reuse code,
  setup_parent() has been tweaked a bit.
- kobject_move() can fall back to the kset's kobject.
- sysfs_move_dir() uses the sysfs root dir as fallback.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/core.c |   76 +++++++++++++++++++++++++++++++-------------------
 fs/sysfs/dir.c      |    6 +---
 lib/kobject.c       |    6 ++--
 3 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 36eedfd..c60114d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -390,22 +390,23 @@ void device_initialize(struct device *dev)
 }
 
 #ifdef CONFIG_SYSFS_DEPRECATED
-static int setup_parent(struct device *dev, struct device *parent)
+static struct kobject * get_device_parent(struct device *dev,
+					  struct device *parent)
 {
 	/* Set the parent to the class, not the parent device */
 	/* this keeps sysfs from having a symlink to make old udevs happy */
 	if (dev->class)
-		dev->kobj.parent = &dev->class->subsys.kset.kobj;
+		return &dev->class->subsys.kset.kobj;
 	else if (parent)
-		dev->kobj.parent = &parent->kobj;
+		return &parent->kobj;
 
-	return 0;
+	return NULL;
 }
 #else
-static int virtual_device_parent(struct device *dev)
+static struct kobject * virtual_device_parent(struct device *dev)
 {
 	if (!dev->class)
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	if (!dev->class->virtual_dir) {
 		static struct kobject *virtual_dir = NULL;
@@ -415,25 +416,31 @@ static int virtual_device_parent(struct device *dev)
 		dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
 	}
 
-	dev->kobj.parent = dev->class->virtual_dir;
-	return 0;
+	return dev->class->virtual_dir;
 }
 
-static int setup_parent(struct device *dev, struct device *parent)
+static struct kobject * get_device_parent(struct device *dev,
+					  struct device *parent)
 {
-	int error;
-
 	/* if this is a class device, and has no parent, create one */
 	if ((dev->class) && (parent == NULL)) {
-		error = virtual_device_parent(dev);
-		if (error)
-			return error;
+		return virtual_device_parent(dev);
 	} else if (parent)
-		dev->kobj.parent = &parent->kobj;
+		return &parent->kobj;
+	return NULL;
+}
 
+#endif
+static int setup_parent(struct device *dev, struct device *parent)
+{
+	struct kobject *kobj;
+	kobj = get_device_parent(dev, parent);
+	if (IS_ERR(kobj))
+		return PTR_ERR(kobj);
+	if (kobj)
+		dev->kobj.parent = kobj;
 	return 0;
 }
-#endif
 
 /**
  *	device_add - add device to device hierarchy.
@@ -976,12 +983,18 @@ static int device_move_class_links(struct device *dev,
 		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");
+	if (new_parent) {
+		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");
+	}
+	else
+		error = 0;
 out:
 	kfree(class_name);
 	return error;
@@ -993,25 +1006,28 @@ out:
 /**
  * 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
+ * @new_parent: the new parent of the device (can by NULL)
  */
 int device_move(struct device *dev, struct device *new_parent)
 {
 	int error;
 	struct device *old_parent;
+	struct kobject *new_parent_kobj;
 
 	dev = get_device(dev);
 	if (!dev)
 		return -EINVAL;
 
 	new_parent = get_device(new_parent);
-	if (!new_parent) {
-		error = -EINVAL;
+	new_parent_kobj = get_device_parent (dev, new_parent);
+	if (IS_ERR(new_parent_kobj)) {
+		error = PTR_ERR(new_parent_kobj);
+		put_device(new_parent);
 		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);
+		 new_parent ? new_parent->bus_id : "<NULL>");
+	error = kobject_move(&dev->kobj, new_parent_kobj);
 	if (error) {
 		put_device(new_parent);
 		goto out;
@@ -1020,7 +1036,8 @@ int device_move(struct device *dev, struct device *new_parent)
 	dev->parent = new_parent;
 	if (old_parent)
 		klist_remove(&dev->knode_parent);
-	klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+	if (new_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);
@@ -1028,7 +1045,8 @@ int device_move(struct device *dev, struct device *new_parent)
 		/* 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_remove(&dev->knode_parent);
+			if (new_parent)
+				klist_remove(&dev->knode_parent);
 			if (old_parent)
 				klist_add_tail(&dev->knode_parent,
 					       &old_parent->klist_children);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 511edef..2bab1b4 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -378,12 +378,10 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
 	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;
+	new_parent_dentry = new_parent ?
+		new_parent->dentry : sysfs_mount->mnt_sb->s_root;
 
 again:
 	mutex_lock(&old_parent_dentry->d_inode->i_mutex);
diff --git a/lib/kobject.c b/lib/kobject.c
index 9aed594..c033dc8 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -314,7 +314,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
 /**
  *	kobject_move - move object to another parent
  *	@kobj:	object in question.
- *	@new_parent: object's new parent
+ *	@new_parent: object's new parent (can be NULL)
  */
 
 int kobject_move(struct kobject *kobj, struct kobject *new_parent)
@@ -330,8 +330,8 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent)
 		return -EINVAL;
 	new_parent = kobject_get(new_parent);
 	if (!new_parent) {
-		error = -EINVAL;
-		goto out;
+		if (kobj->kset)
+			new_parent = kobject_get(&kobj->kset->kobj);
 	}
 	/* old object path */
 	devpath = kobject_get_path(kobj, GFP_KERNEL);
-- 
1.4.4.4


  reply	other threads:[~2007-02-08  0:39 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-08  0:29 [GIT PATCH] Driver core patches for 2.6.20 Greg KH
2007-02-08  0:29 ` [PATCH 1/28] Kobject: make kobject apis more robust in handling NULL pointers Greg KH
2007-02-08  0:29   ` [PATCH 2/28] Driver core: convert pcmcia code to use struct device Greg KH
2007-02-08  0:29     ` [PATCH 3/28] Driver core: convert SPI " Greg KH
2007-02-08  0:29       ` [PATCH 4/28] Network: convert network devices to use struct device instead of class_device Greg KH
2007-02-08  0:29         ` [PATCH 5/28] driver core: Remove device_is_registered() in device_move() Greg KH
2007-02-08  0:29           ` Greg KH [this message]
2007-02-08  0:29             ` [PATCH 7/28] MODULES: add the module name for built in kernel drivers Greg KH
2007-02-08  0:29               ` [PATCH 8/28] Modules: only add drivers/ direcory if needed Greg KH
2007-02-08  0:29                 ` [PATCH 9/28] PCI: add the sysfs driver name to all modules Greg KH
2007-02-08  0:29                   ` [PATCH 10/28] SERIO: " Greg KH
2007-02-08  0:29                     ` [PATCH 11/28] USB: " Greg KH
2007-02-08  0:30                       ` [PATCH 12/28] /sys/modules/*/holders Greg KH
2007-02-08  0:30                         ` [PATCH 13/28] driver core fixes: make_class_name() retval checks Greg KH
2007-02-08  0:30                           ` [PATCH 14/28] driver core fixes: device_register() retval check in platform.c Greg KH
2007-02-08  0:30                             ` [PATCH 15/28] driver core: Don't stop probing on ->probe errors Greg KH
2007-02-08  0:30                               ` [PATCH 16/28] driver core: Change function call order in device_bind_driver() Greg KH
2007-02-08  0:30                                 ` [PATCH 17/28] Driver core: fix race in sysfs between sysfs_remove_file() and read()/write() Greg KH
2007-02-08  0:30                                   ` [PATCH 18/28] sysfs: suppress lockdep warnings Greg KH
2007-02-08  0:30                                     ` [PATCH 19/28] sysfs: kobject_put cleanup Greg KH
2007-02-08  0:30                                       ` [PATCH 20/28] kobject: " Greg KH
2007-02-08  0:30                                         ` [PATCH 21/28] sysfs: error handling in sysfs, fill_read_buffer() Greg KH
2007-02-08  0:30                                           ` [PATCH 22/28] HOWTO: Add a reference to Harbison and Steele Greg KH
2007-02-08  0:30                                             ` [PATCH 23/28] SYSFS: Fix missing include of list.h in sysfs.h Greg KH
2007-02-08  0:30                                               ` [PATCH 24/28] Driver core: add uevent vars for devices of a class Greg KH
2007-02-08  0:30                                                 ` [PATCH 25/28] Driver core: add device_type to struct device Greg KH
2007-02-08  0:30                                                   ` [PATCH 26/28] Driver core: allow to delay the uevent at device creation time Greg KH
2007-02-08  0:30                                                     ` [PATCH 27/28] Driver Core: Increase the default timeout value of the firmware subsystem Greg KH
2007-02-08  0:30                                                       ` [PATCH 28/28] sysfs: Shadow directory support Greg KH
2007-02-08 17:20                     ` [PATCH 10/28] SERIO: add the sysfs driver name to all modules Dmitry Torokhov
2007-02-08 18:51                       ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11708946391465-git-send-email-greg@kroah.com \
    --to=greg@kroah.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --subject='Re: [PATCH 6/28] driver core: Allow device_move(dev, NULL).' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).