* [PATCH liburing 0/8] update reg-wait to use region API
@ 2024-11-15 21:33 Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 1/8] queue: break reg wait setup Pavel Begunkov
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Reflect changes of the kernel API for registered waits and fix up
tests. The only thing that changed for the user is how we register
the area, which is now more generic and called areas. It should
also be done now while the ring is in the disabled state,
see IORING_SETUP_R_DISABLED.
In the future we might want to improve the liburing API for
regions, i.e. adding a structure and a bunch of functions
setting up the region in different modes.
Pavel Begunkov (8):
queue: break reg wait setup
Update io_uring.h
queue: add region helpers and fix up wait reg kernel api
examples: convert reg-wait to new api
tests: convert reg-wait to regions
tests: add region testing
tests: test arbitrary offset reg waits
Remove leftovers of old reg-wait registration api
examples/reg-wait.c | 45 +++-
src/include/liburing.h | 7 +-
src/include/liburing/io_uring.h | 27 ++-
src/liburing-ffi.map | 3 +-
src/liburing.map | 3 +-
src/queue.c | 4 +-
src/register.c | 13 +-
src/setup.c | 29 ---
test/reg-wait.c | 377 +++++++++++++++++++++-----------
9 files changed, 332 insertions(+), 176 deletions(-)
--
2.46.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH liburing 1/8] queue: break reg wait setup
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 2/8] Update io_uring.h Pavel Begunkov
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
We're changing the registration and kernel api, kill reg wait
registration but leave definitions so that tests build.
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/register.c | 9 +--------
src/setup.c | 19 -------------------
2 files changed, 1 insertion(+), 27 deletions(-)
diff --git a/src/register.c b/src/register.c
index aef5baf..d566f5c 100644
--- a/src/register.c
+++ b/src/register.c
@@ -468,12 +468,5 @@ out:
int io_uring_register_wait_reg(struct io_uring *ring,
struct io_uring_reg_wait *reg, int nr)
{
- struct io_uring_cqwait_reg_arg arg = {
- .flags = 0,
- .struct_size = sizeof(*reg),
- .nr_entries = nr,
- .user_addr = (unsigned long) (uintptr_t) reg,
- };
-
- return do_register(ring, IORING_REGISTER_CQWAIT_REG, &arg, 1);
+ return -EINVAL;
}
diff --git a/src/setup.c b/src/setup.c
index 073de50..7c0cfab 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -689,29 +689,10 @@ int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
void io_uring_free_reg_wait(struct io_uring_reg_wait *reg, unsigned nentries)
{
- __sys_munmap(reg, nentries * sizeof(struct io_uring_reg_wait));
}
struct io_uring_reg_wait *io_uring_setup_reg_wait(struct io_uring *ring,
unsigned nentries, int *err)
{
- struct io_uring_reg_wait *reg;
- size_t size = nentries * sizeof(*reg);
- int ret;
-
- reg = __sys_mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_SHARED|MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
- if (IS_ERR(reg)) {
- *err = PTR_ERR(reg);
- return NULL;
- }
-
- memset(reg, 0, size);
- ret = io_uring_register_wait_reg(ring, reg, nentries);
- if (!ret)
- return reg;
-
- __sys_munmap(reg, size);
- *err = ret;
return NULL;
}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 2/8] Update io_uring.h
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 1/8] queue: break reg wait setup Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 3/8] queue: add region helpers and fix up wait reg kernel api Pavel Begunkov
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Remove the wait register opcode and add region registration
bits.
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/include/liburing/io_uring.h | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 20bc570..b2adc3f 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -615,7 +615,7 @@ enum io_uring_register_op {
IORING_REGISTER_RESIZE_RINGS = 33,
- IORING_REGISTER_CQWAIT_REG = 34,
+ IORING_REGISTER_MEM_REGION = 34,
/* this goes last */
IORING_REGISTER_LAST,
@@ -637,6 +637,31 @@ struct io_uring_files_update {
__aligned_u64 /* __s32 * */ fds;
};
+enum {
+ /* initialise with user provided memory pointed by user_addr */
+ IORING_MEM_REGION_TYPE_USER = 1,
+};
+
+struct io_uring_region_desc {
+ __u64 user_addr;
+ __u64 size;
+ __u32 flags;
+ __u32 id;
+ __u64 mmap_offset;
+ __u64 __resv[4];
+};
+
+enum {
+ /* expose the region as registered wait arguments */
+ IORING_MEM_REGION_REG_WAIT_ARG = 1,
+};
+
+struct io_uring_mem_region_reg {
+ __u64 region_uptr; /* struct io_uring_region_desc * */
+ __u64 flags;
+ __u64 __resv[2];
+};
+
/*
* Register a fully sparse file space, rather than pass in an array of all
* -1 file descriptors.
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 3/8] queue: add region helpers and fix up wait reg kernel api
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 1/8] queue: break reg wait setup Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 2/8] Update io_uring.h Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 4/8] examples: convert reg-wait to new api Pavel Begunkov
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Now the kernel expects a byte offset instead of a
struct io_uring_reg_wait index. Also add a helper
for registering a region of memory.
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/include/liburing.h | 4 +++-
src/liburing-ffi.map | 1 +
src/liburing.map | 1 +
src/queue.c | 4 +++-
src/register.c | 6 ++++++
5 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index 4d45dca..81ffe6e 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -285,8 +285,10 @@ int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
unsigned int nr_args);
/*
- * Mapped/registered wait regions
+ * Mapped/registered regions
*/
+int io_uring_register_region(struct io_uring *ring,
+ struct io_uring_mem_region_reg *reg);
struct io_uring_reg_wait *io_uring_setup_reg_wait(struct io_uring *ring,
unsigned nentries, int *err);
void io_uring_free_reg_wait(struct io_uring_reg_wait *reg, unsigned nentries);
diff --git a/src/liburing-ffi.map b/src/liburing-ffi.map
index 0985f78..117a46a 100644
--- a/src/liburing-ffi.map
+++ b/src/liburing-ffi.map
@@ -224,4 +224,5 @@ LIBURING_2.9 {
io_uring_free_reg_wait;
io_uring_setup_reg_wait;
io_uring_clone_buffers_offset;
+ io_uring_register_region;
} LIBURING_2.8;
diff --git a/src/liburing.map b/src/liburing.map
index 998621d..46edbc9 100644
--- a/src/liburing.map
+++ b/src/liburing.map
@@ -111,4 +111,5 @@ LIBURING_2.9 {
io_uring_free_reg_wait;
io_uring_setup_reg_wait;
io_uring_clone_buffers_offset;
+ io_uring_register_region;
} LIBURING_2.8;
diff --git a/src/queue.c b/src/queue.c
index 1692866..5f28e01 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -324,6 +324,8 @@ int io_uring_submit_and_wait_reg(struct io_uring *ring,
struct io_uring_cqe **cqe_ptr,
unsigned wait_nr, int reg_index)
{
+ unsigned long offset = reg_index * sizeof(struct io_uring_reg_wait);
+
struct get_data data = {
.submit = __io_uring_flush_sq(ring),
.wait_nr = wait_nr,
@@ -331,7 +333,7 @@ int io_uring_submit_and_wait_reg(struct io_uring *ring,
IORING_ENTER_EXT_ARG_REG,
.sz = sizeof(struct io_uring_reg_wait),
.has_ts = true,
- .arg = (void *) (uintptr_t) reg_index,
+ .arg = (void *) (uintptr_t) offset,
};
if (!(ring->features & IORING_FEAT_EXT_ARG))
diff --git a/src/register.c b/src/register.c
index d566f5c..0fff208 100644
--- a/src/register.c
+++ b/src/register.c
@@ -470,3 +470,9 @@ int io_uring_register_wait_reg(struct io_uring *ring,
{
return -EINVAL;
}
+
+int io_uring_register_region(struct io_uring *ring,
+ struct io_uring_mem_region_reg *reg)
+{
+ return do_register(ring, IORING_REGISTER_MEM_REGION, reg, 1);
+}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 4/8] examples: convert reg-wait to new api
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (2 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 3/8] queue: add region helpers and fix up wait reg kernel api Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 5/8] tests: convert reg-wait to regions Pavel Begunkov
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
examples/reg-wait.c | 45 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 39 insertions(+), 6 deletions(-)
diff --git a/examples/reg-wait.c b/examples/reg-wait.c
index 375538c..0e119aa 100644
--- a/examples/reg-wait.c
+++ b/examples/reg-wait.c
@@ -38,6 +38,20 @@ static unsigned long long mtime_since_now(struct timeval *tv)
return mtime_since(tv, &end);
}
+static int register_memory(struct io_uring *ring, void *ptr, size_t size)
+{
+ struct io_uring_region_desc rd = {};
+ struct io_uring_mem_region_reg mr = {};
+
+ rd.user_addr = (__u64)(unsigned long)ptr;
+ rd.size = size;
+ rd.flags = IORING_MEM_REGION_TYPE_USER;
+ mr.region_uptr = (__u64)(unsigned long)&rd;
+ mr.flags = IORING_MEM_REGION_REG_WAIT_ARG;
+
+ return io_uring_register_region(ring, &mr);
+}
+
int main(int argc, char *argv[])
{
struct io_uring_reg_wait *reg;
@@ -48,30 +62,43 @@ int main(int argc, char *argv[])
unsigned long msec;
struct timeval tv;
int ret, fds[2];
+ int page_size;
if (argc > 1) {
fprintf(stdout, "%s: takes no arguments\n", argv[0]);
return 0;
}
+ page_size = sysconf(_SC_PAGESIZE);
+ if (page_size < 0) {
+ fprintf(stderr, "sysconf(_SC_PAGESIZE) failed\n");
+ return 1;
+ }
+
if (pipe(fds) < 0) {
perror("pipe");
return 1;
}
- ret = io_uring_queue_init(8, &ring, 0);
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
if (ret) {
fprintf(stderr, "Queue init: %d\n", ret);
return 1;
}
/*
- * Setup wait region. We'll use 32 here, but 64 is probably a more
- * logical value, as it'll pin a page regardless of size. 64 is the
- * max value on a 4k page size architecture.
+ * Setup a region we'll use to pass wait arguments. It should be
+ * page aligned, we're using only first two wait entries here and
+ * the rest of the memory can be reused for other purposes.
*/
- reg = io_uring_setup_reg_wait(&ring, 32, &ret);
+ reg = aligned_alloc(page_size, page_size);
if (!reg) {
+ fprintf(stderr, "allocation failed\n");
+ return 1;
+ }
+
+ ret = register_memory(&ring, reg, page_size);
+ if (ret) {
if (ret == -EINVAL) {
fprintf(stderr, "Kernel doesn't support registered waits\n");
return 1;
@@ -80,6 +107,12 @@ int main(int argc, char *argv[])
return 1;
}
+ ret = io_uring_enable_rings(&ring);
+ if (ret) {
+ fprintf(stderr, "io_uring_enable_rings failure %i\n", ret);
+ return 1;
+ }
+
/*
* Setup two distinct wait regions. Index 0 will be a 1 second wait,
* and region 2 is a short wait using min_wait_usec as well. Neither
@@ -154,6 +187,6 @@ int main(int argc, char *argv[])
* Cleanup after ourselves
*/
io_uring_queue_exit(&ring);
- io_uring_free_reg_wait(reg, 32);
+ free(reg);
return 0;
}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 5/8] tests: convert reg-wait to regions
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (3 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 4/8] examples: convert reg-wait to new api Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 6/8] tests: add region testing Pavel Begunkov
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/reg-wait.c | 217 ++++++++++++++++++------------------------------
1 file changed, 83 insertions(+), 134 deletions(-)
diff --git a/test/reg-wait.c b/test/reg-wait.c
index 6a5123a..5f5a62a 100644
--- a/test/reg-wait.c
+++ b/test/reg-wait.c
@@ -14,123 +14,9 @@
#include "helpers.h"
#include "test.h"
+static int page_size;
static struct io_uring_reg_wait *reg;
-static int test_invalid_reg2(void)
-{
- struct io_uring ring;
- void *buf, *ptr;
- int ret;
-
- io_uring_queue_init(1, &ring, 0);
-
- if (posix_memalign(&buf, 4096, 4096))
- return T_EXIT_FAIL;
- memset(buf, 0, 4096);
- ptr = buf + 4096 - 32;
-
- ret = io_uring_register_wait_reg(&ring, ptr, 1);
- if (ret != -EINVAL) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- ptr = buf + (sizeof(struct io_uring_reg_wait) / 2);
- ret = io_uring_register_wait_reg(&ring, ptr, 1);
- if (ret != -EINVAL) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- free(buf);
- buf = (void *) 0x1000;
- ret = io_uring_register_wait_reg(&ring, buf, 1);
- if (ret != -EFAULT) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- buf = (void *) 0x1240;
- ret = io_uring_register_wait_reg(&ring, buf, 1);
- if (ret != -EFAULT) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- buf = (void *) 0x1241;
- ret = io_uring_register_wait_reg(&ring, buf, 1);
- if (ret != -EINVAL) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- io_uring_queue_exit(&ring);
- return T_EXIT_PASS;
-}
-
-static int test_invalid_reg(void)
-{
- struct io_uring_reg_wait *ireg;
- struct io_uring_cqe *cqe;
- struct io_uring ring;
- struct timeval tv;
- void *buf, *ptr;
- int ret;
-
- io_uring_queue_init(1, &ring, 0);
-
- if (posix_memalign(&buf, 4096, 4096))
- return T_EXIT_FAIL;
- memset(buf, 0, 4096);
- ptr = buf + 512;
- ireg = ptr;
-
- ret = io_uring_register_wait_reg(&ring, ireg, 56);
- if (ret) {
- fprintf(stderr, "register cqwait: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- ireg = ptr;
- memset(ireg, 0, sizeof(*ireg));
- ireg->ts.tv_sec = 1;
- ireg->ts.tv_nsec = 0;
- ireg->flags = IORING_REG_WAIT_TS;
-
- gettimeofday(&tv, NULL);
- ret = io_uring_submit_and_wait_reg(&ring, &cqe, 1, 0);
- if (ret != -ETIME) {
- fprintf(stderr, "wait_reg failed: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- ret = mtime_since_now(&tv);
- /* allow some slack, should be around 1.1s */
- if (ret < 1000 || ret > 1200) {
- fprintf(stderr, "wait too long or short: %d\n", ret);
- goto err;
- }
-
- memset(ireg, 0, sizeof(*ireg));
- ireg->ts.tv_sec = 1;
- ireg->ts.tv_nsec = 0;
- ireg->flags = IORING_REG_WAIT_TS;
-
- gettimeofday(&tv, NULL);
- ret = io_uring_submit_and_wait_reg(&ring, &cqe, 1, 56);
- if (ret != -EFAULT) {
- fprintf(stderr, "out-of-range reg_wait failed: %d\n", ret);
- return T_EXIT_FAIL;
- }
-
- free(buf);
- io_uring_queue_exit(&ring);
- return T_EXIT_PASS;
-err:
- io_uring_queue_exit(&ring);
- return T_EXIT_FAIL;
-}
-
static int test_invalid_sig(struct io_uring *ring)
{
struct io_uring_cqe *cqe;
@@ -164,6 +50,39 @@ static int test_invalid_sig(struct io_uring *ring)
return T_EXIT_PASS;
}
+static int test_offsets(struct io_uring *ring)
+{
+ struct io_uring_cqe *cqe;
+ int max_index = page_size / sizeof(struct io_uring_reg_wait);
+ struct io_uring_reg_wait *rw;
+ int ret;
+
+ rw = reg + max_index;
+ memset(rw, 0, sizeof(*rw));
+ rw->ts.tv_sec = 0;
+ rw->ts.tv_nsec = 1000;
+
+ ret = io_uring_submit_and_wait_reg(ring, &cqe, 1, 0);
+ if (ret != -EFAULT) {
+ fprintf(stderr, "max+1 index failed: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ rw = reg + max_index - 1;
+ memset(rw, 0, sizeof(*rw));
+ rw->flags = IORING_REG_WAIT_TS;
+ rw->ts.tv_sec = 0;
+ rw->ts.tv_nsec = 1000;
+
+ ret = io_uring_submit_and_wait_reg(ring, &cqe, 1, max_index - 1);
+ if (ret != -ETIME) {
+ fprintf(stderr, "last index failed: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ return 0;
+}
+
static int test_basic(struct io_uring *ring)
{
struct io_uring_cqe *cqe;
@@ -192,27 +111,50 @@ err:
return T_EXIT_FAIL;
}
-static int test_ring(void)
+static int test_wait_arg(void)
{
+ struct io_uring_region_desc rd = {};
+ struct io_uring_mem_region_reg mr = {};
struct io_uring ring;
- struct io_uring_params p = { };
+ void *buffer;
int ret;
- p.flags = 0;
- ret = io_uring_queue_init_params(8, &ring, &p);
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
if (ret) {
+ if (ret == -EINVAL) {
+ printf("IORING_SETUP_R_DISABLED not supported, skip\n");
+ return 0;
+ }
fprintf(stderr, "ring setup failed: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ buffer = aligned_alloc(page_size, page_size * 4);
+ if (!buffer) {
+ fprintf(stderr, "allocation failed\n");
+ return T_EXIT_FAIL;
+ }
+
+ rd.user_addr = (__u64)(unsigned long)buffer;
+ rd.size = page_size;
+ rd.flags = IORING_MEM_REGION_TYPE_USER;
+ mr.region_uptr = (__u64)(unsigned long)&rd;
+ mr.flags = IORING_MEM_REGION_REG_WAIT_ARG;
+
+ ret = io_uring_register_region(&ring, &mr);
+ if (ret) {
+ fprintf(stderr, "region reg failed %i\n", ret);
return 1;
}
- reg = io_uring_setup_reg_wait(&ring, 64, &ret);
- if (!reg) {
- if (ret == -EINVAL)
- return T_EXIT_SKIP;
- fprintf(stderr, "setup_reg_wait: %d\n", ret);
+ ret = io_uring_enable_rings(&ring);
+ if (ret) {
+ fprintf(stderr, "io_uring_enable_rings failure %i\n", ret);
return T_EXIT_FAIL;
}
+ reg = buffer;
+
ret = test_basic(&ring);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test failed\n");
@@ -225,27 +167,34 @@ static int test_ring(void)
goto err;
}
- ret = test_invalid_reg();
+ ret = test_offsets(&ring);
if (ret == T_EXIT_FAIL) {
- fprintf(stderr, "test_invalid_reg failed\n");
+ fprintf(stderr, "test_offsets failed\n");
goto err;
}
-
- ret = test_invalid_reg2();
- if (ret == T_EXIT_FAIL) {
- fprintf(stderr, "test_invalid_reg2 failed\n");
- goto err;
- }
-
err:
+ free(buffer);
io_uring_queue_exit(&ring);
return ret;
}
int main(int argc, char *argv[])
{
+ int ret;
+
if (argc > 1)
return 0;
- return test_ring();
+ page_size = sysconf(_SC_PAGESIZE);
+ if (page_size < 0) {
+ perror("sysconf(_SC_PAGESIZE)");
+ return 1;
+ }
+
+ ret = test_wait_arg();
+ if (ret == T_EXIT_FAIL) {
+ fprintf(stderr, "test_wait_arg failed\n");
+ return 1;
+ }
+ return 0;
}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 6/8] tests: add region testing
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (4 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 5/8] tests: convert reg-wait to regions Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 7/8] tests: test arbitrary offset reg waits Pavel Begunkov
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/reg-wait.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/test/reg-wait.c b/test/reg-wait.c
index 5f5a62a..13f6d51 100644
--- a/test/reg-wait.c
+++ b/test/reg-wait.c
@@ -178,6 +178,134 @@ err:
return ret;
}
+static int test_try_register_region(struct io_uring_mem_region_reg *pr,
+ bool disabled, bool reenable)
+{
+ struct io_uring ring;
+ int flags = 0;
+ int ret;
+
+ if (disabled)
+ flags = IORING_SETUP_R_DISABLED;
+
+ ret = io_uring_queue_init(8, &ring, flags);
+ if (ret) {
+ fprintf(stderr, "ring setup failed: %d\n", ret);
+ return 1;
+ }
+
+ if (reenable) {
+ ret = io_uring_enable_rings(&ring);
+ if (ret) {
+ fprintf(stderr, "io_uring_enable_rings failure %i\n", ret);
+ return 1;
+ }
+ }
+
+ ret = io_uring_register_region(&ring, pr);
+ io_uring_queue_exit(&ring);
+ return ret;
+}
+
+static int test_regions(void)
+{
+ struct io_uring_region_desc rd = {};
+ struct io_uring_mem_region_reg mr = {};
+ void *buffer;
+ int ret;
+
+ buffer = aligned_alloc(4096, 4096 * 4);
+ if (!buffer) {
+ fprintf(stderr, "allocation failed\n");
+ return T_EXIT_FAIL;
+ }
+
+ rd.user_addr = (__u64)(unsigned long)buffer;
+ rd.size = 4096;
+ rd.flags = IORING_MEM_REGION_TYPE_USER;
+
+ mr.region_uptr = (__u64)(unsigned long)&rd;
+ mr.flags = IORING_MEM_REGION_REG_WAIT_ARG;
+
+ ret = test_try_register_region(&mr, true, false);
+ if (ret == -EINVAL)
+ return T_EXIT_SKIP;
+ if (ret) {
+ fprintf(stderr, "test_try_register_region(true, false) fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ ret = test_try_register_region(&mr, false, false);
+ if (ret != -EINVAL) {
+ fprintf(stderr, "test_try_register_region(false, false) fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ ret = test_try_register_region(&mr, true, true);
+ if (ret != -EINVAL) {
+ fprintf(stderr, "test_try_register_region(true, true) fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ rd.size = 4096 * 4;
+ ret = test_try_register_region(&mr, true, false);
+ if (ret) {
+ fprintf(stderr, "test_try_register_region() 16KB fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ rd.size = 4096;
+
+ rd.user_addr = 0;
+ ret = test_try_register_region(&mr, true, false);
+ if (ret != -EFAULT) {
+ fprintf(stderr, "test_try_register_region() null uptr fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ rd.user_addr = (__u64)(unsigned long)buffer;
+
+ rd.flags = 0;
+ ret = test_try_register_region(&mr, true, false);
+ if (!ret) {
+ fprintf(stderr, "test_try_register_region() kernel alloc with uptr fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ rd.flags = IORING_MEM_REGION_TYPE_USER;
+
+ rd.size = 0;
+ ret = test_try_register_region(&mr, true, false);
+ if (!ret) {
+ fprintf(stderr, "test_try_register_region() 0-size fail %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ rd.size = 4096;
+
+ mr.region_uptr = 0;
+ ret = test_try_register_region(&mr, true, false);
+ if (!ret) {
+ fprintf(stderr, "test_try_register_region() NULL region %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ mr.region_uptr = (__u64)(unsigned long)&rd;
+
+ rd.user_addr += 16;
+ ret = test_try_register_region(&mr, true, false);
+ if (!ret) {
+ fprintf(stderr, "test_try_register_region() misaligned region %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ rd.user_addr = 0x1000;
+ ret = test_try_register_region(&mr, true, false);
+ if (!ret) {
+ fprintf(stderr, "test_try_register_region() bogus uptr %i\n", ret);
+ return T_EXIT_FAIL;
+ }
+ rd.user_addr = (__u64)(unsigned long)buffer;
+
+ free(buffer);
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int ret;
@@ -191,6 +319,15 @@ int main(int argc, char *argv[])
return 1;
}
+ ret = test_regions();
+ if (ret == T_EXIT_SKIP) {
+ printf("regions are not supported, skip\n");
+ return 0;
+ } else if (ret) {
+ fprintf(stderr, "test_region failed\n");
+ return 1;
+ }
+
ret = test_wait_arg();
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test_wait_arg failed\n");
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 7/8] tests: test arbitrary offset reg waits
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (5 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 6/8] tests: add region testing Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 8/8] Remove leftovers of old reg-wait registration api Pavel Begunkov
2024-11-16 17:07 ` [PATCH liburing 0/8] update reg-wait to use region API Jens Axboe
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
The exported io_uring API operates with wait index, which is safer, but
the kernel takes byte offsets. Add a local raw syscall helper passing
byte offsets and add edge testing of more edge cases.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/reg-wait.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/test/reg-wait.c b/test/reg-wait.c
index 13f6d51..aef4546 100644
--- a/test/reg-wait.c
+++ b/test/reg-wait.c
@@ -13,6 +13,18 @@
#include "liburing.h"
#include "helpers.h"
#include "test.h"
+#include "../src/syscall.h"
+
+static int test_wait_reg_offset(struct io_uring *ring,
+ unsigned wait_nr, unsigned long offset)
+{
+ return __sys_io_uring_enter2(ring->ring_fd, 0, wait_nr,
+ IORING_ENTER_GETEVENTS |
+ IORING_ENTER_EXT_ARG |
+ IORING_ENTER_EXT_ARG_REG,
+ (void *)offset,
+ sizeof(struct io_uring_reg_wait));
+}
static int page_size;
static struct io_uring_reg_wait *reg;
@@ -55,6 +67,7 @@ static int test_offsets(struct io_uring *ring)
struct io_uring_cqe *cqe;
int max_index = page_size / sizeof(struct io_uring_reg_wait);
struct io_uring_reg_wait *rw;
+ unsigned long offset;
int ret;
rw = reg + max_index;
@@ -80,6 +93,36 @@ static int test_offsets(struct io_uring *ring)
return T_EXIT_FAIL;
}
+ offset = 0UL - sizeof(long);
+ ret = test_wait_reg_offset(ring, 1, offset);
+ if (ret != -EFAULT) {
+ fprintf(stderr, "overflow offset failed: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ offset = 4096 - sizeof(long);
+ rw = (void *)reg + offset;
+ memset(rw, 0, sizeof(*rw));
+ rw->flags = IORING_REG_WAIT_TS;
+ rw->ts.tv_sec = 0;
+ rw->ts.tv_nsec = 1000;
+
+ ret = test_wait_reg_offset(ring, 1, offset);
+ if (ret != -EFAULT) {
+ fprintf(stderr, "OOB offset failed: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+
+ offset = 1;
+ rw = (void *)reg + offset;
+ memset(rw, 0, sizeof(*rw));
+ rw->flags = IORING_REG_WAIT_TS;
+ rw->ts.tv_sec = 0;
+ rw->ts.tv_nsec = 1000;
+
+ /* undefined behaviour, check the kernel doesn't crash */
+ (void)test_wait_reg_offset(ring, 1, offset);
+
return 0;
}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH liburing 8/8] Remove leftovers of old reg-wait registration api
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (6 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 7/8] tests: test arbitrary offset reg waits Pavel Begunkov
@ 2024-11-15 21:33 ` Pavel Begunkov
2024-11-16 17:07 ` [PATCH liburing 0/8] update reg-wait to use region API Jens Axboe
8 siblings, 0 replies; 10+ messages in thread
From: Pavel Begunkov @ 2024-11-15 21:33 UTC (permalink / raw)
To: io-uring; +Cc: asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/include/liburing.h | 3 ---
src/liburing-ffi.map | 2 --
src/liburing.map | 2 --
src/setup.c | 10 ----------
4 files changed, 17 deletions(-)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index 81ffe6e..627fc47 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -289,9 +289,6 @@ int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
*/
int io_uring_register_region(struct io_uring *ring,
struct io_uring_mem_region_reg *reg);
-struct io_uring_reg_wait *io_uring_setup_reg_wait(struct io_uring *ring,
- unsigned nentries, int *err);
-void io_uring_free_reg_wait(struct io_uring_reg_wait *reg, unsigned nentries);
/*
* Mapped buffer ring alloc/register + unregister/free helpers
diff --git a/src/liburing-ffi.map b/src/liburing-ffi.map
index 117a46a..9af1fb9 100644
--- a/src/liburing-ffi.map
+++ b/src/liburing-ffi.map
@@ -221,8 +221,6 @@ LIBURING_2.9 {
io_uring_resize_rings;
io_uring_register_wait_reg;
io_uring_submit_and_wait_reg;
- io_uring_free_reg_wait;
- io_uring_setup_reg_wait;
io_uring_clone_buffers_offset;
io_uring_register_region;
} LIBURING_2.8;
diff --git a/src/liburing.map b/src/liburing.map
index 46edbc9..9f7b211 100644
--- a/src/liburing.map
+++ b/src/liburing.map
@@ -108,8 +108,6 @@ LIBURING_2.9 {
io_uring_resize_rings;
io_uring_register_wait_reg;
io_uring_submit_and_wait_reg;
- io_uring_free_reg_wait;
- io_uring_setup_reg_wait;
io_uring_clone_buffers_offset;
io_uring_register_region;
} LIBURING_2.8;
diff --git a/src/setup.c b/src/setup.c
index 7c0cfab..d4694f5 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -686,13 +686,3 @@ int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
__sys_munmap(br, nentries * sizeof(struct io_uring_buf));
return 0;
}
-
-void io_uring_free_reg_wait(struct io_uring_reg_wait *reg, unsigned nentries)
-{
-}
-
-struct io_uring_reg_wait *io_uring_setup_reg_wait(struct io_uring *ring,
- unsigned nentries, int *err)
-{
- return NULL;
-}
--
2.46.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH liburing 0/8] update reg-wait to use region API
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
` (7 preceding siblings ...)
2024-11-15 21:33 ` [PATCH liburing 8/8] Remove leftovers of old reg-wait registration api Pavel Begunkov
@ 2024-11-16 17:07 ` Jens Axboe
8 siblings, 0 replies; 10+ messages in thread
From: Jens Axboe @ 2024-11-16 17:07 UTC (permalink / raw)
To: io-uring, Pavel Begunkov
On Fri, 15 Nov 2024 21:33:47 +0000, Pavel Begunkov wrote:
> Reflect changes of the kernel API for registered waits and fix up
> tests. The only thing that changed for the user is how we register
> the area, which is now more generic and called areas. It should
> also be done now while the ring is in the disabled state,
> see IORING_SETUP_R_DISABLED.
>
> In the future we might want to improve the liburing API for
> regions, i.e. adding a structure and a bunch of functions
> setting up the region in different modes.
>
> [...]
Applied, thanks!
[1/8] queue: break reg wait setup
commit: b38747291d5034ef8392d1b76ebe748c9ba32847
[2/8] Update io_uring.h
commit: 4843183eeadaf6ac53ccf6121950d4a254636cae
[3/8] queue: add region helpers and fix up wait reg kernel api
commit: e37a3bdebb8814888eeec67c7721b8f365d08ec7
[4/8] examples: convert reg-wait to new api
commit: 12c18dabafeb89dd95250b19f3d044c116f57938
[5/8] tests: convert reg-wait to regions
commit: 00b42a502f23747f353d3a3f47baf34259d1d1b0
[6/8] tests: add region testing
commit: be7bc8538b748f5f43b1c8f43a84970034ca98c9
[7/8] tests: test arbitrary offset reg waits
commit: 65d67c0f0f046da401bcd605029545e1f15070a0
[8/8] Remove leftovers of old reg-wait registration api
commit: 425cfec1027af251b3128dd0f8be51f2095b8c0b
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-11-16 17:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-15 21:33 [PATCH liburing 0/8] update reg-wait to use region API Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 1/8] queue: break reg wait setup Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 2/8] Update io_uring.h Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 3/8] queue: add region helpers and fix up wait reg kernel api Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 4/8] examples: convert reg-wait to new api Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 5/8] tests: convert reg-wait to regions Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 6/8] tests: add region testing Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 7/8] tests: test arbitrary offset reg waits Pavel Begunkov
2024-11-15 21:33 ` [PATCH liburing 8/8] Remove leftovers of old reg-wait registration api Pavel Begunkov
2024-11-16 17:07 ` [PATCH liburing 0/8] update reg-wait to use region API Jens Axboe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox