Commit 23745996 authored by Changpeng Liu's avatar Changpeng Liu Committed by Daniel Verkamp
Browse files

spdk: fix wrong length parameter for large IO when uses hardware SGL



When I/O spans a stripe boundary, the driver splits the request into
multiple requests, so for 1 segment memory larger than the stripe
size, we also need to split the segment memory.

Change-Id: I22ea5734d7066865a57a3c90fe18d5f76f373f1d
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent 04cde460
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -727,7 +727,7 @@ _nvme_qpair_build_hw_sgl_request(struct spdk_nvme_qpair *qpair, struct nvme_requ
{
	int rc;
	uint64_t phys_addr;
	uint32_t remaining_transfer_len, length;
	uint32_t data_transfered, remaining_transfer_len, length;
	struct spdk_nvme_sgl_descriptor *sgl;
	uint32_t nseg = 0;

@@ -752,10 +752,11 @@ _nvme_qpair_build_hw_sgl_request(struct spdk_nvme_qpair *qpair, struct nvme_requ
			return -1;
		}

		remaining_transfer_len -= length;
		data_transfered = nvme_min(remaining_transfer_len, length);
		remaining_transfer_len -= data_transfered;

		sgl->type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
		sgl->length = length;
		sgl->length = data_transfered;
		sgl->address = phys_addr;
		sgl->type_specific = 0;

@@ -771,7 +772,7 @@ _nvme_qpair_build_hw_sgl_request(struct spdk_nvme_qpair *qpair, struct nvme_requ
	if (nseg == 1) {
		req->cmd.dptr.sgl1.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
		req->cmd.dptr.sgl1.address = phys_addr;
		req->cmd.dptr.sgl1.length = length;
		req->cmd.dptr.sgl1.length = data_transfered;
	} else if (nseg > 1) {
		/* For now we can only support 1 SGL segment in NVMe controller */
		req->cmd.dptr.sgl1.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT;
+50 −47
Original line number Diff line number Diff line
@@ -146,6 +146,40 @@ static uint32_t build_io_request_0(struct io_request *req)
}

static uint32_t build_io_request_1(struct io_request *req)
{
	int i;
	uint32_t len = 0;

	req->nseg = 1;

	/* 512B for 1st sge */
	req->iovs[0].iov_base = rte_zmalloc(NULL, 0x200, 0x200);
	req->iovs[0].iov_len = 0x200;

	for (i = 0; i < req->nseg; i++)
		len += req->iovs[i].iov_len;

	return len;
}

static uint32_t build_io_request_2(struct io_request *req)
{
	int i;
	uint32_t len = 0;

	req->nseg = 1;

	/* 256KB for 1st sge */
	req->iovs[0].iov_base = rte_zmalloc(NULL, 0x40000, 0x1000);
	req->iovs[0].iov_len = 0x40000;

	for (i = 0; i < req->nseg; i++)
		len += req->iovs[i].iov_len;

	return len;
}

static uint32_t build_io_request_3(struct io_request *req)
{
	int i, found = 0;
	uint8_t *buf;
@@ -183,7 +217,7 @@ static uint32_t build_io_request_1(struct io_request *req)
	return len;
}

static uint32_t build_io_request_2(struct io_request *req)
static uint32_t build_io_request_4(struct io_request *req)
{
	int i;
	uint32_t len = 0;
@@ -206,7 +240,7 @@ static uint32_t build_io_request_2(struct io_request *req)
	return len;
}

static uint32_t build_io_request_3(struct io_request *req)
static uint32_t build_io_request_5(struct io_request *req)
{
	int i;
	uint32_t len = 0;
@@ -223,7 +257,7 @@ static uint32_t build_io_request_3(struct io_request *req)
	return len;
}

static uint32_t build_io_request_4(struct io_request *req)
static uint32_t build_io_request_6(struct io_request *req)
{
	int i;
	uint32_t len = 0;
@@ -244,40 +278,6 @@ static uint32_t build_io_request_4(struct io_request *req)
	return len;
}

static uint32_t build_io_request_5(struct io_request *req)
{
	int i;
	uint32_t len = 0;

	req->nseg = 1;

	/* 256KB for 1st sge */
	req->iovs[0].iov_base = rte_zmalloc(NULL, 0x40000, 0x1000);
	req->iovs[0].iov_len = 0x40000;

	for (i = 0; i < req->nseg; i++)
		len += req->iovs[i].iov_len;

	return len;
}

static uint32_t build_io_request_6(struct io_request *req)
{
	int i;
	uint32_t len = 0;

	req->nseg = 1;

	/* 512B for 1st sge */
	req->iovs[0].iov_base = rte_zmalloc(NULL, 0x200, 0x200);
	req->iovs[0].iov_len = 0x200;

	for (i = 0; i < req->nseg; i++)
		len += req->iovs[i].iov_len;

	return len;
}

typedef uint32_t (*nvme_build_io_req_fn_t)(struct io_request *req);

static int
@@ -294,25 +294,28 @@ writev_readv_tests(struct dev *dev, nvme_build_io_req_fn_t build_io_fn)

	ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, 1);
	if (!ns) {
		return -1;
		fprintf(stderr, "Null namespace\n");
		return 0;
	}
	nsdata = spdk_nvme_ns_get_data(ns);
	if (!nsdata || !spdk_nvme_ns_get_sector_size(ns))
		return -1;
	if (!nsdata || !spdk_nvme_ns_get_sector_size(ns)) {
		fprintf(stderr, "Empty nsdata or wrong sector size\n");
		return 0;
	}

	req = rte_zmalloc(NULL, sizeof(*req), 0);
	if (!req)
		return -1;
	if (!req) {
		fprintf(stderr, "Allocate request failed\n");
		return 0;
	}

	/* IO parameters setting */
	len = build_io_fn(req);
	if (!len)
		return 0;

	lba_count = len / spdk_nvme_ns_get_sector_size(ns);
	if (BASE_LBA_START + lba_count > (uint32_t)nsdata->nsze) {
	if (!lba_count || (BASE_LBA_START + lba_count > (uint32_t)nsdata->nsze)) {
		fprintf(stderr, "Invalid IO length parameter\n");
		rte_free(req);
		return -1;
		return 0;
	}

	nseg = req->nseg;