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:
parent
04cde460cf
commit
2374599671
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user