vdpa_sim_blk: add support for discard and write-zeroes
authorStefano Garzarella <sgarzare@redhat.com>
Thu, 11 Aug 2022 08:36:32 +0000 (10:36 +0200)
committerMichael S. Tsirkin <mst@redhat.com>
Thu, 11 Aug 2022 08:44:58 +0000 (04:44 -0400)
Expose VIRTIO_BLK_F_DISCARD and VIRTIO_BLK_F_WRITE_ZEROES features
to the drivers and handle VIRTIO_BLK_T_DISCARD and
VIRTIO_BLK_T_WRITE_ZEROES requests checking ranges and flags.

The simulator behaves like a ramdisk, so for VIRTIO_BLK_F_DISCARD
does nothing, while for VIRTIO_BLK_T_WRITE_ZEROES sets to 0 the
specified region.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Message-Id: <20220811083632.77525-5-sgarzare@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c

index 1f18f33..c8bfea3 100644 (file)
                                 (1ULL << VIRTIO_BLK_F_SEG_MAX)  | \
                                 (1ULL << VIRTIO_BLK_F_BLK_SIZE) | \
                                 (1ULL << VIRTIO_BLK_F_TOPOLOGY) | \
-                                (1ULL << VIRTIO_BLK_F_MQ))
+                                (1ULL << VIRTIO_BLK_F_MQ)       | \
+                                (1ULL << VIRTIO_BLK_F_DISCARD)  | \
+                                (1ULL << VIRTIO_BLK_F_WRITE_ZEROES))
 
 #define VDPASIM_BLK_CAPACITY   0x40000
 #define VDPASIM_BLK_SIZE_MAX   0x1000
 #define VDPASIM_BLK_SEG_MAX    32
+#define VDPASIM_BLK_DWZ_MAX_SECTORS UINT_MAX
 
 /* 1 virtqueue, 1 address space, 1 virtqueue group */
 #define VDPASIM_BLK_VQ_NUM     1
@@ -193,6 +196,64 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
                /* nothing to do */
                break;
 
+       case VIRTIO_BLK_T_DISCARD:
+       case VIRTIO_BLK_T_WRITE_ZEROES: {
+               struct virtio_blk_discard_write_zeroes range;
+               u32 num_sectors, flags;
+
+               if (to_pull != sizeof(range)) {
+                       dev_dbg(&vdpasim->vdpa.dev,
+                               "discard/write_zeroes header len: 0x%zx [expected: 0x%zx]\n",
+                               to_pull, sizeof(range));
+                       status = VIRTIO_BLK_S_IOERR;
+                       break;
+               }
+
+               bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &range,
+                                             to_pull);
+               if (bytes < 0) {
+                       dev_dbg(&vdpasim->vdpa.dev,
+                               "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
+                               bytes, offset, to_pull);
+                       status = VIRTIO_BLK_S_IOERR;
+                       break;
+               }
+
+               sector = le64_to_cpu(range.sector);
+               offset = sector << SECTOR_SHIFT;
+               num_sectors = le32_to_cpu(range.num_sectors);
+               flags = le32_to_cpu(range.flags);
+
+               if (type == VIRTIO_BLK_T_DISCARD && flags != 0) {
+                       dev_dbg(&vdpasim->vdpa.dev,
+                               "discard unexpected flags set - flags: 0x%x\n",
+                               flags);
+                       status = VIRTIO_BLK_S_UNSUPP;
+                       break;
+               }
+
+               if (type == VIRTIO_BLK_T_WRITE_ZEROES &&
+                   flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
+                       dev_dbg(&vdpasim->vdpa.dev,
+                               "write_zeroes unexpected flags set - flags: 0x%x\n",
+                               flags);
+                       status = VIRTIO_BLK_S_UNSUPP;
+                       break;
+               }
+
+               if (!vdpasim_blk_check_range(vdpasim, sector, num_sectors,
+                                            VDPASIM_BLK_DWZ_MAX_SECTORS)) {
+                       status = VIRTIO_BLK_S_IOERR;
+                       break;
+               }
+
+               if (type == VIRTIO_BLK_T_WRITE_ZEROES) {
+                       memset(vdpasim->buffer + offset, 0,
+                              num_sectors << SECTOR_SHIFT);
+               }
+
+               break;
+       }
        default:
                dev_dbg(&vdpasim->vdpa.dev,
                        "Unsupported request type %d\n", type);
@@ -281,6 +342,17 @@ static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
        blk_config->min_io_size = cpu_to_vdpasim16(vdpasim, 1);
        blk_config->opt_io_size = cpu_to_vdpasim32(vdpasim, 1);
        blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
+       /* VIRTIO_BLK_F_DISCARD */
+       blk_config->discard_sector_alignment =
+               cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
+       blk_config->max_discard_sectors =
+               cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS);
+       blk_config->max_discard_seg = cpu_to_vdpasim32(vdpasim, 1);
+       /* VIRTIO_BLK_F_WRITE_ZEROES */
+       blk_config->max_write_zeroes_sectors =
+               cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS);
+       blk_config->max_write_zeroes_seg = cpu_to_vdpasim32(vdpasim, 1);
+
 }
 
 static void vdpasim_blk_mgmtdev_release(struct device *dev)