]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/core/linux-aio.hh
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / include / seastar / core / linux-aio.hh
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 (C) 2017 ScyllaDB
20 */
21
22 #pragma once
23
24 #include <endian.h>
25 #include <sys/time.h>
26 #include <sys/uio.h>
27 #include <signal.h>
28 #include <cstdint>
29
30 namespace seastar {
31
32 namespace internal {
33
34 namespace linux_abi {
35
36 using aio_context_t = unsigned long;
37
38 enum class iocb_cmd : uint16_t {
39 PREAD = 0,
40 PWRITE = 1,
41 FSYNC = 2,
42 FDSYNC = 3,
43 POLL = 5,
44 NOOP = 6,
45 PREADV = 7,
46 PWRITEV = 8,
47 };
48
49 struct io_event {
50 uint64_t data;
51 uint64_t obj;
52 int64_t res;
53 int64_t res2;
54 };
55
56 constexpr int IOCB_FLAG_RESFD = 1;
57
58 struct iocb {
59 uint64_t aio_data;
60
61 #if __BYTE_ORDER == __LITTLE_ENDIAN
62 uint32_t aio_key;
63 int32_t aio_rw_flags;
64 #elif __BYTE_ORDER == __BIG_ENDIAN
65 int32_t aio_rw_flags;
66 uint32_t aio_key;
67 #else
68 #error bad byteorder
69 #endif
70
71 iocb_cmd aio_lio_opcode;
72 int16_t aio_reqprio;
73 uint32_t aio_fildes;
74
75 uint64_t aio_buf;
76 uint64_t aio_nbytes;
77 int64_t aio_offset;
78
79 uint64_t aio_reserved2;
80
81 uint32_t aio_flags;
82
83 uint32_t aio_resfd;
84 };
85
86 struct aio_sigset {
87 const sigset_t *sigmask;
88 size_t sigsetsize;
89 };
90
91 }
92
93 linux_abi::iocb make_read_iocb(int fd, uint64_t offset, void* buffer, size_t len);
94 linux_abi::iocb make_write_iocb(int fd, uint64_t offset, const void* buffer, size_t len);
95 linux_abi::iocb make_readv_iocb(int fd, uint64_t offset, const ::iovec* iov, size_t niov);
96 linux_abi::iocb make_writev_iocb(int fd, uint64_t offset, const ::iovec* iov, size_t niov);
97 linux_abi::iocb make_poll_iocb(int fd, uint32_t events);
98
99 void set_user_data(linux_abi::iocb& iocb, void* data);
100 void* get_user_data(const linux_abi::iocb& iocb);
101 void set_nowait(linux_abi::iocb& iocb, bool nowait);
102
103 void set_eventfd_notification(linux_abi::iocb& iocb, int eventfd);
104
105 linux_abi::iocb* get_iocb(const linux_abi::io_event& ioev);
106
107 int io_setup(int nr_events, linux_abi::aio_context_t* io_context);
108 int io_destroy(linux_abi::aio_context_t io_context) noexcept;
109 int io_submit(linux_abi::aio_context_t io_context, long nr, linux_abi::iocb** iocbs);
110 int io_cancel(linux_abi::aio_context_t io_context, linux_abi::iocb* iocb, linux_abi::io_event* result);
111 int io_getevents(linux_abi::aio_context_t io_context, long min_nr, long nr, linux_abi::io_event* events, const ::timespec* timeout,
112 bool force_syscall = false);
113 int io_pgetevents(linux_abi::aio_context_t io_context, long min_nr, long nr, linux_abi::io_event* events, const ::timespec* timeout, const sigset_t* sigmask,
114 bool force_syscall = false);
115
116 void setup_aio_context(size_t nr, linux_abi::aio_context_t* io_context);
117
118 }
119
120 extern bool aio_nowait_supported;
121
122 namespace internal {
123
124 inline
125 linux_abi::iocb
126 make_read_iocb(int fd, uint64_t offset, void* buffer, size_t len) {
127 linux_abi::iocb iocb{};
128 iocb.aio_lio_opcode = linux_abi::iocb_cmd::PREAD;
129 iocb.aio_fildes = fd;
130 iocb.aio_offset = offset;
131 iocb.aio_buf = reinterpret_cast<uintptr_t>(buffer);
132 iocb.aio_nbytes = len;
133 return iocb;
134 }
135
136 inline
137 linux_abi::iocb
138 make_write_iocb(int fd, uint64_t offset, const void* buffer, size_t len) {
139 linux_abi::iocb iocb{};
140 iocb.aio_lio_opcode = linux_abi::iocb_cmd::PWRITE;
141 iocb.aio_fildes = fd;
142 iocb.aio_offset = offset;
143 iocb.aio_buf = reinterpret_cast<uintptr_t>(buffer);
144 iocb.aio_nbytes = len;
145 return iocb;
146 }
147
148 inline
149 linux_abi::iocb
150 make_readv_iocb(int fd, uint64_t offset, const ::iovec* iov, size_t niov) {
151 linux_abi::iocb iocb{};
152 iocb.aio_lio_opcode = linux_abi::iocb_cmd::PREADV;
153 iocb.aio_fildes = fd;
154 iocb.aio_offset = offset;
155 iocb.aio_buf = reinterpret_cast<uintptr_t>(iov);
156 iocb.aio_nbytes = niov;
157 return iocb;
158 }
159
160 inline
161 linux_abi::iocb
162 make_writev_iocb(int fd, uint64_t offset, const ::iovec* iov, size_t niov) {
163 linux_abi::iocb iocb{};
164 iocb.aio_lio_opcode = linux_abi::iocb_cmd::PWRITEV;
165 iocb.aio_fildes = fd;
166 iocb.aio_offset = offset;
167 iocb.aio_buf = reinterpret_cast<uintptr_t>(iov);
168 iocb.aio_nbytes = niov;
169 return iocb;
170 }
171
172 inline
173 linux_abi::iocb
174 make_poll_iocb(int fd, uint32_t events) {
175 linux_abi::iocb iocb{};
176 iocb.aio_lio_opcode = linux_abi::iocb_cmd::POLL;
177 iocb.aio_fildes = fd;
178 iocb.aio_buf = events;
179 return iocb;
180 }
181
182 inline
183 linux_abi::iocb
184 make_fdsync_iocb(int fd) {
185 linux_abi::iocb iocb{};
186 iocb.aio_lio_opcode = linux_abi::iocb_cmd::FDSYNC;
187 iocb.aio_fildes = fd;
188 return iocb;
189 }
190
191 inline
192 void
193 set_user_data(linux_abi::iocb& iocb, void* data) {
194 iocb.aio_data = reinterpret_cast<uintptr_t>(data);
195 }
196
197 inline
198 void*
199 get_user_data(const linux_abi::iocb& iocb) {
200 return reinterpret_cast<void*>(uintptr_t(iocb.aio_data));
201 }
202
203 inline
204 void
205 set_eventfd_notification(linux_abi::iocb& iocb, int eventfd) {
206 iocb.aio_flags |= linux_abi::IOCB_FLAG_RESFD;
207 iocb.aio_resfd = eventfd;
208 }
209
210 inline
211 linux_abi::iocb*
212 get_iocb(const linux_abi::io_event& ev) {
213 return reinterpret_cast<linux_abi::iocb*>(uintptr_t(ev.obj));
214 }
215
216 inline
217 void
218 set_nowait(linux_abi::iocb& iocb, bool nowait) {
219 #ifdef RWF_NOWAIT
220 if (aio_nowait_supported) {
221 if (nowait) {
222 iocb.aio_rw_flags |= RWF_NOWAIT;
223 } else {
224 iocb.aio_rw_flags &= ~RWF_NOWAIT;
225 }
226 }
227 #endif
228 }
229
230 }
231
232
233 }
234