diff options
author | James Simmons <jsimmons@infradead.org> | 2007-02-21 12:44:51 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-23 17:52:09 -0500 |
commit | 82f0cf9b7c42684c29189ddb6d0bc86eb1137fc4 (patch) | |
tree | 3052eb95a5e6070cbee8a1262952abc48f2eedbe /drivers/base/core.c | |
parent | 4541ac94d0ea0b00776edd5904ac91dd6d6330f7 (diff) |
Driver core: fix error by cleanup up symlinks properly
When a device fails to register the class symlinks where not cleaned up.
This left a symlink in the /sys/class/"device"/ directory that pointed
to no where. This caused the sysfs_follow_link Oops I reported earlier.
This patch cleanups up the symlink. Please apply. Thank you.
Signed-Off: James Simmons <jsimmons@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index d04fd33dcd91..cf2a398aaaa1 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -637,12 +637,41 @@ int device_add(struct device *dev) | |||
637 | BUS_NOTIFY_DEL_DEVICE, dev); | 637 | BUS_NOTIFY_DEL_DEVICE, dev); |
638 | device_remove_groups(dev); | 638 | device_remove_groups(dev); |
639 | GroupError: | 639 | GroupError: |
640 | device_remove_attrs(dev); | 640 | device_remove_attrs(dev); |
641 | AttrsError: | 641 | AttrsError: |
642 | if (dev->devt_attr) { | 642 | if (dev->devt_attr) { |
643 | device_remove_file(dev, dev->devt_attr); | 643 | device_remove_file(dev, dev->devt_attr); |
644 | kfree(dev->devt_attr); | 644 | kfree(dev->devt_attr); |
645 | } | 645 | } |
646 | |||
647 | if (dev->class) { | ||
648 | sysfs_remove_link(&dev->kobj, "subsystem"); | ||
649 | /* If this is not a "fake" compatible device, remove the | ||
650 | * symlink from the class to the device. */ | ||
651 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | ||
652 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | ||
653 | dev->bus_id); | ||
654 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
655 | if (parent) { | ||
656 | char *class_name = make_class_name(dev->class->name, | ||
657 | &dev->kobj); | ||
658 | if (class_name) | ||
659 | sysfs_remove_link(&dev->parent->kobj, | ||
660 | class_name); | ||
661 | kfree(class_name); | ||
662 | sysfs_remove_link(&dev->kobj, "device"); | ||
663 | } | ||
664 | #endif | ||
665 | |||
666 | down(&dev->class->sem); | ||
667 | /* notify any interfaces that the device is now gone */ | ||
668 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | ||
669 | if (class_intf->remove_dev) | ||
670 | class_intf->remove_dev(dev, class_intf); | ||
671 | /* remove the device from the class list */ | ||
672 | list_del_init(&dev->node); | ||
673 | up(&dev->class->sem); | ||
674 | } | ||
646 | ueventattrError: | 675 | ueventattrError: |
647 | device_remove_file(dev, &dev->uevent_attr); | 676 | device_remove_file(dev, &dev->uevent_attr); |
648 | attrError: | 677 | attrError: |