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: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Changpeng Liu 2016-03-09 15:08:31 +08:00 committed by Daniel Verkamp
parent 04cde460cf
commit 2374599671
2 changed files with 55 additions and 51 deletions

View File

@ -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;

View File

@ -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;