From: Cornelia Huck Some more fixes in the driver core: - make_class_name() returns an ERR_PTR on error, not NULL. - fixup some more unwinding on errors. CC: Greg K-H Signed-off-by: Cornelia Huck Signed-off-by: Andrew Morton --- drivers/base/bus.c | 24 +++++++++++++++---- drivers/base/class.c | 5 +++- drivers/base/core.c | 46 +++++++++++++++++++++++--------------- drivers/base/platform.c | 29 ++++++++++++++--------- 4 files changed, 69 insertions(+), 35 deletions(-) diff -puN drivers/base/bus.c~yet-further-driver-core-fixes-for-mm drivers/base/bus.c --- a/drivers/base/bus.c~yet-further-driver-core-fixes-for-mm +++ a/drivers/base/bus.c @@ -372,18 +372,28 @@ int bus_add_device(struct device * dev) pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); error = device_add_attrs(bus, dev); if (error) - goto out; + goto out_put; error = sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); if (error) - goto out; + goto out_id; error = sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); if (error) - goto out; + goto out_subsys; error = sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); - } + if (!error) + goto out; + } else + goto out; + sysfs_remove_link(&dev->kobj, "subsystem"); +out_subsys: + sysfs_remove_link(&bus->devices.kobj, dev->bus_id); +out_id: + device_remove_attrs(bus, dev); +out_put: + put_bus(dev->bus); out: return error; } @@ -763,11 +773,15 @@ int bus_register(struct bus_type * bus) klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put); - bus_add_attrs(bus); + retval = bus_add_attrs(bus); + if (retval) + goto bus_attrs_fail; pr_debug("bus type '%s' registered\n", bus->name); return 0; +bus_attrs_fail: + kset_unregister(&bus->drivers); bus_drivers_fail: kset_unregister(&bus->devices); bus_devices_fail: diff -puN drivers/base/class.c~yet-further-driver-core-fixes-for-mm drivers/base/class.c --- a/drivers/base/class.c~yet-further-driver-core-fixes-for-mm +++ a/drivers/base/class.c @@ -153,7 +153,10 @@ int class_register(struct class * cls) error = subsystem_register(&cls->subsys); if (!error) { error = add_class_attrs(class_get(cls)); - class_put(cls); + if (error) + subsystem_unregister(&cls->subsys); + else + class_put(cls); } return error; } diff -puN drivers/base/core.c~yet-further-driver-core-fixes-for-mm drivers/base/core.c --- a/drivers/base/core.c~yet-further-driver-core-fixes-for-mm +++ a/drivers/base/core.c @@ -817,7 +817,7 @@ int device_rename(struct device *dev, ch { char *old_class_name = NULL; char *new_class_name = NULL; - char *old_symlink_name = NULL; + char *old_device_name = NULL; int error; dev = get_device(dev); @@ -826,33 +826,43 @@ int device_rename(struct device *dev, ch pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name); - if ((dev->class) && (dev->parent)) + if ((dev->class) && (dev->parent)) { old_class_name = make_class_name(dev->class->name, &dev->kobj); - - if (dev->class) { - old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); - if (!old_symlink_name) - return -ENOMEM; - strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); + if (IS_ERR(old_class_name)) { + error = PTR_ERR(old_class_name); + old_class_name = NULL; + goto out; + } } - + old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); + if (!old_device_name) { + error = -ENOMEM; + goto out; + } + strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); error = kobject_rename(&dev->kobj, new_name); - + if (error) { + strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); + goto out; + } if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); - if (new_class_name) { - error = sysfs_create_link(&dev->parent->kobj, - &dev->kobj, new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); + if (IS_ERR(new_class_name)) { + error = PTR_ERR(new_class_name); + new_class_name = NULL; + goto out; } + error = sysfs_create_link(&dev->parent->kobj, + &dev->kobj, new_class_name); + if (error) + goto out; + sysfs_remove_link(&dev->parent->kobj, old_class_name); } if (dev->class) { sysfs_remove_link(&dev->class->subsys.kset.kobj, - old_symlink_name); + old_device_name); error = sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, dev->bus_id); if (error) { @@ -866,7 +876,7 @@ out: kfree(old_class_name); kfree(new_class_name); - kfree(old_symlink_name); + kfree(old_device_name); return error; } diff -puN drivers/base/platform.c~yet-further-driver-core-fixes-for-mm drivers/base/platform.c --- a/drivers/base/platform.c~yet-further-driver-core-fixes-for-mm +++ a/drivers/base/platform.c @@ -202,6 +202,17 @@ int platform_device_add_resources(struct } EXPORT_SYMBOL_GPL(platform_device_add_resources); +static void platform_device_del_resources(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; + if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) + release_resource(r); + } +} + /** * platform_device_add_data * @pdev: platform device allocated by platform_device_alloc to add resources to @@ -296,15 +307,8 @@ EXPORT_SYMBOL_GPL(platform_device_add); */ void platform_device_del(struct platform_device *pdev) { - int i; - if (pdev) { - for (i = 0; i < pdev->num_resources; i++) { - struct resource *r = &pdev->resource[i]; - if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) - release_resource(r); - } - + platform_device_del_resources(pdev); device_del(&pdev->dev); } } @@ -365,17 +369,20 @@ struct platform_device *platform_device_ if (num) { retval = platform_device_add_resources(pdev, res, num); if (retval) - goto error; + goto error_put; } retval = platform_device_add(pdev); if (retval) - goto error; + goto error_resources; return pdev; -error: +error_resources: + platform_device_del_resources(pdev); +error_put: platform_device_put(pdev); +error: return ERR_PTR(retval); } EXPORT_SYMBOL_GPL(platform_device_register_simple); _