Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit f310970e737975088e41ea14c399450ba8ae3a49:

  t/aio-ring: cleanup the code a bit (2019-01-05 07:42:30 -0700)

are available in the Git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to 6e70fd303855575c99c520e8c46b7d85c9f21dc8:

  io_uring.h should include <linux/fs.h> (2019-01-08 05:43:38 -0700)

----------------------------------------------------------------
Jens Axboe (3):
      Rename t/aio-ring to t/io_uring
      Rename aioring engine to io_uring
      io_uring.h should include <linux/fs.h>

 Makefile                          |  15 +-
 arch/arch-x86_64.h                |   2 +-
 engines/{aioring.c => io_uring.c} | 283 ++++++++++++++------------------------
 options.c                         |   8 +-
 os/io_uring.h                     | 101 ++++++++++++++
 t/{aio-ring.c => io_uring.c}      | 121 ++++++----------
 6 files changed, 254 insertions(+), 276 deletions(-)
 rename engines/{aioring.c => io_uring.c} (58%)
 create mode 100644 os/io_uring.h
 rename t/{aio-ring.c => io_uring.c} (81%)

---

Diff of recent changes:

diff --git a/Makefile b/Makefile
index f111ae6a..5bc82f9a 100644
--- a/Makefile
+++ b/Makefile
@@ -68,9 +68,6 @@ endif
 ifdef CONFIG_LIBAIO
   SOURCE += engines/libaio.c
 endif
-ifdef CONFIG_LIBAIO
-  SOURCE += engines/aioring.c
-endif
 ifdef CONFIG_RDMA
   SOURCE += engines/rdma.c
 endif
@@ -154,7 +151,7 @@ endif
 
 ifeq ($(CONFIG_TARGET_OS), Linux)
   SOURCE += diskutil.c fifo.c blktrace.c cgroup.c trim.c engines/sg.c \
-		oslib/linux-dev-lookup.c
+		oslib/linux-dev-lookup.c engines/io_uring.c
   LIBS += -lpthread -ldl
   LDFLAGS += -rdynamic
 endif
@@ -266,8 +263,8 @@ T_VS_PROGS = t/fio-verify-state
 T_PIPE_ASYNC_OBJS = t/read-to-pipe-async.o
 T_PIPE_ASYNC_PROGS = t/read-to-pipe-async
 
-T_AIO_RING_OBJS = t/aio-ring.o
-T_AIO_RING_PROGS = t/aio-ring
+T_IOU_RING_OBJS = t/io_uring.o
+T_IOU_RING_PROGS = t/io_uring
 
 T_MEMLOCK_OBJS = t/memlock.o
 T_MEMLOCK_PROGS = t/memlock
@@ -287,7 +284,7 @@ T_OBJS += $(T_VS_OBJS)
 T_OBJS += $(T_PIPE_ASYNC_OBJS)
 T_OBJS += $(T_MEMLOCK_OBJS)
 T_OBJS += $(T_TT_OBJS)
-T_OBJS += $(T_AIO_RING_OBJS)
+T_OBJS += $(T_IOU_RING_OBJS)
 
 ifneq (,$(findstring CYGWIN,$(CONFIG_TARGET_OS)))
     T_DEDUPE_OBJS += os/windows/posix.o lib/hweight.o
@@ -447,8 +444,8 @@ cairo_text_helpers.o: cairo_text_helpers.c cairo_text_helpers.h
 printing.o: printing.c printing.h
 	$(QUIET_CC)$(CC) $(CFLAGS) $(GTK_CFLAGS) $(CPPFLAGS) -c $<
 
-t/aio-ring: $(T_AIO_RING_OBJS)
-	$(QUIET_LINK)$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(T_AIO_RING_OBJS) $(LIBS)
+t/io_uring: $(T_IOU_RING_OBJS)
+	$(QUIET_LINK)$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(T_IOU_RING_OBJS) $(LIBS)
 
 t/read-to-pipe-async: $(T_PIPE_ASYNC_OBJS)
 	$(QUIET_LINK)$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(T_PIPE_ASYNC_OBJS) $(LIBS)
diff --git a/arch/arch-x86_64.h b/arch/arch-x86_64.h
index d0a98b8b..a5864bab 100644
--- a/arch/arch-x86_64.h
+++ b/arch/arch-x86_64.h
@@ -44,7 +44,7 @@ static inline unsigned long long get_cpu_clock(void)
 #define ARCH_HAVE_FFZ
 #define ARCH_HAVE_SSE4_2
 #define ARCH_HAVE_CPU_CLOCK
-#define ARCH_HAVE_AIORING
+#define ARCH_HAVE_IOURING
 
 #define RDRAND_LONG	".byte 0x48,0x0f,0xc7,0xf0"
 #define RDSEED_LONG	".byte 0x48,0x0f,0xc7,0xf8"
diff --git a/engines/aioring.c b/engines/io_uring.c
similarity index 58%
rename from engines/aioring.c
rename to engines/io_uring.c
index 8cecb6ad..ebca08c8 100644
--- a/engines/aioring.c
+++ b/engines/io_uring.c
@@ -1,15 +1,14 @@
 /*
- * aioring engine
+ * io_uring engine
  *
- * IO engine using the new native Linux libaio ring interface. See:
+ * IO engine using the new native Linux aio io_uring interface. See:
  *
- * http://git.kernel.dk/cgit/linux-block/log/?h=aio-poll
+ * http://git.kernel.dk/cgit/linux-block/log/?h=io_uring
  *
  */
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <libaio.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 
@@ -19,81 +18,17 @@
 #include "../lib/memalign.h"
 #include "../lib/fls.h"
 
