|
@@ -854,82 +854,73 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
|
|
transport_configure_device(&starget->dev);
|
|
transport_configure_device(&starget->dev);
|
|
error = device_add(&sdev->sdev_gendev);
|
|
error = device_add(&sdev->sdev_gendev);
|
|
if (error) {
|
|
if (error) {
|
|
- put_device(sdev->sdev_gendev.parent);
|
|
|
|
printk(KERN_INFO "error 1\n");
|
|
printk(KERN_INFO "error 1\n");
|
|
- return error;
|
|
|
|
|
|
+ goto out_remove;
|
|
}
|
|
}
|
|
error = device_add(&sdev->sdev_dev);
|
|
error = device_add(&sdev->sdev_dev);
|
|
if (error) {
|
|
if (error) {
|
|
printk(KERN_INFO "error 2\n");
|
|
printk(KERN_INFO "error 2\n");
|
|
- goto clean_device;
|
|
|
|
|
|
+ device_del(&sdev->sdev_gendev);
|
|
|
|
+ goto out_remove;
|
|
}
|
|
}
|
|
|
|
+ transport_add_device(&sdev->sdev_gendev);
|
|
|
|
+ sdev->is_visible = 1;
|
|
|
|
|
|
/* create queue files, which may be writable, depending on the host */
|
|
/* create queue files, which may be writable, depending on the host */
|
|
if (sdev->host->hostt->change_queue_depth)
|
|
if (sdev->host->hostt->change_queue_depth)
|
|
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
|
|
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
|
|
else
|
|
else
|
|
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
|
|
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
|
|
- if (error) {
|
|
|
|
- __scsi_remove_device(sdev);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_remove;
|
|
|
|
+
|
|
if (sdev->host->hostt->change_queue_type)
|
|
if (sdev->host->hostt->change_queue_type)
|
|
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
|
|
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
|
|
else
|
|
else
|
|
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
|
|
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
|
|
- if (error) {
|
|
|
|
- __scsi_remove_device(sdev);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_remove;
|
|
|
|
|
|
error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
|
|
error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
|
|
|
|
|
|
if (error)
|
|
if (error)
|
|
|
|
+ /* we're treating error on bsg register as non-fatal,
|
|
|
|
+ * so pretend nothing went wrong */
|
|
sdev_printk(KERN_INFO, sdev,
|
|
sdev_printk(KERN_INFO, sdev,
|
|
"Failed to register bsg queue, errno=%d\n", error);
|
|
"Failed to register bsg queue, errno=%d\n", error);
|
|
|
|
|
|
- /* we're treating error on bsg register as non-fatal, so pretend
|
|
|
|
- * nothing went wrong */
|
|
|
|
- error = 0;
|
|
|
|
-
|
|
|
|
/* add additional host specific attributes */
|
|
/* add additional host specific attributes */
|
|
if (sdev->host->hostt->sdev_attrs) {
|
|
if (sdev->host->hostt->sdev_attrs) {
|
|
for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
|
|
for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
|
|
error = device_create_file(&sdev->sdev_gendev,
|
|
error = device_create_file(&sdev->sdev_gendev,
|
|
sdev->host->hostt->sdev_attrs[i]);
|
|
sdev->host->hostt->sdev_attrs[i]);
|
|
- if (error) {
|
|
|
|
- __scsi_remove_device(sdev);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (error)
|
|
|
|
+ goto out_remove;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- transport_add_device(&sdev->sdev_gendev);
|
|
|
|
- out:
|
|
|
|
- return error;
|
|
|
|
-
|
|
|
|
- clean_device:
|
|
|
|
- scsi_device_set_state(sdev, SDEV_CANCEL);
|
|
|
|
-
|
|
|
|
- device_del(&sdev->sdev_gendev);
|
|
|
|
- transport_destroy_device(&sdev->sdev_gendev);
|
|
|
|
- put_device(&sdev->sdev_dev);
|
|
|
|
- put_device(&sdev->sdev_gendev);
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
|
|
|
+ out_remove:
|
|
|
|
+ __scsi_remove_device(sdev);
|
|
return error;
|
|
return error;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
void __scsi_remove_device(struct scsi_device *sdev)
|
|
void __scsi_remove_device(struct scsi_device *sdev)
|
|
{
|
|
{
|
|
struct device *dev = &sdev->sdev_gendev;
|
|
struct device *dev = &sdev->sdev_gendev;
|
|
|
|
|
|
- if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (sdev->is_visible) {
|
|
|
|
+ if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
|
|
|
|
+ return;
|
|
|
|
|
|
- bsg_unregister_queue(sdev->request_queue);
|
|
|
|
- device_unregister(&sdev->sdev_dev);
|
|
|
|
- transport_remove_device(dev);
|
|
|
|
- device_del(dev);
|
|
|
|
|
|
+ bsg_unregister_queue(sdev->request_queue);
|
|
|
|
+ device_unregister(&sdev->sdev_dev);
|
|
|
|
+ transport_remove_device(dev);
|
|
|
|
+ device_del(dev);
|
|
|
|
+ } else
|
|
|
|
+ put_device(&sdev->sdev_dev);
|
|
scsi_device_set_state(sdev, SDEV_DEL);
|
|
scsi_device_set_state(sdev, SDEV_DEL);
|
|
if (sdev->host->hostt->slave_destroy)
|
|
if (sdev->host->hostt->slave_destroy)
|
|
sdev->host->hostt->slave_destroy(sdev);
|
|
sdev->host->hostt->slave_destroy(sdev);
|