From 1b9e42a20af3d1e336e516dffd13cc2b97e7ff4d Mon Sep 17 00:00:00 2001 From: yangxianzhao Date: Mon, 8 Aug 2022 11:12:03 +0800 Subject: [PATCH] import liburing-1.0.7-3.0.1 --- ...olis-Add-percpu-io-sq-thread-support.patch | 54 +++ ...liburing-header-files-again-compatib.patch | 127 ++++++++ ...de-liburing-barrier.h-Restore-clang-.patch | 40 +++ ...de-liburing-barrier.h-Use-C11-atomic.patch | 75 +++++ ...ter-revert-change-to-only-enter-if-s.patch | 55 ++++ ...ring.h-update-with-5.11-pending-copy.patch | 51 +++ ...-Include-features-in-struct-io_uring.patch | 58 ++++ ...ing-anolis-Add-__sys_io_uring_enter2.patch | 53 +++ ...s-Add-wrapper-for-__io_uring_get_cqe.patch | 117 +++++++ ...ENTER_GETEVENTS_TIMEOUT-if-available.patch | 64 ++++ ...e-SIG_IS_DATA-to-modified-kernel-API.patch | 78 +++++ ...ng-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch | 81 +++++ ...olis-support-async-ioctl-in-liburing.patch | 46 +++ ...timeout-new-test-for-timeout-feature.patch | 307 ++++++++++++++++++ ...to-define-test-files-devices-we-need.patch | 68 ++++ ...-liburing-anolis-test-add-ioctl-test.patch | 223 +++++++++++++ ...-overflow-don-t-run-on-newer-kernels.patch | 70 ++++ ...-us-granularity-of-io_sq_thread_idle.patch | 56 ++++ ...-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch | 137 ++++++++ liburing-1.0.7.tar.bz2 | Bin 0 -> 86339 bytes liburing-always-build-with-fPIC.patch | 16 + liburing.spec | 96 ++++++ 22 files changed, 1872 insertions(+) create mode 100644 1001-liburing-anolis-Add-percpu-io-sq-thread-support.patch create mode 100644 1002-liburing-anolis-Revert-Make-the-liburing-header-files-again-compatib.patch create mode 100644 1003-liburing-anolis-Revert-src-include-liburing-barrier.h-Restore-clang-.patch create mode 100644 1004-liburing-anolis-Revert-src-include-liburing-barrier.h-Use-C11-atomic.patch create mode 100644 1005-liburing-anolis-sq_ring_needs_enter-revert-change-to-only-enter-if-s.patch create mode 100644 1006-liburing-anolis-io_uring.h-update-with-5.11-pending-copy.patch create mode 100644 1007-liburing-anolis-Include-features-in-struct-io_uring.patch create mode 100644 1008-liburing-anolis-Add-__sys_io_uring_enter2.patch create mode 100644 1009-liburing-anolis-Add-wrapper-for-__io_uring_get_cqe.patch create mode 100644 1010-liburing-anolis-Use-IORING_ENTER_GETEVENTS_TIMEOUT-if-available.patch create mode 100644 1011-liburing-anolis-Update-SIG_IS_DATA-to-modified-kernel-API.patch create mode 100644 1012-liburing-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch create mode 100644 1013-liburing-anolis-support-async-ioctl-in-liburing.patch create mode 100644 1014-liburing-anolis-test-timeout-new-test-for-timeout-feature.patch create mode 100644 1015-liburing-anolis-test-use-a-map-to-define-test-files-devices-we-need.patch create mode 100644 1016-liburing-anolis-test-add-ioctl-test.patch create mode 100644 1017-liburing-anolis-test-timeout-overflow-don-t-run-on-newer-kernels.patch create mode 100644 1018-liburing-anolis-support-us-granularity-of-io_sq_thread_idle.patch create mode 100644 1019-liburing-anolis-add-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch create mode 100644 liburing-1.0.7.tar.bz2 create mode 100644 liburing-always-build-with-fPIC.patch create mode 100644 liburing.spec diff --git a/1001-liburing-anolis-Add-percpu-io-sq-thread-support.patch b/1001-liburing-anolis-Add-percpu-io-sq-thread-support.patch new file mode 100644 index 0000000..1ca7830 --- /dev/null +++ b/1001-liburing-anolis-Add-percpu-io-sq-thread-support.patch @@ -0,0 +1,54 @@ +From c629576a5f266eedf2efbf74211581c68217d67c Mon Sep 17 00:00:00 2001 +From: Xiaoguang Wang +Date: Thu, 6 Aug 2020 14:23:01 +0800 +Subject: [PATCH] Add percpu io sq thread support + +Add a new IORING_SETUP_SQPOLL_PERCPU flag, this flag is only meaningful +when IORING_SETUP_SQPOLL and IORING_SETUP_SQ_AFF are both specified, that +means if user creates multiple io_uring instances which are all bound +to one same cpu, only a kernel thread is created for this cpu to perform +these io_uring instances' submission queue polling. + +Signed-off-by: Xiaoguang Wang +Acked-by: Joseph Qi +--- + man/io_uring_setup.2 | 9 +++++++++ + src/include/liburing/io_uring.h | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 +index d48bb32..3788084 100644 +--- a/man/io_uring_setup.2 ++++ b/man/io_uring_setup.2 +@@ -131,6 +131,15 @@ This flag is only meaningful when + .B IORING_SETUP_SQPOLL + is specified. + .TP ++.B IORING_SETUP_SQPOLL_PERCPU ++This flag is only meaningful when ++.B IORING_SETUP_SQPOLL ++and ++.B IORING_SETUP_SQ_AFF ++are both specified, that means if user creates multiple io_uring instances ++which are all bound to one same cpu, only a kernel thread is created for this ++cpu to perform these io_uring instances' submission queue polling. ++.TP + .B IORING_SETUP_CQSIZE + Create the completion queue with + .IR "struct io_uring_params.cq_entries" +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index 7843742..dbc3e4d 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -94,6 +94,8 @@ enum { + #define IORING_SETUP_CQSIZE (1U << 3) /* app defines CQ size */ + #define IORING_SETUP_CLAMP (1U << 4) /* clamp SQ/CQ ring sizes */ + #define IORING_SETUP_ATTACH_WQ (1U << 5) /* attach to existing wq */ ++/* use percpu SQ poll thread */ ++#define IORING_SETUP_SQPOLL_PERCPU (1U << 31) + + enum { + IORING_OP_NOP, +-- +2.17.2 + diff --git a/1002-liburing-anolis-Revert-Make-the-liburing-header-files-again-compatib.patch b/1002-liburing-anolis-Revert-Make-the-liburing-header-files-again-compatib.patch new file mode 100644 index 0000000..a997e85 --- /dev/null +++ b/1002-liburing-anolis-Revert-Make-the-liburing-header-files-again-compatib.patch @@ -0,0 +1,127 @@ +From d88bcf0e719c380d645d014984ec7e363163faa0 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 12 Nov 2020 19:22:12 +0800 +Subject: [PATCH 1/3] Revert "Make the liburing header files again compatible + with C++" + +This reverts commit 3d74c677c45eccf36b92f7ad4b3317adc1ed06bb. +--- + src/include/liburing.h | 8 ++++---- + src/include/liburing/barrier.h | 37 ++----------------------------------- + src/include/liburing/io_uring.h | 8 -------- + 3 files changed, 6 insertions(+), 47 deletions(-) + +diff --git a/src/include/liburing.h b/src/include/liburing.h +index 0505a4f50367..92e5018951d4 100644 +--- a/src/include/liburing.h ++++ b/src/include/liburing.h +@@ -2,6 +2,10 @@ + #ifndef LIB_URING_H + #define LIB_URING_H + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + #include + #include + #include +@@ -15,10 +19,6 @@ + #include "liburing/io_uring.h" + #include "liburing/barrier.h" + +-#ifdef __cplusplus +-extern "C" { +-#endif +- + /* + * Library interface to io_uring + */ +diff --git a/src/include/liburing/barrier.h b/src/include/liburing/barrier.h +index a4a59fb499d6..57324348466b 100644 +--- a/src/include/liburing/barrier.h ++++ b/src/include/liburing/barrier.h +@@ -2,6 +2,8 @@ + #ifndef LIBURING_BARRIER_H + #define LIBURING_BARRIER_H + ++#include ++ + /* + From the kernel documentation file refcount-vs-atomic.rst: + +@@ -21,40 +23,6 @@ after the acquire operation executes. This is implemented using + :c:func:`smp_acquire__after_ctrl_dep`. + */ + +-#ifdef __cplusplus +-#include +- +-template +-static inline void IO_URING_WRITE_ONCE(T &var, T val) +-{ +- std::atomic_store_explicit(reinterpret_cast *>(&var), +- val, std::memory_order_relaxed); +-} +-template +-static inline T IO_URING_READ_ONCE(const T &var) +-{ +- return std::atomic_load_explicit( +- reinterpret_cast *>(&var), +- std::memory_order_relaxed); +-} +- +-template +-static inline void io_uring_smp_store_release(T *p, T v) +-{ +- std::atomic_store_explicit(reinterpret_cast *>(p), v, +- std::memory_order_release); +-} +- +-template +-static inline T io_uring_smp_load_acquire(const T *p) +-{ +- return std::atomic_load_explicit( +- reinterpret_cast *>(p), +- std::memory_order_acquire); +-} +-#else +-#include +- + #define IO_URING_WRITE_ONCE(var, val) \ + atomic_store_explicit((_Atomic typeof(var) *)&(var), \ + (val), memory_order_relaxed) +@@ -68,6 +36,5 @@ static inline T io_uring_smp_load_acquire(const T *p) + #define io_uring_smp_load_acquire(p) \ + atomic_load_explicit((_Atomic typeof(*(p)) *)(p), \ + memory_order_acquire) +-#endif + + #endif /* defined(LIBURING_BARRIER_H) */ +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index d39b45fddb22..d65fde732518 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -11,10 +11,6 @@ + #include + #include + +-#ifdef __cplusplus +-extern "C" { +-#endif +- + /* + * IO submission data structure (Submission Queue Entry) + */ +@@ -294,8 +290,4 @@ struct io_uring_probe { + struct io_uring_probe_op ops[0]; + }; + +-#ifdef __cplusplus +-} +-#endif +- + #endif +-- +1.8.3.1 + diff --git a/1003-liburing-anolis-Revert-src-include-liburing-barrier.h-Restore-clang-.patch b/1003-liburing-anolis-Revert-src-include-liburing-barrier.h-Restore-clang-.patch new file mode 100644 index 0000000..52053ac --- /dev/null +++ b/1003-liburing-anolis-Revert-src-include-liburing-barrier.h-Restore-clang-.patch @@ -0,0 +1,40 @@ +From 0b51d4b2046f6c16179fbaff6c56c90c4985a0cb Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 12 Nov 2020 19:25:50 +0800 +Subject: [PATCH 2/3] Revert "src/include/liburing/barrier.h: Restore clang + compatibility" + +This reverts commit 56ff6c964c5078d76cb3c2da1a62ad671749fd42. +--- + src/include/liburing/barrier.h | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/src/include/liburing/barrier.h b/src/include/liburing/barrier.h +index 57324348466b..c8aa4210371c 100644 +--- a/src/include/liburing/barrier.h ++++ b/src/include/liburing/barrier.h +@@ -24,17 +24,13 @@ after the acquire operation executes. This is implemented using + */ + + #define IO_URING_WRITE_ONCE(var, val) \ +- atomic_store_explicit((_Atomic typeof(var) *)&(var), \ +- (val), memory_order_relaxed) ++ atomic_store_explicit(&(var), (val), memory_order_relaxed) + #define IO_URING_READ_ONCE(var) \ +- atomic_load_explicit((_Atomic typeof(var) *)&(var), \ +- memory_order_relaxed) ++ atomic_load_explicit(&(var), memory_order_relaxed) + + #define io_uring_smp_store_release(p, v) \ +- atomic_store_explicit((_Atomic typeof(*(p)) *)(p), (v), \ +- memory_order_release) ++ atomic_store_explicit((p), (v), memory_order_release) + #define io_uring_smp_load_acquire(p) \ +- atomic_load_explicit((_Atomic typeof(*(p)) *)(p), \ +- memory_order_acquire) ++ atomic_load_explicit((p), memory_order_acquire) + + #endif /* defined(LIBURING_BARRIER_H) */ +-- +1.8.3.1 + diff --git a/1004-liburing-anolis-Revert-src-include-liburing-barrier.h-Use-C11-atomic.patch b/1004-liburing-anolis-Revert-src-include-liburing-barrier.h-Use-C11-atomic.patch new file mode 100644 index 0000000..cb41bed --- /dev/null +++ b/1004-liburing-anolis-Revert-src-include-liburing-barrier.h-Use-C11-atomic.patch @@ -0,0 +1,75 @@ +From 1fc7bb3aecf344847d13d0c3c25e1b98d1687219 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 12 Nov 2020 19:26:04 +0800 +Subject: [PATCH 3/3] Revert "src/include/liburing/barrier.h: Use C11 atomics" + +This reverts commit b9c0bf79aa879727f55f4fe7333dd41bebd0acd4. +--- + src/include/liburing/barrier.h | 44 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 34 insertions(+), 10 deletions(-) + +diff --git a/src/include/liburing/barrier.h b/src/include/liburing/barrier.h +index c8aa4210371c..ad69506bb248 100644 +--- a/src/include/liburing/barrier.h ++++ b/src/include/liburing/barrier.h +@@ -2,8 +2,6 @@ + #ifndef LIBURING_BARRIER_H + #define LIBURING_BARRIER_H + +-#include +- + /* + From the kernel documentation file refcount-vs-atomic.rst: + +@@ -23,14 +21,40 @@ after the acquire operation executes. This is implemented using + :c:func:`smp_acquire__after_ctrl_dep`. + */ + +-#define IO_URING_WRITE_ONCE(var, val) \ +- atomic_store_explicit(&(var), (val), memory_order_relaxed) +-#define IO_URING_READ_ONCE(var) \ +- atomic_load_explicit(&(var), memory_order_relaxed) ++/* From tools/include/linux/compiler.h */ ++/* Optimization barrier */ ++/* The "volatile" is due to gcc bugs */ ++#define io_uring_barrier() __asm__ __volatile__("": : :"memory") ++ ++/* From tools/virtio/linux/compiler.h */ ++#define IO_URING_WRITE_ONCE(var, val) \ ++ (*((volatile __typeof(val) *)(&(var))) = (val)) ++#define IO_URING_READ_ONCE(var) (*((volatile __typeof(var) *)(&(var)))) ++ + +-#define io_uring_smp_store_release(p, v) \ +- atomic_store_explicit((p), (v), memory_order_release) +-#define io_uring_smp_load_acquire(p) \ +- atomic_load_explicit((p), memory_order_acquire) ++#if defined(__x86_64__) || defined(__i386__) ++/* Adapted from arch/x86/include/asm/barrier.h */ ++#define io_uring_smp_store_release(p, v) \ ++do { \ ++ io_uring_barrier(); \ ++ IO_URING_WRITE_ONCE(*(p), (v)); \ ++} while (0) ++ ++#define io_uring_smp_load_acquire(p) \ ++({ \ ++ __typeof(*p) ___p1 = IO_URING_READ_ONCE(*(p)); \ ++ io_uring_barrier(); \ ++ ___p1; \ ++}) ++ ++#else /* defined(__x86_64__) || defined(__i386__) */ ++/* ++ * Add arch appropriate definitions. Use built-in atomic operations for ++ * archs we don't have support for. ++ */ ++#define io_uring_smp_store_release(p, v) \ ++ __atomic_store_n(p, v, __ATOMIC_RELEASE) ++#define io_uring_smp_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE) ++#endif /* defined(__x86_64__) || defined(__i386__) */ + + #endif /* defined(LIBURING_BARRIER_H) */ +-- +1.8.3.1 + diff --git a/1005-liburing-anolis-sq_ring_needs_enter-revert-change-to-only-enter-if-s.patch b/1005-liburing-anolis-sq_ring_needs_enter-revert-change-to-only-enter-if-s.patch new file mode 100644 index 0000000..e0d64f3 --- /dev/null +++ b/1005-liburing-anolis-sq_ring_needs_enter-revert-change-to-only-enter-if-s.patch @@ -0,0 +1,55 @@ +From 07b476fc25e29dda33b83e540d054bd95b82bb1e Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Thu, 20 Aug 2020 21:40:16 -0600 +Subject: [PATCH 1/8] sq_ring_needs_enter: revert change to only enter if + submit != 0 + +This reverts commit f0c5c54945ae92a00cdbb43bdf3abaeab6bd3a23. + +Glauber reports a regressions for his polled setup with this change. +As it's purely speculative, just revert it. + +Reported-by: Glauber Costa +Signed-off-by: Jens Axboe +--- + src/queue.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/queue.c b/src/queue.c +index be80d7a2c760..bdb473c1ba19 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -19,10 +19,9 @@ + * or if IORING_SQ_NEED_WAKEUP is set, so submit thread must be explicitly + * awakened. For the latter case, we set the thread wakeup flag. + */ +-static inline bool sq_ring_needs_enter(struct io_uring *ring, +- unsigned submitted, unsigned *flags) ++static inline bool sq_ring_needs_enter(struct io_uring *ring, unsigned *flags) + { +- if (!(ring->flags & IORING_SETUP_SQPOLL) && submitted) ++ if (!(ring->flags & IORING_SETUP_SQPOLL)) + return true; + if (IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_NEED_WAKEUP) { + *flags |= IORING_ENTER_SQ_WAKEUP; +@@ -90,7 +89,7 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + if (wait_nr || cq_overflow_flush) + flags = IORING_ENTER_GETEVENTS; + if (submit) +- sq_ring_needs_enter(ring, submit, &flags); ++ sq_ring_needs_enter(ring, &flags); + if (wait_nr || submit || cq_overflow_flush) + ret = __sys_io_uring_enter(ring->ring_fd, submit, + wait_nr, flags, sigmask); +@@ -256,7 +255,7 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted, + int ret; + + flags = 0; +- if (sq_ring_needs_enter(ring, submitted, &flags) || wait_nr) { ++ if (sq_ring_needs_enter(ring, &flags) || wait_nr) { + if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL)) + flags |= IORING_ENTER_GETEVENTS; + +-- +1.8.3.1 + diff --git a/1006-liburing-anolis-io_uring.h-update-with-5.11-pending-copy.patch b/1006-liburing-anolis-io_uring.h-update-with-5.11-pending-copy.patch new file mode 100644 index 0000000..418f342 --- /dev/null +++ b/1006-liburing-anolis-io_uring.h-update-with-5.11-pending-copy.patch @@ -0,0 +1,51 @@ +From a3680c5479fb84ebc224f4626c361ec1293c1f31 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 11:25:55 -0700 +Subject: [PATCH 2/8] io_uring.h: update with 5.11-pending copy + +Backport Notes + +manully backport struct io_uring_getevents_arg since the patch +0002-Revert-Make-the-liburing-header-files-again-compatib.patch +stoped the auto backporting + +Signed-off-by: Jens Axboe +--- + src/include/liburing/io_uring.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index c55878e0a200..7f7701c86eb4 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -226,6 +226,7 @@ struct io_cqring_offsets { + */ + #define IORING_ENTER_GETEVENTS (1U << 0) + #define IORING_ENTER_SQ_WAKEUP (1U << 1) ++#define IORING_ENTER_GETEVENTS_TIMEOUT (1U << 3) + + /* + * Passed in for io_uring_setup(2). Copied back with updated info on success +@@ -253,6 +254,7 @@ struct io_uring_params { + #define IORING_FEAT_CUR_PERSONALITY (1U << 4) + #define IORING_FEAT_FAST_POLL (1U << 5) + #define IORING_FEAT_POLL_32BITS (1U << 6) ++#define IORING_FEAT_GETEVENTS_TIMEOUT (1U << 8) + + /* + * io_uring_register(2) opcodes and arguments +@@ -292,4 +294,11 @@ struct io_uring_probe { + struct io_uring_probe_op ops[0]; + }; + ++struct io_uring_getevents_arg { ++ __u64 sigmask; ++ __u32 sigmask_sz; ++ __u32 pad; ++ __u64 ts; ++}; ++ + #endif +-- +1.8.3.1 + diff --git a/1007-liburing-anolis-Include-features-in-struct-io_uring.patch b/1007-liburing-anolis-Include-features-in-struct-io_uring.patch new file mode 100644 index 0000000..b59f078 --- /dev/null +++ b/1007-liburing-anolis-Include-features-in-struct-io_uring.patch @@ -0,0 +1,58 @@ +From fc063be2896b15e8083d25f932758c34ef7b9540 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 11:35:41 -0700 +Subject: [PATCH 3/8] Include 'features' in struct io_uring + +Then we'll have it for later, should we need to know what features the +ring has. This grabs one of the reserved unsigneds from the struct. + +Backport Notes + +pad[4] in struct io_uring {} is introduced in +25bbcbef3e0a ("Bump major version to 2"), backporting it causes a chain +reaction of backporting __io_uring_sqring_wait(). So here we manully +add pad[3] + +Signed-off-by: Jens Axboe +--- + src/include/liburing.h | 3 +++ + src/setup.c | 7 +++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/include/liburing.h b/src/include/liburing.h +index 92e5018951d4..ac2d4a1cbeba 100644 +--- a/src/include/liburing.h ++++ b/src/include/liburing.h +@@ -57,6 +57,9 @@ struct io_uring { + struct io_uring_cq cq; + unsigned flags; + int ring_fd; ++ ++ unsigned features; ++ unsigned pad[3]; + }; + + /* +diff --git a/src/setup.c b/src/setup.c +index 2b17b949cda6..260dd2be8e85 100644 +--- a/src/setup.c ++++ b/src/setup.c +@@ -142,10 +142,13 @@ int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, + return -errno; + + ret = io_uring_queue_mmap(fd, p, ring); +- if (ret) ++ if (ret) { + close(fd); ++ return ret; ++ } + +- return ret; ++ ring->features = p->features; ++ return 0; + } + + /* +-- +1.8.3.1 + diff --git a/1008-liburing-anolis-Add-__sys_io_uring_enter2.patch b/1008-liburing-anolis-Add-__sys_io_uring_enter2.patch new file mode 100644 index 0000000..15bfae2 --- /dev/null +++ b/1008-liburing-anolis-Add-__sys_io_uring_enter2.patch @@ -0,0 +1,53 @@ +From b1e4e2dfaa657de06a401d418e370b2b42e6ba3f Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 11:55:25 -0700 +Subject: [PATCH 4/8] Add __sys_io_uring_enter2() + +Just like __sys_io_uring_enter(), except it allows passing in the size +of the last argument. + +Signed-off-by: Jens Axboe +--- + src/syscall.c | 11 +++++++++-- + src/syscall.h | 2 ++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/syscall.c b/src/syscall.c +index c41e0998d0dd..9b455a911df8 100644 +--- a/src/syscall.c ++++ b/src/syscall.c +@@ -47,9 +47,16 @@ int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p) + return syscall(__NR_io_uring_setup, entries, p); + } + ++int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, ++ unsigned flags, sigset_t *sig, int sz) ++{ ++ return syscall(__NR_io_uring_enter, fd, to_submit, min_complete, ++ flags, sig, sz); ++} ++ + int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, + unsigned flags, sigset_t *sig) + { +- return syscall(__NR_io_uring_enter, fd, to_submit, min_complete, +- flags, sig, _NSIG / 8); ++ return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, ++ _NSIG / 8); + } +diff --git a/src/syscall.h b/src/syscall.h +index 7e299d419e3e..a4c8e9bbb3f7 100644 +--- a/src/syscall.h ++++ b/src/syscall.h +@@ -8,6 +8,8 @@ + extern int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); + extern int __sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, sigset_t *sig); ++extern int __sys_io_uring_enter2(int fd, unsigned to_submit, ++ unsigned min_complete, unsigned flags, sigset_t *sig, int sz); + extern int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, + unsigned int nr_args); + +-- +1.8.3.1 + diff --git a/1009-liburing-anolis-Add-wrapper-for-__io_uring_get_cqe.patch b/1009-liburing-anolis-Add-wrapper-for-__io_uring_get_cqe.patch new file mode 100644 index 0000000..a0b6ab4 --- /dev/null +++ b/1009-liburing-anolis-Add-wrapper-for-__io_uring_get_cqe.patch @@ -0,0 +1,117 @@ +From 12d141534e1747525656087b357440cc68a43fda Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 11:44:48 -0700 +Subject: [PATCH 5/8] Add wrapper for __io_uring_get_cqe() + +In preparation for allowing passing in a timeout. + +Signed-off-by: Jens Axboe +--- + src/queue.c | 58 ++++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 42 insertions(+), 16 deletions(-) + +diff --git a/src/queue.c b/src/queue.c +index bdb473c1ba19..3f3099be8a6d 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -63,11 +63,19 @@ static int __io_uring_peek_cqe(struct io_uring *ring, + return err; + } + +-int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, +- unsigned submit, unsigned wait_nr, sigset_t *sigmask) ++struct get_data { ++ unsigned submit; ++ unsigned wait_nr; ++ unsigned get_flags; ++ int sz; ++ void *arg; ++}; ++ ++static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, ++ struct get_data *data) + { + struct io_uring_cqe *cqe = NULL; +- const int to_wait = wait_nr; ++ const int to_wait = data->wait_nr; + int ret = 0, err; + + do { +@@ -77,26 +85,30 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + err = __io_uring_peek_cqe(ring, &cqe); + if (err) + break; +- if (!cqe && !to_wait && !submit) { ++ ++ if (!cqe && !to_wait && !data->submit) { + if (!cq_ring_needs_flush(ring)) { + err = -EAGAIN; + break; + } + cq_overflow_flush = true; + } +- if (wait_nr && cqe) +- wait_nr--; +- if (wait_nr || cq_overflow_flush) +- flags = IORING_ENTER_GETEVENTS; +- if (submit) ++ ++ if (data->wait_nr && cqe) ++ data->wait_nr--; ++ if (data->wait_nr || cq_overflow_flush) ++ flags = IORING_ENTER_GETEVENTS | data->get_flags; ++ if (data->submit) + sq_ring_needs_enter(ring, &flags); +- if (wait_nr || submit || cq_overflow_flush) +- ret = __sys_io_uring_enter(ring->ring_fd, submit, +- wait_nr, flags, sigmask); ++ if (data->wait_nr || data->submit || cq_overflow_flush) ++ ret = __sys_io_uring_enter2(ring->ring_fd, data->submit, ++ data->wait_nr, flags, data->arg, ++ data->sz); ++ + if (ret < 0) { + err = -errno; +- } else if (ret == (int)submit) { +- submit = 0; ++ } else if (ret == (int)data->submit) { ++ data->submit = 0; + /* + * When SETUP_IOPOLL is set, __sys_io_uring enter() + * must be called to reap new completions but the call +@@ -104,9 +116,9 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + * so preserve wait_nr. + */ + if (!(ring->flags & IORING_SETUP_IOPOLL)) +- wait_nr = 0; ++ data->wait_nr = 0; + } else { +- submit -= ret; ++ data->submit -= ret; + } + if (cqe) + break; +@@ -116,6 +128,20 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + return err; + } + ++int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, ++ unsigned submit, unsigned wait_nr, sigset_t *sigmask) ++{ ++ struct get_data data = { ++ .submit = submit, ++ .wait_nr = wait_nr, ++ .extra_flags = 0, ++ .sz = _NSIG / 8, ++ .arg = sigmask, ++ }; ++ ++ return _io_uring_get_cqe(ring, cqe_ptr, &data); ++} ++ + /* + * Fill in an array of IO completions up to count, if any are available. + * Returns the amount of IO completions filled. +-- +1.8.3.1 + diff --git a/1010-liburing-anolis-Use-IORING_ENTER_GETEVENTS_TIMEOUT-if-available.patch b/1010-liburing-anolis-Use-IORING_ENTER_GETEVENTS_TIMEOUT-if-available.patch new file mode 100644 index 0000000..c650c9b --- /dev/null +++ b/1010-liburing-anolis-Use-IORING_ENTER_GETEVENTS_TIMEOUT-if-available.patch @@ -0,0 +1,64 @@ +From 91a6a81fc75c8f02b8c5b6b2b069dd3d1e96f6b9 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 12:02:28 -0700 +Subject: [PATCH 6/8] Use IORING_ENTER_GETEVENTS_TIMEOUT if available + +If the kernel has flagged support for IORING_FEAT_GETEVENTS_TIMEOUT, +then we can pass in a timespec instead of queueing an internal timeout +request. That's more efficient (and trivial), so use it if it's +available. + +Signed-off-by: Jens Axboe +--- + src/queue.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/src/queue.c b/src/queue.c +index 3f3099be8a6d..cd800fc5b6e8 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -218,6 +218,31 @@ out: + } + + /* ++ * If we have kernel suppor for IORING_ENTER_GETEVENTS_TIMEOUT, then we can ++ * use that more efficiently than queueing an internal timeout command. ++ */ ++static int io_uring_wait_cqes_new(struct io_uring *ring, ++ struct io_uring_cqe **cqe_ptr, ++ unsigned wait_nr, struct __kernel_timespec *ts, ++ sigset_t *sigmask) ++{ ++ struct io_uring_getevents_arg arg = { ++ .sigmask = (unsigned long) sigmask, ++ .sigmask_sz = _NSIG / 8, ++ .ts = (unsigned long) ts ++ }; ++ struct get_data data = { ++ .submit = __io_uring_flush_sq(ring), ++ .wait_nr = wait_nr, ++ .extra_flags = ts ? IORING_ENTER_GETEVENTS_TIMEOUT : 0, ++ .sz = sizeof(arg), ++ .arg = &arg ++ }; ++ ++ return _io_uring_get_cqe(ring, cqe_ptr, &data); ++} ++ ++/* + * Like io_uring_wait_cqe(), except it accepts a timeout value as well. Note + * that an sqe is used internally to handle the timeout. Applications using + * this function must never set sqe->user_data to LIBURING_UDATA_TIMEOUT! +@@ -234,6 +259,9 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + { + unsigned to_submit = 0; + ++ if (ring->features & IORING_FEAT_GETEVENTS_TIMEOUT) ++ return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ts, sigmask); ++ + if (ts) { + struct io_uring_sqe *sqe; + int ret; +-- +1.8.3.1 + diff --git a/1011-liburing-anolis-Update-SIG_IS_DATA-to-modified-kernel-API.patch b/1011-liburing-anolis-Update-SIG_IS_DATA-to-modified-kernel-API.patch new file mode 100644 index 0000000..67ecab4 --- /dev/null +++ b/1011-liburing-anolis-Update-SIG_IS_DATA-to-modified-kernel-API.patch @@ -0,0 +1,78 @@ +From dd75ea9d5ef1eceba7b1e49b437a08c8a2753364 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 13:57:17 -0700 +Subject: [PATCH 7/8] Update SIG_IS_DATA to modified kernel API + +Still ironing out the kinks... + +Signed-off-by: Jens Axboe +--- + src/include/liburing/io_uring.h | 4 ++-- + src/queue.c | 8 ++++---- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index 7f7701c86eb4..b892dbe77d86 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -226,7 +226,7 @@ struct io_cqring_offsets { + */ + #define IORING_ENTER_GETEVENTS (1U << 0) + #define IORING_ENTER_SQ_WAKEUP (1U << 1) +-#define IORING_ENTER_GETEVENTS_TIMEOUT (1U << 3) ++#define IORING_ENTER_SIG_IS_DATA (1U << 3) + + /* + * Passed in for io_uring_setup(2). Copied back with updated info on success +@@ -254,7 +254,7 @@ struct io_uring_params { + #define IORING_FEAT_CUR_PERSONALITY (1U << 4) + #define IORING_FEAT_FAST_POLL (1U << 5) + #define IORING_FEAT_POLL_32BITS (1U << 6) +-#define IORING_FEAT_GETEVENTS_TIMEOUT (1U << 8) ++#define IORING_FEAT_SIG_IS_DATA (1U << 8) + + /* + * io_uring_register(2) opcodes and arguments +diff --git a/src/queue.c b/src/queue.c +index cd800fc5b6e8..6df391c33c6f 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -134,7 +134,7 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + struct get_data data = { + .submit = submit, + .wait_nr = wait_nr, +- .extra_flags = 0, ++ .get_flags = 0, + .sz = _NSIG / 8, + .arg = sigmask, + }; +@@ -218,7 +218,7 @@ out: + } + + /* +- * If we have kernel suppor for IORING_ENTER_GETEVENTS_TIMEOUT, then we can ++ * If we have kernel support for IORING_ENTERSIG_IS_DATA, then we can + * use that more efficiently than queueing an internal timeout command. + */ + static int io_uring_wait_cqes_new(struct io_uring *ring, +@@ -234,7 +234,7 @@ static int io_uring_wait_cqes_new(struct io_uring *ring, + struct get_data data = { + .submit = __io_uring_flush_sq(ring), + .wait_nr = wait_nr, +- .extra_flags = ts ? IORING_ENTER_GETEVENTS_TIMEOUT : 0, ++ .get_flags = ts ? IORING_ENTER_SIG_IS_DATA : 0, + .sz = sizeof(arg), + .arg = &arg + }; +@@ -259,7 +259,7 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + { + unsigned to_submit = 0; + +- if (ring->features & IORING_FEAT_GETEVENTS_TIMEOUT) ++ if (ring->features & IORING_FEAT_SIG_IS_DATA) + return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ts, sigmask); + + if (ts) { +-- +1.8.3.1 + diff --git a/1012-liburing-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch b/1012-liburing-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch new file mode 100644 index 0000000..8f39924 --- /dev/null +++ b/1012-liburing-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch @@ -0,0 +1,81 @@ +From 8424cff4705e62784b8042d71e12e22554a038ac Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Wed, 4 Nov 2020 14:34:03 -0700 +Subject: [PATCH 8/8] Rename SIG_IS_DATA -> EXT_ARG + +This is the final name. While doing this change, also change it so that +we only call the new variant if 'ts' is indeed set. + +Signed-off-by: Jens Axboe +--- + src/include/liburing/io_uring.h | 4 ++-- + src/queue.c | 13 +++++++------ + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index b892dbe77d86..e8393b87e7bd 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -226,7 +226,7 @@ struct io_cqring_offsets { + */ + #define IORING_ENTER_GETEVENTS (1U << 0) + #define IORING_ENTER_SQ_WAKEUP (1U << 1) +-#define IORING_ENTER_SIG_IS_DATA (1U << 3) ++#define IORING_ENTER_EXT_ARG (1U << 3) + + /* + * Passed in for io_uring_setup(2). Copied back with updated info on success +@@ -254,7 +254,7 @@ struct io_uring_params { + #define IORING_FEAT_CUR_PERSONALITY (1U << 4) + #define IORING_FEAT_FAST_POLL (1U << 5) + #define IORING_FEAT_POLL_32BITS (1U << 6) +-#define IORING_FEAT_SIG_IS_DATA (1U << 8) ++#define IORING_FEAT_EXT_ARG (1U << 8) + + /* + * io_uring_register(2) opcodes and arguments +diff --git a/src/queue.c b/src/queue.c +index 6df391c33c6f..2662e671fb34 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -218,8 +218,8 @@ out: + } + + /* +- * If we have kernel support for IORING_ENTERSIG_IS_DATA, then we can +- * use that more efficiently than queueing an internal timeout command. ++ * If we have kernel support for IORING_ENTER_EXT_ARG, then we can use that ++ * more efficiently than queueing an internal timeout command. + */ + static int io_uring_wait_cqes_new(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, +@@ -234,7 +234,7 @@ static int io_uring_wait_cqes_new(struct io_uring *ring, + struct get_data data = { + .submit = __io_uring_flush_sq(ring), + .wait_nr = wait_nr, +- .get_flags = ts ? IORING_ENTER_SIG_IS_DATA : 0, ++ .get_flags = IORING_ENTER_EXT_ARG, + .sz = sizeof(arg), + .arg = &arg + }; +@@ -259,13 +259,14 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + { + unsigned to_submit = 0; + +- if (ring->features & IORING_FEAT_SIG_IS_DATA) +- return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ts, sigmask); +- + if (ts) { + struct io_uring_sqe *sqe; + int ret; + ++ if (ring->features & IORING_FEAT_EXT_ARG) ++ return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ++ ts, sigmask); ++ + /* + * If the SQ ring is full, we may need to submit IO first + */ +-- +1.8.3.1 + diff --git a/1013-liburing-anolis-support-async-ioctl-in-liburing.patch b/1013-liburing-anolis-support-async-ioctl-in-liburing.patch new file mode 100644 index 0000000..74594b5 --- /dev/null +++ b/1013-liburing-anolis-support-async-ioctl-in-liburing.patch @@ -0,0 +1,46 @@ +From e8dbd563b3a355b8885f2bf5ae96be83a1624432 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 26 Nov 2020 14:56:58 +0800 +Subject: [PATCH] support async ioctl in liburing + +Async ioctl is now supported in io_uring kernel part. Add the +counterpart in liburing. Currently we just support BLKDISCARD. + +Signed-off-by: Hao Xu +--- + src/include/liburing.h | 6 ++++++ + src/include/liburing/io_uring.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/src/include/liburing.h b/src/include/liburing.h +index ac2d4a1cbeba..9fa5bc92986d 100644 +--- a/src/include/liburing.h ++++ b/src/include/liburing.h +@@ -438,6 +438,12 @@ static inline void io_uring_prep_remove_buffers(struct io_uring_sqe *sqe, + sqe->buf_group = bgid; + } + ++static inline void io_uring_prep_ioctl(struct io_uring_sqe *sqe, int fd, ++ unsigned len, void *buf) ++{ ++ io_uring_prep_rw(IORING_OP_IOCTL, sqe, fd, buf, len, 0); ++} ++ + static inline unsigned io_uring_sq_ready(struct io_uring *ring) + { + /* always use real head, to avoid losing sync for short submit */ +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index e8393b87e7bd..05d58cebcfcc 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -133,6 +133,7 @@ enum { + IORING_OP_PROVIDE_BUFFERS, + IORING_OP_REMOVE_BUFFERS, + IORING_OP_TEE, ++ IORING_OP_IOCTL, + + /* this goes last, obviously */ + IORING_OP_LAST, +-- +1.8.3.1 + diff --git a/1014-liburing-anolis-test-timeout-new-test-for-timeout-feature.patch b/1014-liburing-anolis-test-timeout-new-test-for-timeout-feature.patch new file mode 100644 index 0000000..0037a51 --- /dev/null +++ b/1014-liburing-anolis-test-timeout-new-test-for-timeout-feature.patch @@ -0,0 +1,307 @@ +From ce520b2655e8d14d3a94cc9f596f128eb4c36140 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Sat, 12 Dec 2020 12:49:39 +0800 +Subject: [PATCH] test/timeout-new: test for timeout feature + +Tests for the new timeout feature. It covers: + - wake up when timeout, sleeping time calculated as well + - wake up by a cqe before timeout + - the above two in sqpoll thread mode + - multi child-threads wake up by a cqe issuing in main thread before + timeout + +Signed-off-by: Hao Xu +Signed-off-by: Jens Axboe +--- + test/Makefile | 7 +- + test/timeout-new.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 251 insertions(+), 2 deletions(-) + create mode 100644 test/timeout-new.c + +diff --git a/test/Makefile b/test/Makefile +index cbbd400391dd..0720dcd39950 100644 +--- a/test/Makefile ++++ b/test/Makefile +@@ -25,7 +25,8 @@ all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register + short-read openat2 probe shared-wq personality eventfd \ + send_recv eventfd-ring across-fork sq-poll-kthread splice \ + lfs-openat lfs-openat-write iopoll d4ae271dfaae-test \ +- eventfd-disable close-opath ce593a6c480a-test cq-overflow-peek ++ eventfd-disable close-opath ce593a6c480a-test cq-overflow-peek \ ++ timeout-new + + include ../Makefile.quiet + +@@ -65,7 +66,8 @@ test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \ + madvise.c short-read.c openat2.c probe.c shared-wq.c \ + personality.c eventfd.c eventfd-ring.c across-fork.c sq-poll-kthread.c \ + splice.c lfs-openat.c lfs-openat-write.c iopoll.c d4ae271dfaae-test.c \ +- eventfd-disable.c close-opath.c ce593a6c480a-test.c cq-overflow-peek.c ++ eventfd-disable.c close-opath.c ce593a6c480a-test.c cq-overflow-peek.c \ ++ timeout-new.c + + ifdef CONFIG_HAVE_STATX + test_srcs += statx.c +@@ -87,6 +89,7 @@ submit-reuse: XCFLAGS = -lpthread + poll-v-poll: XCFLAGS = -lpthread + across-fork: XCFLAGS = -lpthread + ce593a6c480a-test: XCFLAGS = -lpthread ++timeout-new: XCFLAGS = -lpthread + + install: $(all_targets) runtests.sh runtests-loop.sh + $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ +diff --git a/test/timeout-new.c b/test/timeout-new.c +new file mode 100644 +index 000000000000..45b9a149ae11 +--- /dev/null ++++ b/test/timeout-new.c +@@ -0,0 +1,246 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Description: tests for getevents timeout ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "liburing.h" ++ ++#define TIMEOUT_MSEC 200 ++#define TIMEOUT_SEC 10 ++ ++int thread_ret0, thread_ret1; ++int cnt = 0; ++pthread_mutex_t mutex; ++ ++static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec) ++{ ++ ts->tv_sec = msec / 1000; ++ ts->tv_nsec = (msec % 1000) * 1000000; ++} ++ ++static unsigned long long mtime_since(const struct timeval *s, ++ const struct timeval *e) ++{ ++ long long sec, usec; ++ ++ sec = e->tv_sec - s->tv_sec; ++ usec = (e->tv_usec - s->tv_usec); ++ if (sec > 0 && usec < 0) { ++ sec--; ++ usec += 1000000; ++ } ++ ++ sec *= 1000; ++ usec /= 1000; ++ return sec + usec; ++} ++ ++static unsigned long long mtime_since_now(struct timeval *tv) ++{ ++ struct timeval end; ++ ++ gettimeofday(&end, NULL); ++ return mtime_since(tv, &end); ++} ++ ++ ++static int test_return_before_timeout(struct io_uring *ring) ++{ ++ struct io_uring_cqe *cqe; ++ struct io_uring_sqe *sqe; ++ int ret; ++ struct __kernel_timespec ts; ++ ++ sqe = io_uring_get_sqe(ring); ++ if (!sqe) { ++ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); ++ return 1; ++ } ++ ++ io_uring_prep_nop(sqe); ++ ++ ret = io_uring_submit(ring); ++ if (ret <= 0) { ++ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); ++ return 1; ++ } ++ ++ msec_to_ts(&ts, TIMEOUT_MSEC); ++ ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts); ++ if (ret < 0) { ++ fprintf(stderr, "%s: timeout error: %d\n", __FUNCTION__, ret); ++ return 1; ++ } ++ ++ io_uring_cqe_seen(ring, cqe); ++ return 0; ++} ++ ++static int test_return_after_timeout(struct io_uring *ring) ++{ ++ struct io_uring_cqe *cqe; ++ int ret; ++ struct __kernel_timespec ts; ++ struct timeval tv; ++ unsigned long long exp; ++ ++ msec_to_ts(&ts, TIMEOUT_MSEC); ++ gettimeofday(&tv, NULL); ++ ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts); ++ exp = mtime_since_now(&tv); ++ if (ret != -ETIME) { ++ fprintf(stderr, "%s: timeout error: %d\n", __FUNCTION__, ret); ++ return 1; ++ } ++ ++ if (exp < TIMEOUT_MSEC / 2 || exp > (TIMEOUT_MSEC * 3) / 2) { ++ fprintf(stderr, "%s: Timeout seems wonky (got %llu)\n", __FUNCTION__, exp); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int __reap_thread_fn(void *data) { ++ struct io_uring *ring = (struct io_uring *)data; ++ struct io_uring_cqe *cqe; ++ struct __kernel_timespec ts; ++ ++ msec_to_ts(&ts, TIMEOUT_SEC); ++ pthread_mutex_lock(&mutex); ++ cnt++; ++ pthread_mutex_unlock(&mutex); ++ return io_uring_wait_cqe_timeout(ring, &cqe, &ts); ++} ++ ++void *reap_thread_fn0(void *data) { ++ thread_ret0 = __reap_thread_fn(data); ++ return NULL; ++} ++ ++void *reap_thread_fn1(void *data) { ++ thread_ret1 = __reap_thread_fn(data); ++ return NULL; ++} ++ ++/* ++ * This is to test issuing a sqe in main thread and reaping it in two child-thread ++ * at the same time. To see if timeout feature works or not. ++ */ ++int test_multi_threads_timeout() { ++ struct io_uring ring; ++ int ret; ++ bool both_wait = false; ++ pthread_t reap_thread0, reap_thread1; ++ struct io_uring_sqe *sqe; ++ ++ ret = io_uring_queue_init(8, &ring, 0); ++ if (ret) { ++ fprintf(stderr, "%s: ring setup failed: %d\n", __FUNCTION__, ret); ++ return 1; ++ } ++ ++ pthread_create(&reap_thread0, NULL, reap_thread_fn0, &ring); ++ pthread_create(&reap_thread1, NULL, reap_thread_fn1, &ring); ++ ++ /* ++ * make two threads both enter io_uring_wait_cqe_timeout() before issuing the sqe ++ * as possible as we can. So that there are two threads in the ctx->wait queue. ++ * In this way, we can test if a cqe wakes up two threads at the same time. ++ */ ++ while(!both_wait) { ++ pthread_mutex_lock(&mutex); ++ if (cnt == 2) ++ both_wait = true; ++ pthread_mutex_unlock(&mutex); ++ sleep(1); ++ } ++ ++ sqe = io_uring_get_sqe(&ring); ++ if (!sqe) { ++ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ io_uring_prep_nop(sqe); ++ ++ ret = io_uring_submit(&ring); ++ if (ret <= 0) { ++ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); ++ goto err; ++ } ++ ++ pthread_join(reap_thread0, NULL); ++ pthread_join(reap_thread1, NULL); ++ ++ if ((thread_ret0 && thread_ret0 != -ETIME) || (thread_ret1 && thread_ret1 != -ETIME)) { ++ fprintf(stderr, "%s: thread wait cqe timeout failed: %d %d\n", ++ __FUNCTION__, thread_ret0, thread_ret1); ++ goto err; ++ } ++ ++ return 0; ++err: ++ return 1; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct io_uring ring_normal, ring_sq; ++ int ret; ++ ++ if (argc > 1) ++ return 0; ++ ++ ret = io_uring_queue_init(8, &ring_normal, 0); ++ if (ret) { ++ fprintf(stderr, "ring_normal setup failed: %d\n", ret); ++ return 1; ++ } ++ if (!(ring_normal.features & IORING_FEAT_EXT_ARG)) { ++ fprintf(stderr, "feature IORING_FEAT_EXT_ARG not supported.\n"); ++ return 1; ++ } ++ ++ ret = test_return_before_timeout(&ring_normal); ++ if (ret) { ++ fprintf(stderr, "ring_normal: test_return_before_timeout failed\n"); ++ return ret; ++ } ++ ++ ret = test_return_after_timeout(&ring_normal); ++ if (ret) { ++ fprintf(stderr, "ring_normal: test_return_after_timeout failed\n"); ++ return ret; ++ } ++ ++ ret = io_uring_queue_init(8, &ring_sq, IORING_SETUP_SQPOLL); ++ if (ret) { ++ fprintf(stderr, "ring_sq setup failed: %d\n", ret); ++ return 1; ++ } ++ ++ ret = test_return_before_timeout(&ring_sq); ++ if (ret) { ++ fprintf(stderr, "ring_sq: test_return_before_timeout failed\n"); ++ return ret; ++ } ++ ++ ret = test_return_after_timeout(&ring_sq); ++ if (ret) { ++ fprintf(stderr, "ring_sq: test_return_after_timeout failed\n"); ++ return ret; ++ } ++ ++ ret = test_multi_threads_timeout(); ++ if (ret) { ++ fprintf(stderr, "test_multi_threads_timeout failed\n"); ++ return ret; ++ } ++ ++ return 0; ++} +-- +1.8.3.1 + diff --git a/1015-liburing-anolis-test-use-a-map-to-define-test-files-devices-we-need.patch b/1015-liburing-anolis-test-use-a-map-to-define-test-files-devices-we-need.patch new file mode 100644 index 0000000..7bb1e7f --- /dev/null +++ b/1015-liburing-anolis-test-use-a-map-to-define-test-files-devices-we-need.patch @@ -0,0 +1,68 @@ +From c2f5708119a8249feda4e5e283c1e17dc90d4773 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 25 Feb 2021 16:39:02 +0800 +Subject: [PATCH] test: use a map to define test files / devices we need + +Different tests need different files / devices, use a map to indicate +what each test need. + +Signed-off-by: Hao Xu +Signed-off-by: Jens Axboe +--- + test/config | 2 +- + test/runtests.sh | 13 ++++++------- + 2 files changed, 7 insertions(+), 8 deletions(-) + +diff --git a/test/config b/test/config +index 80a5f467c0c4..d1ea7858ee7a 100644 +--- a/test/config ++++ b/test/config +@@ -1,4 +1,4 @@ + # Define raw test devices (or files) for test cases, if any + # Copy this to config.local, and uncomment + define test files + # +-# TEST_FILES="/dev/nvme0n1p2 /data/file" ++declare -A TEST_FILES=() +diff --git a/test/runtests.sh b/test/runtests.sh +index a891f4b91acd..171470bbd5a7 100755 +--- a/test/runtests.sh ++++ b/test/runtests.sh +@@ -6,6 +6,7 @@ RET=0 + TIMEOUT=60 + FAILED="" + MAYBE_FAILED="" ++declare -A TEST_FILES + + do_kmsg="1" + if ! [ $(id -u) = 0 ]; then +@@ -13,10 +14,9 @@ if ! [ $(id -u) = 0 ]; then + fi + + TEST_DIR=$(dirname $0) +-TEST_FILES="" + if [ -f "$TEST_DIR/config.local" ]; then + . $TEST_DIR/config.local +- for dev in $TEST_FILES; do ++ for dev in ${TEST_FILES[@]}; do + if [ ! -e "$dev" ]; then + echo "Test file $dev not valid" + exit 1 +@@ -102,11 +102,10 @@ run_test() + } + + for t in $TESTS; do +- run_test $t +- if [ ! -z "$TEST_FILES" ]; then +- for dev in $TEST_FILES; do +- run_test $t $dev +- done ++ if [ ! -n "${TEST_FILES[$t]}" ]; then ++ run_test $t ++ else ++ run_test $t ${TEST_FILES[$t]} + fi + done + +-- +1.8.3.1 + diff --git a/1016-liburing-anolis-test-add-ioctl-test.patch b/1016-liburing-anolis-test-add-ioctl-test.patch new file mode 100644 index 0000000..3b35ace --- /dev/null +++ b/1016-liburing-anolis-test-add-ioctl-test.patch @@ -0,0 +1,223 @@ +From c838127df8046c4b2ab83a8b75125f91ff4d03c2 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Thu, 25 Feb 2021 17:26:59 +0800 +Subject: [PATCH] test: add ioctl test + +add a test for ioctl, make sure there is a device for this test in the +TEST_FILES in conifg.local. +eg. declare -A TEST_FILES=(["ioctl"]="/dev/nvme0n1") + +Signed-off-by: Hao Xu +--- + test/Makefile | 4 +- + test/ioctl.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 178 insertions(+), 2 deletions(-) + create mode 100644 test/ioctl.c + +diff --git a/test/Makefile b/test/Makefile +index 0720dcd39950..9e911e6a596a 100644 +--- a/test/Makefile ++++ b/test/Makefile +@@ -26,7 +26,7 @@ all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register + send_recv eventfd-ring across-fork sq-poll-kthread splice \ + lfs-openat lfs-openat-write iopoll d4ae271dfaae-test \ + eventfd-disable close-opath ce593a6c480a-test cq-overflow-peek \ +- timeout-new ++ timeout-new ioctl + + include ../Makefile.quiet + +@@ -67,7 +67,7 @@ test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \ + personality.c eventfd.c eventfd-ring.c across-fork.c sq-poll-kthread.c \ + splice.c lfs-openat.c lfs-openat-write.c iopoll.c d4ae271dfaae-test.c \ + eventfd-disable.c close-opath.c ce593a6c480a-test.c cq-overflow-peek.c \ +- timeout-new.c ++ timeout-new.c ioctl.c + + ifdef CONFIG_HAVE_STATX + test_srcs += statx.c +diff --git a/test/ioctl.c b/test/ioctl.c +new file mode 100644 +index 000000000000..33077fb5ffc7 +--- /dev/null ++++ b/test/ioctl.c +@@ -0,0 +1,176 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Description: test io_uring ioctl ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "liburing.h" ++ ++#ifndef BLKDISCARD ++#define BLKDISCARD _IO(0x12,119) ++#endif ++ ++typedef unsigned long long ull; ++char *dev_path; ++ ++static int init_params(int cmd, int *fd, int *len, void **buf) ++{ ++ *len = cmd; ++ switch (cmd) { ++ case BLKDISCARD: ++ *fd = open(dev_path, O_RDWR); ++ ull *range = (ull *)malloc(sizeof(ull) * 2); ++ range[0] = 0; ++ range[1] = 1024; ++ *buf = range; ++ break; ++ default: ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ioctl_clean(int cmd, int fd, void *buf) ++{ ++ int ret; ++ if (fd > 0) { ++ ret = close(fd); ++ if (ret) ++ return ret; ++ } ++ ++ switch (cmd) { ++ case BLKDISCARD: ++ if (buf) ++ free(buf); ++ break; ++ } ++ ++ return 0; ++} ++static int ioctl_extra_check(int cmd, void *buf) ++{ ++ switch (cmd) { ++ case BLKDISCARD: ++ break; ++ } ++ return 0; ++} ++ ++static int test_ioctl(struct io_uring *ring, int cmd) ++{ ++ struct io_uring_cqe *cqe; ++ struct io_uring_sqe *sqe; ++ int fd = 0, len, ret, ret2; ++ void *buf = NULL; ++ ++ ret = init_params(cmd, &fd, &len, &buf); ++ if (ret == -1) { ++ perror("invalid command"); ++ goto err; ++ } ++ if (fd < 0) { ++ perror("open"); ++ goto err; ++ } ++ ++ sqe = io_uring_get_sqe(ring); ++ if (!sqe) { ++ fprintf(stderr, "get sqe failed\n"); ++ goto err; ++ } ++ io_uring_prep_ioctl(sqe, fd, len, buf); ++ ++ ret = io_uring_submit(ring); ++ if (ret <= 0) { ++ fprintf(stderr, "sqe submit failed: %d\n", ret); ++ goto err; ++ } ++ ++ ret = io_uring_wait_cqe(ring, &cqe); ++ if (ret < 0) { ++ fprintf(stderr, "wait completion %d\n", ret); ++ goto err; ++ } ++ ++ ret = 1; ++ switch (cqe->res) { ++ /* ++ * Two cases return -EINVAL: ++ * - sys_ioctl() itself returns it ++ * - IORING_OP_IOCTL isn't supported in io_uring ++ * ++ * To distinguish them, one solution is to return other stuff other ++ * than -EINVAL when sys_ioctl() logic returns -EINVAL. But this ++ * change the logic of the original sys_ioctl() syscall. ++ * Leave it as it is for now. ++ */ ++ case -EINVAL: ++ fprintf(stderr, "cqe->res is -EINVAL\n"); ++ break; ++ case -EFAULT: ++ fprintf(stderr, "cqe->res is -EFAULT\n"); ++ break; ++ case -EBADF: ++ fprintf(stderr, "cqe->res is -EBADF\n"); ++ break; ++ case -ENOTTY: ++ fprintf(stderr, "cqe->res is -ENOTTY\n"); ++ break; ++ default: ++ if (cqe->res) { ++ fprintf(stderr, "cqe->res is %d\n", cqe->res); ++ } else if (ioctl_extra_check(cmd, buf)) { ++ fprintf(stderr, "ioctl cmd:%d failed\n", cmd); ++ } else { ++ ret = 0; ++ } ++ } ++ ++ io_uring_cqe_seen(ring, cqe); ++err: ++ ret2 = ioctl_clean(cmd, fd, buf); ++ /* ++ * it's not a test error, just print warning, still return 0 ++ */ ++ if (ret2) ++ fprintf(stderr, "close test file failure\n"); ++ ++ return ret; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct io_uring ring; ++ int ret; ++ ++ if (argc < 2) { ++ fprintf(stderr, "no ssd device indicated, skip.\n"); ++ return 0; ++ } ++ ++ dev_path = argv[1]; ++ ++ ret = io_uring_queue_init(8, &ring, 0); ++ if (ret) { ++ fprintf(stderr, "ring setup failed\n"); ++ return 1; ++ } ++ ++ ret = test_ioctl(&ring, BLKDISCARD); ++ if (ret) { ++ fprintf(stderr, "test_ioctl BLKDISCARD failed\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ +-- +1.8.3.1 + diff --git a/1017-liburing-anolis-test-timeout-overflow-don-t-run-on-newer-kernels.patch b/1017-liburing-anolis-test-timeout-overflow-don-t-run-on-newer-kernels.patch new file mode 100644 index 0000000..fea8178 --- /dev/null +++ b/1017-liburing-anolis-test-timeout-overflow-don-t-run-on-newer-kernels.patch @@ -0,0 +1,70 @@ +From 4fe73ec45c51096459971727089a0f0b1f86f926 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Thu, 13 Aug 2020 18:00:06 -0600 +Subject: [PATCH] test/timeout-overflow: don't run on newer kernels + +It's known to fail with the batched completions, just disable it +on newer kernels. + +Signed-off-by: Jens Axboe +Signed-off-by: Joseph Qi +--- + test/timeout-overflow.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/test/timeout-overflow.c b/test/timeout-overflow.c +index 1074e2b..f952f80 100644 +--- a/test/timeout-overflow.c ++++ b/test/timeout-overflow.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + #include "liburing.h" +@@ -19,19 +20,29 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec) + ts->tv_nsec = (msec % 1000) * 1000000; + } + +-static int check_timeout_support() ++static int check_timeout_support(void) + { + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct __kernel_timespec ts; ++ struct io_uring_params p; + struct io_uring ring; + int ret; + +- ret = io_uring_queue_init(8, &ring, 0); ++ memset(&p, 0, sizeof(p)); ++ ret = io_uring_queue_init_params(1, &ring, &p); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } ++ ++ /* not really a match, but same kernel added batched completions */ ++ if (p.features & IORING_FEAT_POLL_32BITS) { ++ fprintf(stdout, "Skipping\n"); ++ not_supported = 1; ++ return 0; ++ } ++ + sqe = io_uring_get_sqe(&ring); + msec_to_ts(&ts, TIMEOUT_MSEC); + io_uring_prep_timeout(sqe, &ts, 1, 0); +@@ -74,7 +85,7 @@ err: + * successful after the patch. And req1/req2 will completed successful with + * req3/req4 return -ETIME without this patch! + */ +-static int test_timeout_overflow() ++static int test_timeout_overflow(void) + { + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; +-- +1.8.3.1 + diff --git a/1018-liburing-anolis-support-us-granularity-of-io_sq_thread_idle.patch b/1018-liburing-anolis-support-us-granularity-of-io_sq_thread_idle.patch new file mode 100644 index 0000000..b55d0cc --- /dev/null +++ b/1018-liburing-anolis-support-us-granularity-of-io_sq_thread_idle.patch @@ -0,0 +1,56 @@ +From 65ac402fb0feb4ee74d71317f04c1b4422d78665 Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Mon, 10 May 2021 11:34:29 +0800 +Subject: [PATCH] support us granularity of io_sq_thread_idle + +add flag IORING_SETUP_IDLE_US to support microsecond granularity +io_sq_thread_idle. + +Signed-off-by: Hao Xu +--- + man/io_uring_setup.2 | 9 ++++++++- + src/include/liburing/io_uring.h | 1 + + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 +index 8c71e200d8b7..a2a9072423de 100644 +--- a/man/io_uring_setup.2 ++++ b/man/io_uring_setup.2 +@@ -80,7 +80,9 @@ doing a single system call. + + If the kernel thread is idle for more than + .I sq_thread_idle +-milliseconds, it will set the ++milliseconds/microseconds(depends on if ++.B IORING_SETUP_IDLE_US ++is set), it will set the + .B IORING_SQ_NEED_WAKEUP + bit in the + .I flags +@@ -146,6 +148,11 @@ Create the completion queue with + entries. The value must be greater than + .IR entries , + and may be rounded up to the next power-of-two. ++.TP ++.B IORING_SETUP_IDLE_US ++If this flag is set, the unit of ++.I sq_thread_idle ++is microsecond, rather than millisecond. + .PP + If no flags are specified, the io_uring instance is setup for + interrupt driven I/O. I/O may be submitted using +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index 05d58cebcfcc..8b412fb21567 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -95,6 +95,7 @@ enum { + #define IORING_SETUP_CQSIZE (1U << 3) /* app defines CQ size */ + #define IORING_SETUP_CLAMP (1U << 4) /* clamp SQ/CQ ring sizes */ + #define IORING_SETUP_ATTACH_WQ (1U << 5) /* attach to existing wq */ ++#define IORING_SETUP_IDLE_US (1U << 30) /* unit of thread_idle is microsecond */ + /* use percpu SQ poll thread */ + #define IORING_SETUP_SQPOLL_PERCPU (1U << 31) + +-- +1.8.3.1 + diff --git a/1019-liburing-anolis-add-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch b/1019-liburing-anolis-add-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch new file mode 100644 index 0000000..d0853d5 --- /dev/null +++ b/1019-liburing-anolis-add-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch @@ -0,0 +1,137 @@ +From edc1b76b8d8a81b26e9a8399f91f73b066b112bf Mon Sep 17 00:00:00 2001 +From: Hao Xu +Date: Mon, 10 May 2021 14:39:02 +0800 +Subject: [PATCH] add IORING_ENTER_SQ_SUBMIT_ON_IDLE flag + +add this flag to allow the original task to submit some sqes to reduce +sqthread wakeup latency. + +Signed-off-by: Hao Xu +--- + debian/liburing1.symbols | 6 ++++++ + src/include/liburing.h | 2 ++ + src/include/liburing/io_uring.h | 1 + + src/liburing.map | 3 +++ + src/queue.c | 29 ++++++++++++++++++++++------- + 5 files changed, 34 insertions(+), 7 deletions(-) + +diff --git a/debian/liburing1.symbols b/debian/liburing1.symbols +index cc4d504895d3..dccce71d0e11 100644 +--- a/debian/liburing1.symbols ++++ b/debian/liburing1.symbols +@@ -26,3 +26,9 @@ liburing.so.1 liburing1 #MINVER# + io_uring_register_probe@LIBURING_0.4 0.4-1 + io_uring_ring_dontfork@LIBURING_0.4 0.4-1 + io_uring_unregister_personality@LIBURING_0.4 0.4-1 ++ (symver)LIBURING_0.5 0.5-1 ++ (symver)LIBURING_0.6 0.6-1 ++ (symver)LIBURING_0.7 0.7-8 ++ io_uring_submit_on_idle@LIBURING_0.7 0.7-8 ++ io_uring_submit_on_idle_and_wait@LIBURING_0.7 0.7-8 ++ +diff --git a/src/include/liburing.h b/src/include/liburing.h +index 9fa5bc92986d..8a1dc7c6591f 100644 +--- a/src/include/liburing.h ++++ b/src/include/liburing.h +@@ -97,7 +97,9 @@ extern int io_uring_wait_cqes(struct io_uring *ring, + extern int io_uring_wait_cqe_timeout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, struct __kernel_timespec *ts); + extern int io_uring_submit(struct io_uring *ring); ++extern int io_uring_submit_on_idle(struct io_uring *ring); + extern int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); ++extern int io_uring_submit_on_idle_and_wait(struct io_uring *ring, unsigned wait_nr); + extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); + + extern int io_uring_register_buffers(struct io_uring *ring, +diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h +index 8b412fb21567..cd1c68a753b9 100644 +--- a/src/include/liburing/io_uring.h ++++ b/src/include/liburing/io_uring.h +@@ -229,6 +229,7 @@ struct io_cqring_offsets { + #define IORING_ENTER_GETEVENTS (1U << 0) + #define IORING_ENTER_SQ_WAKEUP (1U << 1) + #define IORING_ENTER_EXT_ARG (1U << 3) ++#define IORING_ENTER_SQ_SUBMIT_ON_IDLE (1U << 4) + + /* + * Passed in for io_uring_setup(2). Copied back with updated info on success +diff --git a/src/liburing.map b/src/liburing.map +index 38bd558a5a50..8c2ccfaca8c2 100644 +--- a/src/liburing.map ++++ b/src/liburing.map +@@ -56,4 +56,7 @@ LIBURING_0.6 { + } LIBURING_0.5; + + LIBURING_0.7 { ++ global: ++ io_uring_submit_on_idle; ++ io_uring_submit_on_idle_and_wait; + } LIBURING_0.6; +diff --git a/src/queue.c b/src/queue.c +index 2662e671fb34..d8ee64f25601 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -304,12 +304,12 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring, + * Returns number of sqes submitted + */ + static int __io_uring_submit(struct io_uring *ring, unsigned submitted, +- unsigned wait_nr) ++ unsigned wait_nr, unsigned enter_flags) + { +- unsigned flags; ++ unsigned flags = 0; + int ret; + +- flags = 0; ++ flags |= enter_flags; + if (sq_ring_needs_enter(ring, &flags) || wait_nr) { + if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL)) + flags |= IORING_ENTER_GETEVENTS; +@@ -324,9 +324,10 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted, + return ret; + } + +-static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) ++static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr, unsigned enter_flags) + { +- return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr); ++ return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr, ++ enter_flags); + } + + /* +@@ -336,7 +337,16 @@ static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) + */ + int io_uring_submit(struct io_uring *ring) + { +- return __io_uring_submit_and_wait(ring, 0); ++ return __io_uring_submit_and_wait(ring, 0, 0); ++} ++ ++/* ++ * Similar to io_uring_submit(), but with flag IORING_ENTER_SUBMIT_ON_IDLE ++ * to allow submitting sqes in original context when waking up sqthread. ++ */ ++int io_uring_submit_on_idle(struct io_uring *ring) ++{ ++ return __io_uring_submit_and_wait(ring, 0, IORING_ENTER_SQ_SUBMIT_ON_IDLE); + } + + /* +@@ -346,7 +356,12 @@ int io_uring_submit(struct io_uring *ring) + */ + int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) + { +- return __io_uring_submit_and_wait(ring, wait_nr); ++ return __io_uring_submit_and_wait(ring, wait_nr, 0); ++} ++ ++int io_uring_submit_on_idle_and_wait(struct io_uring *ring, unsigned wait_nr) ++{ ++ return __io_uring_submit_and_wait(ring, wait_nr, IORING_ENTER_SQ_SUBMIT_ON_IDLE); + } + + static inline struct io_uring_sqe * +-- +1.8.3.1 + diff --git a/liburing-1.0.7.tar.bz2 b/liburing-1.0.7.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..f893e56ae0f7ee911c6c624777c1649e5a547f81 GIT binary patch literal 86339 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'-qJB`Tg_t{La-Qn@b*Dt{XHv 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�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 C`*42% literal 0 HcmV?d00001 diff --git a/liburing-always-build-with-fPIC.patch b/liburing-always-build-with-fPIC.patch new file mode 100644 index 0000000..6daa3d0 --- /dev/null +++ b/liburing-always-build-with-fPIC.patch @@ -0,0 +1,16 @@ +diff --git a/src/Makefile b/src/Makefile +index 44a95ad..6fd050d 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -4,9 +4,9 @@ libdir ?= $(prefix)/lib + libdevdir ?= $(prefix)/lib + + CFLAGS ?= -g -fomit-frame-pointer -O2 +-override CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare\ ++override CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -fPIC\ + -Iinclude/ -include ../config-host.h +-SO_CFLAGS=-fPIC $(CFLAGS) ++SO_CFLAGS=$(CFLAGS) + L_CFLAGS=$(CFLAGS) + LINK_FLAGS= + LINK_FLAGS+=$(LDFLAGS) diff --git a/liburing.spec b/liburing.spec new file mode 100644 index 0000000..cf65dd8 --- /dev/null +++ b/liburing.spec @@ -0,0 +1,96 @@ +%define anolis_release .0.1 + +Name: liburing +Version: 1.0.7 +Release: 3%{anolis_release}%{?dist} +Summary: Linux-native io_uring I/O access library +License: LGPLv2+ +Source: %{name}-%{version}.tar.bz2 +URL: http://brick.kernel.dk/snaps/%{name}-%{version}.tar.bz2 +BuildRequires: gcc +Patch0: liburing-always-build-with-fPIC.patch +# Begin: Anolis customized patches +Patch1001: 1001-liburing-anolis-Add-percpu-io-sq-thread-support.patch +Patch1002: 1002-liburing-anolis-Revert-Make-the-liburing-header-files-again-compatib.patch +Patch1003: 1003-liburing-anolis-Revert-src-include-liburing-barrier.h-Restore-clang-.patch +Patch1004: 1004-liburing-anolis-Revert-src-include-liburing-barrier.h-Use-C11-atomic.patch +Patch1005: 1005-liburing-anolis-sq_ring_needs_enter-revert-change-to-only-enter-if-s.patch +Patch1006: 1006-liburing-anolis-io_uring.h-update-with-5.11-pending-copy.patch +Patch1007: 1007-liburing-anolis-Include-features-in-struct-io_uring.patch +Patch1008: 1008-liburing-anolis-Add-__sys_io_uring_enter2.patch +Patch1009: 1009-liburing-anolis-Add-wrapper-for-__io_uring_get_cqe.patch +Patch1010: 1010-liburing-anolis-Use-IORING_ENTER_GETEVENTS_TIMEOUT-if-available.patch +Patch1011: 1011-liburing-anolis-Update-SIG_IS_DATA-to-modified-kernel-API.patch +Patch1012: 1012-liburing-anolis-Rename-SIG_IS_DATA-EXT_ARG.patch +Patch1013: 1013-liburing-anolis-support-async-ioctl-in-liburing.patch +Patch1014: 1014-liburing-anolis-test-timeout-new-test-for-timeout-feature.patch +Patch1015: 1015-liburing-anolis-test-use-a-map-to-define-test-files-devices-we-need.patch +Patch1016: 1016-liburing-anolis-test-add-ioctl-test.patch +Patch1017: 1017-liburing-anolis-test-timeout-overflow-don-t-run-on-newer-kernels.patch +Patch1018: 1018-liburing-anolis-support-us-granularity-of-io_sq_thread_idle.patch +Patch1019: 1019-liburing-anolis-add-IORING_ENTER_SQ_SUBMIT_ON_IDLE-flag.patch +# End: Anolis customized patches + +%description +Provides native async IO for the Linux kernel, in a fast and efficient +manner, for both buffered and O_DIRECT. + +%package devel +Summary: Development files for Linux-native io_uring I/O access library +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + +%description devel +This package provides header files to include and libraries to link with +for the Linux-native io_uring. + +%prep +%autosetup -p1 + +%build +./configure --prefix=%{_prefix} --libdir=/%{_libdir} --libdevdir=/%{_libdir} --mandir=%{_mandir} --includedir=%{_includedir} + +%make_build V=1 + +%install +%make_install + +%files +%attr(0755,root,root) %{_libdir}/liburing.so.* +%doc COPYING + +%files devel +%{_includedir}/liburing/ +%{_includedir}/liburing.h +%{_libdir}/liburing.so +%{_libdir}/liburing.a +%{_libdir}/pkgconfig/* +%{_mandir}/man2/* + +%changelog +* Mon Nov 29 2021 Hao Xu - 1.0.7-3.0.1 +- add anolis customized patches to support features in Anolis OS Kernel + +* Thu Aug 20 2020 Jeff Moyer - 1.0.7-3.el8 +- Build with V=1 so that the build logs are useful. +- Related: rhbz#1862551 + +* Thu Aug 20 2020 Jeff Moyer - 1.0.7-2.el8 +- Fix versioning. The installed library is 1.0.7, make the rpm match. +- bump release number for build, which includes -fPIC fix +- Related: rhbz#1862551 + +* Fri Jul 31 2020 Jeff Moyer - 0.7-1.el8 +- Update to upstream version 0.7. +- Resolves: 1862551 + +* Wed Nov 6 2019 Jeff Moyer - 0.2-2.el8 +- bump release to trigger gating tests +- Related: bz#1724804 + +* Thu Oct 31 2019 Jeff Moyer - 0.2-1 +- Initial rhel8 package. +- Resolves: bz#1724804 + +* Tue Jan 8 2019 Jens Axboe - 0.1 +- Initial version -- Gitee