linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] [SCSI] sd: workaround invalid OPTIMAL TRANSFER LENGTH
@ 2013-04-03 20:21 Mike Snitzer
  2013-04-03 20:38 ` Ewan Milne
  2013-04-25  1:19 ` Martin K. Petersen
  0 siblings, 2 replies; 4+ messages in thread
From: Mike Snitzer @ 2013-04-03 20:21 UTC (permalink / raw)
  To: linux-scsi; +Cc: Martin K. Petersen

Workaround disk firmware that improperly sets OPTIMAL TRANSFER LENGTH to
0xFFFFFFFF (aka UINT_MAX or 4294967295U) by assuming this _optional_
BLOCK LIMITS VPD field was not specified (0).

It should be noted that a disk firmware fix is being developed but that
these disks are already in the wild (and when optimal_io_size is so
large it prevents standard Linux distribution installers, e.g. Anaconda,
from creating partitions smaller than 4GB via libparted due to parted
looking to align the created partitions relative to optimal_io_size).

The disk model in this instance is "SEAGATE ST900MM0006".  The BLOCK
LIMITS VPD page for this disk is:
# sg_inq --vpd --page=0xb0 /dev/sdb
VPD INQUIRY: Block limits page (SBC)
  Optimal transfer length granularity: 1 blocks
  Maximum transfer length: 0 blocks
  Optimal transfer length: 4294967295 blocks
  Maximum prefetch, xdread, xdwrite transfer length: 0 blocks
  Maximum unmap LBA count: 0
  Maximum unmap block descriptor count: 0
  Optimal unmap granularity: 0
  Unmap granularity alignment valid: 0
  Unmap granularity alignment: 0

Before this fix:
# cat /sys/block/sdb/queue/optimal_io_size
4294966784

After this fix:
# cat /sys/block/sdb/queue/optimal_io_size
0

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/scsi/sd.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7992635..34638c1 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2516,6 +2516,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
+	unsigned int optimal_transfer_length;
 	unsigned int sector_sz = sdkp->device->sector_size;
 	const int vpd_len = 64;
 	unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
@@ -2527,8 +2528,11 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 
 	blk_queue_io_min(sdkp->disk->queue,
 			 get_unaligned_be16(&buffer[6]) * sector_sz);
+	optimal_transfer_length = get_unaligned_be32(&buffer[12]);
+	if (optimal_transfer_length == UINT_MAX)
+		optimal_transfer_length = 0; /* firmware bug, use 0 instead */
 	blk_queue_io_opt(sdkp->disk->queue,
-			 get_unaligned_be32(&buffer[12]) * sector_sz);
+			 optimal_transfer_length * sector_sz);
 
 	if (buffer[3] == 0x3c) {
 		unsigned int lba_count, desc_count;

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-04-25  1:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-03 20:21 [PATCH] [SCSI] sd: workaround invalid OPTIMAL TRANSFER LENGTH Mike Snitzer
2013-04-03 20:38 ` Ewan Milne
2013-04-25  1:19 ` Martin K. Petersen
2013-04-25  1:44   ` Mike Snitzer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).