All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@suse.de>
To: linux-kernel@vger.kernel.org
Cc: Kay Sievers <kay.sievers@vrfy.org>, Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 02/46] driver core: fix namespace issue with devices assigned to classes
Date: Fri, 27 Apr 2007 11:53:16 -0700	[thread overview]
Message-ID: <11777000433552-git-send-email-gregkh@suse.de> (raw)
In-Reply-To: <1177700040520-git-send-email-gregkh@suse.de>

From: Kay Sievers <kay.sievers@vrfy.org>

  - uses a kset in "struct class" to keep track of all directories
    belonging to this class
  - merges with the /sys/devices/virtual logic.
  - removes the namespace-dir if the last member of that class
    leaves the directory.

There may be locking or refcounting fixes left, I stopped when it seemed
to work with network and sound modules. :)

From: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/base/class.c    |    2 +-
 drivers/base/core.c     |   82 +++++++++++++++++++++++++++++++++++++----------
 include/linux/device.h  |    3 +-
 include/linux/kobject.h |    2 +
 lib/kobject.c           |   12 ++++++-
 lib/kobject_uevent.c    |   16 ++++++---
 6 files changed, 89 insertions(+), 28 deletions(-)

diff --git a/drivers/base/class.c b/drivers/base/class.c
index d596812..80bbb20 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -145,6 +145,7 @@ int class_register(struct class * cls)
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->devices);
 	INIT_LIST_HEAD(&cls->interfaces);
+	kset_init(&cls->class_dirs);
 	init_MUTEX(&cls->sem);
 	error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
 	if (error)
@@ -163,7 +164,6 @@ int class_register(struct class * cls)
 void class_unregister(struct class * cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
-	kobject_unregister(cls->virtual_dir);
 	remove_class_attrs(cls);
 	subsystem_unregister(&cls->subsys);
 }
diff --git a/drivers/base/core.c b/drivers/base/core.c
index db3a151..658eae5 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -477,34 +477,58 @@ static struct kobject * get_device_parent(struct device *dev,
 	return NULL;
 }
 #else
-static struct kobject * virtual_device_parent(struct device *dev)
+static struct kobject *virtual_device_parent(struct device *dev)
 {
-	if (!dev->class)
-		return ERR_PTR(-ENODEV);
-
-	if (!dev->class->virtual_dir) {
-		static struct kobject *virtual_dir = NULL;
+	static struct kobject *virtual_dir = NULL;
 
-		if (!virtual_dir)
-			virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
-		dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
-	}
+	if (!virtual_dir)
+		virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
 
-	return dev->class->virtual_dir;
+	return virtual_dir;
 }
 
 static struct kobject * get_device_parent(struct device *dev,
 					  struct device *parent)
 {
-	/* if this is a class device, and has no parent, create one */
-	if ((dev->class) && (parent == NULL)) {
-		return virtual_device_parent(dev);
-	} else if (parent)
+	if (dev->class) {
+		struct kobject *kobj = NULL;
+		struct kobject *parent_kobj;
+		struct kobject *k;
+
+		/*
+		 * If we have no parent, we live in "virtual".
+		 * Class-devices with a bus-device as parent, live
+		 * in a class-directory to prevent namespace collisions.
+		 */
+		if (parent == NULL)
+			parent_kobj = virtual_device_parent(dev);
+		else if (parent->class)
+			return &parent->kobj;
+		else
+			parent_kobj = &parent->kobj;
+
+		/* find our class-directory at the parent and reference it */
+		spin_lock(&dev->class->class_dirs.list_lock);
+		list_for_each_entry(k, &dev->class->class_dirs.list, entry)
+			if (k->parent == parent_kobj) {
+				kobj = kobject_get(k);
+				break;
+			}
+		spin_unlock(&dev->class->class_dirs.list_lock);
+		if (kobj)
+			return kobj;
+
+		/* or create a new class-directory at the parent device */
+		return kobject_kset_add_dir(&dev->class->class_dirs,
+					    parent_kobj, dev->class->name);
+	}
+
+	if (parent)
 		return &parent->kobj;
 	return NULL;
 }
