]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: sd: Implement blacklist option for WRITE SAME w/ UNMAP
authorMartin K. Petersen <martin.petersen@oracle.com>
Thu, 28 Sep 2017 01:35:12 +0000 (21:35 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Oct 2017 09:56:18 +0000 (11:56 +0200)
commit 28a0bc4120d38a394499382ba21d6965a67a3703 upstream.

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.

Reported-by: Bill Kuzeja <William.Kuzeja@stratus.com>
Reported-by: Ewan D. Milne <emilne@redhat.com>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Tested-by: Laurence Oberman <loberman@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
include/scsi/scsi_device.h
include/scsi/scsi_devinfo.h

index fd88dabd599d4d2f24d3bebf78c2b9ea9baa2e89..9f1d53e1895635546237c799ad8a32c45bee1d70 100644 (file)
@@ -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)
index e2647f2d44304b0ded65ebb0f55d629c7289d0b7..67e2d11c592a0b0b367b3e7ca46e773449322bdd 100644 (file)
@@ -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:
index 0979a5f3b69a30ce384db82728fb28ad6a136a6d..6ff1bab23679df74c50db7daab77b56707d6b3e1 100644 (file)
@@ -182,6 +182,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 */
 
index 9592570e092a3bba93065d6e66a21665f8bd52ae..36b03013d6291cf9fda3c99eec690d3841f0ca5e 100644 (file)
@@ -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