Line data Source code
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 : #include "spdk/log.h"
8 :
9 : void
10 16 : spdk_iov_memset(struct iovec *iovs, int iovcnt, int c)
11 : {
12 16 : int iov_idx = 0;
13 : struct iovec *iov;
14 :
15 35 : while (iov_idx < iovcnt) {
16 19 : iov = &iovs[iov_idx];
17 19 : memset(iov->iov_base, c, iov->iov_len);
18 19 : iov_idx++;
19 : }
20 16 : }
21 :
22 : size_t
23 70 : spdk_ioviter_first(struct spdk_ioviter *iter,
24 : struct iovec *siov, size_t siovcnt,
25 : struct iovec *diov, size_t diovcnt,
26 : void **src, void **dst)
27 : {
28 : struct iovec *iovs[2];
29 : size_t iovcnts[2];
30 : void *out[2];
31 : size_t len;
32 :
33 70 : iovs[0] = siov;
34 70 : iovcnts[0] = siovcnt;
35 :
36 70 : iovs[1] = diov;
37 70 : iovcnts[1] = diovcnt;
38 :
39 70 : len = spdk_ioviter_firstv(iter, 2, iovs, iovcnts, out);
40 :
41 70 : if (len > 0) {
42 70 : *src = out[0];
43 70 : *dst = out[1];
44 70 : }
45 :
46 70 : return len;
47 : }
48 :
49 : size_t
50 70 : spdk_ioviter_firstv(struct spdk_ioviter *iter,
51 : uint32_t count,
52 : struct iovec **iov,
53 : size_t *iovcnt,
54 : void **out)
55 : {
56 : struct spdk_single_ioviter *it;
57 : uint32_t i;
58 :
59 70 : iter->count = count;
60 :
61 210 : for (i = 0; i < count; i++) {
62 140 : it = &iter->iters[i];
63 140 : it->iov = iov[i];
64 140 : it->iovcnt = iovcnt[i];
65 140 : it->idx = 0;
66 140 : it->iov_len = iov[i][0].iov_len;
67 140 : it->iov_base = iov[i][0].iov_base;
68 140 : }
69 :
70 70 : return spdk_ioviter_nextv(iter, out);
71 : }
72 :
73 : size_t
74 91 : spdk_ioviter_next(struct spdk_ioviter *iter, void **src, void **dst)
75 : {
76 : void *out[2];
77 : size_t len;
78 :
79 91 : len = spdk_ioviter_nextv(iter, out);
80 :
81 91 : if (len > 0) {
82 21 : *src = out[0];
83 21 : *dst = out[1];
84 21 : }
85 :
86 91 : return len;
87 : }
88 :
89 : size_t
90 161 : spdk_ioviter_nextv(struct spdk_ioviter *iter, void **out)
91 : {
92 : struct spdk_single_ioviter *it;
93 : size_t len;
94 : uint32_t i;
95 :
96 : /* Figure out the minimum size of each iovec's next segment */
97 161 : len = UINT32_MAX;
98 345 : for (i = 0; i < iter->count; i++) {
99 254 : it = &iter->iters[i];
100 254 : if (it->idx == it->iovcnt || it->iov_len == 0) {
101 : /* This element has 0 bytes remaining, so we're done. */
102 70 : return 0;
103 : }
104 :
105 184 : len = spdk_min(len, it->iov_len);
106 184 : }
107 :
108 273 : for (i = 0; i < iter->count; i++) {
109 182 : it = &iter->iters[i];
110 :
111 182 : out[i] = it->iov_base;
112 :
113 182 : if (it->iov_len == len) {
114 : /* Advance to next element */
115 164 : it->idx++;
116 164 : if (it->idx != it->iovcnt) {
117 : /* Set up for next element */
118 28 : it->iov_len = it->iov[it->idx].iov_len;
119 28 : it->iov_base = it->iov[it->idx].iov_base;
120 28 : }
121 164 : } else {
122 : /* Partial buffer */
123 18 : it->iov_base += len;
124 18 : it->iov_len -= len;
125 : }
126 182 : }
127 :
128 91 : return len;
129 161 : }
130 :
131 : size_t
132 26 : spdk_iovcpy(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt)
133 : {
134 : struct spdk_ioviter iter;
135 : size_t len, total_sz;
136 : void *src, *dst;
137 :
138 26 : total_sz = 0;
139 73 : for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst);
140 73 : len != 0;
141 47 : len = spdk_ioviter_next(&iter, &src, &dst)) {
142 47 : memcpy(dst, src, len);
143 47 : total_sz += len;
144 47 : }
145 :
146 26 : return total_sz;
147 : }
148 :
149 : size_t
150 35 : spdk_iovmove(struct iovec *siov, size_t siovcnt, struct iovec *diov, size_t diovcnt)
151 : {
152 : struct spdk_ioviter iter;
153 : size_t len, total_sz;
154 : void *src, *dst;
155 :
156 35 : total_sz = 0;
157 70 : for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst);
158 70 : len != 0;
159 35 : len = spdk_ioviter_next(&iter, &src, &dst)) {
160 35 : memmove(dst, src, len);
161 35 : total_sz += len;
162 35 : }
163 :
164 35 : return total_sz;
165 : }
166 :
167 : void
168 147 : spdk_iov_xfer_init(struct spdk_iov_xfer *ix, struct iovec *iovs, int iovcnt)
169 : {
170 147 : ix->iovs = iovs;
171 147 : ix->iovcnt = iovcnt;
172 147 : ix->cur_iov_idx = 0;
173 147 : ix->cur_iov_offset = 0;
174 147 : }
175 :
176 : static size_t
177 177 : iov_xfer(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len, bool to_buf)
178 : {
179 177 : size_t len, iov_remain_len, copied_len = 0;
180 : struct iovec *iov;
181 :
182 177 : if (buf_len == 0) {
183 0 : return 0;
184 : }
185 :
186 230 : while (ix->cur_iov_idx < ix->iovcnt) {
187 229 : iov = &ix->iovs[ix->cur_iov_idx];
188 229 : iov_remain_len = iov->iov_len - ix->cur_iov_offset;
189 229 : if (iov_remain_len == 0) {
190 27 : ix->cur_iov_idx++;
191 27 : ix->cur_iov_offset = 0;
192 27 : continue;
193 : }
194 :
195 202 : len = spdk_min(iov_remain_len, buf_len - copied_len);
196 :
197 202 : if (to_buf) {
198 204 : memcpy((char *)buf + copied_len,
199 102 : (char *)iov->iov_base + ix->cur_iov_offset, len);
200 102 : } else {
201 200 : memcpy((char *)iov->iov_base + ix->cur_iov_offset,
202 100 : (const char *)buf + copied_len, len);
203 : }
204 202 : copied_len += len;
205 202 : ix->cur_iov_offset += len;
206 :
207 202 : if (buf_len == copied_len) {
208 176 : return copied_len;
209 : }
210 : }
211 :
212 1 : return copied_len;
213 177 : }
214 :
215 : size_t
216 88 : spdk_iov_xfer_from_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len)
217 : {
218 88 : return iov_xfer(ix, buf, buf_len, false);
219 : }
220 :
221 : size_t
222 89 : spdk_iov_xfer_to_buf(struct spdk_iov_xfer *ix, const void *buf, size_t buf_len)
223 : {
224 89 : return iov_xfer(ix, buf, buf_len, true);
225 : }
226 :
227 : void
228 20 : spdk_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt)
229 : {
230 : struct spdk_iov_xfer ix;
231 :
232 20 : spdk_iov_xfer_init(&ix, iovs, iovcnt);
233 20 : spdk_iov_xfer_to_buf(&ix, buf, buf_len);
234 20 : }
235 :
236 : void
237 12 : spdk_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len)
238 : {
239 : struct spdk_iov_xfer ix;
240 :
241 12 : spdk_iov_xfer_init(&ix, iovs, iovcnt);
242 12 : spdk_iov_xfer_from_buf(&ix, buf, buf_len);
243 12 : }
|