-
 #endif
+
 static int setup_parent(struct device *dev, struct device *parent)
 {
 	struct kobject *kobj;
@@ -541,7 +565,6 @@ int device_add(struct device *dev)
 	pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
 
 	parent = get_device(dev->parent);
-
 	error = setup_parent(dev, parent);
 	if (error)
 		goto Error;
@@ -787,6 +810,31 @@ void device_del(struct device * dev)
 		/* remove the device from the class list */
 		list_del_init(&dev->node);
 		up(&dev->class->sem);
+
+		/* If we live in a parent class-directory, unreference it */
+		if (dev->kobj.parent->kset == &dev->class->class_dirs) {
+			struct device *d;
+			int other = 0;
+
+			/*
+			 * if we are the last child of our class, delete
+			 * our class-directory at this parent
+			 */
+			down(&dev->class->sem);
+			list_for_each_entry(d, &dev->class->devices, node) {
+				if (d == dev)
+					continue;
+				if (d->kobj.parent == dev->kobj.parent) {
+					other = 1;
+					break;
+				}
+			}
+			if (!other)
+				kobject_del(dev->kobj.parent);
+
+			kobject_put(dev->kobj.parent);
+			up(&dev->class->sem);
+		}
 	}
 	device_remove_file(dev, &dev->uevent_attr);
 	device_remove_groups(dev);
diff --git a/include/linux/device.h b/include/linux/device.h
index 5cf30e9..de0e73e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -181,10 +181,9 @@ struct class {
 	struct list_head	children;
 	struct list_head	devices;
 	struct list_head	interfaces;
+	struct kset		class_dirs;
 	struct semaphore	sem;	/* locks both the children and interfaces lists */
 
-	struct kobject		*virtual_dir;
-
 	struct class_attribute		* class_attrs;
 	struct class_device_attribute	* class_dev_attrs;
 	struct device_attribute		* dev_attrs;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index b850e03..d37cd7f 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -89,6 +89,8 @@ extern void kobject_unregister(struct kobject *);
 extern struct kobject * kobject_get(struct kobject *);
 extern void kobject_put(struct kobject *);
 
+extern struct kobject *kobject_kset_add_dir(struct kset *kset,
+					    struct kobject *, const char *);
 extern struct kobject *kobject_add_dir(struct kobject *, const char *);
 
 extern char * kobject_get_path(struct kobject *, gfp_t);
diff --git a/lib/kobject.c b/lib/kobject.c
index 057921c..f664551 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -488,13 +488,15 @@ static struct kobj_type dir_ktype = {
 };
 
 /**
- *	kobject_add_dir - add sub directory of object.
+ *	kobject__kset_add_dir - add sub directory of object.
+ *	@kset:		kset the directory is belongs to.
  *	@parent:	object in which a directory is created.
  *	@name:	directory name.
  *
  *	Add a plain directory object as child of given object.
  */
-struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+struct kobject *kobject_kset_add_dir(struct kset *kset,
+				     struct kobject *parent, const char *name)
 {
 	struct kobject *k;
 	int ret;
@@ -506,6 +508,7 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
 	if (!k)
 		return NULL;
 
+	k->kset = kset;
 	k->parent = parent;
 	k->ktype = &dir_ktype;
 	kobject_set_name(k, name);
@@ -520,6 +523,11 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
 	return k;
 }
 
+struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+{
+	return kobject_kset_add_dir(NULL, parent, name);
+}
+
 /**
  *	kset_init - initialize a kset for use
  *	@k:	kset 
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 82fc179..4122f38 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -115,6 +115,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 			return 0;
 		}
 
+	/* originating subsystem */
+	if (uevent_ops && uevent_ops->name)
+		subsystem = uevent_ops->name(kset, kobj);
+	else
+		subsystem = kobject_name(&kset->kobj);
+	if (!subsystem) {
+		pr_debug("unset subsytem caused the event to drop!\n");
+		return 0;
+	}
+
 	/* environment index */
 	envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
 	if (!envp)
@@ -134,12 +144,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 		goto exit;
 	}
 
