Spdk/lib/util/iov.c
yidong0635 dabca25646 util: Extract a common lib between iovs and buf.
It's useful to add these APIs.
spdk_copy_iovs_to_buf and spdk_copy_buf_to_iovs.

It prepares that other ones can call these.
We don't need to define them in static state
repeatedly.

And add corresponding unit tests.

Change-Id: Ife40fec8d047a48af67b04e6c055e4932282abfb
Signed-off-by: yidong0635 <dongx.yi@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12075
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2022-06-20 10:01:15 +00:00

136 lines
3.0 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "spdk/util.h"
size_t
spdk_ioviter_first(struct spdk_ioviter *iter,
struct iovec *siov, size_t siovcnt,
struct iovec *diov, size_t diovcnt,
void **src, void **dst)
{
iter->siov = siov;
iter->siovcnt = siovcnt;
iter->diov = diov;
iter->diovcnt = diovcnt;
iter->sidx = 0;
iter->didx = 0;
iter->siov_len = siov[0].iov_len;
iter->siov_base = siov[0].iov_base;
iter->diov_len = diov[0].iov_len;
iter->diov_base = diov[0].iov_base;
return spdk_ioviter_next(iter, src, dst);
}
size_t
spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst)
{
size_t len = 0;
if (iter->sidx == iter->siovcnt ||
iter->didx == iter->diovcnt ||
iter->siov_len == 0 ||
iter->diov_len == 0) {
return 0;
}
*src = iter->siov_base;
*dst = iter->diov_base;
len = spdk_min(iter->siov_len, iter->diov_len);
if (iter->siov_len == iter->diov_len) {
/* Advance both iovs to the next element */
iter->sidx++;
if (iter->sidx == iter->siovcnt) {
return len;
}
iter->didx++;
if (iter->didx == iter->diovcnt) {
return len;
}
iter->siov_len = iter->siov[iter->sidx].iov_len;
iter->siov_base = iter->siov[iter->sidx].iov_base;
iter->diov_len = iter->diov[iter->didx].iov_len;
iter->diov_base = iter->diov[iter->didx].iov_base;
} else if (iter->siov_len < iter->diov_len) {
/* Advance only the source to the next element */
iter->sidx++;
if (iter->sidx == iter->siovcnt) {
return len;
}
iter->diov_base += iter->siov_len;
iter->diov_len -= iter->siov_len;
iter->siov_len = iter->siov[iter->sidx].iov_len;
iter->siov_base = iter->siov[iter->sidx].iov_base;
} else {
/* Advance only the destination to the next element */
iter->didx++;
if (iter->didx == iter->diovcnt) {
return len;
}
iter->siov_base += iter->diov_len;
iter->siov_len -= iter->diov_len;
iter->diov_len = iter->diov[iter->didx].iov_len;
iter->diov_base = iter->diov[iter->didx].iov_base;
}
return len;
}
size_t
spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt)
{
struct spdk_ioviter iter;
size_t len, total_sz;
void *src, *dst;
total_sz = 0;
for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst);
len != 0;
len = spdk_ioviter_next(&iter, &src, &dst)) {
memcpy(dst, src, len);
total_sz += len;
}
return total_sz;
}
void
spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt)
{
int i;
size_t len;
for (i = 0; i < iovcnt; i++) {
len = spdk_min(iovs[i].iov_len, buf_len);
memcpy(buf, iovs[i].iov_base, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
}
void
spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len)
{
int i;
size_t len;
for (i = 0; i < iovcnt; i++) {
len = spdk_min(iovs[i].iov_len, buf_len);
memcpy(iovs[i].iov_base, buf, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
}