|
30 | 30 | (1ULL << VIRTIO_BLK_F_SEG_MAX) | \
|
31 | 31 | (1ULL << VIRTIO_BLK_F_BLK_SIZE) | \
|
32 | 32 | (1ULL << VIRTIO_BLK_F_TOPOLOGY) | \
|
33 |
| - (1ULL << VIRTIO_BLK_F_MQ)) |
| 33 | + (1ULL << VIRTIO_BLK_F_MQ) | \ |
| 34 | + (1ULL << VIRTIO_BLK_F_DISCARD) | \ |
| 35 | + (1ULL << VIRTIO_BLK_F_WRITE_ZEROES)) |
34 | 36 |
|
35 | 37 | #define VDPASIM_BLK_CAPACITY 0x40000
|
36 | 38 | #define VDPASIM_BLK_SIZE_MAX 0x1000
|
37 | 39 | #define VDPASIM_BLK_SEG_MAX 32
|
| 40 | +#define VDPASIM_BLK_DWZ_MAX_SECTORS UINT_MAX |
38 | 41 |
|
39 | 42 | /* 1 virtqueue, 1 address space, 1 virtqueue group */
|
40 | 43 | #define VDPASIM_BLK_VQ_NUM 1
|
@@ -193,6 +196,64 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
|
193 | 196 | /* nothing to do */
|
194 | 197 | break;
|
195 | 198 |
|
| 199 | + case VIRTIO_BLK_T_DISCARD: |
| 200 | + case VIRTIO_BLK_T_WRITE_ZEROES: { |
| 201 | + struct virtio_blk_discard_write_zeroes range; |
| 202 | + u32 num_sectors, flags; |
| 203 | + |
| 204 | + if (to_pull != sizeof(range)) { |
| 205 | + dev_dbg(&vdpasim->vdpa.dev, |
| 206 | + "discard/write_zeroes header len: 0x%zx [expected: 0x%zx]\n", |
| 207 | + to_pull, sizeof(range)); |
| 208 | + status = VIRTIO_BLK_S_IOERR; |
| 209 | + break; |
| 210 | + } |
| 211 | + |
| 212 | + bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &range, |
| 213 | + to_pull); |
| 214 | + if (bytes < 0) { |
| 215 | + dev_dbg(&vdpasim->vdpa.dev, |
| 216 | + "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", |
| 217 | + bytes, offset, to_pull); |
| 218 | + status = VIRTIO_BLK_S_IOERR; |
| 219 | + break; |
| 220 | + } |
| 221 | + |
| 222 | + sector = le64_to_cpu(range.sector); |
| 223 | + offset = sector << SECTOR_SHIFT; |
| 224 | + num_sectors = le32_to_cpu(range.num_sectors); |
| 225 | + flags = le32_to_cpu(range.flags); |
| 226 | + |
| 227 | + if (type == VIRTIO_BLK_T_DISCARD && flags != 0) { |
| 228 | + dev_dbg(&vdpasim->vdpa.dev, |
| 229 | + "discard unexpected flags set - flags: 0x%x\n", |
| 230 | + flags); |
| 231 | + status = VIRTIO_BLK_S_UNSUPP; |
| 232 | + break; |
| 233 | + } |
| 234 | + |
| 235 | + if (type == VIRTIO_BLK_T_WRITE_ZEROES && |
| 236 | + flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) { |
| 237 | + dev_dbg(&vdpasim->vdpa.dev, |
| 238 | + "write_zeroes unexpected flags set - flags: 0x%x\n", |
| 239 | + flags); |
| 240 | + status = VIRTIO_BLK_S_UNSUPP; |
| 241 | + break; |
| 242 | + } |
| 243 | + |
| 244 | + if (!vdpasim_blk_check_range(vdpasim, sector, num_sectors, |
| 245 | + VDPASIM_BLK_DWZ_MAX_SECTORS)) { |
| 246 | + status = VIRTIO_BLK_S_IOERR; |
| 247 | + break; |
| 248 | + } |
| 249 | + |
| 250 | + if (type == VIRTIO_BLK_T_WRITE_ZEROES) { |
| 251 | + memset(vdpasim->buffer + offset, 0, |
| 252 | + num_sectors << SECTOR_SHIFT); |
| 253 | + } |
| 254 | + |
| 255 | + break; |
| 256 | + } |
196 | 257 | default:
|
197 | 258 | dev_dbg(&vdpasim->vdpa.dev,
|
198 | 259 | "Unsupported request type %d\n", type);
|
@@ -281,6 +342,17 @@ static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)
|
281 | 342 | blk_config->min_io_size = cpu_to_vdpasim16(vdpasim, 1);
|
282 | 343 | blk_config->opt_io_size = cpu_to_vdpasim32(vdpasim, 1);
|
283 | 344 | blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE);
|
| 345 | + /* VIRTIO_BLK_F_DISCARD */ |
| 346 | + blk_config->discard_sector_alignment = |
| 347 | + cpu_to_vdpasim32(vdpasim, SECTOR_SIZE); |
| 348 | + blk_config->max_discard_sectors = |
| 349 | + cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS); |
| 350 | + blk_config->max_discard_seg = cpu_to_vdpasim32(vdpasim, 1); |
| 351 | + /* VIRTIO_BLK_F_WRITE_ZEROES */ |
| 352 | + blk_config->max_write_zeroes_sectors = |
| 353 | + cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS); |
| 354 | + blk_config->max_write_zeroes_seg = cpu_to_vdpasim32(vdpasim, 1); |
| 355 | + |
284 | 356 | }
|
285 | 357 |
|
286 | 358 | static void vdpasim_blk_mgmtdev_release(struct device *dev)
|
|
0 commit comments