Skip to content

Commit bcdb247

Browse files
martinkpetersenChristoph Hellwig
authored andcommitted
sd: Limit transfer length
Until now the per-command transfer length has exclusively been gated by the max_sectors parameter in the scsi_host template. Given that the size of this parameter has been bumped to an unsigned int we have to be careful not to exceed the target device's capabilities. If the if the device specifies a Maximum Transfer Length in the Block Limits VPD we'll use that value. Otherwise we'll use 0xffffffff for devices that have use_16_for_rw set and 0xffff for the rest. We then combine the chosen disk limit with max_sectors in the host template. The smaller of the two will be used to set the max_hw_sectors queue limit. Signed-off-by: Martin K. Petersen <[email protected]> Reviewed-by: Ewan D. Milne <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 8d96447 commit bcdb247

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

drivers/scsi/sd.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2236,7 +2236,11 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
22362236
}
22372237
}
22382238

2239-
sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
2239+
if (sdkp->capacity > 0xffffffff) {
2240+
sdp->use_16_for_rw = 1;
2241+
sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
2242+
} else
2243+
sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
22402244

22412245
/* Rescale capacity to 512-byte units */
22422246
if (sector_size == 4096)
@@ -2551,13 +2555,18 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
25512555
{
25522556
unsigned int sector_sz = sdkp->device->sector_size;
25532557
const int vpd_len = 64;
2558+
u32 max_xfer_length;
25542559
unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
25552560

25562561
if (!buffer ||
25572562
/* Block Limits VPD */
25582563
scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
25592564
goto out;
25602565

2566+
max_xfer_length = get_unaligned_be32(&buffer[8]);
2567+
if (max_xfer_length)
2568+
sdkp->max_xfer_blocks = max_xfer_length;
2569+
25612570
blk_queue_io_min(sdkp->disk->queue,
25622571
get_unaligned_be16(&buffer[6]) * sector_sz);
25632572
blk_queue_io_opt(sdkp->disk->queue,
@@ -2712,6 +2721,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
27122721
struct scsi_disk *sdkp = scsi_disk(disk);
27132722
struct scsi_device *sdp = sdkp->device;
27142723
unsigned char *buffer;
2724+
unsigned int max_xfer;
27152725

27162726
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
27172727
"sd_revalidate_disk\n"));
@@ -2759,6 +2769,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
27592769
*/
27602770
sd_set_flush_flag(sdkp);
27612771

2772+
max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
2773+
sdkp->max_xfer_blocks);
2774+
max_xfer <<= ilog2(sdp->sector_size) - 9;
2775+
blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
27622776
set_capacity(disk, sdkp->capacity);
27632777
sd_config_write_same(sdkp);
27642778
kfree(buffer);

drivers/scsi/sd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ enum {
4444
};
4545

4646
enum {
47+
SD_DEF_XFER_BLOCKS = 0xffff,
48+
SD_MAX_XFER_BLOCKS = 0xffffffff,
4749
SD_MAX_WS10_BLOCKS = 0xffff,
4850
SD_MAX_WS16_BLOCKS = 0x7fffff,
4951
};
@@ -64,6 +66,7 @@ struct scsi_disk {
6466
struct gendisk *disk;
6567
atomic_t openers;
6668
sector_t capacity; /* size in 512-byte sectors */
69+
u32 max_xfer_blocks;
6770
u32 max_ws_blocks;
6871
u32 max_unmap_blocks;
6972
u32 unmap_granularity;

0 commit comments

Comments
 (0)