diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 115 |
1 files changed, 27 insertions, 88 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 62eb9921cc94..73e6f5f0f37c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -38,7 +38,6 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bio.h> -#include <linux/genhd.h> #include <linux/hdreg.h> #include <linux/errno.h> #include <linux/idr.h> @@ -122,11 +121,6 @@ static void scsi_disk_release(struct device *cdev); static DEFINE_IDA(sd_index_ida); -/* This semaphore is used to mediate the 0->1 reference get in the - * face of object destruction (i.e. we can't allow a get on an - * object after last put) */ -static DEFINE_MUTEX(sd_ref_mutex); - static struct kmem_cache *sd_cdb_cache; static mempool_t *sd_cdb_pool; static mempool_t *sd_page_pool; @@ -664,33 +658,6 @@ static int sd_major(int major_idx) } } -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) - get_device(&sdkp->dev); - else - sdkp = NULL; - } - mutex_unlock(&sd_ref_mutex); - return sdkp; -} - -static void scsi_disk_put(struct scsi_disk *sdkp) -{ - struct scsi_device *sdev = sdkp->device; - - mutex_lock(&sd_ref_mutex); - put_device(&sdkp->dev); - scsi_device_put(sdev); - mutex_unlock(&sd_ref_mutex); -} - #ifdef CONFIG_BLK_SED_OPAL static int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, bool send) @@ -1419,17 +1386,15 @@ static bool sd_need_revalidate(struct block_device *bdev, **/ static int sd_open(struct block_device *bdev, fmode_t mode) { - struct scsi_disk *sdkp = scsi_disk_get(bdev->bd_disk); - struct scsi_device *sdev; + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_device *sdev = sdkp->device; int retval; - if (!sdkp) + if (scsi_device_get(sdev)) return -ENXIO; SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); - sdev = sdkp->device; - /* * If the device is in error recovery, wait until it is done. * If the device is offline, then disallow any access to it. @@ -1474,7 +1439,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) return 0; error_out: - scsi_disk_put(sdkp); + scsi_device_put(sdev); return retval; } @@ -1503,7 +1468,7 @@ static void sd_release(struct gendisk *disk, fmode_t mode) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } - scsi_disk_put(sdkp); + scsi_device_put(sdev); } static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) @@ -1617,7 +1582,7 @@ static int media_not_present(struct scsi_disk *sdkp, **/ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) { - struct scsi_disk *sdkp = scsi_disk_get(disk); + struct scsi_disk *sdkp = disk->private_data; struct scsi_device *sdp; int retval; bool disk_changed; @@ -1680,7 +1645,6 @@ out: */ disk_changed = sdp->changed; sdp->changed = 0; - scsi_disk_put(sdkp); return disk_changed ? DISK_EVENT_MEDIA_CHANGE : 0; } @@ -1888,6 +1852,13 @@ static const struct pr_ops sd_pr_ops = { .pr_clear = sd_pr_clear, }; +static void scsi_disk_free_disk(struct gendisk *disk) +{ + struct scsi_disk *sdkp = scsi_disk(disk); + + put_device(&sdkp->disk_dev); +} + static const struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, @@ -1899,6 +1870,7 @@ static const struct block_device_operations sd_fops = { .unlock_native_capacity = sd_unlock_native_capacity, .report_zones = sd_zbc_report_zones, .get_unique_id = sd_get_unique_id, + .free_disk = scsi_disk_free_disk, .pr_ops = &sd_pr_ops, }; @@ -3516,7 +3488,6 @@ static int sd_probe(struct device *dev) } sdkp->device = sdp; - sdkp->driver = &sd_template; sdkp->disk = gd; sdkp->index = index; sdkp->max_retries = SD_MAX_RETRIES; @@ -3531,14 +3502,14 @@ static int sd_probe(struct device *dev) SD_MOD_TIMEOUT); } - device_initialize(&sdkp->dev); - sdkp->dev.parent = get_device(dev); - sdkp->dev.class = &sd_disk_class; - dev_set_name(&sdkp->dev, "%s", dev_name(dev)); + device_initialize(&sdkp->disk_dev); + sdkp->disk_dev.parent = get_device(dev); + sdkp->disk_dev.class = &sd_disk_class; + dev_set_name(&sdkp->disk_dev, "%s", dev_name(dev)); - error = device_add(&sdkp->dev); + error = device_add(&sdkp->disk_dev); if (error) { - put_device(&sdkp->dev); + put_device(&sdkp->disk_dev); goto out; } @@ -3549,7 +3520,7 @@ static int sd_probe(struct device *dev) gd->minors = SD_MINORS; gd->fops = &sd_fops; - gd->private_data = &sdkp->driver; + gd->private_data = sdkp; /* defaults, until the device tells us otherwise */ sdp->sector_size = 512; @@ -3579,7 +3550,7 @@ static int sd_probe(struct device *dev) error = device_add_disk(dev, gd, NULL); if (error) { - put_device(&sdkp->dev); + put_device(&sdkp->disk_dev); goto out; } @@ -3625,58 +3596,26 @@ static int sd_probe(struct device *dev) **/ static int sd_remove(struct device *dev) { - struct scsi_disk *sdkp; + struct scsi_disk *sdkp = dev_get_drvdata(dev); - sdkp = dev_get_drvdata(dev); scsi_autopm_get_device(sdkp->device); - device_del(&sdkp->dev); + device_del(&sdkp->disk_dev); del_gendisk(sdkp->disk); sd_shutdown(dev); - free_opal_dev(sdkp->opal_dev); - - mutex_lock(&sd_ref_mutex); - dev_set_drvdata(dev, NULL); - put_device(&sdkp->dev); - mutex_unlock(&sd_ref_mutex); - + put_disk(sdkp->disk); return 0; } -/** - * scsi_disk_release - Called to free the scsi_disk structure - * @dev: pointer to embedded class device - * - * sd_ref_mutex must be held entering this routine. Because it is - * called on last put, you should always use the scsi_disk_get() - * scsi_disk_put() helpers which manipulate the semaphore directly - * and never do a direct put_device. - **/ static void scsi_disk_release(struct device *dev) { struct scsi_disk *sdkp = to_scsi_disk(dev); - struct gendisk *disk = sdkp->disk; - struct request_queue *q = disk->queue; ida_free(&sd_index_ida, sdkp->index); - - /* - * Wait until all requests that are in progress have completed. - * This is necessary to avoid that e.g. scsi_end_request() crashes - * due to clearing the disk->private_data pointer. Wait from inside - * scsi_disk_release() instead of from sd_release() to avoid that - * freezing and unfreezing the request queue affects user space I/O - * in case multiple processes open a /dev/sd... node concurrently. - */ - blk_mq_freeze_queue(q); - blk_mq_unfreeze_queue(q); - - disk->private_data = NULL; - put_disk(disk); - put_device(&sdkp->device->sdev_gendev); - sd_zbc_release_disk(sdkp); + put_device(&sdkp->device->sdev_gendev); + free_opal_dev(sdkp->opal_dev); kfree(sdkp); } |