[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>
This commit is contained in:
Родитель
37e0333c68
Коммит
5e4009ba3d
|
@ -1795,7 +1795,7 @@ static void sd_shutdown(struct device *dev)
|
||||||
**/
|
**/
|
||||||
static int __init init_sd(void)
|
static int __init init_sd(void)
|
||||||
{
|
{
|
||||||
int majors = 0, i;
|
int majors = 0, i, err;
|
||||||
|
|
||||||
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
|
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
|
||||||
|
|
||||||
|
@ -1806,9 +1806,22 @@ static int __init init_sd(void)
|
||||||
if (!majors)
|
if (!majors)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
class_register(&sd_disk_class);
|
err = class_register(&sd_disk_class);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
return scsi_register_driver(&sd_template.gendrv);
|
err = scsi_register_driver(&sd_template.gendrv);
|
||||||
|
if (err)
|
||||||
|
goto err_out_class;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_out_class:
|
||||||
|
class_unregister(&sd_disk_class);
|
||||||
|
err_out:
|
||||||
|
for (i = 0; i < SD_MAJORS; i++)
|
||||||
|
unregister_blkdev(sd_major(i), "sd");
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1823,10 +1836,10 @@ static void __exit exit_sd(void)
|
||||||
SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
|
SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
|
||||||
|
|
||||||
scsi_unregister_driver(&sd_template.gendrv);
|
scsi_unregister_driver(&sd_template.gendrv);
|
||||||
|
class_unregister(&sd_disk_class);
|
||||||
|
|
||||||
for (i = 0; i < SD_MAJORS; i++)
|
for (i = 0; i < SD_MAJORS; i++)
|
||||||
unregister_blkdev(sd_major(i), "sd");
|
unregister_blkdev(sd_major(i), "sd");
|
||||||
|
|
||||||
class_unregister(&sd_disk_class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(init_sd);
|
module_init(init_sd);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче