Skip to content

Commit

Permalink
scsi: sd: Implement blacklist option for WRITE SAME w/ UNMAP
Browse files Browse the repository at this point in the history
SBC-4 states:

  "A MAXIMUM UNMAP LBA COUNT field set to a non-zero value indicates the
   maximum number of LBAs that may be unmapped by an UNMAP command"

  "A MAXIMUM WRITE SAME LENGTH field set to a non-zero value indicates
   the maximum number of contiguous logical blocks that the device server
   allows to be unmapped or written in a single WRITE SAME command."

Despite the spec being clear on the topic, some devices incorrectly
expect WRITE SAME commands with the UNMAP bit set to be limited to the
value reported in MAXIMUM UNMAP LBA COUNT in the Block Limits VPD.

Implement a blacklist option that can be used to accommodate devices
with this behavior.

Cc: <[email protected]>
Reported-by: Bill Kuzeja <[email protected]>
Reported-by: Ewan D. Milne <[email protected]>
Reviewed-by: Ewan D. Milne <[email protected]>
Tested-by: Laurence Oberman <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
martinkpetersen committed Oct 3, 2017
1 parent d0b7a90 commit 28a0bc4
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 4 deletions.
3 changes: 3 additions & 0 deletions drivers/scsi/scsi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
if (*bflags & BLIST_NO_DIF)
sdev->no_dif = 1;

if (*bflags & BLIST_UNMAP_LIMIT_WS)
sdev->unmap_limit_for_ws = 1;

sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT;

if (*bflags & BLIST_TRY_VPD_PAGES)
Expand Down
16 changes: 12 additions & 4 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,13 +715,21 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
break;

case SD_LBP_WS16:
max_blocks = min_not_zero(sdkp->max_ws_blocks,
(u32)SD_MAX_WS16_BLOCKS);
if (sdkp->device->unmap_limit_for_ws)
max_blocks = sdkp->max_unmap_blocks;
else
max_blocks = sdkp->max_ws_blocks;

max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS);
break;

case SD_LBP_WS10:
max_blocks = min_not_zero(sdkp->max_ws_blocks,
(u32)SD_MAX_WS10_BLOCKS);
if (sdkp->device->unmap_limit_for_ws)
max_blocks = sdkp->max_unmap_blocks;
else
max_blocks = sdkp->max_ws_blocks;

max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS);
break;

case SD_LBP_ZERO:
Expand Down
1 change: 1 addition & 0 deletions include/scsi/scsi_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct scsi_device {
unsigned no_dif:1; /* T10 PI (DIF) should be disabled */
unsigned broken_fua:1; /* Don't set FUA bit */
unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */
unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */

atomic_t disk_events_disable_depth; /* disable depth for disk events */

Expand Down
1 change: 1 addition & 0 deletions include/scsi/scsi_devinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
#define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */
#define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */
#define BLIST_MAX_1024 0x40000000 /* maximum 1024 sector cdb length */
#define BLIST_UNMAP_LIMIT_WS 0x80000000 /* Use UNMAP limit for WRITE SAME */

#endif

0 comments on commit 28a0bc4

Please sign in to comment.