Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] fix crash when disconnecting usb storage
  [SCSI] fix async scan add/remove race resulting in an oops
  [SCSI] sd: Return correct error code for DIF
This commit is contained in:
Linus Torvalds 2009-11-30 15:21:50 -08:00
commit ed9fd93e9a
5 changed files with 34 additions and 52 deletions

View file

@ -164,8 +164,8 @@ void scsi_remove_host(struct Scsi_Host *shost)
return;
}
spin_unlock_irqrestore(shost->host_lock, flags);
mutex_unlock(&shost->scan_mutex);
scsi_forget_host(shost);
mutex_unlock(&shost->scan_mutex);
scsi_proc_host_rm(shost);
spin_lock_irqsave(shost->host_lock, flags);

View file

@ -952,16 +952,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
return SCSI_SCAN_LUN_PRESENT;
}
static inline void scsi_destroy_sdev(struct scsi_device *sdev)
{
scsi_device_set_state(sdev, SDEV_DEL);
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_dev);
put_device(&sdev->sdev_gendev);
}
#ifdef CONFIG_SCSI_LOGGING
/**
* scsi_inq_str - print INQUIRY data from min to max index, strip trailing whitespace
@ -1139,7 +1129,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
}
}
} else
scsi_destroy_sdev(sdev);
__scsi_remove_device(sdev);
out:
return res;
}
@ -1500,7 +1490,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
/*
* the sdev we used didn't appear in the report luns scan
*/
scsi_destroy_sdev(sdev);
__scsi_remove_device(sdev);
return ret;
}
@ -1710,7 +1700,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
shost_for_each_device(sdev, shost) {
if (!scsi_host_scan_allowed(shost) ||
scsi_sysfs_add_sdev(sdev) != 0)
scsi_destroy_sdev(sdev);
__scsi_remove_device(sdev);
}
}
@ -1943,7 +1933,7 @@ void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
scsi_destroy_sdev(sdev);
__scsi_remove_device(sdev);
}
EXPORT_SYMBOL(scsi_free_host_dev);

View file

@ -854,82 +854,73 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
transport_configure_device(&starget->dev);
error = device_add(&sdev->sdev_gendev);
if (error) {
put_device(sdev->sdev_gendev.parent);
printk(KERN_INFO "error 1\n");
return error;
goto out_remove;
}
error = device_add(&sdev->sdev_dev);
if (error) {
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 */
if (sdev->host->hostt->change_queue_depth)
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
else
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)
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
else
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);
if (error)
/* we're treating error on bsg register as non-fatal,
* so pretend nothing went wrong */
sdev_printk(KERN_INFO, sdev,
"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 */
if (sdev->host->hostt->sdev_attrs) {
for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
error = device_create_file(&sdev->sdev_gendev,
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 0;
out_remove:
__scsi_remove_device(sdev);
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 error;
}
void __scsi_remove_device(struct scsi_device *sdev)
{
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);
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);

View file

@ -418,7 +418,7 @@ error:
__func__, virt, phys, be32_to_cpu(sdt->ref_tag),
be16_to_cpu(sdt->app_tag));
return -EIO;
return -EILSEQ;
}
/*

View file

@ -145,6 +145,7 @@ struct scsi_device {
unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned last_sector_bug:1; /* do not use multisector accesses on
SD_LAST_BUGGY_SECTORS */
unsigned is_visible:1; /* is the device visible in sysfs */
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */