summaryrefslogtreecommitdiff
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2019-01-15 16:49:59 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2019-01-22 21:18:27 -0500
commitec029758a10095c66fd24398f742c695c2e6ec2c (patch)
tree4eb233e879a02f4b8b1ebf38d9a837491938d3a4 /drivers/scsi/sd.c
parentc6c93fdd3451cc0de393dad891d6b0be71e50888 (diff)
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.c57
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;