diff mbox series

[1/3] scsi: sd: disable discard when set target full provisioning

Message ID 20240702030118.2198570-2-haoqian.he@smartx.com (mailing list archive)
State Changes Requested
Headers show
Series scsi: disable discard when set target full provisioning | expand

Commit Message

Haoqian He July 2, 2024, 3:01 a.m. UTC
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@smartx.com>
Signed-off-by: Li Feng <fengli@smartx.com>
---
 drivers/scsi/sd.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

Comments

Martin K. Petersen July 3, 2024, 2:31 a.m. UTC | #1
Haoqian,

> +	if (!sdkp->lbpvpd)
> +		/* Disable discard if LBP VPD page not provided */
> +		return SD_LBP_DISABLE;

That is not a valid assumption. Many devices which support thin
provisioning either predate the LBP VPD being defined or have decided
not to support that page. The current heuristics are very deliberate.
diff mbox series

Patch

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);