aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-08-31 18:15:22 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-01 17:56:56 -0400
commit85b6c720b0931101c8bcc3a5abdc2b8514b0fb4b (patch)
treea6d2883ef3b4f40a71d59c9db0fda87d43419463 /drivers/scsi
parent86e33a296c2c9ed6eece0bfff4ac776f42040504 (diff)
[SCSI] sd: fix cache flushing on module removal (and individual device removal)
The fix isn't actually in sd: it's in scsi_device_get(). I modified it to allow devices to be returned in SDEV_CANCEL, but not SDEV_DEL. This means that the device_remove_driver, which occurs in device_del() in scsi_remove_device() after the device has gone into SDEV_CANCEL is now effective at flushing the cache. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 94df671d776a..37843927e47f 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -851,14 +851,14 @@ EXPORT_SYMBOL(scsi_track_queue_full);
851 */ 851 */
852int scsi_device_get(struct scsi_device *sdev) 852int scsi_device_get(struct scsi_device *sdev)
853{ 853{
854 if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL) 854 if (sdev->sdev_state == SDEV_DEL)
855 return -ENXIO; 855 return -ENXIO;
856 if (!get_device(&sdev->sdev_gendev)) 856 if (!get_device(&sdev->sdev_gendev))
857 return -ENXIO; 857 return -ENXIO;
858 if (!try_module_get(sdev->host->hostt->module)) { 858 /* We can fail this if we're doing SCSI operations
859 put_device(&sdev->sdev_gendev); 859 * from module exit (like cache flush) */
860 return -ENXIO; 860 try_module_get(sdev->host->hostt->module);
861 } 861
862 return 0; 862 return 0;
863} 863}
864EXPORT_SYMBOL(scsi_device_get); 864EXPORT_SYMBOL(scsi_device_get);
@@ -873,7 +873,10 @@ EXPORT_SYMBOL(scsi_device_get);
873 */ 873 */
874void scsi_device_put(struct scsi_device *sdev) 874void scsi_device_put(struct scsi_device *sdev)
875{ 875{
876 module_put(sdev->host->hostt->module); 876 /* The module refcount will be zero if scsi_device_get()
877 * was called from a module removal routine */
878 if (likely(module_refcount(sdev->host->hostt->module) != 0))
879 module_put(sdev->host->hostt->module);
877 put_device(&sdev->sdev_gendev); 880 put_device(&sdev->sdev_gendev);
878} 881}
879EXPORT_SYMBOL(scsi_device_put); 882EXPORT_SYMBOL(scsi_device_put);