diff mbox series

[RFC,2/8] scsi: add REQ_OP_VERIFY support

Message ID 20211104064634.4481-3-chaitanyak@nvidia.com (mailing list archive)
State Deferred, archived
Headers show
Series block: add support for REQ_OP_VERIFY | expand

Commit Message

Chaitanya Kulkarni Nov. 4, 2021, 6:46 a.m. UTC
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(+)

Comments

Damien Le Moal Nov. 4, 2021, 12:33 p.m. UTC | #1
On 2021/11/04 15:46, Chaitanya Kulkarni wrote:
> 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 ?

> +       /* 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 ?

> +       }
> +}
> +
>  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;
>
Chaitanya Kulkarni Nov. 11, 2021, 8:07 a.m. UTC | #2
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@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.
> 

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.
diff mbox series

Patch

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);
+}
+
+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;
+
+       cmd->cmd_len = 16;
+       cmd->cmnd[0] = VERIFY_16;
+       /* 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");
+       if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, VERIFY_16) == 1) {
+	       sd_printk(KERN_INFO, sdkp, " VERIFY16 in ON .\n");
+               sdkp->verify_16 = 1;
+       }
+}
+
 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;
 	unsigned	rc_basis: 2;
 	unsigned	zoned: 2;
 	unsigned	urswrz : 1;