vhost: use DPDK APIs to split non-contiguous virtual memory buffers
Currently, we translate each 2MB chunk to manually check if it's contiguous with the previous one, but there are rte_vhost APIs that do it way more efficiently. rte_vhost_va_from_guest_pa() was introduced in DPDK 18.02, but was backported to 17.11 as well, so we don't even need any RTE_VERSION ifdefs to use it now. This function calculates the remaining region size instead of trying to translate subsequent 2MB chunks over and over. The previous rte_vhost_gpa_to_vva() was deprecated a long time ago and after this patch we no longer make any use of it. DPDK usages of this new function check if the translated memory region has 0 length, which seems very silly, but let's just do it in SPDK as well. Change-Id: Ifae8daa5f810b5a2ba1524958ad2399af700b532 Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454878 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
5931284f74
commit
ac498fa31c
@ -479,9 +479,8 @@ int
|
||||
spdk_vhost_vring_desc_to_iov(struct spdk_vhost_session *vsession, struct iovec *iov,
|
||||
uint16_t *iov_index, const struct vring_desc *desc)
|
||||
{
|
||||
uint32_t remaining = desc->len;
|
||||
uint32_t to_boundary;
|
||||
uint32_t len;
|
||||
uint64_t len;
|
||||
uint64_t remaining = desc->len;
|
||||
uintptr_t payload = desc->addr;
|
||||
uintptr_t vva;
|
||||
|
||||
@ -490,31 +489,12 @@ spdk_vhost_vring_desc_to_iov(struct spdk_vhost_session *vsession, struct iovec *
|
||||
SPDK_ERRLOG("SPDK_VHOST_IOVS_MAX(%d) reached\n", SPDK_VHOST_IOVS_MAX);
|
||||
return -1;
|
||||
}
|
||||
vva = (uintptr_t)rte_vhost_gpa_to_vva(vsession->mem, payload);
|
||||
if (vva == 0) {
|
||||
len = remaining;
|
||||
vva = (uintptr_t)rte_vhost_va_from_guest_pa(vsession->mem, payload, &len);
|
||||
if (vva == 0 || len == 0) {
|
||||
SPDK_ERRLOG("gpa_to_vva(%p) == NULL\n", (void *)payload);
|
||||
return -1;
|
||||
}
|
||||
to_boundary = VALUE_2MB - _2MB_OFFSET(payload);
|
||||
if (spdk_likely(remaining <= to_boundary)) {
|
||||
len = remaining;
|
||||
} else {
|
||||
/*
|
||||
* Descriptor crosses a 2MB hugepage boundary. vhost memory regions are allocated
|
||||
* from hugepage memory, so this means this descriptor may be described by
|
||||
* discontiguous vhost memory regions. Do not blindly split on the 2MB boundary,
|
||||
* only split it if the two sides of the boundary do not map to the same vhost
|
||||
* memory region. This helps ensure we do not exceed the max number of IOVs
|
||||
* defined by SPDK_VHOST_IOVS_MAX.
|
||||
*/
|
||||
len = to_boundary;
|
||||
while (len < remaining) {
|
||||
if (vva + len != (uintptr_t)rte_vhost_gpa_to_vva(vsession->mem, payload + len)) {
|
||||
break;
|
||||
}
|
||||
len += spdk_min(remaining - len, VALUE_2MB);
|
||||
}
|
||||
}
|
||||
iov[*iov_index].iov_base = (void *)vva;
|
||||
iov[*iov_index].iov_len = len;
|
||||
remaining -= len;
|
||||
|
Loading…
Reference in New Issue
Block a user