[PATCH 2/3] block/sd: Fix device-imposed transfer length limits

2015-11-13 Thread Martin K. Petersen
Commit 4f258a46346c ("sd: Fix maximum I/O size for BLOCK_PC requests")
had the unfortunate side-effect of removing an implicit clamp to
BLK_DEF_MAX_SECTORS for REQ_TYPE_FS requests in the block layer
code. This caused problems for some SMR drives.

Debugging this issue revealed a few problems with the existing
infrastructure since the block layer didn't know how to deal with
device-imposed limits, only limits set by the I/O controller.

 - Introduce a new queue limit, max_dev_sectors, which is used by the
   ULD to signal the maximum sectors for a REQ_TYPE_FS request.

 - Ensure that max_dev_sectors is correctly stacked and taken into
   account when overriding max_sectors through sysfs.

 - Rework sd_read_block_limits() so it saves the max_xfer and opt_xfer
   values for later processing.

 - In sd_revalidate() set the queue's max_dev_sectors based on the
   MAXIMUM TRANSFER LENGTH value in the Block Limits VPD. If this value
   is not reported, fall back to a cap based on the CDB TRANSFER LENGTH
   field size.

 - In sd_revalidate(), use OPTIMAL TRANSFER LENGTH from the Block Limits
   VPD--if reported and sane--to signal the preferred device transfer
   size for FS requests. Otherwise use BLK_DEF_MAX_SECTORS.

 - blk_limits_max_hw_sectors() is no longer used and can be removed.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=93581
Signed-off-by: Martin K. Petersen 
---
 block/blk-settings.c   | 36 
 block/blk-sysfs.c  |  3 +++
 drivers/scsi/sd.c  | 46 ++
 drivers/scsi/sd.h  |  1 +
 include/linux/blkdev.h |  2 +-
 5 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/block/blk-settings.c b/block/blk-settings.c
index 7d8f129a1516..dd4973583978 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -91,7 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
lim->virt_boundary_mask = 0;
lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
-   lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
+   lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors =
+   BLK_SAFE_MAX_SECTORS;
lim->chunk_sectors = 0;
lim->max_write_same_sectors = 0;
lim->max_discard_sectors = 0;
@@ -127,6 +128,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_hw_sectors = UINT_MAX;
lim->max_segment_size = UINT_MAX;
lim->max_sectors = UINT_MAX;
+   lim->max_dev_sectors = UINT_MAX;
lim->max_write_same_sectors = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_set_stacking_limits);
@@ -214,8 +216,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 
max_addr)
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 
 /**
- * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for 
request
- * @limits: the queue limits
+ * blk_queue_max_hw_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  *
  * Description:
@@ -224,13 +226,19 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *the device driver based upon the capabilities of the I/O
  *controller.
  *
+ *max_dev_sectors is a hard limit imposed by the storage device for
+ *READ/WRITE requests. It is set by the disk driver.
+ *
  *max_sectors is a soft limit imposed by the block layer for
  *filesystem type requests.  This value can be overridden on a
  *per-device basis in /sys/block//queue/max_sectors_kb.
  *The soft limit can not exceed max_hw_sectors.
  **/
-void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int 
max_hw_sectors)
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int 
max_hw_sectors)
 {
+   struct queue_limits *limits = &q->limits;
+   unsigned int max_sectors;
+
if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
printk(KERN_INFO "%s: set to minimum %d\n",
@@ -238,22 +246,9 @@ void blk_limits_max_hw_sectors(struct queue_limits 
*limits, unsigned int max_hw_
}
 
limits->max_hw_sectors = max_hw_sectors;
-   limits->max_sectors = min_t(unsigned int, max_hw_sectors,
-   BLK_DEF_MAX_SECTORS);
-}
-EXPORT_SYMBOL(blk_limits_max_hw_sectors);
-
-/**
- * blk_queue_max_hw_sectors - set max sectors for a request for this queue
- * @q:  the request queue for the device
- * @max_hw_sectors:  max hardware sectors in the usual 512b unit
- *
- * Description:
- *See description for blk_limits_max_hw_sectors().
- **/
-void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int 
max_hw_sectors)
-{
-   blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
+   max_sectors = min_not_zero(max_hw_sectors, limits->max_dev_sectors);
+   max_sectors = min_t(unsigned int, max_

Re: [PATCH 2/3] block/sd: Fix device-imposed transfer length limits

2015-11-19 Thread Christoph Hellwig
>  - blk_limits_max_hw_sectors() is no longer used and can be removed.

Killing that first in a separate patch would have been a tad cleaner.

Otherwise looks fine,

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