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