When the target lun is set to full provisioning, the kernel cannot perceive this change, so the kernel still thinks the device supports the discard feature. Discard will be disabled only after encountering a discard IO error (a fully provisioned logical unit does not support logical block provisioning management, so subsequent discard IO will fail) or reconnection. To fix this issue, we can disable device discard feature as soon as possible during the iSCSI initiator rescanning session. Specifically, we can reset lbpme bit 0 during the SCSI probe if found the target lun does not support lbpm, then adjust the discard mode to SD_LBP_DISABLE. With this patch, the kernel can sync whether the target lun supports logical block provisioning management after the iSCSI initiator rescanning session, without IO error or reconnection. Signed-off-by: Haoqian He <haoqian.he@xxxxxxxxxx> Signed-off-by: Li Feng <fengli@xxxxxxxxxx> --- drivers/scsi/sd.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 548c74ecc836..44a19945b5b6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2709,6 +2709,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, if (buffer[14] & 0x40) /* LBPRZ */ sdkp->lbprz = 1; + } else { + sdkp->lbpme = 0; + sdkp->lbprz = 0; } sdkp->capacity = lba + 1; @@ -3303,12 +3306,9 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) static unsigned int sd_discard_mode(struct scsi_disk *sdkp) { - if (!sdkp->lbpvpd) { - /* LBP VPD page not provided */ - if (sdkp->max_unmap_blocks) - return SD_LBP_UNMAP; - return SD_LBP_WS16; - } + if (!sdkp->lbpvpd) + /* Disable discard if LBP VPD page not provided */ + return SD_LBP_DISABLE; /* LBP VPD page tells us what to use */ if (sdkp->lbpu && sdkp->max_unmap_blocks) @@ -3343,8 +3343,12 @@ static void sd_read_block_limits(struct scsi_disk *sdkp, sdkp->max_ws_blocks = (u32)get_unaligned_be64(&vpd->data[36]); - if (!sdkp->lbpme) + if (!sdkp->lbpme) { + sdkp->max_unmap_blocks = 0; + sdkp->unmap_granularity = 0; + sdkp->unmap_alignment = 0; goto config_atomic; + } lba_count = get_unaligned_be32(&vpd->data[20]); desc_count = get_unaligned_be32(&vpd->data[24]); @@ -3425,8 +3429,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp) { struct scsi_vpd *vpd; - if (sdkp->lbpme == 0) + if (!sdkp->lbpme) { + sdkp->lbpvpd = 0; + sdkp->lbpu = 0; + sdkp->lbpws = 0; + sdkp->lbpws10 = 0; return; + } rcu_read_lock(); vpd = rcu_dereference(sdkp->device->vpd_pgb2); -- 2.44.0