Commit 28f91107 authored by Doug Ledford's avatar Doug Ledford Committed by Doug Ledford

st.c: Clean up init failure paths

	Fix the detach code so it doesn't call sysfs unregister with
		a lock held
parent 45493905
...@@ -3673,19 +3673,18 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3673,19 +3673,18 @@ static int st_attach(Scsi_Device * SDp)
buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i);
if (buffer == NULL) { if (buffer == NULL) {
printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n");
return 1; goto out_slave_detach;
} }
disk = alloc_disk(1); disk = alloc_disk(1);
if (!disk) { if (!disk) {
printk(KERN_ERR "st: out of memory. Device not attached.\n"); printk(KERN_ERR "st: out of memory. Device not attached.\n");
return 1; goto out_buffer_free;
} }
write_lock(&st_dev_arr_lock); write_lock(&st_dev_arr_lock);
if (st_nr_dev >= st_dev_max) { if (st_nr_dev >= st_dev_max) {
Scsi_Tape **tmp_da; Scsi_Tape **tmp_da;
ST_buffer **tmp_ba;
int tmp_dev_max; int tmp_dev_max;
tmp_dev_max = st_nr_dev + ST_DEV_ARR_LUMP; tmp_dev_max = st_nr_dev + ST_DEV_ARR_LUMP;
...@@ -3695,23 +3694,14 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3695,23 +3694,14 @@ static int st_attach(Scsi_Device * SDp)
write_unlock(&st_dev_arr_lock); write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Too many tape devices (max. %d).\n", printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
ST_MAX_TAPES); ST_MAX_TAPES);
put_disk(disk); goto out_put_disk;
scsi_slave_detach(SDp);
return 1;
} }
tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC); tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC);
tmp_ba = kmalloc(tmp_dev_max * sizeof(ST_buffer *), GFP_ATOMIC); if (tmp_da == NULL) {
if (tmp_da == NULL || tmp_ba == NULL) {
if (tmp_da != NULL)
kfree(tmp_da);
if (tmp_ba != NULL)
kfree(tmp_ba);
write_unlock(&st_dev_arr_lock); write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Can't extend device array.\n"); printk(KERN_ERR "st: Can't extend device array.\n");
put_disk(disk); goto out_put_disk;
scsi_slave_detach(SDp);
return 1;
} }
memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *)); memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *));
...@@ -3735,9 +3725,7 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3735,9 +3725,7 @@ static int st_attach(Scsi_Device * SDp)
if (tpnt == NULL) { if (tpnt == NULL) {
write_unlock(&st_dev_arr_lock); write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Can't allocate device descriptor.\n"); printk(KERN_ERR "st: Can't allocate device descriptor.\n");
put_disk(disk); goto out_put_disk;
scsi_slave_detach(SDp);
return 1;
} }
memset(tpnt, 0, sizeof(Scsi_Tape)); memset(tpnt, 0, sizeof(Scsi_Tape));
tpnt->disk = disk; tpnt->disk = disk;
...@@ -3840,14 +3828,14 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3840,14 +3828,14 @@ static int st_attach(Scsi_Device * SDp)
tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type; tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type;
tpnt->driverfs_dev_r[mode].driver_data = tpnt->driverfs_dev_r[mode].driver_data =
(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5)); (void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5));
device_register(&tpnt->driverfs_dev_r[mode]); device_register(&tpnt->driverfs_dev_r[mode]);
device_create_file(&tpnt->driverfs_dev_r[mode], device_create_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type); &dev_attr_type);
device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
tpnt->de_r[mode] = tpnt->de_r[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, dev_num + (mode << 5), SCSI_TAPE_MAJOR, dev_num + (mode << 5),
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,
&st_fops, NULL); &st_fops, NULL);
/* No-rewind entry */ /* No-rewind entry */
...@@ -3859,7 +3847,7 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3859,7 +3847,7 @@ static int st_attach(Scsi_Device * SDp)
tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type; tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type;
tpnt->driverfs_dev_n[mode].driver_data = tpnt->driverfs_dev_n[mode].driver_data =
(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5) + 128); (void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128);
device_register(&tpnt->driverfs_dev_n[mode]); device_register(&tpnt->driverfs_dev_n[mode]);
device_create_file(&tpnt->driverfs_dev_n[mode], device_create_file(&tpnt->driverfs_dev_n[mode],
&dev_attr_type); &dev_attr_type);
...@@ -3867,7 +3855,7 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3867,7 +3855,7 @@ static int st_attach(Scsi_Device * SDp)
&dev_attr_kdev); &dev_attr_kdev);
tpnt->de_n[mode] = tpnt->de_n[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, dev_num + (mode << 5) + 128, SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128,
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,
&st_fops, NULL); &st_fops, NULL);
} }
...@@ -3880,6 +3868,14 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3880,6 +3868,14 @@ static int st_attach(Scsi_Device * SDp)
tape_name(tpnt), tpnt->try_dio ? "yes" : "no", tpnt->max_pfn); tape_name(tpnt), tpnt->try_dio ? "yes" : "no", tpnt->max_pfn);
return 0; return 0;
out_put_disk:
put_disk(disk);
out_buffer_free:
kfree(buffer);
out_slave_detach:
scsi_slave_detach(SDp);
return 1;
}; };
static void st_detach(Scsi_Device * SDp) static void st_detach(Scsi_Device * SDp)
...@@ -3891,20 +3887,15 @@ static void st_detach(Scsi_Device * SDp) ...@@ -3891,20 +3887,15 @@ static void st_detach(Scsi_Device * SDp)
for (i = 0; i < st_dev_max; i++) { for (i = 0; i < st_dev_max; i++) {
tpnt = scsi_tapes[i]; tpnt = scsi_tapes[i];
if (tpnt != NULL && tpnt->device == SDp) { if (tpnt != NULL && tpnt->device == SDp) {
tpnt->device = NULL; scsi_tapes[i] = 0;
st_nr_dev--;
write_unlock(&st_dev_arr_lock);
devfs_unregister_tape(tpnt->disk->number);
for (mode = 0; mode < ST_NBR_MODES; ++mode) { for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_unregister (tpnt->de_r[mode]); devfs_unregister (tpnt->de_r[mode]);
tpnt->de_r[mode] = NULL; tpnt->de_r[mode] = NULL;
devfs_unregister (tpnt->de_n[mode]); devfs_unregister (tpnt->de_n[mode]);
tpnt->de_n[mode] = NULL; tpnt->de_n[mode] = NULL;
}
devfs_unregister_tape(tpnt->disk->number);
scsi_tapes[i] = 0;
scsi_slave_detach(SDp);
st_nr_dev--;
write_unlock(&st_dev_arr_lock);
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
device_remove_file(&tpnt->driverfs_dev_r[mode], device_remove_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type); &dev_attr_type);
device_remove_file(&tpnt->driverfs_dev_r[mode], device_remove_file(&tpnt->driverfs_dev_r[mode],
...@@ -3916,11 +3907,14 @@ static void st_detach(Scsi_Device * SDp) ...@@ -3916,11 +3907,14 @@ static void st_detach(Scsi_Device * SDp)
&dev_attr_kdev); &dev_attr_kdev);
device_unregister(&tpnt->driverfs_dev_n[mode]); device_unregister(&tpnt->driverfs_dev_n[mode]);
} }
tpnt->device = NULL;
if (tpnt->buffer) { if (tpnt->buffer) {
tpnt->buffer->orig_frp_segs = 0; tpnt->buffer->orig_frp_segs = 0;
normalize_buffer(tpnt->buffer); normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer); kfree(tpnt->buffer);
} }
scsi_slave_detach(SDp);
put_disk(tpnt->disk); put_disk(tpnt->disk);
kfree(tpnt); kfree(tpnt);
return; return;
...@@ -3944,9 +3938,10 @@ static int __init init_st(void) ...@@ -3944,9 +3938,10 @@ static int __init init_st(void)
if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) { if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
if (scsi_register_device(&st_template) == 0) if (scsi_register_device(&st_template) == 0)
return 0; return 0;
unregister_chrdev(SCSI_TAPE_MAJOR, "st");
} }
printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR); printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
return 1; return 1;
} }
...@@ -3959,8 +3954,9 @@ static void __exit exit_st(void) ...@@ -3959,8 +3954,9 @@ static void __exit exit_st(void)
if (scsi_tapes != NULL) { if (scsi_tapes != NULL) {
for (i=0; i < st_dev_max; ++i) for (i=0; i < st_dev_max; ++i)
if (scsi_tapes[i]) { if (scsi_tapes[i]) {
put_disk(scsi_tapes[i]->disk); printk(KERN_WARNING "st: scsi_tapes[] not "
kfree(scsi_tapes[i]); "empty after scsi_unregister_device\n");
st_detach(scsi_tapes[i]->device);
} }
kfree(scsi_tapes); kfree(scsi_tapes);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment