Re: [RFC PATCH 2/8] scsi: add REQ_OP_VERIFY support
From: Damien Le Moal <hidden>
Date: 2021-11-04 12:33:14
Also in:
dm-devel, linux-fsdevel, linux-nvme, linux-raid, linux-scsi, linux-xfs, target-devel
On 2021/11/04 15:46, Chaitanya Kulkarni wrote:
quoted hunk ↗ jump to hunk
From: Chaitanya Kulkarni <kch@nvidia.com> Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com> --- drivers/scsi/sd.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/sd.h | 1 + 2 files changed, 53 insertions(+)diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a3d2d4bc4a3d..7f2c4eb98cf8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c@@ -106,6 +106,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC); static void sd_config_discard(struct scsi_disk *, unsigned int); static void sd_config_write_same(struct scsi_disk *); +static void sd_config_verify(struct scsi_disk *sdkp); static int sd_revalidate_disk(struct gendisk *); static void sd_unlock_native_capacity(struct gendisk *disk); static int sd_probe(struct device *);@@ -995,6 +996,41 @@ static blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd) return sd_setup_write_same10_cmnd(cmd, false); } +static void sd_config_verify(struct scsi_disk *sdkp) +{ + struct request_queue *q = sdkp->disk->queue; + + /* XXX: use same pattern as sd_config_write_same(). */ + blk_queue_max_verify_sectors(q, UINT_MAX >> 9);
VERIFY 10, 12, 16 and 32 commands are optional and may not be implemented by a device. So setting this unconditionally is wrong. At the very least you must have an "if (sdkp->verify_16)" here, and call "blk_queue_max_verify_sectors(q, 0);" if the device does not support verify.
+}
+
+static blk_status_t sd_setup_verify_cmnd(struct scsi_cmnd *cmd)
+{
+ struct request *rq = cmd->request;
+ struct scsi_device *sdp = cmd->device;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
+ u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
+
+ if (!sdkp->verify_16)
+ return BLK_STS_NOTSUPP;I think this should be "return BLK_STS_TARGET;"
+ + cmd->cmd_len = 16; + cmd->cmnd[0] = VERIFY_16;
And what if the device supports VERIFY 10 or 12 but not VERIFY 16 ?
quoted hunk ↗ jump to hunk
+ /* skip veprotect / dpo / bytchk */ + cmd->cmnd[1] = 0; + put_unaligned_be64(lba, &cmd->cmnd[2]); + put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); + cmd->cmnd[14] = 0; + cmd->cmnd[15] = 0; + + cmd->allowed = SD_MAX_RETRIES; + cmd->sc_data_direction = DMA_NONE; + cmd->transfersize = 0; + + return BLK_STS_OK; +} + static void sd_config_write_same(struct scsi_disk *sdkp) { struct request_queue *q = sdkp->disk->queue;@@ -1345,6 +1381,8 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd) } case REQ_OP_WRITE_ZEROES: return sd_setup_write_zeroes_cmnd(cmd); + case REQ_OP_VERIFY: + return sd_setup_verify_cmnd(cmd); case REQ_OP_WRITE_SAME: return sd_setup_write_same_cmnd(cmd); case REQ_OP_FLUSH:@@ -2029,6 +2067,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) switch (req_op(req)) { case REQ_OP_DISCARD: case REQ_OP_WRITE_ZEROES: + case REQ_OP_VERIFY: case REQ_OP_WRITE_SAME: case REQ_OP_ZONE_RESET: case REQ_OP_ZONE_RESET_ALL:@@ -3096,6 +3135,17 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) sdkp->ws10 = 1; } +static void sd_read_verify(struct scsi_disk *sdkp, unsigned char *buffer) +{ + struct scsi_device *sdev = sdkp->device; + + sd_printk(KERN_INFO, sdkp, "VERIFY16 check.\n");
Remove this message please.
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, VERIFY_16) == 1) {
+ sd_printk(KERN_INFO, sdkp, " VERIFY16 in ON .\n");And this one too.
+ sdkp->verify_16 = 1;
Why not checking for VERIFY 10 and 12 if VERIFY 16 is not supported ? Also, why don't you call "blk_queue_max_verify_sectors(q, UINT_MAX >> 9);" here instead of adding the not so useful sd_config_verify() helper ?
quoted hunk ↗ jump to hunk
+ } +} + static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) { struct scsi_device *sdev = sdkp->device;@@ -3224,6 +3274,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); sd_read_write_same(sdkp, buffer); + sd_read_verify(sdkp, buffer); sd_read_security(sdkp, buffer); }@@ -3265,6 +3316,7 @@ static int sd_revalidate_disk(struct gendisk *disk) set_capacity_and_notify(disk, logical_to_sectors(sdp, sdkp->capacity)); sd_config_write_same(sdkp); + sd_config_verify(sdkp); kfree(buffer); /*diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index b59136c4125b..94a86bf6dac4 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h@@ -120,6 +120,7 @@ struct scsi_disk { unsigned lbpvpd : 1; unsigned ws10 : 1; unsigned ws16 : 1; + unsigned verify_16 : 1;
See right above this line how write same supports the 10 and 16 variants. I think you need the same here. And very likely, you also need the 32 version in case the device has DIF/DIX (type 2 protection).
unsigned rc_basis: 2; unsigned zoned: 2; unsigned urswrz : 1;
-- Damien Le Moal Western Digital Research