-#ifdef ARCH_HAVE_AIORING
-
-/*
- * io_uring_setup(2) flags
- */
-#ifndef IOCTX_FLAG_SCQRING
-#define IOCTX_FLAG_SCQRING	(1 << 0)
-#endif
-#ifndef IOCTX_FLAG_IOPOLL
-#define IOCTX_FLAG_IOPOLL	(1 << 1)
-#endif
-#ifndef IOCTX_FLAG_FIXEDBUFS
-#define IOCTX_FLAG_FIXEDBUFS	(1 << 2)
-#endif
-#ifndef IOCTX_FLAG_SQTHREAD
-#define IOCTX_FLAG_SQTHREAD	(1 << 3)
-#endif
-#ifndef IOCTX_FLAG_SQWQ
-#define IOCTX_FLAG_SQWQ		(1 << 4)
-#endif
-#ifndef IOCTX_FLAG_SQPOLL
-#define IOCTX_FLAG_SQPOLL	(1 << 5)
-#endif
-
-#define IORING_OFF_SQ_RING	0ULL
-#define IORING_OFF_CQ_RING	0x8000000ULL
-#define IORING_OFF_IOCB		0x10000000ULL
-
-/*
- * io_uring_enter(2) flags
- */
-#ifndef IORING_ENTER_GETEVENTS
-#define IORING_ENTER_GETEVENTS	(1 << 0)
-#endif
+#ifdef ARCH_HAVE_IOURING
 
 typedef uint64_t u64;
 typedef uint32_t u32;
+typedef int32_t s32;
 typedef uint16_t u16;
+typedef uint8_t u8;
 
-#define IORING_SQ_NEED_WAKEUP	(1 << 0)
-
-#define IOEV_RES2_CACHEHIT	(1 << 0)
-
-struct aio_sqring_offsets {
-	u32 head;
-	u32 tail;
-	u32 ring_mask;
-	u32 ring_entries;
-	u32 flags;
-	u32 dropped;
-	u32 array;
-	u32 resv[3];
-};
-
-struct aio_cqring_offsets {
-	u32 head;
-	u32 tail;
-	u32 ring_mask;
-	u32 ring_entries;
-	u32 overflow;
-	u32 events;
-	u32 resv[4];
-};
-
-struct aio_uring_params {
-	u32 sq_entries;
-	u32 cq_entries;
-	u32 flags;
-	u16 sq_thread_cpu;
-	u16 resv[9];
-	struct aio_sqring_offsets sq_off;
-	struct aio_cqring_offsets cq_off;
-};
+#include "../os/io_uring.h"
 
