^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #ifndef LIB_URING_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #define LIB_URING_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #ifdef __cplusplus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) extern "C" {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sys/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "../../include/uapi/linux/io_uring.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/swab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "barrier.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Library interface to io_uring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct io_uring_sq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned *khead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned *ktail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned *kring_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned *kring_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned *kflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned *kdropped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned *array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct io_uring_sqe *sqes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned sqe_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned sqe_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) size_t ring_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct io_uring_cq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned *khead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned *ktail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned *kring_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned *kring_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned *koverflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct io_uring_cqe *cqes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) size_t ring_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct io_uring {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct io_uring_sq sq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct io_uring_cq cq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int ring_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * System calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) extern int io_uring_setup(unsigned entries, struct io_uring_params *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) extern int io_uring_enter(int fd, unsigned to_submit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned min_complete, unsigned flags, sigset_t *sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) extern int io_uring_register(int fd, unsigned int opcode, void *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int nr_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Library interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) extern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) extern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct io_uring *ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) extern void io_uring_queue_exit(struct io_uring *ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) extern int io_uring_peek_cqe(struct io_uring *ring,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct io_uring_cqe **cqe_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) extern int io_uring_wait_cqe(struct io_uring *ring,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct io_uring_cqe **cqe_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) extern int io_uring_submit(struct io_uring *ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * been processed by the application.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline void io_uring_cqe_seen(struct io_uring *ring,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct io_uring_cqe *cqe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (cqe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct io_uring_cq *cq = &ring->cq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) (*cq->khead)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Ensure that the kernel sees our new head, the kernel has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * the matching read barrier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) write_barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Command prep helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) sqe->user_data = (unsigned long) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return (void *) (uintptr_t) cqe->user_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const void *addr, unsigned len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) memset(sqe, 0, sizeof(*sqe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) sqe->opcode = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) sqe->fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) sqe->off = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) sqe->addr = (unsigned long) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sqe->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const struct iovec *iovecs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned nr_vecs, off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void *buf, unsigned nbytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const struct iovec *iovecs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned nr_vecs, off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const void *buf, unsigned nbytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned poll_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) memset(sqe, 0, sizeof(*sqe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sqe->opcode = IORING_OP_POLL_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) sqe->fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #if __BYTE_ORDER == __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) poll_mask = __swahw32(poll_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) sqe->poll_events = poll_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void *user_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) memset(sqe, 0, sizeof(*sqe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) sqe->opcode = IORING_OP_POLL_REMOVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sqe->addr = (unsigned long) user_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned fsync_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) memset(sqe, 0, sizeof(*sqe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) sqe->opcode = IORING_OP_FSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) sqe->fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) sqe->fsync_flags = fsync_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static inline void io_uring_prep_nop(struct io_uring_sqe *sqe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) memset(sqe, 0, sizeof(*sqe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) sqe->opcode = IORING_OP_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #ifdef __cplusplus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #endif