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>
This commit is contained in:
parent
c6c93fdd34
commit
ec029758a1
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user