linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare@suse.de>
To: linux-hotplug@vger.kernel.org
Subject: Delayed hotplug events
Date: Thu, 17 Jun 2004 11:21:48 +0000	[thread overview]
Message-ID: <40D17ECC.20501@suse.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 1576 bytes --]

Hi all,

currently we have the problem that the driver core might send out 
hotplug events even though the initialisation of a device has not been 
finished; worse, we might get an "add" followed by an "remove" event if 
the device fails to initialise properly, with the corresponding device 
never appearing in sysfs properly.
This is due to the design of the driver core:
a call to device_register will trigger a hotplug event, but any sysfs 
attributes which are added _after_ device_register() will in fact 
created after the hotplug event has been triggered. For the unbelievers, 
look at drivers/scsi/scsi_sysfs.c:scsi_sysfs_add_sdev().
This leads to all sorts of nasty race conditions and waiting loops in 
the hotplug agents.

To solve this I've wrapped up a patch for delaying / suspending hotplug 
events until they are explicitely enabled again.
As an example of how it should be used I've patched 
drivers/scsi/scsi_sysfs.c:scsi_sysfs_add_sdev(), so that the device 
"add" event will now be triggered only _after_ the device has been 
initialised properly, including all sysfs attributes.

Is this approach feasible or am I completely off kilter here?
And if the latter, how should it be solved properly?

(Note: this is a proof of concept. No devices have been harmed in 
creating this patch. I just wanted to get a general opinion before 
venturing any further.)

Cheers,

Hannes
-- 
Dr. Hannes Reinecke			hare@suse.de
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de

[-- Attachment #2: delay-hotplug-events.patch --]
[-- Type: text/x-patch, Size: 3864 bytes --]

--- ./lib/kobject.c.orig	2004-06-17 09:18:27.000000000 +0200
+++ ./lib/kobject.c	2004-06-17 12:59:55.000000000 +0200
@@ -472,6 +472,53 @@
 		kobject_cleanup(kobj);
 }
 
