diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2020-09-17 10:44:53 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2020-09-23 13:41:58 +0100 |
commit | 9dd6f7c28eaa7d001a526d51c74bbf89d5402b8c (patch) | |
tree | 5ce0c2924bf4607bbdbc892eb806b37971c52dff /util | |
parent | bd0bbb9aba2afbc2ea24b0475be04f795468b381 (diff) |
util/iov: add iov_discard_undo()
The iov_discard_front/back() operations are useful for parsing iovecs
but they modify the array elements. If the original array is needed
after parsing finishes there is currently no way to restore it.
Although g_memdup() can be used before performing destructive
iov_discard_front/back() operations, this is inefficient.
Introduce iov_discard_undo() to restore the array to the state prior to
an iov_discard_front/back() operation.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Message-Id: <20200917094455.822379-2-stefanha@redhat.com>
Diffstat (limited to 'util')
-rw-r--r-- | util/iov.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/util/iov.c b/util/iov.c index ae61d696aa..f3a9e92a37 100644 --- a/util/iov.c +++ b/util/iov.c @@ -636,14 +636,33 @@ void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf) } } -size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, - size_t bytes) +void iov_discard_undo(IOVDiscardUndo *undo) +{ + /* Restore original iovec if it was modified */ + if (undo->modified_iov) { + *undo->modified_iov = undo->orig; + } +} + +size_t iov_discard_front_undoable(struct iovec **iov, + unsigned int *iov_cnt, + size_t bytes, + IOVDiscardUndo *undo) { size_t total = 0; struct iovec *cur; + if (undo) { + undo->modified_iov = NULL; + } + for (cur = *iov; *iov_cnt > 0; cur++) { if (cur->iov_len > bytes) { + if (undo) { + undo->modified_iov = cur; + undo->orig = *cur; + } + cur->iov_base += bytes; cur->iov_len -= bytes; total += bytes; @@ -659,12 +678,24 @@ size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, return total; } -size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, - size_t bytes) +size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, + size_t bytes) +{ + return iov_discard_front_undoable(iov, iov_cnt, bytes, NULL); +} + +size_t iov_discard_back_undoable(struct iovec *iov, + unsigned int *iov_cnt, + size_t bytes, + IOVDiscardUndo *undo) { size_t total = 0; struct iovec *cur; + if (undo) { + undo->modified_iov = NULL; + } + if (*iov_cnt == 0) { return 0; } @@ -673,6 +704,11 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, while (*iov_cnt > 0) { if (cur->iov_len > bytes) { + if (undo) { + undo->modified_iov = cur; + undo->orig = *cur; + } + cur->iov_len -= bytes; total += bytes; break; @@ -687,6 +723,12 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, return total; } +size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt, + size_t bytes) +{ + return iov_discard_back_undoable(iov, iov_cnt, bytes, NULL); +} + void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes) { size_t total; |