diff options
author | Christoph Hellwig <hch@lst.de> | 2015-02-02 14:01:25 +0100 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2015-03-19 14:40:53 +0100 |
commit | 3d9a1f530e508ff6fc9ab8220016b02f1bce255b (patch) | |
tree | afcdbfbdaea6b1a604dbc62f1f17d7da4fec7de5 /drivers/scsi/sd.c | |
parent | scsi: serialize ->rescan against ->remove (diff) | |
download | linux-3d9a1f530e508ff6fc9ab8220016b02f1bce255b.tar.xz linux-3d9a1f530e508ff6fc9ab8220016b02f1bce255b.zip |
sd: don't grab a device references from driver methods
The device model already takes care of races between ->remove and
->shutdown vs its other methods, and we now take care about locking
them out for ->rescan as well.
This is a partial revert of commit 39b7f1 ("[SCSI] sd: Fix refcounting").
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to '')
-rw-r--r-- | drivers/scsi/sd.c | 55 |
1 files changed, 11 insertions, 44 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6b78476d04bb..9e0c63e57aff 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -564,10 +564,12 @@ static int sd_major(int major_idx) } } -static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) +static struct scsi_disk *scsi_disk_get(struct gendisk *disk) { struct scsi_disk *sdkp = NULL; + mutex_lock(&sd_ref_mutex); + if (disk->private_data) { sdkp = scsi_disk(disk); if (scsi_device_get(sdkp->device) == 0) @@ -575,27 +577,6 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) else sdkp = NULL; } - return sdkp; -} - -static struct scsi_disk *scsi_disk_get(struct gendisk *disk) -{ - struct scsi_disk *sdkp; - - mutex_lock(&sd_ref_mutex); - sdkp = __scsi_disk_get(disk); - mutex_unlock(&sd_ref_mutex); - return sdkp; -} - -static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev) -{ - struct scsi_disk *sdkp; - - mutex_lock(&sd_ref_mutex); - sdkp = dev_get_drvdata(dev); - if (sdkp) - sdkp = __scsi_disk_get(sdkp->disk); mutex_unlock(&sd_ref_mutex); return sdkp; } @@ -610,8 +591,6 @@ static void scsi_disk_put(struct scsi_disk *sdkp) mutex_unlock(&sd_ref_mutex); } - - static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, unsigned int dix, unsigned int dif) { @@ -1525,12 +1504,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) static void sd_rescan(struct device *dev) { - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + struct scsi_disk *sdkp = dev_get_drvdata(dev); - if (sdkp) { - revalidate_disk(sdkp->disk); - scsi_disk_put(sdkp); - } + revalidate_disk(sdkp->disk); } @@ -3149,13 +3125,13 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) */ static void sd_shutdown(struct device *dev) { - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + struct scsi_disk *sdkp = dev_get_drvdata(dev); if (!sdkp) return; /* this can happen */ if (pm_runtime_suspended(dev)) - goto exit; + return; if (sdkp->WCE && sdkp->media_present) { sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); @@ -3166,14 +3142,11 @@ static void sd_shutdown(struct device *dev) sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); sd_start_stop_device(sdkp, 0); } - -exit: - scsi_disk_put(sdkp); } static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) { - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + struct scsi_disk *sdkp = dev_get_drvdata(dev); int ret = 0; if (!sdkp) @@ -3199,7 +3172,6 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) } done: - scsi_disk_put(sdkp); return ret; } @@ -3215,18 +3187,13 @@ static int sd_suspend_runtime(struct device *dev) static int sd_resume(struct device *dev) { - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); - int ret = 0; + struct scsi_disk *sdkp = dev_get_drvdata(dev); if (!sdkp->device->manage_start_stop) - goto done; + return 0; sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - ret = sd_start_stop_device(sdkp, 1); - -done: - scsi_disk_put(sdkp); - return ret; + return sd_start_stop_device(sdkp, 1); } /** |