[RFC PATCH 2/8] scsi: add REQ_OP_VERIFY support
Chaitanya Kulkarni
chaitanyak at nvidia.com
Thu Nov 11 00:07:39 PST 2021
On 11/4/2021 5:33 AM, Damien Le Moal wrote:
> External email: Use caution opening links or attachments
>
>
> On 2021/11/04 15:46, Chaitanya Kulkarni wrote:
>> From: Chaitanya Kulkarni <kch at nvidia.com>
>>
>> Signed-off-by: Chaitanya Kulkarni <kch at 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.
>
Yes, I put it together for the RFC, this needs to consider the device
unsupported case just like what we do for write zeroes and emulate the
same.
>> +}
>> +
>> +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 ?
For first implementation we can only VERIFY 16, later we can add cases
for VERIFY 10-12 versions.
>
>> + /* 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 ?
>
Okay, let me see if I can add that in V1.
>> + }
>> +}
>> +
>> 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).
>
Agree with write same 10/16 versions, let me see if I can add that for V1.
>> unsigned rc_basis: 2;
>> unsigned zoned: 2;
>> unsigned urswrz : 1;
>>
>
>
> --
> Damien Le Moal
> Western Digital Research
>
Thanks for the comments Damien.
More information about the Linux-nvme
mailing list