sd: Limit transfer length
authorMartin K. Petersen <martin.petersen@oracle.com>
Tue, 3 Jun 2014 22:45:51 +0000 (18:45 -0400)
committerChristoph Hellwig <hch@lst.de>
Thu, 17 Jul 2014 20:07:33 +0000 (22:07 +0200)
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 <martin.petersen@oracle.com>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/sd.c
drivers/scsi/sd.h

index 5167b96782409d63599057175bc497b7ae82da90..87566b51fcf7bdd269b7dbf626cda570599b0ca1 100644 (file)
@@ -2236,7 +2236,11 @@ got_data:
                }
        }
 
-       sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
+       if (sdkp->capacity > 0xffffffff) {
+               sdp->use_16_for_rw = 1;
+               sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
+       } else
+               sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
 
        /* Rescale capacity to 512-byte units */
        if (sector_size == 4096)
@@ -2551,6 +2555,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
        unsigned int sector_sz = sdkp->device->sector_size;
        const int vpd_len = 64;
+       u32 max_xfer_length;
        unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
 
        if (!buffer ||
@@ -2558,6 +2563,10 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
            scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
                goto out;
 
+       max_xfer_length = get_unaligned_be32(&buffer[8]);
+       if (max_xfer_length)
+               sdkp->max_xfer_blocks = max_xfer_length;
+
        blk_queue_io_min(sdkp->disk->queue,
                         get_unaligned_be16(&buffer[6]) * sector_sz);
        blk_queue_io_opt(sdkp->disk->queue,
@@ -2712,6 +2721,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        struct scsi_disk *sdkp = scsi_disk(disk);
        struct scsi_device *sdp = sdkp->device;
        unsigned char *buffer;
+       unsigned int max_xfer;
 
        SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
                                      "sd_revalidate_disk\n"));
@@ -2759,6 +2769,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
         */
        sd_set_flush_flag(sdkp);
 
+       max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
+                               sdkp->max_xfer_blocks);
+       max_xfer <<= ilog2(sdp->sector_size) - 9;
+       blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
        set_capacity(disk, sdkp->capacity);
        sd_config_write_same(sdkp);
        kfree(buffer);
index 620871efbf0a38e4cb496ef80b16c7bf1c9d1f5a..4c3ab8377fd3fe9a9ab749f873e69f8948525a98 100644 (file)
@@ -44,6 +44,8 @@ enum {
 };
 
 enum {
+       SD_DEF_XFER_BLOCKS = 0xffff,
+       SD_MAX_XFER_BLOCKS = 0xffffffff,
        SD_MAX_WS10_BLOCKS = 0xffff,
        SD_MAX_WS16_BLOCKS = 0x7fffff,
 };
@@ -64,6 +66,7 @@ struct scsi_disk {
        struct gendisk  *disk;
        atomic_t        openers;
        sector_t        capacity;       /* size in 512-byte sectors */
+       u32             max_xfer_blocks;
        u32             max_ws_blocks;
        u32             max_unmap_blocks;
        u32             unmap_granularity;