Commit f999d891 authored by Nadja Brix Koch's avatar Nadja Brix Koch Committed by Konrad Sztyber
Browse files

bdev_xnvme: add support for dataset management



Change-Id: I273302b84533f2610678b1b9720dcce8fbc6e24e
Signed-off-by: default avatarNadja Brix Koch <n.koch@samsung.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/23976


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
parent 95d6c9fa
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -98,10 +98,17 @@ bdev_xnvme_get_io_channel(void *ctx)
static bool
bdev_xnvme_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
{
	struct bdev_xnvme *xnvme = ctx;

	switch (io_type) {
	case SPDK_BDEV_IO_TYPE_READ:
	case SPDK_BDEV_IO_TYPE_WRITE:
		return true;
	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
	case SPDK_BDEV_IO_TYPE_UNMAP:
		/* libaio and io_uring only supports read and write */
		return !strcmp(xnvme->io_mechanism, "io_uring_cmd") &&
		       xnvme_dev_get_csi(xnvme->dev) == XNVME_SPEC_CSI_NVM;
	default:
		return false;
	}
@@ -126,6 +133,56 @@ bdev_xnvme_destruct(void *ctx)
	return 0;
}

static int
bdev_xnvme_unmap(struct spdk_bdev_io *bdev_io, struct xnvme_cmd_ctx *ctx, struct bdev_xnvme *xnvme)
{
	struct spdk_nvme_dsm_range *range;
	uint64_t offset, remaining;
	uint64_t num_ranges_u64, num_blocks, offset_blocks;
	uint16_t num_ranges;

	num_blocks = bdev_io->u.bdev.num_blocks;
	offset_blocks = bdev_io->u.bdev.offset_blocks;

	num_ranges_u64 = spdk_divide_round_up(num_blocks, xnvme->bdev.max_unmap);
	if (num_ranges_u64 > xnvme->bdev.max_unmap_segments) {
		SPDK_ERRLOG("Unmap request for %" PRIu64 " blocks is too large\n", num_blocks);
		return -EINVAL;
	}
	num_ranges = (uint16_t)num_ranges_u64;

	offset = offset_blocks;
	remaining = num_blocks;

	assert(bdev_io->u.bdev.iovcnt == 1);
	range = (struct spdk_nvme_dsm_range *) bdev_io->u.bdev.iovs->iov_base;

	/* Fill max-size ranges until the remaining blocks fit into one range */
	while (remaining > xnvme->bdev.max_unmap) {
		range->attributes.raw = 0;
		range->length = xnvme->bdev.max_unmap;
		range->starting_lba = offset;

		offset += xnvme->bdev.max_unmap;
		remaining -= xnvme->bdev.max_unmap;
		range++;
	}

	/* Final range describes the remaining blocks */
	range->attributes.raw = 0;
	range->length = remaining;
	range->starting_lba = offset;

	ctx->cmd.common.opcode = XNVME_SPEC_NVM_OPC_DATASET_MANAGEMENT;
	ctx->cmd.common.nsid = xnvme->nsid;
	ctx->cmd.nvm.nlb = num_blocks - 1;
	ctx->cmd.nvm.slba = offset_blocks;
	ctx->cmd.dsm.nr = num_ranges - 1;
	ctx->cmd.dsm.ad = true;

	return 0;
}

static void
_xnvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
{
@@ -157,6 +214,13 @@ _xnvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
		ctx->cmd.nvm.nlb = bdev_io->u.bdev.num_blocks - 1;
		ctx->cmd.nvm.slba = bdev_io->u.bdev.offset_blocks;
		break;
	case SPDK_BDEV_IO_TYPE_UNMAP:
		if (bdev_xnvme_unmap(bdev_io, ctx, xnvme)) {
			xnvme_queue_put_cmd_ctx(xnvme_ch->queue, ctx);
			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
			return;
		}
		break;
	default:
		SPDK_ERRLOG("Wrong io type\n");

@@ -225,6 +289,11 @@ bdev_xnvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_
		spdk_bdev_io_get_buf(bdev_io, bdev_xnvme_get_buf_cb,
				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
		break;
	case SPDK_BDEV_IO_TYPE_UNMAP:
		/* The max number of segments defined by spec is 256 and an
		 * spdk_nvme_dsm_range structure is 16 bytes */
		spdk_bdev_io_get_buf(bdev_io, bdev_xnvme_get_buf_cb, 256 * 16);
		break;
	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
		_xnvme_submit_request(ch, bdev_io);
		break;
@@ -325,6 +394,7 @@ create_xnvme_bdev(const char *name, const char *filename, const char *io_mechani
		  bool conserve_cpu)
{
	struct bdev_xnvme *xnvme;
	const struct xnvme_spec_nvm_idfy_ctrlr *ctrlr;
	uint32_t block_size;
	uint64_t bdev_size;
	int rc;
@@ -383,6 +453,13 @@ create_xnvme_bdev(const char *name, const char *filename, const char *io_mechani
	xnvme->bdev.write_cache = 0;
	xnvme->bdev.max_write_zeroes = UINT16_MAX + 1;

	if (xnvme_dev_get_csi(xnvme->dev) == XNVME_SPEC_CSI_NVM) {
		ctrlr = (struct xnvme_spec_nvm_idfy_ctrlr *) xnvme_dev_get_ctrlr_css(xnvme->dev);
		xnvme->bdev.max_unmap = ctrlr->dmrsl ? ctrlr->dmrsl : SPDK_NVME_DATASET_MANAGEMENT_RANGE_MAX_BLOCKS;
		xnvme->bdev.max_unmap_segments = ctrlr->dmrl ? ctrlr->dmrl :
						 SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES;
	}

	if (block_size == 0) {
		SPDK_ERRLOG("Block size could not be auto-detected\n");
		goto error_return;