]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/include/seastar/core/internal/io_request.hh
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / include / seastar / core / internal / io_request.hh
CommitLineData
9f95a23c
TL
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright 2020 ScyllaDB
20 */
21
22#pragma once
23
24#include <seastar/core/sstring.hh>
25#include <seastar/core/linux-aio.hh>
26#include <seastar/core/internal/io_desc.hh>
20effc67 27#include <seastar/core/on_internal_error.hh>
9f95a23c
TL
28#include <sys/types.h>
29#include <sys/socket.h>
30
31namespace seastar {
20effc67
TL
32extern logger io_log;
33
9f95a23c
TL
34namespace internal {
35
36class io_request {
37public:
38 enum class operation { read, readv, write, writev, fdatasync, recv, recvmsg, send, sendmsg, accept, connect, poll_add, poll_remove, cancel };
39private:
40 operation _op;
41 int _fd;
42 union {
43 uint64_t pos;
44 int flags;
45 int events;
46 } _attr;
47 // the upper layers give us void pointers, but storing void pointers here is just
48 // dangerous. The constructors seem to be happy to convert other pointers to void*,
49 // even if they are marked as explicit, and then you end up losing approximately 3 hours
50 // and 15 minutes (hypothetically, of course), trying to chase the weirdest bug.
51 // Let's store a char* for safety, and cast it back to void* in the accessor.
52 union {
53 char* addr;
54 ::iovec* iovec;
55 ::msghdr* msghdr;
56 ::sockaddr* sockaddr;
57 } _ptr;
58
59 // accept wants a socklen_t*, connect wants a socklen_t
60 union {
61 size_t len;
62 socklen_t* socklen_ptr;
63 socklen_t socklen;
64 } _size;
20effc67
TL
65
66 bool _nowait_works;
9f95a23c
TL
67
68 explicit io_request(operation op, int fd, int flags, ::msghdr* msg)
69 : _op(op)
70 , _fd(fd)
71 {
72 _attr.flags = flags;
73 _ptr.msghdr = msg;
74 }
75
76 explicit io_request(operation op, int fd, sockaddr* sa, socklen_t sl)
77 : _op(op)
78 , _fd(fd)
79 {
80 _ptr.sockaddr = sa;
81 _size.socklen = sl;
82 }
83
84 explicit io_request(operation op, int fd, int flags, sockaddr* sa, socklen_t* sl)
85 : _op(op)
86 , _fd(fd)
87 {
88 _attr.flags = flags;
89 _ptr.sockaddr = sa;
90 _size.socklen_ptr = sl;
91 }
92 explicit io_request(operation op, int fd, uint64_t pos, char* ptr, size_t size)
93 : _op(op)
94 , _fd(fd)
95 {
96 _attr.pos = pos;
97 _ptr.addr = ptr;
98 _size.len = size;
99 }
100
20effc67
TL
101 explicit io_request(operation op, int fd, uint64_t pos, char* ptr, size_t size, bool nowait_works)
102 : _op(op)
103 , _fd(fd)
104 , _nowait_works(nowait_works)
105 {
106 _attr.pos = pos;
107 _ptr.addr = ptr;
108 _size.len = size;
109 }
110
111 explicit io_request(operation op, int fd, uint64_t pos, iovec* ptr, size_t size, bool nowait_works)
9f95a23c
TL
112 : _op(op)
113 , _fd(fd)
20effc67 114 , _nowait_works(nowait_works)
9f95a23c
TL
115 {
116 _attr.pos = pos;
117 _ptr.iovec = ptr;
118 _size.len = size;
119 }
120
121 explicit io_request(operation op, int fd)
122 : _op(op)
123 , _fd(fd)
124 {}
125 explicit io_request(operation op, int fd, int events)
126 : _op(op)
127 , _fd(fd)
128 {
129 _attr.events = events;
130 }
131
132 explicit io_request(operation op, int fd, char *ptr)
133 : _op(op)
134 , _fd(fd)
135 {
136 _ptr.addr = ptr;
137 }
138public:
139 bool is_read() const {
140 switch (_op) {
141 case operation::read:
142 case operation::readv:
143 case operation::recvmsg:
144 case operation::recv:
145 return true;
146 default:
147 return false;
148 }
149 }
150
151 bool is_write() const {
152 switch (_op) {
153 case operation::write:
154 case operation::writev:
155 case operation::send:
156 case operation::sendmsg:
157 return true;
158 default:
159 return false;
160 }
161 }
162
163 sstring opname() const;
164
165 operation opcode() const {
166 return _op;
167 }
168
169 int fd() const {
170 return _fd;
171 }
172
173 uint64_t pos() const {
174 return _attr.pos;
175 }
176
177 int flags() const {
178 return _attr.flags;
179 }
180
181 int events() const {
182 return _attr.events;
183 }
184
185 void* address() const {
186 return reinterpret_cast<void*>(_ptr.addr);
187 }
188
189 iovec* iov() const {
190 return _ptr.iovec;
191 }
192
193 ::sockaddr* posix_sockaddr() const {
194 return _ptr.sockaddr;
195 }
196
197 ::msghdr* msghdr() const {
198 return _ptr.msghdr;
199 }
200
201 size_t size() const {
202 return _size.len;
203 }
204
205 size_t iov_len() const {
206 return _size.len;
207 }
208
209 socklen_t socklen() const {
210 return _size.socklen;
211 }
212
213 socklen_t* socklen_ptr() const {
214 return _size.socklen_ptr;
215 }
216
20effc67
TL
217 bool nowait_works() const {
218 return _nowait_works;
9f95a23c
TL
219 }
220
20effc67
TL
221 static io_request make_read(int fd, uint64_t pos, void* address, size_t size, bool nowait_works) {
222 return io_request(operation::read, fd, pos, reinterpret_cast<char*>(address), size, nowait_works);
9f95a23c
TL
223 }
224
20effc67
TL
225 static io_request make_readv(int fd, uint64_t pos, std::vector<iovec>& iov, bool nowait_works) {
226 return io_request(operation::readv, fd, pos, iov.data(), iov.size(), nowait_works);
9f95a23c
TL
227 }
228
229 static io_request make_recv(int fd, void* address, size_t size, int flags) {
230 return io_request(operation::recv, fd, flags, reinterpret_cast<char*>(address), size);
231 }
232
233 static io_request make_recvmsg(int fd, ::msghdr* msg, int flags) {
234 return io_request(operation::recvmsg, fd, flags, msg);
235 }
236
237 static io_request make_send(int fd, const void* address, size_t size, int flags) {
238 return io_request(operation::send, fd, flags, const_cast<char*>(reinterpret_cast<const char*>(address)), size);
239 }
240
241 static io_request make_sendmsg(int fd, ::msghdr* msg, int flags) {
242 return io_request(operation::sendmsg, fd, flags, msg);
243 }
244
20effc67
TL
245 static io_request make_write(int fd, uint64_t pos, const void* address, size_t size, bool nowait_works) {
246 return io_request(operation::write, fd, pos, const_cast<char*>(reinterpret_cast<const char*>(address)), size, nowait_works);
9f95a23c
TL
247 }
248
20effc67
TL
249 static io_request make_writev(int fd, uint64_t pos, std::vector<iovec>& iov, bool nowait_works) {
250 return io_request(operation::writev, fd, pos, iov.data(), iov.size(), nowait_works);
9f95a23c
TL
251 }
252
253 static io_request make_fdatasync(int fd) {
254 return io_request(operation::fdatasync, fd);
255 }
256
257 static io_request make_accept(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
258 return io_request(operation::accept, fd, flags, addr, addrlen);
259 }
260
261 static io_request make_connect(int fd, struct sockaddr* addr, socklen_t addrlen) {
262 return io_request(operation::connect, fd, addr, addrlen);
263 }
264
265 static io_request make_poll_add(int fd, int events) {
266 return io_request(operation::poll_add, fd, events);
267 }
268
269 static io_request make_poll_remove(int fd, void *addr) {
270 return io_request(operation::poll_remove, fd, reinterpret_cast<char*>(addr));
271 }
272 static io_request make_cancel(int fd, void *addr) {
273 return io_request(operation::cancel, fd, reinterpret_cast<char*>(addr));
274 }
275};
20effc67
TL
276
277// Helper pair of IO direction and length
278struct io_direction_and_length {
279 size_t _directed_length; // bit 0 is R/W flag
280
281public:
282 io_direction_and_length(const io_request& rq, size_t val) {
283 _directed_length = val << 1;
284 if (rq.is_read()) {
285 _directed_length |= 0x1;
286 } else if (!rq.is_write()) {
287 on_internal_error(io_log, fmt::format("Unrecognized request passing through I/O queue {}", rq.opname()));
288 }
289 }
290
291 bool is_read() const noexcept { return (_directed_length & 0x1) == 1; }
292 bool is_write() const noexcept { return (_directed_length & 0x1) == 0; }
293 size_t length() const noexcept { return _directed_length >> 1; }
294 int rw_idx() const noexcept { return _directed_length & 0x1; }
295 static constexpr int read_idx = 1;
296 static constexpr int write_idx = 0;
297};
298
9f95a23c
TL
299}
300}