diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2019-01-15 16:49:59 -0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-01-22 21:18:27 -0500 |
commit | ec029758a10095c66fd24398f742c695c2e6ec2c (patch) | |
tree | 4eb233e879a02f4b8b1ebf38d9a837491938d3a4 /drivers/scsi/sd.c | |
parent | c6c93fdd3451cc0de393dad891d6b0be71e50888 (diff) | |
download | talos-op-linux-ec029758a10095c66fd24398f742c695c2e6ec2c.tar.gz talos-op-linux-ec029758a10095c66fd24398f742c695c2e6ec2c.zip |
scsi: sd: Simplify misaligned I/O check
Avoid open coding the checks for the supported logical block sizes and use
a mask to check for misaligned I/O. Use our helper functions to scale lba
and block count.
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
[ bvanassche: ported this patch from kernel v4.11 to kernel v5.0 ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 57 |
1 files changed, 12 insertions, 45 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4d14208fe6db..13d2137b94b1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1078,10 +1078,11 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) struct scsi_device *sdp = SCpnt->device; struct gendisk *disk = rq->rq_disk; struct scsi_disk *sdkp = scsi_disk(disk); - sector_t lba = blk_rq_pos(rq); + sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq)); sector_t threshold; - unsigned int nr_blocks = blk_rq_sectors(rq); + unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); unsigned int dif, dix; + unsigned int mask = logical_to_sectors(sdp, 1) - 1; unsigned char protect; blk_status_t ret; @@ -1115,63 +1116,29 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) } /* - * Some SD card readers can't handle multi-sector accesses which touch - * the last one or two hardware sectors. Split accesses as needed. + * Some SD card readers can't handle accesses which touch the + * last one or two logical blocks. Split accesses as needed. */ - threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS * - (sdp->sector_size / 512); + threshold = sdkp->capacity - SD_LAST_BUGGY_SECTORS; if (unlikely(sdp->last_sector_bug && lba + nr_blocks > threshold)) { if (lba < threshold) { /* Access up to the threshold but not beyond */ nr_blocks = threshold - lba; } else { - /* Access only a single hardware sector */ - nr_blocks = sdp->sector_size / 512; + /* Access only a single logical block */ + nr_blocks = 1; } } SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", (unsigned long long)lba)); - /* - * If we have a 1K hardware sectorsize, prevent access to single - * 512 byte sectors. In theory we could handle this - in fact - * the scsi cdrom driver must be able to handle this because - * we typically use 1K blocksizes, and cdroms typically have - * 2K hardware sectorsizes. Of course, things are simpler - * with the cdrom, since it is read-only. For performance - * reasons, the filesystems should be able to handle this - * and not force the scsi disk driver to use bounce buffers - * for this. - */ - if (sdp->sector_size == 1024) { - if ((lba & 1) || (blk_rq_sectors(rq) & 1)) { - scmd_printk(KERN_ERR, SCpnt, - "Bad block number requested\n"); - return BLK_STS_IOERR; - } - lba = lba >> 1; - nr_blocks = nr_blocks >> 1; - } - if (sdp->sector_size == 2048) { - if ((lba & 3) || (blk_rq_sectors(rq) & 3)) { - scmd_printk(KERN_ERR, SCpnt, - "Bad block number requested\n"); - return BLK_STS_IOERR; - } - lba = lba >> 2; - nr_blocks = nr_blocks >> 2; - } - if (sdp->sector_size == 4096) { - if ((lba & 7) || (blk_rq_sectors(rq) & 7)) { - scmd_printk(KERN_ERR, SCpnt, - "Bad block number requested\n"); - return BLK_STS_IOERR; - } - lba = lba >> 3; - nr_blocks = nr_blocks >> 3; + if ((blk_rq_pos(rq) & mask) || (blk_rq_sectors(rq) & mask)) { + scmd_printk(KERN_ERR, SCpnt, "request not aligned to the logical block size\n"); + return BLK_STS_IOERR; } + if (rq_data_dir(rq) == WRITE) { SCpnt->cmnd[0] = WRITE_6; |