Commit e7da2487 authored by Changpeng Liu's avatar Changpeng Liu
Browse files

bdev/virtio_blk: add unmap feature support



Change-Id: Ifc841f0bfef0391103c833b16c1e5b8851ac3e95
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/432256


Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarwuzhouhui <wuzhouhui@kingsoft.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 232ca0e6
Loading
Loading
Loading
Loading
+50 −13
Original line number Diff line number Diff line
@@ -55,12 +55,15 @@ struct virtio_blk_dev {
	struct virtio_dev		vdev;
	struct spdk_bdev		bdev;
	bool				readonly;
	bool				unmap;
};

struct virtio_blk_io_ctx {
	struct iovec				iov_req;
	struct iovec				iov_resp;
	struct iovec				iov_unmap;
	struct virtio_blk_outhdr		req;
	struct virtio_blk_discard_write_zeroes	unmap;
	uint8_t					resp;
};

@@ -80,6 +83,7 @@ struct bdev_virtio_blk_io_channel {
	 1ULL << VIRTIO_BLK_F_TOPOLOGY		|	\
	 1ULL << VIRTIO_BLK_F_MQ		|	\
	 1ULL << VIRTIO_BLK_F_RO		|	\
	 1ULL << VIRTIO_BLK_F_DISCARD		|	\
	 1ULL << VIRTIO_RING_F_EVENT_IDX	|	\
	 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)

@@ -102,10 +106,13 @@ bdev_virtio_blk_init_io_vreq(struct spdk_io_channel *ch, struct spdk_bdev_io *bd
{
	struct virtio_blk_outhdr *req;
	uint8_t *resp;
	struct virtio_blk_discard_write_zeroes *desc;

	struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx;

	req = &io_ctx->req;
	resp = &io_ctx->resp;
	desc = &io_ctx->unmap;

	io_ctx->iov_req.iov_base = req;
	io_ctx->iov_req.iov_len = sizeof(*req);
@@ -113,6 +120,9 @@ bdev_virtio_blk_init_io_vreq(struct spdk_io_channel *ch, struct spdk_bdev_io *bd
	io_ctx->iov_resp.iov_base = resp;
	io_ctx->iov_resp.iov_len = sizeof(*resp);

	io_ctx->iov_unmap.iov_base = desc;
	io_ctx->iov_unmap.iov_len = sizeof(*desc);

	memset(req, 0, sizeof(*req));
	return io_ctx;
}
@@ -135,22 +145,38 @@ bdev_virtio_blk_send_io(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io
	}

	virtqueue_req_add_iovs(vq, &io_ctx->iov_req, 1, SPDK_VIRTIO_DESC_RO);
	if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) {
		virtqueue_req_add_iovs(vq, &io_ctx->iov_unmap, 1, SPDK_VIRTIO_DESC_RO);
	} else {
		virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
				       bdev_io->type == SPDK_BDEV_IO_TYPE_READ ?
				       SPDK_VIRTIO_DESC_WR : SPDK_VIRTIO_DESC_RO);
	}
	virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);

	virtqueue_req_flush(vq);
}

static void
bdev_virtio_rw(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
bdev_virtio_command(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
{
	struct virtio_blk_io_ctx *io_ctx = bdev_virtio_blk_init_io_vreq(ch, bdev_io);
	struct virtio_blk_outhdr *req = &io_ctx->req;
	struct virtio_blk_discard_write_zeroes *desc = &io_ctx->unmap;

	req->type = bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE ?
		    VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN;

	if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
		req->type = VIRTIO_BLK_T_IN;
	} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
		req->type = VIRTIO_BLK_T_OUT;
	} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) {
		req->type = VIRTIO_BLK_T_DISCARD;
		desc->sector = bdev_io->u.bdev.offset_blocks *
			       spdk_bdev_get_block_size(bdev_io->bdev) / 512;
		desc->num_sectors = bdev_io->u.bdev.num_blocks *
				    spdk_bdev_get_block_size(bdev_io->bdev) / 512;
		desc->flags = 0;
	}

	req->sector = bdev_io->u.bdev.offset_blocks *
		      spdk_bdev_get_block_size(bdev_io->bdev) / 512;
@@ -165,20 +191,26 @@ _bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bde

	switch (bdev_io->type) {
	case SPDK_BDEV_IO_TYPE_READ:
		spdk_bdev_io_get_buf(bdev_io, bdev_virtio_rw,
		spdk_bdev_io_get_buf(bdev_io, bdev_virtio_command,
				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
		return 0;
	case SPDK_BDEV_IO_TYPE_WRITE:
		if (bvdev->readonly) {
			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
		} else {
			bdev_virtio_rw(ch, bdev_io);
			bdev_virtio_command(ch, bdev_io);
		}
		return 0;
	case SPDK_BDEV_IO_TYPE_RESET:
		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
		return 0;
	case SPDK_BDEV_IO_TYPE_UNMAP:
		if (bvdev->unmap) {
			bdev_virtio_command(ch, bdev_io);
		} else {
			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
		}
		return 0;
	case SPDK_BDEV_IO_TYPE_FLUSH:
	default:
		return -1;
@@ -206,8 +238,9 @@ bdev_virtio_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
		return true;
	case SPDK_BDEV_IO_TYPE_WRITE:
		return !bvdev->readonly;
	case SPDK_BDEV_IO_TYPE_FLUSH:
	case SPDK_BDEV_IO_TYPE_UNMAP:
		return bvdev->unmap;
	case SPDK_BDEV_IO_TYPE_FLUSH:
	default:
		return false;
	}
@@ -424,6 +457,10 @@ virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues)
		bvdev->readonly = true;
	}

	if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
		bvdev->unmap = true;
	}

	if (max_queues == 0) {
		SPDK_ERRLOG("%s: requested 0 request queues (%"PRIu16" available).\n",
			    vdev->name, host_max_queues);