diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-10-04 05:32:54 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-10-04 14:14:16 -0400 |
commit | 5e4009ba3d5af40f5615fdb4304cc4a9947cca0a (patch) | |
tree | a6dd31cd9f6dfa1c85b3b5fefcded5b74d0ac2f5 /drivers/scsi | |
parent | 37e0333c68ca9cbddfc0108e1889556287563df0 (diff) |
[SCSI] SCSI sd: fix module init/exit error handling
- Properly handle and unwind errors in init_sd(). Fixes leaks on error,
if class_register() or scsi_register_driver() failed.
- Ensure that exit_sd() execution order is the perfect inverse of
initialization order.
FIXME: If some-but-not-all register_blkdev() calls fail, we wind up
calling unregister_blkdev() for block devices we did not register.
This was a pre-existing bug.
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sd.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 638cff41d436..7a9d552f50e6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1795,7 +1795,7 @@ static void sd_shutdown(struct device *dev) | |||
1795 | **/ | 1795 | **/ |
1796 | static int __init init_sd(void) | 1796 | static int __init init_sd(void) |
1797 | { | 1797 | { |
1798 | int majors = 0, i; | 1798 | int majors = 0, i, err; |
1799 | 1799 | ||
1800 | SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); | 1800 | SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); |
1801 | 1801 | ||
@@ -1806,9 +1806,22 @@ static int __init init_sd(void) | |||
1806 | if (!majors) | 1806 | if (!majors) |
1807 | return -ENODEV; | 1807 | return -ENODEV; |
1808 | 1808 | ||
1809 | class_register(&sd_disk_class); | 1809 | err = class_register(&sd_disk_class); |
1810 | if (err) | ||
1811 | goto err_out; | ||
1810 | 1812 | ||
1811 | return scsi_register_driver(&sd_template.gendrv); | 1813 | err = scsi_register_driver(&sd_template.gendrv); |
1814 | if (err) | ||
1815 | goto err_out_class; | ||
1816 | |||
1817 | return 0; | ||
1818 | |||
1819 | err_out_class: | ||
1820 | class_unregister(&sd_disk_class); | ||
1821 | err_out: | ||
1822 | for (i = 0; i < SD_MAJORS; i++) | ||
1823 | unregister_blkdev(sd_major(i), "sd"); | ||
1824 | return err; | ||
1812 | } | 1825 | } |
1813 | 1826 | ||
1814 | /** | 1827 | /** |
@@ -1823,10 +1836,10 @@ static void __exit exit_sd(void) | |||
1823 | SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); | 1836 | SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); |
1824 | 1837 | ||
1825 | scsi_unregister_driver(&sd_template.gendrv); | 1838 | scsi_unregister_driver(&sd_template.gendrv); |
1839 | class_unregister(&sd_disk_class); | ||
1840 | |||
1826 | for (i = 0; i < SD_MAJORS; i++) | 1841 | for (i = 0; i < SD_MAJORS; i++) |
1827 | unregister_blkdev(sd_major(i), "sd"); | 1842 | unregister_blkdev(sd_major(i), "sd"); |
1828 | |||
1829 | class_unregister(&sd_disk_class); | ||
1830 | } | 1843 | } |
1831 | 1844 | ||
1832 | module_init(init_sd); | 1845 | module_init(init_sd); |