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;
|
int rc;
|
||||||
uint64_t phys_addr;
|
uint64_t phys_addr;
|
||||||
uint32_t remaining_transfer_len, length;
|
uint32_t data_transfered, remaining_transfer_len, length;
|
||||||
struct spdk_nvme_sgl_descriptor *sgl;
|
struct spdk_nvme_sgl_descriptor *sgl;
|
||||||
uint32_t nseg = 0;
|
uint32_t nseg = 0;
|
||||||
|
|
||||||
@ -752,10 +752,11 @@ _nvme_qpair_build_hw_sgl_request(struct spdk_nvme_qpair *qpair, struct nvme_requ
|
|||||||
return -1;
|
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->type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
|
||||||
sgl->length = length;
|
sgl->length = data_transfered;
|
||||||
sgl->address = phys_addr;
|
sgl->address = phys_addr;
|
||||||
sgl->type_specific = 0;
|
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) {
|
if (nseg == 1) {
|
||||||
req->cmd.dptr.sgl1.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
|
req->cmd.dptr.sgl1.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
|
||||||
req->cmd.dptr.sgl1.address = phys_addr;
|
req->cmd.dptr.sgl1.address = phys_addr;
|
||||||
req->cmd.dptr.sgl1.length = length;
|
req->cmd.dptr.sgl1.length = data_transfered;
|
||||||
} else if (nseg > 1) {
|
} else if (nseg > 1) {
|
||||||
/* For now we can only support 1 SGL segment in NVMe controller */
|
/* For now we can only support 1 SGL segment in NVMe controller */
|
||||||
req->cmd.dptr.sgl1.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT;
|
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)
|
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;
|
int i, found = 0;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
@ -183,7 +217,7 @@ static uint32_t build_io_request_1(struct io_request *req)
|
|||||||
return len;
|
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;
|
int i;
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
@ -206,7 +240,7 @@ static uint32_t build_io_request_2(struct io_request *req)
|
|||||||
return len;
|
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;
|
int i;
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
@ -223,7 +257,7 @@ static uint32_t build_io_request_3(struct io_request *req)
|
|||||||
return len;
|
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;
|
int i;
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
@ -244,40 +278,6 @@ static uint32_t build_io_request_4(struct io_request *req)
|
|||||||
return len;
|
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);
|
typedef uint32_t (*nvme_build_io_req_fn_t)(struct io_request *req);
|
||||||
|
|
||||||
static int
|
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);
|
ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, 1);
|
||||||
if (!ns) {
|
if (!ns) {
|
||||||
return -1;
|
fprintf(stderr, "Null namespace\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
nsdata = spdk_nvme_ns_get_data(ns);
|
nsdata = spdk_nvme_ns_get_data(ns);
|
||||||
if (!nsdata || !spdk_nvme_ns_get_sector_size(ns))
|
if (!nsdata || !spdk_nvme_ns_get_sector_size(ns)) {
|
||||||
return -1;
|
fprintf(stderr, "Empty nsdata or wrong sector size\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
req = rte_zmalloc(NULL, sizeof(*req), 0);
|
req = rte_zmalloc(NULL, sizeof(*req), 0);
|
||||||
if (!req)
|
if (!req) {
|
||||||
return -1;
|
fprintf(stderr, "Allocate request failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* IO parameters setting */
|
/* IO parameters setting */
|
||||||
len = build_io_fn(req);
|
len = build_io_fn(req);
|
||||||
if (!len)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
lba_count = len / spdk_nvme_ns_get_sector_size(ns);
|
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);
|
rte_free(req);
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nseg = req->nseg;
|
nseg = req->nseg;
|
||||||
|
Loading…
Reference in New Issue
Block a user