]> git.hungrycats.org Git - linux/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)
committerBen Hutchings <ben@decadent.org.uk>
Mon, 1 Jan 2018 20:50:55 +0000 (20:50 +0000)
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>
[bwh: Backported to 3.2:
 - Keep using literals for SD_MAX_WS{16,10}_BLOCKS
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
include/scsi/scsi_device.h
include/scsi/scsi_devinfo.h

index 5d207f1aca7a43112af73198f28e722474c275e5..8d640eb8b287a17ad48452837a20bed6539d0296 100644 (file)
@@ -957,6 +957,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
        if (*bflags & BLIST_RETRY_HWERROR)
                sdev->retry_hwerror = 1;
 
+       if (*bflags & BLIST_UNMAP_LIMIT_WS)
+               sdev->unmap_limit_for_ws = 1;
+
        transport_configure_device(&sdev->sdev_gendev);
 
        if (sdev->host->hostt->slave_configure) {
index 6cbe2eb5326d08f7490fe6ddcb6227f62f46436a..ff16bc3057cd76414c512ccaf80741514a80b0e4 100644 (file)
@@ -523,11 +523,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, 0xffffffff);
+               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, 0xffffffff);
                break;
 
        case SD_LBP_WS10:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               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)0xffff);
                break;
 
        case SD_LBP_ZERO:
index 377ba61cf22915a712112fe4f770106bd439592b..4f768ae2185f9f93234531bc71cbe0d995b523de 100644 (file)
@@ -152,6 +152,7 @@ struct scsi_device {
        unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
        unsigned is_visible:1;  /* is the device visible in sysfs */
        unsigned broken_fua:1;          /* Don't set FUA bit */
+       unsigned unmap_limit_for_ws:1;  /* Use the UNMAP limit for WRITE SAME */
 
        DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
        struct list_head event_list;    /* asserted events */
index b4ddd3b18b4c1619fb7c7d9b4c484ed0bca89b2b..f25ba760c22306bd997a2d7dbc4d25a39a38a28d 100644 (file)
@@ -30,4 +30,5 @@
 #define BLIST_RETRY_HWERROR    0x400000 /* retry HARDWARE_ERROR */
 #define BLIST_MAX_512          0x800000 /* maximum 512 sector cdb length */
 #define BLIST_ATTACH_PQ3       0x1000000 /* Scan: Attach to PQ3 devices */
+#define BLIST_UNMAP_LIMIT_WS   0x80000000 /* Use UNMAP limit for WRITE SAME */
 #endif