This patch addresses an issue when 'writesame_16' provisioning mode could be incorrectly set for some storage devices that support logical block provisioning (LBPME=1) but with some other operation than 'writesame_16' specified in a VPD. Prior to this patch, the read_capacity_16() function used to set block provisioning mode to 'writesame_16' for all devices that have the LBPME bit enabled, without checking the logical provisioning VPD page for the correct command to be used. Setting the provisioning mode in the read_capacity_16() function seems unnecessary for multiple reasons: 1. the correct mode is then detected and set by the sd_read_block_provisioning() and sd_read_block_limits() functions 2. it can result in an incorrect provisioning mode to be enabled for some devices that use some other block provisioning mode than 'writesame_16'. Prior to applying this patch, my 5TB WD Black P10 USB external hard drive was detected to support TRIM (verified by lsblk -D). However, any TRIM attempt (fstrim, blkdiscard) resulted in I/O errors in dmesg, and the TRIM operation did not seem to unmap any blocks. The problem was that the kernel used 'writesame_16' even though the hard drive supported 'unmap' command instead. $ cat /sys/block/sdb/device/scsi_disk/6\:0\:0\:0/provisioning_mode writesame_16 $ sudo sg_vpd -a /dev/sdb Logical block provisioning VPD page (SBC): Unmap command supported (LBPU): 1 Write same (16) with unmap bit supported (LBPWS): 0 Write same (10) with unmap bit supported (LBPWS10): 0 The drive uses Bulk-Only USB interface instead of UASP. Because of it, read_capacity_10() is used first. But because the capacity of the drive is 5TB, read_capacity_16() is tried next. This function set the provisioning mode to 'writesame_16' since the drive reports LBPME=1. But because the drive is connected via USB, the VPD page is ignored (skip_vpd_pages is set to true in scsiglue.c), the correct provisioning mode (unmap) is never set, and an incorrect provisioning mode (writesame_16) was kept instead. This was not an issue on my internal SSD which supports 'writesame_16' discard command. In that case, read_capacity_16() set the discard mode to 'writesame_16' (which happened to be the correct one in this case), and shortly after that, sd_read_block_provisioning() and sd_read_block_limits() set the discard mode to 'writesame_16' again. After applying this patch, my USB hard drive is treated as if it didn't support the discard operation (because VPD is not checked in the case of a USB device that does not support UASP). This is better than issuing invalid commands to the device. $ cat /sys/block/sdb/device/scsi_disk/*/provisioning_mode full Signed-off-by: David Sebek <dasebek@xxxxxxxxx> --- drivers/scsi/sd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cb3c37d1e009..2ad4abc1cbc2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2416,8 +2416,6 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, if (buffer[14] & 0x40) /* LBPRZ */ sdkp->lbprz = 1; - - sd_config_discard(sdkp, SD_LBP_WS16); } sdkp->capacity = lba + 1; -- 2.31.1