-	/* originating subsystem */
-	if (uevent_ops && uevent_ops->name)
-		subsystem = uevent_ops->name(kset, kobj);
-	else
-		subsystem = kobject_name(&kset->kobj);
-
 	/* event environemnt for helper process only */
 	envp[i++] = "HOME=/";
 	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-- 
1.5.1.2


  reply	other threads:[~2007-04-27 18:56 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-27 18:51 [GIT PATCH] Driver core patches for 2.6.21 Greg KH
2007-04-27 18:53 ` [PATCH 01/46] driver core: fix device_add error path Greg Kroah-Hartman
2007-04-27 18:53   ` Greg Kroah-Hartman [this message]
2007-04-27 18:53     ` [PATCH 03/46] dev_printk and new-style class devices Greg Kroah-Hartman
     [not found]       ` <11777000511784-git-send-email-gregkh@suse.de>
2007-04-27 18:53         ` [PATCH 05/46] driver core: Use attribute groups in struct device_type Greg Kroah-Hartman
2007-04-27 18:53           ` [PATCH 06/46] Driver core: add name to device_type Greg Kroah-Hartman
2007-04-27 18:53             ` [PATCH 07/46] kobject: kobject_shadow_add cleanup Greg Kroah-Hartman
2007-04-27 18:53               ` [PATCH 08/46] driver core: per-subsystem multithreaded probing Greg Kroah-Hartman
2007-04-27 18:53                 ` [PATCH 09/46] powerpc: make it compile for multithread change Greg Kroah-Hartman
2007-04-27 18:53                   ` [PATCH 10/46] driver core: don't fail attaching the device if it cannot be bound Greg Kroah-Hartman
2007-04-27 18:53                     ` [PATCH 11/46] Driver core: remove unneeded completion from driver release path Greg Kroah-Hartman
2007-04-27 18:53                       ` [PATCH 12/46] kref: fix CPU ordering with respect to krefs Greg Kroah-Hartman
2007-04-27 18:53                         ` [PATCH 13/46] Driver core: notify userspace of network device renames Greg Kroah-Hartman
2007-04-27 18:53                           ` [PATCH 14/46] Driver core: suppress uevents via filter Greg Kroah-Hartman
2007-04-27 18:53                             ` [PATCH 15/46] Driver core: switch firmware_class to uevent_suppress Greg Kroah-Hartman
2007-04-27 18:53                               ` [PATCH 16/46] uevent: use add_uevent_var() instead of open coding it Greg Kroah-Hartman
2007-04-27 18:53                                 ` [PATCH 17/46] Driver core: add suspend() and resume() to struct device_type Greg Kroah-Hartman
2007-04-27 18:53                                   ` [PATCH 18/46] Kobject: kobject_uevent.c: Collapse unnecessary loop nesting (top_kobj) Greg Kroah-Hartman
2007-04-27 18:53                                     ` [PATCH 19/46] kobject: kobject_add() reference leak Greg Kroah-Hartman
2007-04-27 18:53                                       ` [PATCH 20/46] Driver core: remove use of rwsem Greg Kroah-Hartman
2007-04-27 18:53                                         ` [PATCH 21/46] SCSI: use the proper semaphore to protect the class lists Greg Kroah-Hartman
2007-04-27 18:53                                           ` [PATCH 22/46] USB: remove use of the bus rwsem, as it doesn't really protect anything Greg Kroah-Hartman
2007-04-27 18:53                                             ` [PATCH 23/46] PNP: stop using the subsystem rwsem Greg Kroah-Hartman
2007-04-27 18:53                                               ` [PATCH 24/46] Input: serio - do not touch bus's rwsem Greg Kroah-Hartman
2007-04-27 18:53                                                 ` [PATCH 25/46] Input: gameport " Greg Kroah-Hartman
2007-04-27 18:53                                                   ` [PATCH 26/46] IDE: remove rwsem use from ide-proc core Greg Kroah-Hartman
2007-04-27 18:53                                                     ` [PATCH 27/46] IEEE1394: remove rwsem use from ieee1394 core Greg Kroah-Hartman
2007-04-27 18:53                                                       ` [PATCH 28/46] PHY: remove rwsem use from phy core Greg Kroah-Hartman
2007-04-27 18:53                                                         ` [PATCH 29/46] qeth: Remove usage of subsys.rwsem Greg Kroah-Hartman
2007-04-27 18:53                                                           ` [PATCH 30/46] kobject core: remove rwsem from struct subsystem Greg Kroah-Hartman
2007-04-27 18:53                                                             ` [PATCH 31/46] Driver core: make uevent-environment available in uevent-file Greg Kroah-Hartman
2007-04-27 18:53                                                               ` [PATCH 32/46] Driver core: warn when userspace writes to the uevent file in a non-supported way Greg Kroah-Hartman
2007-04-27 18:53                                                                 ` [PATCH 33/46] kobject: Comment and warning fixes to kobject.c Greg Kroah-Hartman
2007-04-27 18:53                                                                   ` [PATCH 34/46] the overdue removal of the mount/umount uevents Greg Kroah-Hartman
2007-04-27 18:53                                                                     ` [PATCH 35/46] debugfs: Add debugfs_create_u64() Greg Kroah-Hartman
2007-04-27 18:53                                                                       ` [PATCH 36/46] driver core: bus_add_driver should return an error if no bus Greg Kroah-Hartman
2007-04-27 18:53                                                                         ` [PATCH 37/46] Driver core: use mutex instead of semaphore in DMA pool handler Greg Kroah-Hartman
2007-04-27 18:53                                                                           ` [PATCH 38/46] sysfs: bin.c printk fix Greg Kroah-Hartman
2007-04-27 18:53                                                                             ` [PATCH 39/46] s390: cio: Delay uevents for subchannels Greg Kroah-Hartman
2007-04-27 18:53                                                                               ` [PATCH 40/46] device_schedule_callback() needs a module reference Greg Kroah-Hartman
2007-04-27 18:53                                                                                 ` [PATCH 41/46] security: prevent permission checking of file removal via sysfs_remove_group() Greg Kroah-Hartman
2007-04-27 18:53                                                                                   ` [PATCH 42/46] define platform wakeup hook, use in pci_enable_wake() Greg Kroah-Hartman
2007-04-27 18:53                                                                                     ` [PATCH 43/46] s2ram: add arch irq disable/enable hooks Greg Kroah-Hartman
2007-04-27 18:53                                                                                       ` [PATCH 44/46] mod_sysfs_setup() doesn't return errno when kobject_add_dir() failure occurs Greg Kroah-Hartman
2007-04-27 18:53                                                                                         ` [PATCH 45/46] drivers/base/attribute_container.c: use mutex instead of binary semaphore Greg Kroah-Hartman
2007-04-27 18:54                                                                                           ` [PATCH 46/46] dev_dbg: check dev_dbg() arguments Greg Kroah-Hartman
2007-04-27 21:11                                                         ` [PATCH 28/46] PHY: remove rwsem use from phy core Andy Fleming
2007-04-27 21:11                                                           ` Andy Fleming
2007-04-27 20:27       ` [PATCH 04/46] Driver core: udev triggered device-driver binding Greg Kroah-Hartman

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=11777000433552-git-send-email-gregkh@suse.de \
    --to=gregkh@suse.de \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-kernel@vger.kernel.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.