mirror of https://gitee.com/openkylin/qemu.git
iov: add qemu_iovec_concat_iov()
The qemu_iovec_concat() function copies a subset of a QEMUIOVector. The new qemu_iovec_concat_iov() function does the same for a iov/cnt pair. It is easy to define qemu_iovec_concat() in terms of qemu_iovec_concat_iov(). The existing code is mostly unchanged, except for the assertion src->size >= soffset, which cannot be efficiently checked upfront on a iov/cnt pair. Instead we assert upon hitting the end of src with an unsatisfied soffset. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
8962e44fe4
commit
530c0bbd73
|
@ -329,6 +329,9 @@ void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
||||||
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
|
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
|
||||||
void qemu_iovec_concat(QEMUIOVector *dst,
|
void qemu_iovec_concat(QEMUIOVector *dst,
|
||||||
QEMUIOVector *src, size_t soffset, size_t sbytes);
|
QEMUIOVector *src, size_t soffset, size_t sbytes);
|
||||||
|
void qemu_iovec_concat_iov(QEMUIOVector *dst,
|
||||||
|
struct iovec *src_iov, unsigned int src_cnt,
|
||||||
|
size_t soffset, size_t sbytes);
|
||||||
void qemu_iovec_destroy(QEMUIOVector *qiov);
|
void qemu_iovec_destroy(QEMUIOVector *qiov);
|
||||||
void qemu_iovec_reset(QEMUIOVector *qiov);
|
void qemu_iovec_reset(QEMUIOVector *qiov);
|
||||||
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
|
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
|
||||||
|
|
47
iov.c
47
iov.c
|
@ -288,6 +288,36 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
|
||||||
++qiov->niov;
|
++qiov->niov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Concatenates (partial) iovecs from src_iov to the end of dst.
|
||||||
|
* It starts copying after skipping `soffset' bytes at the
|
||||||
|
* beginning of src and adds individual vectors from src to
|
||||||
|
* dst copies up to `sbytes' bytes total, or up to the end
|
||||||
|
* of src_iov if it comes first. This way, it is okay to specify
|
||||||
|
* very large value for `sbytes' to indicate "up to the end
|
||||||
|
* of src".
|
||||||
|
* Only vector pointers are processed, not the actual data buffers.
|
||||||
|
*/
|
||||||
|
void qemu_iovec_concat_iov(QEMUIOVector *dst,
|
||||||
|
struct iovec *src_iov, unsigned int src_cnt,
|
||||||
|
size_t soffset, size_t sbytes)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
size_t done;
|
||||||
|
assert(dst->nalloc != -1);
|
||||||
|
for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) {
|
||||||
|
if (soffset < src_iov[i].iov_len) {
|
||||||
|
size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done);
|
||||||
|
qemu_iovec_add(dst, src_iov[i].iov_base + soffset, len);
|
||||||
|
done += len;
|
||||||
|
soffset = 0;
|
||||||
|
} else {
|
||||||
|
soffset -= src_iov[i].iov_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(soffset == 0); /* offset beyond end of src */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Concatenates (partial) iovecs from src to the end of dst.
|
* Concatenates (partial) iovecs from src to the end of dst.
|
||||||
* It starts copying after skipping `soffset' bytes at the
|
* It starts copying after skipping `soffset' bytes at the
|
||||||
|
@ -301,22 +331,7 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
|
||||||
void qemu_iovec_concat(QEMUIOVector *dst,
|
void qemu_iovec_concat(QEMUIOVector *dst,
|
||||||
QEMUIOVector *src, size_t soffset, size_t sbytes)
|
QEMUIOVector *src, size_t soffset, size_t sbytes)
|
||||||
{
|
{
|
||||||
int i;
|
qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
|
||||||
size_t done;
|
|
||||||
struct iovec *siov = src->iov;
|
|
||||||
assert(dst->nalloc != -1);
|
|
||||||
assert(src->size >= soffset);
|
|
||||||
for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
|
|
||||||
if (soffset < siov[i].iov_len) {
|
|
||||||
size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
|
|
||||||
qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
|
|
||||||
done += len;
|
|
||||||
soffset = 0;
|
|
||||||
} else {
|
|
||||||
soffset -= siov[i].iov_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* return done; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_iovec_destroy(QEMUIOVector *qiov)
|
void qemu_iovec_destroy(QEMUIOVector *qiov)
|
||||||
|
|
Loading…
Reference in New Issue