Re: [PATCH] sd: Limit transfer length

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2014-06-02 at 15:11 -0400, Martin K. Petersen wrote:
> 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@xxxxxxxxxx>
> 
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 321faf603035..56018f37518d 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -2228,7 +2228,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)
> @@ -2540,6 +2544,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 ||
> @@ -2547,6 +2552,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,
> @@ -2702,6 +2711,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
>  	struct scsi_device *sdp = sdkp->device;
>  	unsigned char *buffer;
>  	unsigned flush = 0;
> +	unsigned int max_xfer;
>  
>  	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
>  				      "sd_revalidate_disk\n"));
> @@ -2755,6 +2765,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
>  
>  	blk_queue_flush(sdkp->disk->queue, flush);
>  
> +	max_xfer = min_not_zero((unsigned int)sdp->host->max_sectors,
> +				(unsigned int)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);
> diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
> index 620871efbf0a..4c3ab8377fd3 100644
> --- a/drivers/scsi/sd.h
> +++ b/drivers/scsi/sd.h
> @@ -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;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Looks good.

Reviewed-by: Ewan D. Milne <emilne@xxxxxxxxxx>


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux