[PATCH 2/2] virtio-blk: support BLKSECDISCARD

yadong.qi@intel.com posted 2 patches 4 years, 2 months ago
Maintainers: Fam Zheng <fam@euphon.net>, "Michael S. Tsirkin" <mst@redhat.com>, Ari Sundholm <ari@tuxera.com>, Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>, Stefan Hajnoczi <stefanha@redhat.com>, Eric Blake <eblake@redhat.com>, Klaus Jensen <its@irrelevant.dk>, Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>, "Philippe Mathieu-Daudé" <philmd@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>, John Snow <jsnow@redhat.com>, Keith Busch <kbusch@kernel.org>, Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
[PATCH 2/2] virtio-blk: support BLKSECDISCARD
Posted by yadong.qi@intel.com 4 years, 2 months ago
From: Yadong Qi <yadong.qi@intel.com>

Add new virtio feature: VIRTIO_BLK_F_SECDISCARD.
Add new virtio command: VIRTIO_BLK_T_SECDISCARD.

This feature is disabled by default, it will check the backend
bs->open_flags & BDRV_O_SECDISCARD, enable it if BDRV_O_SECDISCARD
is supported.

Signed-off-by: Yadong Qi <yadong.qi@intel.com>
---
 hw/block/virtio-blk.c                       | 26 +++++++++++++++++----
 include/standard-headers/linux/virtio_blk.h |  4 ++++
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index dbc4c5a3cd..7bc3484521 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -536,7 +536,8 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
 }
 
 static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
-    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
+    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes,
+    bool is_secdiscard)
 {
     VirtIOBlock *s = req->dev;
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
@@ -577,8 +578,8 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
         goto err;
     }
 
+    int blk_aio_flags = 0;
     if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
-        int blk_aio_flags = 0;
 
         if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
             blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
@@ -600,7 +601,12 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
             goto err;
         }
 
-        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes, 0,
+        if (is_secdiscard) {
+            blk_aio_flags |= BDRV_REQ_SECDISCARD;
+        }
+
+        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
+                         blk_aio_flags,
                          virtio_blk_discard_write_zeroes_complete, req);
     }
 
@@ -622,6 +628,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
     unsigned out_num = req->elem.out_num;
     VirtIOBlock *s = req->dev;
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    bool is_secdiscard = false;
 
     if (req->elem.out_num < 1 || req->elem.in_num < 1) {
         virtio_error(vdev, "virtio-blk missing headers");
@@ -722,6 +729,9 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
      * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
      * so we must mask it for these requests, then we will check if it is set.
      */
+    case VIRTIO_BLK_T_SECDISCARD & ~VIRTIO_BLK_T_OUT:
+        is_secdiscard = true;
+        __attribute__((fallthrough));
     case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
     case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
     {
@@ -752,7 +762,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
         }
 
         err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
-                                                            is_write_zeroes);
+                                                            is_write_zeroes,
+                                                            is_secdiscard);
         if (err_status != VIRTIO_BLK_S_OK) {
             virtio_blk_req_complete(req, err_status);
             virtio_blk_free_request(req);
@@ -1201,6 +1212,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (blk_get_flags(conf->conf.blk) & BDRV_O_SECDISCARD)
+        virtio_add_feature(&s->host_features, VIRTIO_BLK_F_SECDISCARD);
+    else
+        virtio_clear_feature(&s->host_features, VIRTIO_BLK_F_SECDISCARD);
+
     if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES) &&
         (!conf->max_write_zeroes_sectors ||
          conf->max_write_zeroes_sectors > BDRV_REQUEST_MAX_SECTORS)) {
@@ -1307,6 +1323,8 @@ static Property virtio_blk_properties[] = {
                      conf.report_discard_granularity, true),
     DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
                       VIRTIO_BLK_F_WRITE_ZEROES, true),
+    DEFINE_PROP_BIT64("secdiscard", VirtIOBlock, host_features,
+                      VIRTIO_BLK_F_SECDISCARD, false),
     DEFINE_PROP_UINT32("max-discard-sectors", VirtIOBlock,
                        conf.max_discard_sectors, BDRV_REQUEST_MAX_SECTORS),
     DEFINE_PROP_UINT32("max-write-zeroes-sectors", VirtIOBlock,
diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
index 2dcc90826a..c55a07840c 100644
--- a/include/standard-headers/linux/virtio_blk.h
+++ b/include/standard-headers/linux/virtio_blk.h
@@ -40,6 +40,7 @@
 #define VIRTIO_BLK_F_MQ		12	/* support more than one vq */
 #define VIRTIO_BLK_F_DISCARD	13	/* DISCARD is supported */
 #define VIRTIO_BLK_F_WRITE_ZEROES	14	/* WRITE ZEROES is supported */
+#define VIRTIO_BLK_F_SECDISCARD	15	/* WRITE ZEROES is supported */
 
 /* Legacy feature bits */
 #ifndef VIRTIO_BLK_NO_LEGACY
@@ -153,6 +154,9 @@ struct virtio_blk_config {
 /* Write zeroes command */
 #define VIRTIO_BLK_T_WRITE_ZEROES	13
 
+/* Secure discard command */
+#define VIRTIO_BLK_T_SECDISCARD	14
+
 #ifndef VIRTIO_BLK_NO_LEGACY
 /* Barrier before this op. */
 #define VIRTIO_BLK_T_BARRIER	0x80000000
-- 
2.25.1


Re: [PATCH 2/2] virtio-blk: support BLKSECDISCARD
Posted by Michael S. Tsirkin 4 years, 2 months ago
On Mon, Nov 15, 2021 at 12:52:00PM +0800, yadong.qi@intel.com wrote:
> From: Yadong Qi <yadong.qi@intel.com>
> 
> Add new virtio feature: VIRTIO_BLK_F_SECDISCARD.
> Add new virtio command: VIRTIO_BLK_T_SECDISCARD.
> 
> This feature is disabled by default, it will check the backend
> bs->open_flags & BDRV_O_SECDISCARD, enable it if BDRV_O_SECDISCARD
> is supported.
> 
> Signed-off-by: Yadong Qi <yadong.qi@intel.com>
> ---
>  hw/block/virtio-blk.c                       | 26 +++++++++++++++++----
>  include/standard-headers/linux/virtio_blk.h |  4 ++++


Any changes to standard headers need to go to linux and virtio TC.

>  2 files changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index dbc4c5a3cd..7bc3484521 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -536,7 +536,8 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
>  }
>  
>  static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
> -    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
> +    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes,
> +    bool is_secdiscard)
>  {
>      VirtIOBlock *s = req->dev;
>      VirtIODevice *vdev = VIRTIO_DEVICE(s);
> @@ -577,8 +578,8 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
>          goto err;
>      }
>  
> +    int blk_aio_flags = 0;
>      if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
> -        int blk_aio_flags = 0;
>  
>          if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
>              blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
> @@ -600,7 +601,12 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
>              goto err;
>          }
>  
> -        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes, 0,
> +        if (is_secdiscard) {
> +            blk_aio_flags |= BDRV_REQ_SECDISCARD;
> +        }
> +
> +        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
> +                         blk_aio_flags,
>                           virtio_blk_discard_write_zeroes_complete, req);
>      }
>  
> @@ -622,6 +628,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
>      unsigned out_num = req->elem.out_num;
>      VirtIOBlock *s = req->dev;
>      VirtIODevice *vdev = VIRTIO_DEVICE(s);
> +    bool is_secdiscard = false;
>  
>      if (req->elem.out_num < 1 || req->elem.in_num < 1) {
>          virtio_error(vdev, "virtio-blk missing headers");
> @@ -722,6 +729,9 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
>       * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
>       * so we must mask it for these requests, then we will check if it is set.
>       */
> +    case VIRTIO_BLK_T_SECDISCARD & ~VIRTIO_BLK_T_OUT:
> +        is_secdiscard = true;
> +        __attribute__((fallthrough));
>      case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
>      case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
>      {
> @@ -752,7 +762,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
>          }
>  
>          err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
> -                                                            is_write_zeroes);
> +                                                            is_write_zeroes,
> +                                                            is_secdiscard);
>          if (err_status != VIRTIO_BLK_S_OK) {
>              virtio_blk_req_complete(req, err_status);
>              virtio_blk_free_request(req);
> @@ -1201,6 +1212,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> +    if (blk_get_flags(conf->conf.blk) & BDRV_O_SECDISCARD)
> +        virtio_add_feature(&s->host_features, VIRTIO_BLK_F_SECDISCARD);
> +    else
> +        virtio_clear_feature(&s->host_features, VIRTIO_BLK_F_SECDISCARD);
> +
>      if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES) &&
>          (!conf->max_write_zeroes_sectors ||
>           conf->max_write_zeroes_sectors > BDRV_REQUEST_MAX_SECTORS)) {
> @@ -1307,6 +1323,8 @@ static Property virtio_blk_properties[] = {
>                       conf.report_discard_granularity, true),
>      DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
>                        VIRTIO_BLK_F_WRITE_ZEROES, true),
> +    DEFINE_PROP_BIT64("secdiscard", VirtIOBlock, host_features,
> +                      VIRTIO_BLK_F_SECDISCARD, false),
>      DEFINE_PROP_UINT32("max-discard-sectors", VirtIOBlock,
>                         conf.max_discard_sectors, BDRV_REQUEST_MAX_SECTORS),
>      DEFINE_PROP_UINT32("max-write-zeroes-sectors", VirtIOBlock,
> diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
> index 2dcc90826a..c55a07840c 100644
> --- a/include/standard-headers/linux/virtio_blk.h
> +++ b/include/standard-headers/linux/virtio_blk.h
> @@ -40,6 +40,7 @@
>  #define VIRTIO_BLK_F_MQ		12	/* support more than one vq */
>  #define VIRTIO_BLK_F_DISCARD	13	/* DISCARD is supported */
>  #define VIRTIO_BLK_F_WRITE_ZEROES	14	/* WRITE ZEROES is supported */
> +#define VIRTIO_BLK_F_SECDISCARD	15	/* WRITE ZEROES is supported */

Surely not.


>  
>  /* Legacy feature bits */
>  #ifndef VIRTIO_BLK_NO_LEGACY
> @@ -153,6 +154,9 @@ struct virtio_blk_config {
>  /* Write zeroes command */
>  #define VIRTIO_BLK_T_WRITE_ZEROES	13
>  
> +/* Secure discard command */
> +#define VIRTIO_BLK_T_SECDISCARD	14
> +
>  #ifndef VIRTIO_BLK_NO_LEGACY
>  /* Barrier before this op. */
>  #define VIRTIO_BLK_T_BARRIER	0x80000000
> -- 
> 2.25.1


RE: [PATCH 2/2] virtio-blk: support BLKSECDISCARD
Posted by Qi, Yadong 4 years, 2 months ago
> On Mon, Nov 15, 2021 at 12:52:00PM +0800, yadong.qi@intel.com wrote:
> > From: Yadong Qi <yadong.qi@intel.com>
> >
> > Add new virtio feature: VIRTIO_BLK_F_SECDISCARD.
> > Add new virtio command: VIRTIO_BLK_T_SECDISCARD.
> >
> > This feature is disabled by default, it will check the backend
> > bs->open_flags & BDRV_O_SECDISCARD, enable it if BDRV_O_SECDISCARD
> > is supported.
> >
> > Signed-off-by: Yadong Qi <yadong.qi@intel.com>
> > ---
> >  hw/block/virtio-blk.c                       | 26 +++++++++++++++++----
> >  include/standard-headers/linux/virtio_blk.h |  4 ++++
> 
> 
> Any changes to standard headers need to go to linux and virtio TC.
Sure. I will draft proposal to virtio-comment for review.



Re: [PATCH 2/2] virtio-blk: support BLKSECDISCARD
Posted by Stefano Garzarella 4 years, 2 months ago
On Mon, Nov 15, 2021 at 12:52:00PM +0800, yadong.qi@intel.com wrote:
>From: Yadong Qi <yadong.qi@intel.com>
>
>Add new virtio feature: VIRTIO_BLK_F_SECDISCARD.
>Add new virtio command: VIRTIO_BLK_T_SECDISCARD.

Has a proposal been sent out yet to virtio-comment mailing list for 
discussing these specification changes?

>
>This feature is disabled by default, it will check the backend
>bs->open_flags & BDRV_O_SECDISCARD, enable it if BDRV_O_SECDISCARD
>is supported.
>
>Signed-off-by: Yadong Qi <yadong.qi@intel.com>
>---
> hw/block/virtio-blk.c                       | 26 +++++++++++++++++----
> include/standard-headers/linux/virtio_blk.h |  4 ++++
> 2 files changed, 26 insertions(+), 4 deletions(-)
>
>diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
>index dbc4c5a3cd..7bc3484521 100644
>--- a/hw/block/virtio-blk.c
>+++ b/hw/block/virtio-blk.c
>@@ -536,7 +536,8 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
> }
>
> static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
>-    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
>+    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes,
>+    bool is_secdiscard)

Since the function now handles 3 commands, I'm thinking if it's better 
to pass the command directly and then make a switch instead of using 2 
booleans.

> {
>     VirtIOBlock *s = req->dev;
>     VirtIODevice *vdev = VIRTIO_DEVICE(s);
>@@ -577,8 +578,8 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
>         goto err;
>     }
>
>+    int blk_aio_flags = 0;

Maybe better to move it to the beginning of the function.

>     if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
>-        int blk_aio_flags = 0;
>
>         if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
>             blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
>@@ -600,7 +601,12 @@ static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
>             goto err;
>         }
>
>-        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes, 0,
>+        if (is_secdiscard) {
>+            blk_aio_flags |= BDRV_REQ_SECDISCARD;
>+        }
>+
>+        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
>+                         blk_aio_flags,
>                          virtio_blk_discard_write_zeroes_complete, req);
>     }
>
>@@ -622,6 +628,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
>     unsigned out_num = req->elem.out_num;
>     VirtIOBlock *s = req->dev;
>     VirtIODevice *vdev = VIRTIO_DEVICE(s);
>+    bool is_secdiscard = false;
>
>     if (req->elem.out_num < 1 || req->elem.in_num < 1) {
>         virtio_error(vdev, "virtio-blk missing headers");
>@@ -722,6 +729,9 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
>      * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
>      * so we must mask it for these requests, then we will check if it is set.
>      */
>+    case VIRTIO_BLK_T_SECDISCARD & ~VIRTIO_BLK_T_OUT:
>+        is_secdiscard = true;
>+        __attribute__((fallthrough));

We can use QEMU_FALLTHROUGH here.

>     case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
>     case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
>     {
>@@ -752,7 +762,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq 
>*req, MultiReqBuffer *mrb)
>         }
>
>         err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
>-                                                            is_write_zeroes);
>+                                                            is_write_zeroes,
>+                                                            is_secdiscard);
>         if (err_status != VIRTIO_BLK_S_OK) {
>             virtio_blk_req_complete(req, err_status);
>             virtio_blk_free_request(req);
>@@ -1201,6 +1212,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
>         return;
>     }
>
>+    if (blk_get_flags(conf->conf.blk) & BDRV_O_SECDISCARD)
>+        virtio_add_feature(&s->host_features, 
>VIRTIO_BLK_F_SECDISCARD);
>+    else
>+        virtio_clear_feature(&s->host_features, VIRTIO_BLK_F_SECDISCARD);
>+

IIUC here we set or not the feature if BDRV_O_SECDISCARD is set.

Should we keep it disabled if "secdiscard" is false? (e.g. to avoid 
migration problems)

Otherwise what is the purpose of the "secdiscard" property?

Thanks,
Stefano


RE: [PATCH 2/2] virtio-blk: support BLKSECDISCARD
Posted by Qi, Yadong 4 years, 2 months ago
> >Add new virtio feature: VIRTIO_BLK_F_SECDISCARD.
> >Add new virtio command: VIRTIO_BLK_T_SECDISCARD.
> 
> Has a proposal been sent out yet to virtio-comment mailing list for discussing
> these specification changes?
> 
Not yet. I will draft a proposal to virtio-comment if no big concern of this patch
From maintainer.
> >
> >diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index
> >dbc4c5a3cd..7bc3484521 100644
> >--- a/hw/block/virtio-blk.c
> >+++ b/hw/block/virtio-blk.c
> >@@ -536,7 +536,8 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock
> >*dev,  }
> >
> > static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
> >-    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
> >+    struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes,
> >+    bool is_secdiscard)
> 
> Since the function now handles 3 commands, I'm thinking if it's better to pass
> the command directly and then make a switch instead of using 2 booleans.
> 
Make sense.

> > {
> >     VirtIOBlock *s = req->dev;
> >     VirtIODevice *vdev = VIRTIO_DEVICE(s); @@ -577,8 +578,8 @@ static
> >uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
> >         goto err;
> >     }
> >
> >+    int blk_aio_flags = 0;
> 
> Maybe better to move it to the beginning of the function.
Sure.

> 
> >
> >-        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes, 0,
> >+        if (is_secdiscard) {
> >+            blk_aio_flags |= BDRV_REQ_SECDISCARD;
> >+        }
> >+
> >+        blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
> >+                         blk_aio_flags,
> >                          virtio_blk_discard_write_zeroes_complete, req);
> >     }
> >
> >@@ -622,6 +628,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq
> *req, MultiReqBuffer *mrb)
> >     unsigned out_num = req->elem.out_num;
> >     VirtIOBlock *s = req->dev;
> >     VirtIODevice *vdev = VIRTIO_DEVICE(s);
> >+    bool is_secdiscard = false;
> >
> >     if (req->elem.out_num < 1 || req->elem.in_num < 1) {
> >         virtio_error(vdev, "virtio-blk missing headers"); @@ -722,6
> >+729,9 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req,
> MultiReqBuffer *mrb)
> >      * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
> >      * so we must mask it for these requests, then we will check if it is set.
> >      */
> >+    case VIRTIO_BLK_T_SECDISCARD & ~VIRTIO_BLK_T_OUT:
> >+        is_secdiscard = true;
> >+        __attribute__((fallthrough));
> 
> We can use QEMU_FALLTHROUGH here.
Sure.

> 
> >
> >         err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
> >-                                                            is_write_zeroes);
> >+                                                            is_write_zeroes,
> >+
> >+ is_secdiscard);


> >
> >+    if (blk_get_flags(conf->conf.blk) & BDRV_O_SECDISCARD)
> >+        virtio_add_feature(&s->host_features,
> >VIRTIO_BLK_F_SECDISCARD);
> >+    else
> >+        virtio_clear_feature(&s->host_features,
> >+ VIRTIO_BLK_F_SECDISCARD);
> >+
> 
> IIUC here we set or not the feature if BDRV_O_SECDISCARD is set.
> 
> Should we keep it disabled if "secdiscard" is false? (e.g. to avoid migration
> problems)
Yes, BDRV_O_SECDISCARD=(secdiscard=="on") ? 1 : 0;

> 
> Otherwise what is the purpose of the "secdiscard" property?
I cannot find a good method to detect whether host device support BLKSECDISCARD.
So I add this "secdiscard" property to explicitly enable this feature.

Best Regard
Yadong
> 
> Thanks,
> Stefano