1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/util.h" 7 8 size_t 9 spdk_ioviter_first(struct spdk_ioviter *iter, 10 struct iovec *siov, size_t siovcnt, 11 struct iovec *diov, size_t diovcnt, 12 void **src, void **dst) 13 { 14 iter->siov = siov; 15 iter->siovcnt = siovcnt; 16 17 iter->diov = diov; 18 iter->diovcnt = diovcnt; 19 20 iter->sidx = 0; 21 iter->didx = 0; 22 iter->siov_len = siov[0].iov_len; 23 iter->siov_base = siov[0].iov_base; 24 iter->diov_len = diov[0].iov_len; 25 iter->diov_base = diov[0].iov_base; 26 27 return spdk_ioviter_next(iter, src, dst); 28 } 29 30 size_t 31 spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst) 32 { 33 size_t len = 0; 34 35 if (iter->sidx == iter->siovcnt || 36 iter->didx == iter->diovcnt || 37 iter->siov_len == 0 || 38 iter->diov_len == 0) { 39 return 0; 40 } 41 42 *src = iter->siov_base; 43 *dst = iter->diov_base; 44 len = spdk_min(iter->siov_len, iter->diov_len); 45 46 if (iter->siov_len == iter->diov_len) { 47 /* Advance both iovs to the next element */ 48 iter->sidx++; 49 if (iter->sidx == iter->siovcnt) { 50 return len; 51 } 52 53 iter->didx++; 54 if (iter->didx == iter->diovcnt) { 55 return len; 56 } 57 58 iter->siov_len = iter->siov[iter->sidx].iov_len; 59 iter->siov_base = iter->siov[iter->sidx].iov_base; 60 iter->diov_len = iter->diov[iter->didx].iov_len; 61 iter->diov_base = iter->diov[iter->didx].iov_base; 62 } else if (iter->siov_len < iter->diov_len) { 63 /* Advance only the source to the next element */ 64 iter->sidx++; 65 if (iter->sidx == iter->siovcnt) { 66 return len; 67 } 68 69 iter->diov_base += iter->siov_len; 70 iter->diov_len -= iter->siov_len; 71 iter->siov_len = iter->siov[iter->sidx].iov_len; 72 iter->siov_base = iter->siov[iter->sidx].iov_base; 73 } else { 74 /* Advance only the destination to the next element */ 75 iter->didx++; 76 if (iter->didx == iter->diovcnt) { 77 return len; 78 } 79 80 iter->siov_base += iter->diov_len; 81 iter->siov_len -= iter->diov_len; 82 iter->diov_len = iter->diov[iter->didx].iov_len; 83 iter->diov_base = iter->diov[iter->didx].iov_base; 84 } 85 86 return len; 87 } 88 89 size_t 90 spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt) 91 { 92 struct spdk_ioviter iter; 93 size_t len, total_sz; 94 void *src, *dst; 95 96 total_sz = 0; 97 for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst); 98 len != 0; 99 len = spdk_ioviter_next(&iter, &src, &dst)) { 100 memcpy(dst, src, len); 101 total_sz += len; 102 } 103 104 return total_sz; 105 } 106 107 void 108 spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt) 109 { 110 int i; 111 size_t len; 112 113 for (i = 0; i < iovcnt; i++) { 114 len = spdk_min(iovs[i].iov_len, buf_len); 115 memcpy(buf, iovs[i].iov_base, len); 116 buf += len; 117 assert(buf_len >= len); 118 buf_len -= len; 119 } 120 } 121 122 void 123 spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len) 124 { 125 int i; 126 size_t len; 127 128 for (i = 0; i < iovcnt; i++) { 129 len = spdk_min(iovs[i].iov_len, buf_len); 130 memcpy(iovs[i].iov_base, buf, len); 131 buf += len; 132 assert(buf_len >= len); 133 buf_len -= len; 134 } 135 } 136