util: add spdk_iov_xfer_*() API

Add a new API for incremental copying in or out of an iovec, and replace
current code to use the new API.

Signed-off-by: John Levon <john.levon@nutanix.com>
Change-Id: I088b784aef821310699478989e61411952066c18
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16193
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
John Levon 2023-01-07 17:20:44 +00:00 committed by Tomasz Zawadzki
parent 833992d09c
commit ecc80dfcfb
7 changed files with 200 additions and 107 deletions

View File

@ -131,6 +131,9 @@ names with this option to restrict allowed RPCs to only that list.
Added `--vfio-vf-token` command line option to specify a VF token (UUID) Added `--vfio-vf-token` command line option to specify a VF token (UUID)
shared between SR-IOV PF and VFs for vfio_pci driver. shared between SR-IOV PF and VFs for vfio_pci driver.
The `spdk_iov_xfer_*()` APIs were added for handling incremental copying between
an iovec and a buffer.
### json ### json
Added API `spdk_json_write_double` and `spdk_json_write_named_double` to allow Added API `spdk_json_write_double` and `spdk_json_write_named_double` to allow

View File

@ -169,6 +169,37 @@ size_t spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_
*/ */
size_t spdk_iovmove(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt); size_t spdk_iovmove(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt);
/**
* Transfer state for iterative copying in or out of an iovec.
*/
struct spdk_iov_xfer {
struct iovec *iovs;
int iovcnt;
int cur_iov_idx;
size_t cur_iov_offset;
};
/**
* Initialize a transfer context to point to the given iovec.
*/
void
spdk_iov_xfer_init(struct spdk_iov_xfer *ix, struct iovec *iovs, int iovcnt);
/**
* Copy from the given buf up to buf_len bytes, into the given ix iovec
* iterator, advancing the iterator as needed.. Returns the number of bytes
* copied.
*/
size_t
spdk_iov_xfer_from_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len);
/**
* Copy from the given ix iovec iterator into the given buf up to buf_len
* bytes, advancing the iterator as needed. Returns the number of bytes copied.
*/
size_t
spdk_iov_xfer_to_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len);
/** /**
* Copy iovs contents to buf through memcpy. * Copy iovs contents to buf through memcpy.
*/ */

View File

@ -53,56 +53,6 @@ static struct spdk_nvmf_custom_admin_cmd g_nvmf_custom_admin_cmd_hdlrs[SPDK_NVME
static void _nvmf_request_complete(void *ctx); static void _nvmf_request_complete(void *ctx);
struct copy_iovs_ctx {
struct iovec *iovs;
int iovcnt;
int cur_iov_idx;
size_t cur_iov_offset;
};
static void
_init_copy_iovs_ctx(struct copy_iovs_ctx *copy_ctx, struct iovec *iovs, int iovcnt)
{
copy_ctx->iovs = iovs;
copy_ctx->iovcnt = iovcnt;
copy_ctx->cur_iov_idx = 0;
copy_ctx->cur_iov_offset = 0;
}
static size_t
_copy_buf_to_iovs(struct copy_iovs_ctx *copy_ctx, const void *buf, size_t buf_len)
{
size_t len, iov_remain_len, copied_len = 0;
struct iovec *iov;
if (buf_len == 0) {
return 0;
}
while (copy_ctx->cur_iov_idx < copy_ctx->iovcnt) {
iov = &copy_ctx->iovs[copy_ctx->cur_iov_idx];
iov_remain_len = iov->iov_len - copy_ctx->cur_iov_offset;
if (iov_remain_len == 0) {
copy_ctx->cur_iov_idx++;
copy_ctx->cur_iov_offset = 0;
continue;
}
len = spdk_min(iov_remain_len, buf_len - copied_len);
memcpy((char *)iov->iov_base + copy_ctx->cur_iov_offset,
(const char *)buf + copied_len,
len);
copied_len += len;
copy_ctx->cur_iov_offset += len;
if (buf_len == copied_len) {
return copied_len;
}
}
return copied_len;
}
static inline void static inline void
nvmf_invalid_connect_response(struct spdk_nvmf_fabric_connect_rsp *rsp, nvmf_invalid_connect_response(struct spdk_nvmf_fabric_connect_rsp *rsp,
uint8_t iattr, uint16_t ipo) uint8_t iattr, uint16_t ipo)
@ -1712,7 +1662,7 @@ nvmf_ctrlr_get_features_host_identifier(struct spdk_nvmf_request *req)
struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
SPDK_DEBUGLOG(nvmf, "Get Features - Host Identifier\n"); SPDK_DEBUGLOG(nvmf, "Get Features - Host Identifier\n");
@ -1723,14 +1673,14 @@ nvmf_ctrlr_get_features_host_identifier(struct spdk_nvmf_request *req)
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
if (req->data == NULL || req->length < sizeof(ctrlr->hostid)) { if (req->iovcnt < 1 || req->length < sizeof(ctrlr->hostid)) {
SPDK_ERRLOG("Invalid data buffer for Get Features - Host Identifier\n"); SPDK_ERRLOG("Invalid data buffer for Get Features - Host Identifier\n");
response->status.sc = SPDK_NVME_SC_INVALID_FIELD; response->status.sc = SPDK_NVME_SC_INVALID_FIELD;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
_init_copy_iovs_ctx(&copy_ctx, req->iov, req->iovcnt); spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
_copy_buf_to_iovs(&copy_ctx, &ctrlr->hostid, sizeof(ctrlr->hostid)); spdk_iov_xfer_from_buf(&ix, &ctrlr->hostid, sizeof(ctrlr->hostid));
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
@ -1858,11 +1808,11 @@ nvmf_ctrlr_get_features_host_behavior_support(struct spdk_nvmf_request *req)
struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
struct spdk_nvme_host_behavior host_behavior = {}; struct spdk_nvme_host_behavior host_behavior = {};
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
SPDK_DEBUGLOG(nvmf, "Get Features - Host Behavior Support\n"); SPDK_DEBUGLOG(nvmf, "Get Features - Host Behavior Support\n");
if (req->data == NULL || req->length < sizeof(struct spdk_nvme_host_behavior)) { if (req->iovcnt < 1 || req->length < sizeof(struct spdk_nvme_host_behavior)) {
SPDK_ERRLOG("invalid data buffer for Host Behavior Support\n"); SPDK_ERRLOG("invalid data buffer for Host Behavior Support\n");
response->status.sct = SPDK_NVME_SCT_GENERIC; response->status.sct = SPDK_NVME_SCT_GENERIC;
response->status.sc = SPDK_NVME_SC_INVALID_FIELD; response->status.sc = SPDK_NVME_SC_INVALID_FIELD;
@ -1871,8 +1821,8 @@ nvmf_ctrlr_get_features_host_behavior_support(struct spdk_nvmf_request *req)
host_behavior.acre = ctrlr->acre_enabled; host_behavior.acre = ctrlr->acre_enabled;
_init_copy_iovs_ctx(&copy_ctx, req->iov, req->iovcnt); spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
_copy_buf_to_iovs(&copy_ctx, &host_behavior, sizeof(host_behavior)); spdk_iov_xfer_from_buf(&ix, &host_behavior, sizeof(host_behavior));
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
@ -2151,9 +2101,9 @@ nvmf_get_firmware_slot_log_page(struct iovec *iovs, int iovcnt, uint64_t offset,
{ {
struct spdk_nvme_firmware_page fw_page; struct spdk_nvme_firmware_page fw_page;
size_t copy_len; size_t copy_len;
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
_init_copy_iovs_ctx(&copy_ctx, iovs, iovcnt); spdk_iov_xfer_init(&ix, iovs, iovcnt);
memset(&fw_page, 0, sizeof(fw_page)); memset(&fw_page, 0, sizeof(fw_page));
fw_page.afi.active_slot = 1; fw_page.afi.active_slot = 1;
@ -2163,7 +2113,7 @@ nvmf_get_firmware_slot_log_page(struct iovec *iovs, int iovcnt, uint64_t offset,
if (offset < sizeof(fw_page)) { if (offset < sizeof(fw_page)) {
copy_len = spdk_min(sizeof(fw_page) - offset, length); copy_len = spdk_min(sizeof(fw_page) - offset, length);
if (copy_len > 0) { if (copy_len > 0) {
_copy_buf_to_iovs(&copy_ctx, (const char *)&fw_page + offset, copy_len); spdk_iov_xfer_from_buf(&ix, (const char *)&fw_page + offset, copy_len);
} }
} }
} }
@ -2259,9 +2209,9 @@ nvmf_get_ana_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *iovs, int iov
size_t copy_len, copied_len; size_t copy_len, copied_len;
uint32_t num_anagrp = 0, anagrpid; uint32_t num_anagrp = 0, anagrpid;
struct spdk_nvmf_ns *ns; struct spdk_nvmf_ns *ns;
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
_init_copy_iovs_ctx(&copy_ctx, iovs, iovcnt); spdk_iov_xfer_init(&ix, iovs, iovcnt);
if (length == 0) { if (length == 0) {
goto done; goto done;
@ -2283,7 +2233,7 @@ nvmf_get_ana_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *iovs, int iov
ana_hdr.change_count = 0; ana_hdr.change_count = 0;
copy_len = spdk_min(sizeof(ana_hdr) - offset, length); copy_len = spdk_min(sizeof(ana_hdr) - offset, length);
copied_len = _copy_buf_to_iovs(&copy_ctx, (const char *)&ana_hdr + offset, copy_len); copied_len = spdk_iov_xfer_from_buf(&ix, (const char *)&ana_hdr + offset, copy_len);
assert(copied_len == copy_len); assert(copied_len == copy_len);
length -= copied_len; length -= copied_len;
offset = 0; offset = 0;
@ -2308,8 +2258,8 @@ nvmf_get_ana_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *iovs, int iov
ana_desc.ana_state = nvmf_ctrlr_get_ana_state(ctrlr, anagrpid); ana_desc.ana_state = nvmf_ctrlr_get_ana_state(ctrlr, anagrpid);
copy_len = spdk_min(sizeof(ana_desc) - offset, length); copy_len = spdk_min(sizeof(ana_desc) - offset, length);
copied_len = _copy_buf_to_iovs(&copy_ctx, (const char *)&ana_desc + offset, copied_len = spdk_iov_xfer_from_buf(&ix, (const char *)&ana_desc + offset,
copy_len); copy_len);
assert(copied_len == copy_len); assert(copied_len == copy_len);
length -= copied_len; length -= copied_len;
offset = 0; offset = 0;
@ -2334,8 +2284,8 @@ nvmf_get_ana_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *iovs, int iov
} }
copy_len = spdk_min(sizeof(uint32_t) - offset, length); copy_len = spdk_min(sizeof(uint32_t) - offset, length);
copied_len = _copy_buf_to_iovs(&copy_ctx, (const char *)&ns->nsid + offset, copied_len = spdk_iov_xfer_from_buf(&ix, (const char *)&ns->nsid + offset,
copy_len); copy_len);
assert(copied_len == copy_len); assert(copied_len == copy_len);
length -= copied_len; length -= copied_len;
offset = 0; offset = 0;
@ -2385,14 +2335,14 @@ nvmf_get_changed_ns_list_log_page(struct spdk_nvmf_ctrlr *ctrlr,
struct iovec *iovs, int iovcnt, uint64_t offset, uint32_t length, uint32_t rae) struct iovec *iovs, int iovcnt, uint64_t offset, uint32_t length, uint32_t rae)
{ {
size_t copy_length; size_t copy_length;
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
_init_copy_iovs_ctx(&copy_ctx, iovs, iovcnt); spdk_iov_xfer_init(&ix, iovs, iovcnt);
if (offset < sizeof(ctrlr->changed_ns_list)) { if (offset < sizeof(ctrlr->changed_ns_list)) {
copy_length = spdk_min(length, sizeof(ctrlr->changed_ns_list) - offset); copy_length = spdk_min(length, sizeof(ctrlr->changed_ns_list) - offset);
if (copy_length) { if (copy_length) {
_copy_buf_to_iovs(&copy_ctx, (char *)&ctrlr->changed_ns_list + offset, copy_length); spdk_iov_xfer_from_buf(&ix, (char *)&ctrlr->changed_ns_list + offset, copy_length);
} }
} }
@ -2450,11 +2400,11 @@ nvmf_get_cmds_and_effects_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *
{ {
uint32_t page_size = sizeof(struct spdk_nvme_cmds_and_effect_log_page); uint32_t page_size = sizeof(struct spdk_nvme_cmds_and_effect_log_page);
size_t copy_len = 0; size_t copy_len = 0;
struct copy_iovs_ctx copy_ctx;
struct spdk_nvme_cmds_and_effect_log_page cmds_and_effect_log_page = g_cmds_and_effect_log_page; struct spdk_nvme_cmds_and_effect_log_page cmds_and_effect_log_page = g_cmds_and_effect_log_page;
struct spdk_nvme_cmds_and_effect_entry csupp_and_lbcc_effect_entry = {1, 1, 0, 0, 0, 0, 0, 0}; struct spdk_nvme_cmds_and_effect_entry csupp_and_lbcc_effect_entry = {1, 1, 0, 0, 0, 0, 0, 0};
struct spdk_iov_xfer ix;
_init_copy_iovs_ctx(&copy_ctx, iovs, iovcnt); spdk_iov_xfer_init(&ix, iovs, iovcnt);
if (offset < page_size) { if (offset < page_size) {
if (ctrlr->subsys->zone_append_supported) { if (ctrlr->subsys->zone_append_supported) {
@ -2462,7 +2412,7 @@ nvmf_get_cmds_and_effects_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *
csupp_and_lbcc_effect_entry; csupp_and_lbcc_effect_entry;
} }
copy_len = spdk_min(page_size - offset, length); copy_len = spdk_min(page_size - offset, length);
_copy_buf_to_iovs(&copy_ctx, (char *)(&cmds_and_effect_log_page) + offset, copy_len); spdk_iov_xfer_from_buf(&ix, (char *)(&cmds_and_effect_log_page) + offset, copy_len);
} }
} }
@ -2472,9 +2422,9 @@ nvmf_get_reservation_notification_log_page(struct spdk_nvmf_ctrlr *ctrlr,
{ {
uint32_t unit_log_len, avail_log_len, next_pos, copy_len; uint32_t unit_log_len, avail_log_len, next_pos, copy_len;
struct spdk_nvmf_reservation_log *log, *log_tmp; struct spdk_nvmf_reservation_log *log, *log_tmp;
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
_init_copy_iovs_ctx(&copy_ctx, iovs, iovcnt); spdk_iov_xfer_init(&ix, iovs, iovcnt);
unit_log_len = sizeof(struct spdk_nvme_reservation_notification_log); unit_log_len = sizeof(struct spdk_nvme_reservation_notification_log);
/* No available log, return zeroed log pages */ /* No available log, return zeroed log pages */
@ -2495,7 +2445,7 @@ nvmf_get_reservation_notification_log_page(struct spdk_nvmf_ctrlr *ctrlr,
next_pos += unit_log_len; next_pos += unit_log_len;
if (next_pos > offset) { if (next_pos > offset) {
copy_len = spdk_min(next_pos - offset, length); copy_len = spdk_min(next_pos - offset, length);
_copy_buf_to_iovs(&copy_ctx, &log->log, copy_len); spdk_iov_xfer_from_buf(&ix, &log->log, copy_len);
length -= copy_len; length -= copy_len;
offset += copy_len; offset += copy_len;
} }
@ -3055,9 +3005,9 @@ nvmf_ctrlr_identify(struct spdk_nvmf_request *req)
struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
int ret = SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; int ret = SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
char tmpbuf[SPDK_NVME_IDENTIFY_BUFLEN] = ""; char tmpbuf[SPDK_NVME_IDENTIFY_BUFLEN] = "";
struct copy_iovs_ctx copy_ctx; struct spdk_iov_xfer ix;
if (req->data == NULL || req->length < SPDK_NVME_IDENTIFY_BUFLEN) { if (req->iovcnt < 1 || req->length < SPDK_NVME_IDENTIFY_BUFLEN) {
SPDK_DEBUGLOG(nvmf, "identify command with invalid buffer\n"); SPDK_DEBUGLOG(nvmf, "identify command with invalid buffer\n");
rsp->status.sct = SPDK_NVME_SCT_GENERIC; rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
@ -3076,7 +3026,7 @@ nvmf_ctrlr_identify(struct spdk_nvmf_request *req)
* We must use a temporary buffer: it's entirely possible the out buffer * We must use a temporary buffer: it's entirely possible the out buffer
* is split across more than one IOV. * is split across more than one IOV.
*/ */
_init_copy_iovs_ctx(&copy_ctx, req->iov, req->iovcnt); spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
SPDK_DEBUGLOG(nvmf, "Received identify command with CNS 0x%02x\n", cns); SPDK_DEBUGLOG(nvmf, "Received identify command with CNS 0x%02x\n", cns);
@ -3105,7 +3055,7 @@ nvmf_ctrlr_identify(struct spdk_nvmf_request *req)
} }
if (ret == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE) { if (ret == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE) {
_copy_buf_to_iovs(&copy_ctx, tmpbuf, sizeof(tmpbuf)); spdk_iov_xfer_from_buf(&ix, tmpbuf, sizeof(tmpbuf));
} }
return ret; return ret;

View File

@ -581,7 +581,7 @@ nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
uint16_t nr, i; uint16_t nr, i;
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
struct spdk_nvme_dsm_range *dsm_range; struct spdk_iov_xfer ix;
uint64_t lba; uint64_t lba;
uint32_t lba_count; uint32_t lba_count;
int rc; int rc;
@ -611,10 +611,15 @@ nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
unmap_ctx->count--; /* dequeued */ unmap_ctx->count--; /* dequeued */
} }
dsm_range = (struct spdk_nvme_dsm_range *)req->data; spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
for (i = unmap_ctx->range_index; i < nr; i++) { for (i = unmap_ctx->range_index; i < nr; i++) {
lba = dsm_range[i].starting_lba; struct spdk_nvme_dsm_range dsm_range = { 0 };
lba_count = dsm_range[i].length;
spdk_iov_xfer_to_buf(&ix, &dsm_range, sizeof(dsm_range));
lba = dsm_range.starting_lba;
lba_count = dsm_range.length;
unmap_ctx->count++; unmap_ctx->count++;
@ -667,7 +672,8 @@ nvmf_bdev_ctrlr_copy_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
uint64_t sdlba = ((uint64_t)cmd->cdw11 << 32) + cmd->cdw10; uint64_t sdlba = ((uint64_t)cmd->cdw11 << 32) + cmd->cdw10;
struct spdk_nvme_scc_source_range *range; struct spdk_nvme_scc_source_range range = { 0 };
struct spdk_iov_xfer ix;
int rc; int rc;
SPDK_DEBUGLOG(nvmf, "Copy command: SDLBA %lu, NR %u, desc format %u, PRINFOR %u, " SPDK_DEBUGLOG(nvmf, "Copy command: SDLBA %lu, NR %u, desc format %u, PRINFOR %u, "
@ -696,7 +702,10 @@ nvmf_bdev_ctrlr_copy_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
/* We support only one source range */ /*
* We support only one source range, and rely on this with the xfer
* below.
*/
if (cmd->cdw12_bits.copy.nr > 0) { if (cmd->cdw12_bits.copy.nr > 0) {
response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; response->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
response->status.sc = SPDK_NVME_SC_CMD_SIZE_LIMIT_SIZE_EXCEEDED; response->status.sc = SPDK_NVME_SC_CMD_SIZE_LIMIT_SIZE_EXCEEDED;
@ -709,8 +718,10 @@ nvmf_bdev_ctrlr_copy_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
range = req->data; spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
rc = spdk_bdev_copy_blocks(desc, ch, sdlba, range->slba, range->nlb + 1, spdk_iov_xfer_to_buf(&ix, &range, sizeof(range));
rc = spdk_bdev_copy_blocks(desc, ch, sdlba, range.slba, range.nlb + 1,
nvmf_bdev_ctrlr_complete_cmd, req); nvmf_bdev_ctrlr_complete_cmd, req);
if (spdk_unlikely(rc)) { if (spdk_unlikely(rc)) {
if (rc == -ENOMEM) { if (rc == -ENOMEM) {

View File

@ -143,32 +143,80 @@ spdk_iovmove(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diov
return total_sz; return total_sz;
} }
void
spdk_iov_xfer_init(struct spdk_iov_xfer *ix, struct iovec *iovs, int iovcnt)
{
ix->iovs = iovs;
ix->iovcnt = iovcnt;
ix->cur_iov_idx = 0;
ix->cur_iov_offset = 0;
}
static size_t
iov_xfer(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len, bool to_buf)
{
size_t len, iov_remain_len, copied_len = 0;
struct iovec *iov;
if (buf_len == 0) {
return 0;
}
while (ix->cur_iov_idx < ix->iovcnt) {
iov = &ix->iovs[ix->cur_iov_idx];
iov_remain_len = iov->iov_len - ix->cur_iov_offset;
if (iov_remain_len == 0) {
ix->cur_iov_idx++;
ix->cur_iov_offset = 0;
continue;
}
len = spdk_min(iov_remain_len, buf_len - copied_len);
if (to_buf) {
memcpy((char *)buf + copied_len,
iov->iov_base + ix->cur_iov_offset, len);
} else {
memcpy((char *)iov->iov_base + ix->cur_iov_offset,
(const char *)buf + copied_len, len);
}
copied_len += len;
ix->cur_iov_offset += len;
if (buf_len == copied_len) {
return copied_len;
}
}
return copied_len;
}
size_t
spdk_iov_xfer_from_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len)
{
return iov_xfer(ix, buf, buf_len, false);
}
size_t
spdk_iov_xfer_to_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len)
{
return iov_xfer(ix, buf, buf_len, true);
}
void void
spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt) spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt)
{ {
int i; struct spdk_iov_xfer ix;
size_t len;
for (i = 0; i < iovcnt; i++) { spdk_iov_xfer_init(&ix, iovs, iovcnt);
len = spdk_min(iovs[i].iov_len, buf_len); spdk_iov_xfer_to_buf(&ix, buf, buf_len);
memcpy(buf, iovs[i].iov_base, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
} }
void void
spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len) spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len)
{ {
int i; struct spdk_iov_xfer ix;
size_t len;
for (i = 0; i < iovcnt; i++) { spdk_iov_xfer_init(&ix, iovs, iovcnt);
len = spdk_min(iovs[i].iov_len, buf_len); spdk_iov_xfer_from_buf(&ix, buf, buf_len);
memcpy(iovs[i].iov_base, buf, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
} }

View File

@ -137,6 +137,9 @@
spdk_ioviter_next; spdk_ioviter_next;
spdk_iov_memset; spdk_iov_memset;
spdk_iov_one; spdk_iov_one;
spdk_iov_xfer_init;
spdk_iov_xfer_from_buf;
spdk_iov_xfer_to_buf;
spdk_copy_iovs_to_buf; spdk_copy_iovs_to_buf;
spdk_copy_buf_to_iovs; spdk_copy_buf_to_iovs;
spdk_memset_s; spdk_memset_s;

View File

@ -281,6 +281,52 @@ test_iov_one(void)
CU_ASSERT(iovcnt == 1); CU_ASSERT(iovcnt == 1);
} }
static void
test_iov_xfer(void)
{
struct spdk_iov_xfer ix;
uint8_t data[64] = { 0 };
uint8_t iov_buffer[64];
struct iovec iov[4];
size_t i;
for (i = 0; i < sizeof(iov_buffer); i++) {
iov_buffer[i] = i;
}
iov[0].iov_base = iov_buffer;
iov[0].iov_len = 5;
iov[1].iov_base = iov[0].iov_base + iov[0].iov_len;
iov[1].iov_len = 15;
iov[2].iov_base = iov[1].iov_base + iov[1].iov_len;
iov[2].iov_len = 21;
iov[3].iov_base = iov[2].iov_base + iov[2].iov_len;
iov[3].iov_len = 23;
spdk_iov_xfer_init(&ix, iov, 4);
spdk_iov_xfer_to_buf(&ix, data, 8);
spdk_iov_xfer_to_buf(&ix, data + 8, 56);
for (i = 0; i < sizeof(data); i++) {
CU_ASSERT(data[i] == i);
}
for (i = 0; i < sizeof(data); i++) {
data[i] = sizeof(data) - i;
}
spdk_iov_xfer_init(&ix, iov, 4);
spdk_iov_xfer_from_buf(&ix, data, 5);
spdk_iov_xfer_from_buf(&ix, data + 5, 3);
spdk_iov_xfer_from_buf(&ix, data + 8, 56);
for (i = 0; i < sizeof(iov_buffer); i++) {
CU_ASSERT(iov_buffer[i] == sizeof(iov_buffer) - i);
}
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -299,6 +345,7 @@ main(int argc, char **argv)
CU_ADD_TEST(suite, test_buf_to_iovs); CU_ADD_TEST(suite, test_buf_to_iovs);
CU_ADD_TEST(suite, test_memset); CU_ADD_TEST(suite, test_memset);
CU_ADD_TEST(suite, test_iov_one); CU_ADD_TEST(suite, test_iov_one);
CU_ADD_TEST(suite, test_iov_xfer);
CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_set_mode(CU_BRM_VERBOSE);