-struct aio_sq_ring {
+struct io_sq_ring {
 	u32 *head;
 	u32 *tail;
 	u32 *ring_mask;
@@ -102,32 +37,31 @@ struct aio_sq_ring {
 	u32 *array;
 };
 
-struct aio_cq_ring {
+struct io_cq_ring {
 	u32 *head;
 	u32 *tail;
 	u32 *ring_mask;
 	u32 *ring_entries;
-	struct io_event *events;
+	struct io_uring_event *events;
 };
 
-struct aioring_mmap {
+struct ioring_mmap {
 	void *ptr;
 	size_t len;
 };
 
-struct aioring_data {
+struct ioring_data {
 	int ring_fd;
 
 	struct io_u **io_us;
 	struct io_u **io_u_index;
 
-	struct aio_sq_ring sq_ring;
-	struct iocb *iocbs;
+	struct io_sq_ring sq_ring;
+	struct io_uring_iocb *iocbs;
 	struct iovec *iovecs;
 	unsigned sq_ring_mask;
 
-	struct aio_cq_ring cq_ring;
-	struct io_event *events;
+	struct io_cq_ring cq_ring;
 	unsigned cq_ring_mask;
 
 	int queued;
@@ -137,10 +71,10 @@ struct aioring_data {
 	uint64_t cachehit;
 	uint64_t cachemiss;
 
-	struct aioring_mmap mmap[3];
+	struct ioring_mmap mmap[3];
 };
 
-struct aioring_options {
+struct ioring_options {
 	void *pad;
 	unsigned int hipri;
 	unsigned int fixedbufs;
@@ -150,10 +84,9 @@ struct aioring_options {
 	unsigned int sqwq;
 };
 
-static int fio_aioring_sqthread_cb(void *data,
-				   unsigned long long *val)
+static int fio_ioring_sqthread_cb(void *data, unsigned long long *val)
 {
-	struct aioring_options *o = data;
+	struct ioring_options *o = data;
 
 	o->sqthread = *val;
 	o->sqthread_set = 1;
@@ -165,7 +98,7 @@ static struct fio_option options[] = {
 		.name	= "hipri",
 		.lname	= "High Priority",
 		.type	= FIO_OPT_STR_SET,
-		.off1	= offsetof(struct aioring_options, hipri),
+		.off1	= offsetof(struct ioring_options, hipri),
 		.help	= "Use polled IO completions",
 		.category = FIO_OPT_C_ENGINE,
 		.group	= FIO_OPT_G_LIBAIO,
@@ -174,7 +107,7 @@ static struct fio_option options[] = {
 		.name	= "fixedbufs",
 		.lname	= "Fixed (pre-mapped) IO buffers",
 		.type	= FIO_OPT_STR_SET,
-		.off1	= offsetof(struct aioring_options, fixedbufs),
+		.off1	= offsetof(struct ioring_options, fixedbufs),
 		.help	= "Pre map IO buffers",
 		.category = FIO_OPT_C_ENGINE,
 		.group	= FIO_OPT_G_LIBAIO,
@@ -183,7 +116,7 @@ static struct fio_option options[] = {
 		.name	= "sqthread",
 		.lname	= "Use kernel SQ thread on this CPU",
 		.type	= FIO_OPT_INT,
-		.cb	= fio_aioring_sqthread_cb,
+		.cb	= fio_ioring_sqthread_cb,
 		.help	= "Offload submission to kernel thread",
 		.category = FIO_OPT_C_ENGINE,
 		.group	= FIO_OPT_G_LIBAIO,
@@ -192,7 +125,7 @@ static struct fio_option options[] = {
 		.name	= "sqthread_poll",
 		.lname	= "Kernel SQ thread should poll",
 		.type	= FIO_OPT_STR_SET,
-		.off1	= offsetof(struct aioring_options, sqthread_poll),
+		.off1	= offsetof(struct ioring_options, sqthread_poll),
 		.help	= "Used with sqthread, enables kernel side polling",
 		.category = FIO_OPT_C_ENGINE,
 		.group	= FIO_OPT_G_LIBAIO,
@@ -201,7 +134,7 @@ static struct fio_option options[] = {
 		.name	= "sqwq",
 		.lname	= "Offload submission to kernel workqueue",
 		.type	= FIO_OPT_STR_SET,
-		.off1	= offsetof(struct aioring_options, sqwq),
+		.off1	= offsetof(struct ioring_options, sqwq),
 		.help	= "Offload submission to kernel workqueue",
 		.category = FIO_OPT_C_ENGINE,
 		.group	= FIO_OPT_G_LIBAIO,
@@ -211,50 +144,49 @@ static struct fio_option options[] = {
 	},
 };
 
-static int io_uring_enter(struct aioring_data *ld, unsigned int to_submit,
+static int io_uring_enter(struct ioring_data *ld, unsigned int to_submit,
 			 unsigned int min_complete, unsigned int flags)
 {
 	return syscall(__NR_sys_io_uring_enter, ld->ring_fd, to_submit,
 			min_complete, flags);
 }
 
-static int fio_aioring_prep(struct thread_data *td, struct io_u *io_u)
+static int fio_ioring_prep(struct thread_data *td, struct io_u *io_u)
 {
-	struct aioring_data *ld = td->io_ops_data;
+	struct ioring_data *ld = td->io_ops_data;
 	struct fio_file *f = io_u->file;
-	struct iocb *iocb;
+	struct io_uring_iocb *iocb;
 
 	iocb = &ld->iocbs[io_u->index];
+	iocb->fd = f->fd;
+	iocb->flags = 0;
+	iocb->ioprio = 0;
 
 	if (io_u->ddir == DDIR_READ || io_u->ddir == DDIR_WRITE) {
 		if (io_u->ddir == DDIR_READ)
-			iocb->aio_lio_opcode = IO_CMD_PREAD;
+			iocb->opcode = IORING_OP_READ;
 		else
-			iocb->aio_lio_opcode = IO_CMD_PWRITE;
-		iocb->aio_reqprio = 0;
-		iocb->aio_fildes = f->fd;
-		iocb->u.c.buf = io_u->xfer_buf;
-		iocb->u.c.nbytes = io_u->xfer_buflen;
-		iocb->u.c.offset = io_u->offset;
-		iocb->u.c.flags = 0;
+			iocb->opcode = IORING_OP_WRITE;
+		iocb->off = io_u->offset;
+		iocb->addr = io_u->xfer_buf;
+		iocb->len = io_u->xfer_buflen;
 	} else if (ddir_sync(io_u->ddir))
-		io_prep_fsync(iocb, f->fd);
+		iocb->opcode = IORING_OP_FSYNC;
 
-	iocb->data = io_u;
 	return 0;
 }
 
-static struct io_u *fio_aioring_event(struct thread_data *td, int event)
+static struct io_u *fio_ioring_event(struct thread_data *td, int event)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct io_event *ev;
+	struct ioring_data *ld = td->io_ops_data;
+	struct io_uring_event *ev;
 	struct io_u *io_u;
 	unsigned index;
 
 	index = (event + ld->cq_ring_off) & ld->cq_ring_mask;
 
 	ev = &ld->cq_ring.events[index];
-	io_u = ev->data;
+	io_u = ld->io_u_index[ev->index];
 
 	if (ev->res != io_u->xfer_buflen) {
 		if (ev->res > io_u->xfer_buflen)
@@ -265,7 +197,7 @@ static struct io_u *fio_aioring_event(struct thread_data *td, int event)
 		io_u->error = 0;
 
 	if (io_u->ddir == DDIR_READ) {
-		if (ev->res2 & IOEV_RES2_CACHEHIT)
+		if (ev->flags & IOEV_FLAG_CACHEHIT)
 			ld->cachehit++;
 		else
 			ld->cachemiss++;
@@ -274,11 +206,11 @@ static struct io_u *fio_aioring_event(struct thread_data *td, int event)
 	return io_u;
 }
 
-static int fio_aioring_cqring_reap(struct thread_data *td, unsigned int events,
+static int fio_ioring_cqring_reap(struct thread_data *td, unsigned int events,
 				   unsigned int max)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct aio_cq_ring *ring = &ld->cq_ring;
+	struct ioring_data *ld = td->io_ops_data;
+	struct io_cq_ring *ring = &ld->cq_ring;
 	u32 head, reaped = 0;
 
 	head = *ring->head;
@@ -295,19 +227,19 @@ static int fio_aioring_cqring_reap(struct thread_data *td, unsigned int events,
 	return reaped;
 }
 
-static int fio_aioring_getevents(struct thread_data *td, unsigned int min,
-				 unsigned int max, const struct timespec *t)
+static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
+				unsigned int max, const struct timespec *t)
 {
-	struct aioring_data *ld = td->io_ops_data;
+	struct ioring_data *ld = td->io_ops_data;
 	unsigned actual_min = td->o.iodepth_batch_complete_min == 0 ? 0 : min;
-	struct aioring_options *o = td->eo;
-	struct aio_cq_ring *ring = &ld->cq_ring;
+	struct ioring_options *o = td->eo;
+	struct io_cq_ring *ring = &ld->cq_ring;
 	unsigned events = 0;
 	int r;
 
 	ld->cq_ring_off = *ring->head;
 	do {
-		r = fio_aioring_cqring_reap(td, events, max);
+		r = fio_ioring_cqring_reap(td, events, max);
 		if (r) {
 			events += r;
 			continue;
@@ -328,11 +260,11 @@ static int fio_aioring_getevents(struct thread_data *td, unsigned int min,
 	return r < 0 ? r : events;
 }
 
-static enum fio_q_status fio_aioring_queue(struct thread_data *td,
-					   struct io_u *io_u)
+static enum fio_q_status fio_ioring_queue(struct thread_data *td,
+					  struct io_u *io_u)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct aio_sq_ring *ring = &ld->sq_ring;
+	struct ioring_data *ld = td->io_ops_data;
+	struct io_sq_ring *ring = &ld->sq_ring;
 	unsigned tail, next_tail;
 
 	fio_ro_check(td, io_u);
@@ -364,9 +296,9 @@ static enum fio_q_status fio_aioring_queue(struct thread_data *td,
 	return FIO_Q_QUEUED;
 }
 
-static void fio_aioring_queued(struct thread_data *td, int start, int nr)
+static void fio_ioring_queued(struct thread_data *td, int start, int nr)
 {
-	struct aioring_data *ld = td->io_ops_data;
+	struct ioring_data *ld = td->io_ops_data;
 	struct timespec now;
 
 	if (!fio_fill_issue_time(td))
@@ -375,7 +307,7 @@ static void fio_aioring_queued(struct thread_data *td, int start, int nr)
 	fio_gettime(&now, NULL);
 
 	while (nr--) {
-		struct aio_sq_ring *ring = &ld->sq_ring;
+		struct io_sq_ring *ring = &ld->sq_ring;
 		int index = ring->array[start & ld->sq_ring_mask];
 		struct io_u *io_u = ld->io_u_index[index];
 
@@ -386,10 +318,10 @@ static void fio_aioring_queued(struct thread_data *td, int start, int nr)
 	}
 }
 
-static int fio_aioring_commit(struct thread_data *td)
+static int fio_ioring_commit(struct thread_data *td)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct aioring_options *o = td->eo;
+	struct ioring_data *ld = td->io_ops_data;
+	struct ioring_options *o = td->eo;
 	int ret;
 
 	if (!ld->queued)
@@ -397,7 +329,7 @@ static int fio_aioring_commit(struct thread_data *td)
 
 	/* Nothing to do */
 	if (o->sqthread_poll) {
-		struct aio_sq_ring *ring = &ld->sq_ring;
+		struct io_sq_ring *ring = &ld->sq_ring;
 
 		if (*ring->flags & IORING_SQ_NEED_WAKEUP)
 			io_uring_enter(ld, ld->queued, 0, 0);
@@ -411,7 +343,7 @@ static int fio_aioring_commit(struct thread_data *td)
 
 		ret = io_uring_enter(ld, nr, 0, IORING_ENTER_GETEVENTS);
 		if (ret > 0) {
-			fio_aioring_queued(td, start, ret);
+			fio_ioring_queued(td, start, ret);
 			io_u_mark_submit(td, ret);
 
 			ld->queued -= ret;
@@ -421,7 +353,7 @@ static int fio_aioring_commit(struct thread_data *td)
 			continue;
 		} else {
 			if (errno == EAGAIN) {
-				ret = fio_aioring_cqring_reap(td, 0, ld->queued);
+				ret = fio_ioring_cqring_reap(td, 0, ld->queued);
 				if (ret)
 					continue;
 				/* Shouldn't happen */
@@ -436,7 +368,7 @@ static int fio_aioring_commit(struct thread_data *td)
 	return ret;
 }
 
-static void fio_aioring_unmap(struct aioring_data *ld)
+static void fio_ioring_unmap(struct ioring_data *ld)
 {
 	int i;
 
@@ -445,22 +377,16 @@ static void fio_aioring_unmap(struct aioring_data *ld)
 	close(ld->ring_fd);
 }
 
-static void fio_aioring_cleanup(struct thread_data *td)
+static void fio_ioring_cleanup(struct thread_data *td)
 {
-	struct aioring_data *ld = td->io_ops_data;
+	struct ioring_data *ld = td->io_ops_data;
 
 	if (ld) {
 		td->ts.cachehit += ld->cachehit;
 		td->ts.cachemiss += ld->cachemiss;
 
-		/*
-		 * Work-around to avoid huge RCU stalls at exit time. If we
-		 * don't do this here, then it'll be torn down by exit_aio().
-		 * But for that case we can parallellize the freeing, thus
-		 * speeding it up a lot.
-		 */
 		if (!(td->flags & TD_F_CHILD))
-			fio_aioring_unmap(ld);
+			fio_ioring_unmap(ld);
 
 		free(ld->io_u_index);
 		free(ld->io_us);
@@ -469,10 +395,10 @@ static void fio_aioring_cleanup(struct thread_data *td)
 	}
 }
 
-static int fio_aioring_mmap(struct aioring_data *ld, struct aio_uring_params *p)
+static int fio_ioring_mmap(struct ioring_data *ld, struct io_uring_params *p)
 {
-	struct aio_sq_ring *sring = &ld->sq_ring;
-	struct aio_cq_ring *cring = &ld->cq_ring;
+	struct io_sq_ring *sring = &ld->sq_ring;
+	struct io_cq_ring *cring = &ld->cq_ring;
 	void *ptr;
 
 	ld->mmap[0].len = p->sq_off.array + p->sq_entries * sizeof(u32);
@@ -488,14 +414,14 @@ static int fio_aioring_mmap(struct aioring_data *ld, struct aio_uring_params *p)
 	sring->array = ptr + p->sq_off.array;
 	ld->sq_ring_mask = *sring->ring_mask;
 
-	ld->mmap[1].len = p->sq_entries * sizeof(struct iocb);
+	ld->mmap[1].len = p->sq_entries * sizeof(struct io_uring_iocb);
 	ld->iocbs = mmap(0, ld->mmap[1].len, PROT_READ | PROT_WRITE,
 				MAP_SHARED | MAP_POPULATE, ld->ring_fd,
 				IORING_OFF_IOCB);
 	ld->mmap[1].ptr = ld->iocbs;
 
 	ld->mmap[2].len = p->cq_off.events +
-				p->cq_entries * sizeof(struct io_event);
+				p->cq_entries * sizeof(struct io_uring_event);
 	ptr = mmap(0, ld->mmap[2].len, PROT_READ | PROT_WRITE,
 			MAP_SHARED | MAP_POPULATE, ld->ring_fd,
 			IORING_OFF_CQ_RING);
@@ -509,27 +435,26 @@ static int fio_aioring_mmap(struct aioring_data *ld, struct aio_uring_params *p)
 	return 0;
 }
 
-static int fio_aioring_queue_init(struct thread_data *td)
+static int fio_ioring_queue_init(struct thread_data *td)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct aioring_options *o = td->eo;
+	struct ioring_data *ld = td->io_ops_data;
+	struct ioring_options *o = td->eo;
 	int depth = td->o.iodepth;
-	struct aio_uring_params p;
+	struct io_uring_params p;
 	int ret;
 
 	memset(&p, 0, sizeof(p));
-	p.flags = IOCTX_FLAG_SCQRING;
 
 	if (o->hipri)
-		p.flags |= IOCTX_FLAG_IOPOLL;
+		p.flags |= IORING_SETUP_IOPOLL;
 	if (o->sqthread_set) {
 		p.sq_thread_cpu = o->sqthread;
-		p.flags |= IOCTX_FLAG_SQTHREAD;
+		p.flags |= IORING_SETUP_SQTHREAD;
 		if (o->sqthread_poll)
-			p.flags |= IOCTX_FLAG_SQPOLL;
+			p.flags |= IORING_SETUP_SQPOLL;
 	}
 	if (o->sqwq)
-		p.flags |= IOCTX_FLAG_SQWQ;
+		p.flags |= IORING_SETUP_SQWQ;
 
 	if (o->fixedbufs) {
 		struct rlimit rlim = {
@@ -538,7 +463,7 @@ static int fio_aioring_queue_init(struct thread_data *td)
 		};
 
 		setrlimit(RLIMIT_MEMLOCK, &rlim);
-		p.flags |= IOCTX_FLAG_FIXEDBUFS;
+		p.flags |= IORING_SETUP_FIXEDBUFS;
 	}
 
 	ret = syscall(__NR_sys_io_uring_setup, depth, ld->iovecs, &p);
@@ -546,13 +471,13 @@ static int fio_aioring_queue_init(struct thread_data *td)
 		return ret;
 
 	ld->ring_fd = ret;
-	return fio_aioring_mmap(ld, &p);
+	return fio_ioring_mmap(ld, &p);
 }
 
-static int fio_aioring_post_init(struct thread_data *td)
+static int fio_ioring_post_init(struct thread_data *td)
 {
-	struct aioring_data *ld = td->io_ops_data;
-	struct aioring_options *o = td->eo;
+	struct ioring_data *ld = td->io_ops_data;
+	struct ioring_options *o = td->eo;
 	struct io_u *io_u;
 	int err;
 
@@ -568,7 +493,7 @@ static int fio_aioring_post_init(struct thread_data *td)
 		}
 	}
 
-	err = fio_aioring_queue_init(td);
+	err = fio_ioring_queue_init(td);
 	if (err) {
 		td_verror(td, errno, "io_queue_init");
 		return 1;
@@ -582,9 +507,9 @@ static unsigned roundup_pow2(unsigned depth)
 	return 1UL << __fls(depth - 1);
 }
 
-static int fio_aioring_init(struct thread_data *td)
+static int fio_ioring_init(struct thread_data *td)
 {
-	struct aioring_data *ld;
+	struct ioring_data *ld;
 
 	ld = calloc(1, sizeof(*ld));
 
@@ -602,39 +527,39 @@ static int fio_aioring_init(struct thread_data *td)
 	return 0;
 }
 
-static int fio_aioring_io_u_init(struct thread_data *td, struct io_u *io_u)
+static int fio_ioring_io_u_init(struct thread_data *td, struct io_u *io_u)
 {
-	struct aioring_data *ld = td->io_ops_data;
+	struct ioring_data *ld = td->io_ops_data;
 
 	ld->io_u_index[io_u->index] = io_u;
 	return 0;
 }
 
 static struct ioengine_ops ioengine = {
-	.name			= "aio-ring",
+	.name			= "io_uring",
 	.version		= FIO_IOOPS_VERSION,
-	.init			= fio_aioring_init,
-	.post_init		= fio_aioring_post_init,
-	.io_u_init		= fio_aioring_io_u_init,
-	.prep			= fio_aioring_prep,
-	.queue			= fio_aioring_queue,
-	.commit			= fio_aioring_commit,
-	.getevents		= fio_aioring_getevents,
-	.event			= fio_aioring_event,
-	.cleanup		= fio_aioring_cleanup,
+	.init			= fio_ioring_init,
+	.post_init		= fio_ioring_post_init,
+	.io_u_init		= fio_ioring_io_u_init,
+	.prep			= fio_ioring_prep,
+	.queue			= fio_ioring_queue,
+	.commit			= fio_ioring_commit,
+	.getevents		= fio_ioring_getevents,
+	.event			= fio_ioring_event,
+	.cleanup		= fio_ioring_cleanup,
 	.open_file		= generic_open_file,
 	.close_file		= generic_close_file,
 	.get_file_size		= generic_get_file_size,
 	.options		= options,
-	.option_struct_size	= sizeof(struct aioring_options),
+	.option_struct_size	= sizeof(struct ioring_options),
 };
 
-static void fio_init fio_aioring_register(void)
+static void fio_init fio_ioring_register(void)
 {
 	register_ioengine(&ioengine);
 }
 
-static void fio_exit fio_aioring_unregister(void)
+static void fio_exit fio_ioring_unregister(void)
 {
 	unregister_ioengine(&ioengine);
 }
diff --git a/options.c b/options.c
index 626c7c17..6d832354 100644
--- a/options.c
+++ b/options.c
@@ -1773,13 +1773,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
 			    .help = "Linux native asynchronous IO",
 			  },
 #endif
-#ifdef CONFIG_LIBAIO
-#ifdef ARCH_HAVE_AIORING
-			  { .ival = "aio-ring",
-			    .help = "Linux native asynchronous IO",
+#ifdef ARCH_HAVE_IOURING
+			  { .ival = "io_uring",
+			    .help = "Fast Linux native aio",
 			  },
 #endif
-#endif
 #ifdef CONFIG_POSIXAIO
 			  { .ival = "posixaio",
 			    .help = "POSIX asynchronous IO",
diff --git a/os/io_uring.h b/os/io_uring.h
new file mode 100644
index 00000000..8dda7951
--- /dev/null
+++ b/os/io_uring.h
@@ -0,0 +1,101 @@
+#ifndef IO_URING_H
+#define IO_URING_H
+
+#include <linux/fs.h>
+
+/*
+ * IO submission data structure
+ */
+struct io_uring_iocb {
+	u8	opcode;
+	u8	flags;
+	u16	ioprio;
+	s32	fd;
+	u64	off;
+	union {
+		void	*addr;
+		u64	__pad;
+	};
+	u32	len;
+	union {
+		__kernel_rwf_t	rw_flags;
+		u32		__resv;
+	};
+};
+
+/*
+ * io_uring_setup() flags
+ */
+#define IORING_SETUP_IOPOLL	(1 << 0)	/* io_context is polled */
+#define IORING_SETUP_FIXEDBUFS	(1 << 1)	/* IO buffers are fixed */
+#define IORING_SETUP_SQTHREAD	(1 << 2)	/* Use SQ thread */
+#define IORING_SETUP_SQWQ	(1 << 3)	/* Use SQ workqueue */
+#define IORING_SETUP_SQPOLL	(1 << 4)	/* SQ thread polls */
+
+#define IORING_OP_READ		1
+#define IORING_OP_WRITE		2
+#define IORING_OP_FSYNC		3
+#define IORING_OP_FDSYNC	4
+#define IORING_OP_READ_FIXED	5
+#define IORING_OP_WRITE_FIXED	6
+
+/*
+ * IO completion data structure
+ */
+struct io_uring_event {
+	__u64	index;		/* what iocb this event came from */
+	s32	res;		/* result code for this event */
+	u32	flags;
+};
+
+#define IOEV_FLAG_CACHEHIT	(1 << 0)	/* IO did not hit media */
+
+/*
+ * Magic offsets for the application to mmap the data it needs
+ */
+#define IORING_OFF_SQ_RING		0ULL
+#define IORING_OFF_CQ_RING		0x8000000ULL
+#define IORING_OFF_IOCB			0x10000000ULL
+
+/*
+ * Filled with the offset for mmap(2)
+ */
+struct io_sqring_offsets {
+	u32 head;
+	u32 tail;
+	u32 ring_mask;
+	u32 ring_entries;
+	u32 flags;
+	u32 dropped;
+	u32 array;
+	u32 resv[3];
+};
+
+#define IORING_SQ_NEED_WAKEUP	(1 << 0) /* needs io_uring_enter wakeup */
+
+struct io_cqring_offsets {
+	u32 head;
+	u32 tail;
+	u32 ring_mask;
+	u32 ring_entries;
+	u32 overflow;
+	u32 events;
+	u32 resv[4];
+};
+
+#define IORING_ENTER_GETEVENTS	(1 << 0)
+
+/*
+ * Passed in for io_uring_setup(2). Copied back with updated info on success
+ */
+struct io_uring_params {
+	u32 sq_entries;
+	u32 cq_entries;
+	u32 flags;
+	u16 sq_thread_cpu;
+	u16 resv[9];
+	struct io_sqring_offsets sq_off;
+	struct io_cqring_offsets cq_off;
+};
+
+#endif
diff --git a/t/aio-ring.c b/t/io_uring.c
similarity index 81%
rename from t/aio-ring.c
rename to t/io_uring.c
index 1a4fe44b..83d723f9 100644
--- a/t/aio-ring.c
+++ b/t/io_uring.c
@@ -1,6 +1,3 @@
-/*
- * gcc -D_GNU_SOURCE -Wall -O2 -o aio-ring aio-ring.c  -lpthread -laio
- */
 #include <stdio.h>
 #include <errno.h>
 #include <assert.h>
@@ -15,69 +12,29 @@
 #include <sys/syscall.h>
 #include <sys/resource.h>
 #include <sys/mman.h>
+#include <sys/uio.h>
 #include <linux/fs.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <libaio.h>
 #include <string.h>
 #include <pthread.h>
 #include <sched.h>
 
 #include "../arch/arch.h"
 
-#define IOCTX_FLAG_SCQRING	(1 << 0)	/* Use SQ/CQ rings */
-#define IOCTX_FLAG_IOPOLL	(1 << 1)
-#define IOCTX_FLAG_FIXEDBUFS	(1 << 2)
-#define IOCTX_FLAG_SQTHREAD	(1 << 3)	/* Use SQ thread */
-#define IOCTX_FLAG_SQWQ		(1 << 4)	/* Use SQ wq */
-#define IOCTX_FLAG_SQPOLL	(1 << 5)
-
-#define IOEV_RES2_CACHEHIT	(1 << 0)
-
-#define barrier()	__asm__ __volatile__("": : :"memory")
-
-#define min(a, b)		((a < b) ? (a) : (b))
-
 typedef uint64_t u64;
 typedef uint32_t u32;
+typedef int32_t s32;
 typedef uint16_t u16;
+typedef uint8_t u8;
 
-#define IORING_OFF_SQ_RING	0ULL
-#define IORING_OFF_CQ_RING	0x8000000ULL
-#define IORING_OFF_IOCB		0x10000000ULL
-
-struct aio_sqring_offsets {
-	u32 head;
-	u32 tail;
-	u32 ring_mask;
-	u32 ring_entries;
-	u32 flags;
-	u32 dropped;
-	u32 array;
-	u32 resv[3];
-};
+#include "../os/io_uring.h"
 
-struct aio_cqring_offsets {
-	u32 head;
-	u32 tail;
-	u32 ring_mask;
-	u32 ring_entries;
-	u32 overflow;
-	u32 events;
-	u32 resv[4];
-};
+#define barrier()	__asm__ __volatile__("": : :"memory")
 
-struct aio_uring_params {
-	u32 sq_entries;
-	u32 cq_entries;
-	u32 flags;
-	u16 sq_thread_cpu;
-	u16 resv[9];
-	struct aio_sqring_offsets sq_off;
-	struct aio_cqring_offsets cq_off;
-};
+#define min(a, b)		((a < b) ? (a) : (b))
 
-struct aio_sq_ring {
+struct io_sq_ring {
 	u32 *head;
 	u32 *tail;
 	u32 *ring_mask;
@@ -85,16 +42,14 @@ struct aio_sq_ring {
 	u32 *array;
 };
 
-struct aio_cq_ring {
+struct io_cq_ring {
 	u32 *head;
 	u32 *tail;
 	u32 *ring_mask;
 	u32 *ring_entries;
-	struct io_event *events;
+	struct io_uring_event *events;
 };
 
-#define IORING_ENTER_GETEVENTS	(1 << 0)
-
 #define DEPTH			32
 
 #define BATCH_SUBMIT		8
@@ -109,10 +64,10 @@ struct submitter {
 	unsigned long max_blocks;
 	int ring_fd;
 	struct drand48_data rand;
-	struct aio_sq_ring sq_ring;
-	struct iocb *iocbs;
+	struct io_sq_ring sq_ring;
+	struct io_uring_iocb *iocbs;
 	struct iovec iovecs[DEPTH];
-	struct aio_cq_ring cq_ring;
+	struct io_cq_ring cq_ring;
 	int inflight;
 	unsigned long reaps;
 	unsigned long done;
@@ -132,7 +87,7 @@ static int sq_thread = 0;	/* use kernel submission thread */
 static int sq_thread_cpu = 0;	/* pin above thread to this CPU */
 
 static int io_uring_setup(unsigned entries, struct iovec *iovecs,
-			  struct aio_uring_params *p)
+			  struct io_uring_params *p)
 {
 	return syscall(__NR_sys_io_uring_setup, entries, iovecs, p);
 }
@@ -151,23 +106,25 @@ static int gettid(void)
 
 static void init_io(struct submitter *s, int fd, unsigned index)
 {
-	struct iocb *iocb = &s->iocbs[index];
+	struct io_uring_iocb *iocb = &s->iocbs[index];
 	unsigned long offset;
 	long r;
 
 	lrand48_r(&s->rand, &r);
 	offset = (r % (s->max_blocks - 1)) * BS;
 
-	iocb->aio_fildes = fd;
-	iocb->aio_lio_opcode = IO_CMD_PREAD;
-	iocb->u.c.buf = s->iovecs[index].iov_base;
-	iocb->u.c.nbytes = BS;
-	iocb->u.c.offset = offset;
+	iocb->opcode = IORING_OP_READ;
+	iocb->flags = 0;
+	iocb->ioprio = 0;
+	iocb->fd = fd;
+	iocb->off = offset;
+	iocb->addr = s->iovecs[index].iov_base;
+	iocb->len = BS;
 }
 
 static int prep_more_ios(struct submitter *s, int fd, int max_ios)
 {
-	struct aio_sq_ring *ring = &s->sq_ring;
+	struct io_sq_ring *ring = &s->sq_ring;
 	u32 index, tail, next_tail, prepped = 0;
 
 	next_tail = tail = *ring->tail;
@@ -217,8 +174,8 @@ static int get_file_size(int fd, unsigned long *blocks)
 
 static int reap_events(struct submitter *s)
 {
-	struct aio_cq_ring *ring = &s->cq_ring;
-	struct io_event *ev;
+	struct io_cq_ring *ring = &s->cq_ring;
+	struct io_uring_event *ev;
 	u32 head, reaped = 0;
 
 	head = *ring->head;
@@ -228,15 +185,15 @@ static int reap_events(struct submitter *s)
 			break;
 		ev = &ring->events[head & cq_ring_mask];
 		if (ev->res != BS) {
-			struct iocb *iocb = ev->obj;
+			struct io_uring_iocb *iocb = &s->iocbs[ev->index];
 
-			printf("io: unexpected ret=%ld\n", ev->res);
+			printf("io: unexpected ret=%d\n", ev->res);
 			printf("offset=%lu, size=%lu\n",
-					(unsigned long) iocb->u.c.offset,
-					(unsigned long) iocb->u.c.nbytes);
+					(unsigned long) iocb->off,
+					(unsigned long) iocb->len);
 			return -1;
 		}
-		if (ev->res2 & IOEV_RES2_CACHEHIT)
+		if (ev->flags & IOEV_FLAG_CACHEHIT)
 			s->cachehit++;
 		else
 			s->cachemiss++;
@@ -359,23 +316,22 @@ static void arm_sig_int(void)
 
 static int setup_ring(struct submitter *s)
 {
-	struct aio_sq_ring *sring = &s->sq_ring;
-	struct aio_cq_ring *cring = &s->cq_ring;
-	struct aio_uring_params p;
+	struct io_sq_ring *sring = &s->sq_ring;
+	struct io_cq_ring *cring = &s->cq_ring;
+	struct io_uring_params p;
 	void *ptr;
 	int fd;
 
 	memset(&p, 0, sizeof(p));
 
-	p.flags = IOCTX_FLAG_SCQRING;
 	if (polled)
-		p.flags |= IOCTX_FLAG_IOPOLL;
+		p.flags |= IORING_SETUP_IOPOLL;
 	if (fixedbufs)
-		p.flags |= IOCTX_FLAG_FIXEDBUFS;
+		p.flags |= IORING_SETUP_FIXEDBUFS;
 	if (buffered)
-		p.flags |= IOCTX_FLAG_SQWQ;
+		p.flags |= IORING_SETUP_SQWQ;
 	else if (sq_thread) {
-		p.flags |= IOCTX_FLAG_SQTHREAD;
+		p.flags |= IORING_SETUP_SQTHREAD;
 		p.sq_thread_cpu = sq_thread_cpu;
 	}
 
@@ -400,12 +356,12 @@ static int setup_ring(struct submitter *s)
 	sring->array = ptr + p.sq_off.array;
 	sq_ring_mask = *sring->ring_mask;
 
-	s->iocbs = mmap(0, p.sq_entries * sizeof(struct iocb),
+	s->iocbs = mmap(0, p.sq_entries * sizeof(struct io_uring_iocb),
 			PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd,
 			IORING_OFF_IOCB);
 	printf("iocbs ptr   = 0x%p\n", s->iocbs);
 
-	ptr = mmap(0, p.cq_off.events + p.cq_entries * sizeof(struct io_event),
+	ptr = mmap(0, p.cq_off.events + p.cq_entries * sizeof(struct io_uring_event),
 			PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd,
 			IORING_OFF_CQ_RING);
 	printf("cq_ring ptr = 0x%p\n", ptr);
@@ -501,5 +457,6 @@ int main(int argc, char *argv[])
 	} while (!finish);
 
 	pthread_join(s->thread, &ret);
+	close(s->ring_fd);
 	return 0;
 }



[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux