1/* /usr/include/libaio.h
2 *
3 * Copyright 2000,2001,2002 Red Hat, Inc.
4 *
5 * Written by Benjamin LaHaise <bcrl@redhat.com>
6 *
7 * libaio Linux async I/O interface
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#ifndef __LIBAIO_H
24#define __LIBAIO_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30#include <sys/types.h>
31#include <string.h>
32
33struct timespec;
34struct sockaddr;
35struct iovec;
36
37typedef struct io_context *io_context_t;
38
39typedef enum io_iocb_cmd {
40 IO_CMD_PREAD = 0,
41 IO_CMD_PWRITE = 1,
42
43 IO_CMD_FSYNC = 2,
44 IO_CMD_FDSYNC = 3,
45
46 IO_CMD_POLL = 5, /* Never implemented in mainline, see io_prep_poll */
47 IO_CMD_NOOP = 6,
48 IO_CMD_PREADV = 7,
49 IO_CMD_PWRITEV = 8,
50} io_iocb_cmd_t;
51
52/* little endian, 32 bits */
53#if defined(__i386__) || (defined(__arm__) && !defined(__ARMEB__)) || \
54 (defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
55 defined(__bfin__) || \
56 (defined(__MIPSEL__) && !defined(__mips64)) || \
57 defined(__cris__)
58#define PADDED(x, y) x; unsigned y
59#define PADDEDptr(x, y) x; unsigned y
60#define PADDEDul(x, y) unsigned long x; unsigned y
61
62/* little endian, 64 bits */
63#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) || \
64 (defined(__mips64) && defined(__MIPSEL__)) || \
65 (defined(__aarch64__) && defined(__AARCH64EL__))
66#define PADDED(x, y) x, y
67#define PADDEDptr(x, y) x
68#define PADDEDul(x, y) unsigned long x
69
70/* big endian, 64 bits */
71#elif defined(__powerpc64__) || defined(__s390x__) || \
72 (defined(__hppa__) && defined(__arch64__)) || \
73 (defined(__sparc__) && defined(__arch64__)) || \
74 (defined(__mips64) && defined(__MIPSEB__)) || \
75 (defined(__aarch64__) && defined(__AARCH64EB__))
76#define PADDED(x, y) unsigned y; x
77#define PADDEDptr(x,y) x
78#define PADDEDul(x, y) unsigned long x
79
80/* big endian, 32 bits */
81#elif defined(__PPC__) || defined(__s390__) || \
82 (defined(__arm__) && defined(__ARMEB__)) || \
83 (defined(__sh__) && defined (__BIG_ENDIAN__)) || \
84 defined(__sparc__) || defined(__MIPSEB__) || defined(__m68k__) || \
85 defined(__hppa__) || defined(__frv__) || defined(__avr32__)
86#define PADDED(x, y) unsigned y; x
87#define PADDEDptr(x, y) unsigned y; x
88#define PADDEDul(x, y) unsigned y; unsigned long x
89
90#else
91#error endian?
92#endif
93
94struct io_iocb_poll {
95 PADDED(int events, __pad1);
96}; /* result code is the set of result flags or -'ve errno */
97
98struct io_iocb_sockaddr {
99 struct sockaddr *addr;
100 int len;
101}; /* result code is the length of the sockaddr, or -'ve errno */
102
103struct io_iocb_common {
104 PADDEDptr(void *buf, __pad1);
105 PADDEDul(nbytes, __pad2);
106 long long offset;
107 long long __pad3;
108 unsigned flags;
109 unsigned resfd;
110}; /* result code is the amount read or -'ve errno */
111
112struct io_iocb_vector {
113 const struct iovec *vec;
114 int nr;
115 long long offset;
116}; /* result code is the amount read or -'ve errno */
117
118struct iocb {
119 PADDEDptr(void *data, __pad1); /* Return in the io completion event */
120 PADDED(unsigned key, __pad2); /* For use in identifying io requests */
121
122 short aio_lio_opcode;
123 short aio_reqprio;
124 int aio_fildes;
125
126 union {
127 struct io_iocb_common c;
128 struct io_iocb_vector v;
129 struct io_iocb_poll poll;
130 struct io_iocb_sockaddr saddr;
131 } u;
132};
133
134struct io_event {
135 PADDEDptr(void *data, __pad1);
136 PADDEDptr(struct iocb *obj, __pad2);
137 PADDEDul(res, __pad3);
138 PADDEDul(res2, __pad4);
139};
140
141#undef PADDED
142#undef PADDEDptr
143#undef PADDEDul
144
145typedef void (*io_callback_t)(io_context_t ctx, struct iocb *iocb, long res, long res2);
146
147/* library wrappers */
148extern int io_queue_init(int maxevents, io_context_t *ctxp);
149/*extern int io_queue_grow(io_context_t ctx, int new_maxevents);*/
150extern int io_queue_release(io_context_t ctx);
151/*extern int io_queue_wait(io_context_t ctx, struct timespec *timeout);*/
152extern int io_queue_run(io_context_t ctx);
153
154/* Actual syscalls */
155extern int io_setup(int maxevents, io_context_t *ctxp);
156extern int io_destroy(io_context_t ctx);
157extern int io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
158extern int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
159extern int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
160
161
162static inline void io_set_callback(struct iocb *iocb, io_callback_t cb)
163{
164 iocb->data = (void *)cb;
165}
166
167static inline void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset)
168{
169 memset(iocb, 0, sizeof(*iocb));
170 iocb->aio_fildes = fd;
171 iocb->aio_lio_opcode = IO_CMD_PREAD;
172 iocb->aio_reqprio = 0;
173 iocb->u.c.buf = buf;
174 iocb->u.c.nbytes = count;
175 iocb->u.c.offset = offset;
176}
177
178static inline void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset)
179{
180 memset(iocb, 0, sizeof(*iocb));
181 iocb->aio_fildes = fd;
182 iocb->aio_lio_opcode = IO_CMD_PWRITE;
183 iocb->aio_reqprio = 0;
184 iocb->u.c.buf = buf;
185 iocb->u.c.nbytes = count;
186 iocb->u.c.offset = offset;
187}
188
189static inline void io_prep_preadv(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset)
190{
191 memset(iocb, 0, sizeof(*iocb));
192 iocb->aio_fildes = fd;
193 iocb->aio_lio_opcode = IO_CMD_PREADV;
194 iocb->aio_reqprio = 0;
195 iocb->u.c.buf = (void *)iov;
196 iocb->u.c.nbytes = iovcnt;
197 iocb->u.c.offset = offset;
198}
199
200static inline void io_prep_pwritev(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset)
201{
202 memset(iocb, 0, sizeof(*iocb));
203 iocb->aio_fildes = fd;
204 iocb->aio_lio_opcode = IO_CMD_PWRITEV;
205 iocb->aio_reqprio = 0;
206 iocb->u.c.buf = (void *)iov;
207 iocb->u.c.nbytes = iovcnt;
208 iocb->u.c.offset = offset;
209}
210
211/* Jeff Moyer says this was implemented in Red Hat AS2.1 and RHEL3.
212 * AFAICT, it was never in mainline, and should not be used. --RR */
213static inline void io_prep_poll(struct iocb *iocb, int fd, int events)
214{
215 memset(iocb, 0, sizeof(*iocb));
216 iocb->aio_fildes = fd;
217 iocb->aio_lio_opcode = IO_CMD_POLL;
218 iocb->aio_reqprio = 0;
219 iocb->u.poll.events = events;
220}
221
222static inline int io_poll(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd, int events)
223{
224 io_prep_poll(iocb, fd, events);
225 io_set_callback(iocb, cb);
226 return io_submit(ctx, 1, &iocb);
227}
228
229static inline void io_prep_fsync(struct iocb *iocb, int fd)
230{
231 memset(iocb, 0, sizeof(*iocb));
232 iocb->aio_fildes = fd;
233 iocb->aio_lio_opcode = IO_CMD_FSYNC;
234 iocb->aio_reqprio = 0;
235}
236
237static inline int io_fsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd)
238{
239 io_prep_fsync(iocb, fd);
240 io_set_callback(iocb, cb);
241 return io_submit(ctx, 1, &iocb);
242}
243
244static inline void io_prep_fdsync(struct iocb *iocb, int fd)
245{
246 memset(iocb, 0, sizeof(*iocb));
247 iocb->aio_fildes = fd;
248 iocb->aio_lio_opcode = IO_CMD_FDSYNC;
249 iocb->aio_reqprio = 0;
250}
251
252static inline int io_fdsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd)
253{
254 io_prep_fdsync(iocb, fd);
255 io_set_callback(iocb, cb);
256 return io_submit(ctx, 1, &iocb);
257}
258
259static inline void io_set_eventfd(struct iocb *iocb, int eventfd)
260{
261 iocb->u.c.flags |= (1 << 0) /* IOCB_FLAG_RESFD */;
262 iocb->u.c.resfd = eventfd;
263}
264
265#ifdef __cplusplus
266}
267#endif
268
269#endif /* __LIBAIO_H */
270