From: Greg KH <greg@kroah.com>
To: linux-kernel@vger.kernel.org
Cc: Andrew Morton <akpm@osdl.org>,
Cornelia Huck <cornelia.huck@de.ibm.com>,
Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 41/47] drivers/base: check errors
Date: Mon, 25 Sep 2006 22:38:01 -0700 [thread overview]
Message-ID: <11592492153066-git-send-email-greg@kroah.com> (raw)
In-Reply-To: <11592492123695-git-send-email-greg@kroah.com>
From: Andrew Morton <akpm@osdl.org>
Add lots of return-value checking.
<pcornelia.huck@de.ibm.com>: fix bus_rescan_devices()]
Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/base/base.h | 2 -
drivers/base/bus.c | 107 ++++++++++++++++++++++++++++++++----------------
drivers/base/dd.c | 37 ++++++++++++-----
include/linux/device.h | 8 ++--
4 files changed, 104 insertions(+), 50 deletions(-)
diff --git a/drivers/base/base.h b/drivers/base/base.h
index c3b8dc9..d26644a 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void);
extern int attribute_container_init(void);
extern int bus_add_device(struct device * dev);
-extern void bus_attach_device(struct device * dev);
+extern int bus_attach_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
extern struct bus_type *get_bus(struct bus_type * bus);
extern void put_bus(struct bus_type * bus);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 4d22a1d..aa685a2 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -371,12 +371,20 @@ int bus_add_device(struct device * dev)
if (bus) {
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
error = device_add_attrs(bus, dev);
- if (!error) {
- sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
- sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem");
- sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
- }
+ if (error)
+ goto out;
+ error = sysfs_create_link(&bus->devices.kobj,
+ &dev->kobj, dev->bus_id);
+ if (error)
+ goto out;
+ error = sysfs_create_link(&dev->kobj,
+ &dev->bus->subsys.kset.kobj, "subsystem");
+ if (error)
+ goto out;
+ error = sysfs_create_link(&dev->kobj,
+ &dev->bus->subsys.kset.kobj, "bus");
}
+out:
return error;
}
@@ -386,14 +394,19 @@ int bus_add_device(struct device * dev)
*
* - Try to attach to driver.
*/
-void bus_attach_device(struct device * dev)
+int bus_attach_device(struct device * dev)
{
- struct bus_type * bus = dev->bus;
+ struct bus_type *bus = dev->bus;
+ int ret = 0;
if (bus) {
- device_attach(dev);
- klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+ ret = device_attach(dev);
+ if (ret >= 0) {
+ klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+ ret = 0;
+ }
}
+ return ret;
}
/**
@@ -455,10 +468,17 @@ #ifdef CONFIG_HOTPLUG
* Thanks to drivers making their tables __devinit, we can't allow manual
* bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
*/
-static void add_bind_files(struct device_driver *drv)
+static int __must_check add_bind_files(struct device_driver *drv)
{
- driver_create_file(drv, &driver_attr_unbind);
- driver_create_file(drv, &driver_attr_bind);
+ int ret;
+
+ ret = driver_create_file(drv, &driver_attr_unbind);
+ if (ret == 0) {
+ ret = driver_create_file(drv, &driver_attr_bind);
+ if (ret)
+ driver_remove_file(drv, &driver_attr_unbind);
+ }
+ return ret;
}
static void remove_bind_files(struct device_driver *drv)
@@ -476,7 +496,7 @@ #endif
* @drv: driver.
*
*/
-int bus_add_driver(struct device_driver * drv)
+int bus_add_driver(struct device_driver *drv)
{
struct bus_type * bus = get_bus(drv->bus);
int error = 0;
@@ -484,27 +504,39 @@ int bus_add_driver(struct device_driver
if (bus) {
pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
error = kobject_set_name(&drv->kobj, "%s", drv->name);
- if (error) {
- put_bus(bus);
- return error;
- }
+ if (error)
+ goto out_put_bus;
drv->kobj.kset = &bus->drivers;
- if ((error = kobject_register(&drv->kobj))) {
- put_bus(bus);
- return error;
- }
+ if ((error = kobject_register(&drv->kobj)))
+ goto out_put_bus;
- driver_attach(drv);
+ error = driver_attach(drv);
+ if (error)
+ goto out_unregister;
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
module_add_driver(drv->owner, drv);
- driver_add_attrs(bus, drv);
- add_bind_files(drv);
+ error = driver_add_attrs(bus, drv);
+ if (error) {
+ /* How the hell do we get out of this pickle? Give up */
+ printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
+ __FUNCTION__, drv->name);
+ }
+ error = add_bind_files(drv);
+ if (error) {
+ /* Ditto */
+ printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+ __FUNCTION__, drv->name);
+ }
}
return error;
+out_unregister:
+ kobject_unregister(&drv->kobj);
+out_put_bus:
+ put_bus(bus);
+ return error;
}
-
/**
* bus_remove_driver - delete driver from bus's knowledge.
* @drv: driver.
@@ -530,16 +562,21 @@ void bus_remove_driver(struct device_dri
/* Helper for bus_rescan_devices's iter */
-static int bus_rescan_devices_helper(struct device *dev, void *data)
+static int __must_check bus_rescan_devices_helper(struct device *dev,
+ void *data)
{
+ int ret = 0;
+
if (!dev->driver) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
- device_attach(dev);
+ ret = device_attach(dev);
if (dev->parent)
up(&dev->parent->sem);
+ if (ret > 0)
+ ret = 0;
}
- return 0;
+ return ret < 0 ? ret : 0;
}
/**
@@ -550,9 +587,9 @@ static int bus_rescan_devices_helper(str
* attached and rescan it against existing drivers to see if it matches
* any by calling device_attach() for the unbound devices.
*/
-void bus_rescan_devices(struct bus_type * bus)
+int bus_rescan_devices(struct bus_type * bus)
{
- bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
+ return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
}
/**
@@ -564,7 +601,7 @@ void bus_rescan_devices(struct bus_type
* to use if probing criteria changed during a devices lifetime and
* driver attachment should change accordingly.
*/
-void device_reprobe(struct device *dev)
+int device_reprobe(struct device *dev)
{
if (dev->driver) {
if (dev->parent) /* Needed for USB */
@@ -573,14 +610,14 @@ void device_reprobe(struct device *dev)
if (dev->parent)
up(&dev->parent->sem);
}
-
- bus_rescan_devices_helper(dev, NULL);
+ return bus_rescan_devices_helper(dev, NULL);
}
EXPORT_SYMBOL_GPL(device_reprobe);
-struct bus_type * get_bus(struct bus_type * bus)
+struct bus_type *get_bus(struct bus_type *bus)
{
- return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL;
+ return bus ? container_of(subsys_get(&bus->subsys),
+ struct bus_type, subsys) : NULL;
}
void put_bus(struct bus_type * bus)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 889c711..9f6f11c 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -38,17 +38,29 @@ #define to_drv(node) container_of(node,
*
* This function must be called with @dev->sem held.
*/
-void device_bind_driver(struct device * dev)
+int device_bind_driver(struct device *dev)
{
- if (klist_node_attached(&dev->knode_driver))
- return;
+ int ret;
+
+ if (klist_node_attached(&dev->knode_driver)) {
+ printk(KERN_WARNING "%s: device %s already bound\n",
+ __FUNCTION__, kobject_name(&dev->kobj));
+ return 0;
+ }
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
- sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+ ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
- sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+ if (ret == 0) {
+ ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
+ "driver");
+ if (ret)
+ sysfs_remove_link(&dev->driver->kobj,
+ kobject_name(&dev->kobj));
+ }
+ return ret;
}
/**
@@ -91,7 +103,11 @@ int driver_probe_device(struct device_dr
goto ProbeFailed;
}
}
- device_bind_driver(dev);
+ if (device_bind_driver(dev)) {
+ printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
+ __FUNCTION__, dev->bus_id);
+ /* How does undo a ->probe? We're screwed. */
+ }
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
@@ -139,8 +155,9 @@ int device_attach(struct device * dev)
down(&dev->sem);
if (dev->driver) {
- device_bind_driver(dev);
- ret = 1;
+ ret = device_bind_driver(dev);
+ if (ret == 0)
+ ret = 1;
} else
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
up(&dev->sem);
@@ -182,9 +199,9 @@ static int __driver_attach(struct device
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
-void driver_attach(struct device_driver * drv)
+int driver_attach(struct device_driver * drv)
{
- bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+ return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
/**
diff --git a/include/linux/device.h b/include/linux/device.h
index ad4db72..b3da9a8 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -62,7 +62,7 @@ struct bus_type {
extern int __must_check bus_register(struct bus_type * bus);
extern void bus_unregister(struct bus_type * bus);
-extern void bus_rescan_devices(struct bus_type * bus);
+extern int __must_check bus_rescan_devices(struct bus_type * bus);
/* iterator helpers for buses */
@@ -397,11 +397,11 @@ extern int device_rename(struct device *
* Manual binding of a device to driver. See drivers/base/bus.c
* for information on use.
*/
-extern void device_bind_driver(struct device * dev);
+extern int __must_check device_bind_driver(struct device *dev);
extern void device_release_driver(struct device * dev);
extern int __must_check device_attach(struct device * dev);
-extern void driver_attach(struct device_driver * drv);
-extern void device_reprobe(struct device *dev);
+extern int __must_check driver_attach(struct device_driver *drv);
+extern int __must_check device_reprobe(struct device *dev);
/*
* Easy functions for dynamically creating devices on the fly
--
1.4.2.1
next prev parent reply other threads:[~2006-09-26 5:41 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-26 5:37 [GIT PATCH] Driver Core patches for 2.6.18 Greg KH
2006-09-26 5:37 ` [PATCH 1/47] Documentation/ABI: devfs is not obsolete, but removed! Greg KH
2006-09-26 5:37 ` [PATCH 2/47] deprecate PHYSDEV* keys Greg KH
2006-09-26 5:37 ` [PATCH 3/47] class_device_create(): make fmt argument 'const char *' Greg KH
2006-09-26 5:37 ` [PATCH 4/47] device_create(): " Greg KH
2006-09-26 5:37 ` [PATCH 5/47] Driver core: add const to class_create Greg KH
2006-09-26 5:37 ` [PATCH 6/47] sysfs: Make poll behaviour consistent Greg KH
2006-09-26 5:37 ` [PATCH 7/47] Debugfs: kernel-doc fixes for debugfs Greg KH
2006-09-26 5:37 ` [PATCH 8/47] SYSFS: allow sysfs_create_link to create symlinks in the root of sysfs Greg KH
2006-09-26 5:37 ` [PATCH 9/47] Suspend infrastructure cleanup and extension Greg KH
2006-09-26 5:37 ` [PATCH 10/47] Suspend changes for PCI core Greg KH
2006-09-26 5:37 ` [PATCH 11/47] make suspend quieter Greg KH
2006-09-26 5:37 ` [PATCH 12/47] fix broken/dubious driver suspend() methods Greg KH
2006-09-26 5:37 ` [PATCH 13/47] PM: define PM_EVENT_PRETHAW Greg KH
2006-09-26 5:37 ` [PATCH 14/47] PM: PCI and IDE handle PM_EVENT_PRETHAW Greg KH
2006-09-26 5:37 ` [PATCH 15/47] PM: video drivers and PM_EVENT_PRETHAW Greg KH
2006-09-26 5:37 ` [PATCH 16/47] PM: USB HCDs use PM_EVENT_PRETHAW Greg KH
2006-09-26 5:37 ` [PATCH 17/47] PM: issue PM_EVENT_PRETHAW Greg KH
2006-09-26 5:37 ` [PATCH 18/47] updated Documentation/power/devices.txt Greg KH
2006-09-26 5:37 ` [PATCH 19/47] PM: update docs for writing .../power/state Greg KH
2006-09-26 5:37 ` [PATCH 20/47] PM: add kconfig option for deprecated .../power/state files Greg KH
2006-09-26 5:37 ` [PATCH 21/47] PM: schedule /sys/devices/.../power/state for removal Greg KH
2006-09-26 5:37 ` [PATCH 22/47] PM: no suspend_prepare() phase Greg KH
2006-09-26 5:37 ` [PATCH 23/47] PM: add /sys/power documentation to Documentation/ABI Greg KH
2006-09-26 5:37 ` [PATCH 24/47] PM: device_suspend/resume may sleep Greg KH
2006-09-26 5:37 ` [PATCH 25/47] PM: platform_bus and late_suspend/early_resume Greg KH
2006-09-26 5:37 ` [PATCH 26/47] Driver core: add groups support to struct device Greg KH
2006-09-26 5:37 ` [PATCH 27/47] Driver core: allow devices in classes to have no parent Greg KH
2006-09-26 5:37 ` [PATCH 28/47] Driver core: add ability for classes to handle devices properly Greg KH
2006-09-26 5:37 ` [PATCH 29/47] Driver core: add device_rename function Greg KH
2006-09-26 5:37 ` [PATCH 30/47] Driver core: create devices/virtual/ tree Greg KH
2006-09-26 5:37 ` [PATCH 31/47] Class: add support for class interfaces for devices Greg KH
2006-09-26 5:37 ` [PATCH 32/47] Driver core: add ability for devices to create and remove bin files Greg KH
2006-09-26 5:37 ` [PATCH 33/47] kobject: must_check fixes Greg KH
2006-09-26 5:37 ` [PATCH 34/47] sysfs_remove_bin_file: no return value, dump_stack on error Greg KH
2006-09-26 5:37 ` [PATCH 35/47] Driver core: fix comments in drivers/base/power/resume.c Greg KH
2006-09-26 5:37 ` [PATCH 36/47] Driver core: fixed add_bind_files() definition Greg KH
2006-09-26 5:37 ` [PATCH 37/47] add __must_check to device management code Greg KH
2006-09-26 5:37 ` [PATCH 38/47] add CONFIG_ENABLE_MUST_CHECK Greg KH
2006-09-26 5:37 ` [PATCH 39/47] v4l-dev2: handle __must_check Greg KH
2006-09-26 5:38 ` [PATCH 40/47] drivers/base: Platform notify needs to occur before drivers attach to the device Greg KH
2006-09-26 5:38 ` Greg KH [this message]
2006-09-26 5:38 ` [PATCH 42/47] sysfs: add proper sysfs_init() prototype Greg KH
2006-09-26 5:38 ` [PATCH 43/47] Driver Core: add ability for drivers to do a threaded probe Greg KH
2006-09-26 5:38 ` [PATCH 44/47] PCI: enable driver multi-threaded probe Greg KH
2006-09-26 5:38 ` [PATCH 45/47] Driver core: Fix potential deadlock in driver core Greg KH
2006-09-26 5:38 ` [PATCH 46/47] Driver core: Remove unneeded routines from " Greg KH
2006-09-26 5:38 ` [PATCH 47/47] Driver core: Don't call put methods while holding a spinlock Greg KH
2006-09-27 18:51 ` [PATCH 44/47] PCI: enable driver multi-threaded probe Olaf Hering
2006-09-29 23:32 ` Greg KH
2006-09-30 6:07 ` Olaf Hering
2006-09-26 17:23 ` [PATCH 41/47] drivers/base: check errors Dmitry Torokhov
2006-09-27 4:33 ` Greg KH
2006-09-26 13:24 ` [PATCH 30/47] Driver core: create devices/virtual/ tree Dmitry Torokhov
2006-09-26 13:41 ` Greg KH
2006-09-26 13:51 ` Dmitry Torokhov
2006-09-26 14:26 ` Greg KH
2006-09-26 17:15 ` Dmitry Torokhov
2006-09-26 13:20 ` [PATCH 26/47] Driver core: add groups support to struct device Dmitry Torokhov
2006-09-26 13:46 ` Greg KH
2006-09-26 14:01 ` Dmitry Torokhov
2006-09-26 14:23 ` Greg KH
2006-09-26 17:10 ` Dmitry Torokhov
2006-09-27 14:40 ` Pavel Machek
2006-09-26 15:18 ` Marcel Holtmann
2006-09-26 12:34 ` [GIT PATCH] Driver Core patches for 2.6.18 Mike Galbraith
2006-09-26 20:39 ` Greg KH
2006-09-27 8:47 ` Mike Galbraith
2006-09-27 6:58 ` Rafael J. Wysocki
2006-09-27 10:48 ` Mike Galbraith
2006-09-27 13:03 ` Mike Galbraith
2006-09-27 11:42 ` Rafael J. Wysocki
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=11592492153066-git-send-email-greg@kroah.com \
--to=greg@kroah.com \
--cc=akpm@osdl.org \
--cc=cornelia.huck@de.ibm.com \
--cc=gregkh@suse.de \
--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.