diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2019-04-08 13:03:09 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2019-04-08 13:03:09 +0200 |
commit | 26af34079f1d8299932303cfd2b376b9cf55a35c (patch) | |
tree | f1a9824855fae569aa51c2109a5929715143093d /drivers/scsi/sd.c | |
parent | 27157af66324d529b43231c12b5d1e1a3e9fa620 (diff) | |
parent | 79a3aaa7b82e3106be97842dedfd8429248896e6 (diff) |
Merge tag 'v5.1-rc3' into devel
Linux 5.1-rc3
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 251db30d0882..2b2bc4b49d78 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1415,11 +1415,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } - /* - * XXX and what if there are packets in flight and this close() - * XXX is followed by a "rmmod sd_mod"? - */ - scsi_disk_put(sdkp); } @@ -3076,6 +3071,9 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp, unsigned int opt_xfer_bytes = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); + if (sdkp->opt_xfer_blocks == 0) + return false; + if (sdkp->opt_xfer_blocks > dev_max) { sd_first_printk(KERN_WARNING, sdkp, "Optimal transfer size %u logical blocks " \ @@ -3505,9 +3503,21 @@ 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); |