+static int kobject_hotplug_filter_all(struct kset *kset, struct kobject *kobj)
+{
+	return 0;
+}
+
+/**
+ *      kobject_disable_events - filter out all hotplug events
+ *      @kobj:  object
+ *
+ */
+
+void kobject_disable_events(struct kobject * kobj )
+{
+	struct kset_hotplug_ops *delayed_ops;
+
+	if (kobj && kobj->kset) {
+		down_write(&kobj->kset->subsys->rwsem);
+
+		delayed_ops = kobj->kset->hotplug_ops;
+		kobj->kset->hotplug_ops_stored = delayed_ops;
+
+		delayed_ops->filter = kobject_hotplug_filter_all;
+		kobj->kset->hotplug_ops = delayed_ops;
+
+		up_write(&kobj->kset->subsys->rwsem);
+	}
+}	
+
+/**
+ *      kobject_enable_events - reset hotplug filter to original value
+ *      @kobj:  object
+ *
+ */
+
+void kobject_enable_events(struct kobject * kobj )
+{
+	struct kset_hotplug_ops *delayed_ops;
+
+	if (kobj && kobj->kset && kobj->kset->hotplug_ops_stored) {
+		down_write(&kobj->kset->subsys->rwsem);
+
+		kobj->kset->hotplug_ops = kobj->kset->hotplug_ops_stored;
+		kobj->kset->hotplug_ops_stored = NULL;
+
+		up_write(&kobj->kset->subsys->rwsem);
+	}
+}	
 
 /**
  *	kset_init - initialize a kset for use
@@ -635,6 +682,8 @@
 EXPORT_SYMBOL(kobject_del);
 EXPORT_SYMBOL(kobject_rename);
 EXPORT_SYMBOL(kobject_hotplug);
+EXPORT_SYMBOL(kobject_enable_events);
+EXPORT_SYMBOL(kobject_disable_events);
 
 EXPORT_SYMBOL(kset_register);
 EXPORT_SYMBOL(kset_unregister);
--- ./drivers/base/core.c.orig	2004-06-17 09:03:58.000000000 +0200
+++ ./drivers/base/core.c	2004-06-17 13:06:29.581368704 +0200
@@ -271,6 +271,25 @@
 	return device_add(dev);
 }
 
+void device_suspend_hotplug(struct device *dev)
+{
+	get_device(dev);
+
+	kobject_disable_events(&dev->kobj);
+
+	put_device(dev);
+}
+
+void device_resume_hotplug(struct device *dev)
+{
+	get_device(dev);
+
+	kobject_enable_events(&dev->kobj);
+	
+	kobject_hotplug("add", &dev->kobj);
+
+	put_device(dev);
+}
 
 /**
  *	get_device - increment reference count for device.
@@ -405,3 +424,5 @@
 
 EXPORT_SYMBOL(device_create_file);
 EXPORT_SYMBOL(device_remove_file);
+EXPORT_SYMBOL(device_suspend_hotplug);
+EXPORT_SYMBOL(device_resume_hotplug);
--- ./drivers/scsi/scsi_sysfs.c.orig	2004-06-17 13:00:45.000000000 +0200
+++ ./drivers/scsi/scsi_sysfs.c	2004-06-17 13:03:13.071318353 +0200
@@ -379,6 +379,7 @@
 	if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
 		return error;
 
+	device_suspend_hotplug(&sdev->sdev_gendev);
 	error = device_add(&sdev->sdev_gendev);
 	if (error) {
 		printk(KERN_INFO "error 1\n");
@@ -439,6 +440,8 @@
  		}
  	}
 
+	device_resume_hotplug(&sdev->sdev_gendev);
+
  out:
 	return error;
 
--- ./include/linux/kobject.h.orig	2004-06-17 11:22:29.000000000 +0200
+++ ./include/linux/kobject.h	2004-06-17 12:55:06.000000000 +0200
@@ -47,6 +47,8 @@
 
 extern int kobject_add(struct kobject *);
 extern void kobject_del(struct kobject *);
+extern void kobject_enable_events(struct kobject *kobj);
+extern void kobject_disable_events(struct kobject *kobj);
 
 extern int kobject_rename(struct kobject *, char *new_name);
 
@@ -96,6 +98,7 @@
 	struct list_head	list;
 	struct kobject		kobj;
 	struct kset_hotplug_ops	* hotplug_ops;
+	struct kset_hotplug_ops	* hotplug_ops_stored;
 };
 
 
--- ./include/linux/device.h.orig	2004-06-17 12:14:21.000000000 +0200
+++ ./include/linux/device.h	2004-06-17 12:14:56.000000000 +0200
@@ -332,6 +332,8 @@
 extern void device_bind_driver(struct device * dev);
 extern void device_release_driver(struct device * dev);
 extern void driver_attach(struct device_driver * drv);
+extern void device_suspend_hotplug(struct device *dev);
+extern void device_resume_hotplug(struct device *dev);
 
 
 /* driverfs interface for exporting device attributes */

             reply	other threads:[~2004-06-17 11:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-17 11:21 Hannes Reinecke [this message]
2004-06-17 18:09 ` Delayed hotplug events Greg KH
2004-06-17 19:56 ` Oliver Neukum
2004-06-17 20:22 ` linas
2004-06-17 23:29 ` Patrick Mansfield
2004-06-17 23:39 ` Greg KH
2004-06-17 23:40 ` Greg KH
2004-06-17 23:57 ` Greg KH
2004-06-18  7:44 ` Oliver Neukum
2004-06-18  8:12 ` Hannes Reinecke
2004-06-18  8:47 ` Oliver Neukum
2004-06-18  9:32 ` Hannes Reinecke
2004-06-18 11:28 ` Oliver Neukum
2004-06-19  0:07 ` Greg KH
2004-06-19  8:16 ` Oliver Neukum

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=40D17ECC.20501@suse.de \
    --to=hare@suse.de \
    --cc=linux-hotplug@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 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).