]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/lib/util/pipe.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / lib / util / pipe.c
CommitLineData
f67539c2
TL
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/pipe.h"
35#include "spdk/util.h"
36
37struct spdk_pipe {
38 uint8_t *buf;
39 uint32_t sz;
40
41 uint32_t write;
42 uint32_t read;
43};
44
45struct spdk_pipe *
46spdk_pipe_create(void *buf, uint32_t sz)
47{
48 struct spdk_pipe *pipe;
49
50 pipe = calloc(1, sizeof(*pipe));
51 if (pipe == NULL) {
52 return NULL;
53 }
54
55 pipe->buf = buf;
56 pipe->sz = sz;
57
58 return pipe;
59}
60
61void
62spdk_pipe_destroy(struct spdk_pipe *pipe)
63{
64 free(pipe);
65}
66
67int
68spdk_pipe_writer_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs)
69{
70 uint32_t sz;
71 uint32_t read;
72 uint32_t write;
73
74 read = pipe->read;
75 write = pipe->write;
76
77 if (read <= write) {
78 requested_sz = spdk_min(requested_sz, ((read + pipe->sz) - write - 1));
79
80 sz = spdk_min(requested_sz, pipe->sz - write);
81
82 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write);
83 iovs[0].iov_len = sz;
84
85 requested_sz -= sz;
86
87 if (requested_sz > 0) {
88 sz = spdk_min(requested_sz, read);
89
90 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
91 iovs[1].iov_len = sz;
92 } else {
93 iovs[1].iov_base = NULL;
94 iovs[1].iov_len = 0;
95 }
96 } else {
97 sz = spdk_min(requested_sz, read - write - 1);
98
99 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write);
100 iovs[0].iov_len = sz;
101 iovs[1].iov_base = NULL;
102 iovs[1].iov_len = 0;
103 }
104
105 return iovs[0].iov_len + iovs[1].iov_len;
106}
107
108int
109spdk_pipe_writer_advance(struct spdk_pipe *pipe, uint32_t requested_sz)
110{
111 uint32_t sz;
112 uint32_t read;
113 uint32_t write;
114
115 read = pipe->read;
116 write = pipe->write;
117
118 if (requested_sz > pipe->sz - 1) {
119 return -EINVAL;
120 }
121
122 if (read <= write) {
123 if (requested_sz > (read + pipe->sz) - write) {
124 return -EINVAL;
125 }
126
127 sz = spdk_min(requested_sz, pipe->sz - write);
128
129 write += sz;
130 if (write > pipe->sz - 1) {
131 write = 0;
132 }
133 requested_sz -= sz;
134
135 if (requested_sz > 0) {
136 if (requested_sz >= read) {
137 return -EINVAL;
138 }
139
140 write = requested_sz;
141 }
142 } else {
143 if (requested_sz > (read - write - 1)) {
144 return -EINVAL;
145 }
146
147 write += requested_sz;
148 }
149
150 pipe->write = write;
151
152 return 0;
153}
154
155uint32_t
156spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe)
157{
158 uint32_t read;
159 uint32_t write;
160
161 read = pipe->read;
162 write = pipe->write;
163
164 if (read <= write) {
165 return write - read;
166 }
167
168 return (write + pipe->sz) - read;
169}
170
171int
172spdk_pipe_reader_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs)
173{
174 uint32_t sz;
175 uint32_t read;
176 uint32_t write;
177
178 read = pipe->read;
179 write = pipe->write;
180
181 if (read <= write) {
182 sz = spdk_min(requested_sz, write - read);
183
184 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read);
185 iovs[0].iov_len = sz;
186 iovs[1].iov_base = NULL;
187 iovs[1].iov_len = 0;
188 } else {
189 sz = spdk_min(requested_sz, pipe->sz - read);
190
191 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read);
192 iovs[0].iov_len = sz;
193
194 requested_sz -= sz;
195
196 if (requested_sz > 0) {
197 sz = spdk_min(requested_sz, write);
198 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
199 iovs[1].iov_len = sz;
200 } else {
201 iovs[1].iov_base = NULL;
202 iovs[1].iov_len = 0;
203 }
204 }
205
206 return iovs[0].iov_len + iovs[1].iov_len;
207}
208
209int
210spdk_pipe_reader_advance(struct spdk_pipe *pipe, uint32_t requested_sz)
211{
212 uint32_t sz;
213 uint32_t read;
214 uint32_t write;
215
216 read = pipe->read;
217 write = pipe->write;
218
219 if (read <= write) {
220 if (requested_sz > (write - read)) {
221 return -EINVAL;
222 }
223
224 read += requested_sz;
225 } else {
226 sz = spdk_min(requested_sz, pipe->sz - read);
227
228 read += sz;
229 if (read > pipe->sz - 1) {
230 read = 0;
231 }
232 requested_sz -= sz;
233
234 if (requested_sz > 0) {
235 if (requested_sz > write) {
236 return -EINVAL;
237 }
238
239 read = requested_sz;
240 }
241 }
242
243 pipe->read = read;
244
245 return 0;
246}