1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/util.h" 35 36 size_t 37 spdk_ioviter_first(struct spdk_ioviter *iter, 38 struct iovec *siov, size_t siovcnt, 39 struct iovec *diov, size_t diovcnt, 40 void **src, void **dst) 41 { 42 iter->siov = siov; 43 iter->siovcnt = siovcnt; 44 45 iter->diov = diov; 46 iter->diovcnt = diovcnt; 47 48 iter->sidx = 0; 49 iter->didx = 0; 50 iter->siov_len = siov[0].iov_len; 51 iter->siov_base = siov[0].iov_base; 52 iter->diov_len = diov[0].iov_len; 53 iter->diov_base = diov[0].iov_base; 54 55 return spdk_ioviter_next(iter, src, dst); 56 } 57 58 size_t 59 spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst) 60 { 61 size_t len = 0; 62 63 if (iter->sidx == iter->siovcnt || 64 iter->didx == iter->diovcnt || 65 iter->siov_len == 0 || 66 iter->diov_len == 0) { 67 return 0; 68 } 69 70 *src = iter->siov_base; 71 *dst = iter->diov_base; 72 len = spdk_min(iter->siov_len, iter->diov_len); 73 74 if (iter->siov_len == iter->diov_len) { 75 /* Advance both iovs to the next element */ 76 iter->sidx++; 77 if (iter->sidx == iter->siovcnt) { 78 return len; 79 } 80 81 iter->didx++; 82 if (iter->didx == iter->diovcnt) { 83 return len; 84 } 85 86 iter->siov_len = iter->siov[iter->sidx].iov_len; 87 iter->siov_base = iter->siov[iter->sidx].iov_base; 88 iter->diov_len = iter->diov[iter->didx].iov_len; 89 iter->diov_base = iter->diov[iter->didx].iov_base; 90 } else if (iter->siov_len < iter->diov_len) { 91 /* Advance only the source to the next element */ 92 iter->sidx++; 93 if (iter->sidx == iter->siovcnt) { 94 return len; 95 } 96 97 iter->diov_base += iter->siov_len; 98 iter->diov_len -= iter->siov_len; 99 iter->siov_len = iter->siov[iter->sidx].iov_len; 100 iter->siov_base = iter->siov[iter->sidx].iov_base; 101 } else { 102 /* Advance only the destination to the next element */ 103 iter->didx++; 104 if (iter->didx == iter->diovcnt) { 105 return len; 106 } 107 108 iter->siov_base += iter->diov_len; 109 iter->siov_len -= iter->diov_len; 110 iter->diov_len = iter->diov[iter->didx].iov_len; 111 iter->diov_base = iter->diov[iter->didx].iov_base; 112 } 113 114 return len; 115 } 116 117 size_t 118 spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt) 119 { 120 struct spdk_ioviter iter; 121 size_t len, total_sz; 122 void *src, *dst; 123 124 total_sz = 0; 125 for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst); 126 len != 0; 127 len = spdk_ioviter_next(&iter, &src, &dst)) { 128 memcpy(dst, src, len); 129 total_sz += len; 130 } 131 132 return total_sz; 133 } 134