* [PATCH] io_uring-writev: open output file through io_uring
@ 2026-08-31 8:02 frezidok1
2026-09-01 5:34 ` [OE-core] " Mathieu Dubois-Briand
0 siblings, 1 reply; 3+ messages in thread
From: frezidok1 @ 2026-08-31 8:02 UTC (permalink / raw)
To: openembedded-core; +Cc: martin.jansa, Dmitry Sakhonchik
From: Dmitry Sakhonchik <frezidok1@gmail.com>
The existing test creates the output file with open(), which ends up
using openat() and is therefore intercepted by pseudo before the actual
io_uring write operation happens.
Use IORING_OP_OPENAT to create the output file through io_uring as well.
This makes the test successfully bypass pseudo
io-uring-writev.bb: wrynose doesn't support "S = ${WORKDIR}" anymore, fix it
[YOCTO #15244]
Signed-off-by: Dmitry Sakhonchik <frezidok1@gmail.com>
---
.../recipes-test/io-uring/io-uring-writev.bb | 2 +-
.../io-uring-writev/io-uring-writev.c | 98 ++++++++++++++++---
2 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/meta-selftest/recipes-test/io-uring/io-uring-writev.bb b/meta-selftest/recipes-test/io-uring/io-uring-writev.bb
index 8b2ca6005b..f5de317429 100644
--- a/meta-selftest/recipes-test/io-uring/io-uring-writev.bb
+++ b/meta-selftest/recipes-test/io-uring/io-uring-writev.bb
@@ -5,7 +5,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda
SRC_URI = "file://io-uring-writev.c"
-S = "${WORKDIR}"
+S = "${UNPACKDIR}"
do_compile() {
${BUILD_CC} io-uring-writev.c -o io-uring-writev
diff --git a/meta-selftest/recipes-test/io-uring/io-uring-writev/io-uring-writev.c b/meta-selftest/recipes-test/io-uring/io-uring-writev/io-uring-writev.c
index a5e4253b7a..54f49fa481 100644
--- a/meta-selftest/recipes-test/io-uring/io-uring-writev/io-uring-writev.c
+++ b/meta-selftest/recipes-test/io-uring/io-uring-writev/io-uring-writev.c
@@ -20,10 +20,13 @@
/* If your compilation fails because the header file below is missing,
* your kernel is probably too old to support io_uring.
* */
+#include <errno.h>
+#include <stdbool.h>
#include <linux/io_uring.h>
#define QUEUE_DEPTH 1
#define BLOCK_SZ 1024
+#define OPEN_TAG 1
/* This is x86 specific */
#define read_barrier() __asm__ __volatile__("":::"memory")
@@ -101,6 +104,79 @@ off_t get_file_size(int fd) {
return -1;
}
+int open_with_uring(const char* path, struct submitter *s) {
+ struct app_io_sq_ring *sring = &s->sq_ring;
+ struct app_io_cq_ring *cring = &s->cq_ring;
+
+ // Get position of the next SQE
+ unsigned tail = *sring->tail;
+ read_barrier();
+ unsigned index = tail & *sring->ring_mask;
+ unsigned next_tail = tail + 1;
+ struct io_uring_sqe *sqe = &s->sqes[index];
+
+ // Prepare SQE
+ memset(sqe, 0, sizeof(*sqe));
+ sqe->opcode = IORING_OP_OPENAT;
+ sqe->fd = AT_FDCWD;
+ sqe->addr = (unsigned long)path;
+ sqe->open_flags = O_WRONLY | O_CREAT;
+ sqe->len = 0666;
+ sqe->user_data = OPEN_TAG;
+
+ // Add prepared sqe to the submission queue
+ sring->array[index] = index;
+
+ // Update the tail so the kernel can see it
+ tail = next_tail;
+ if(*sring->tail != tail) {
+ write_barrier();
+ *sring->tail = tail;
+ }
+
+ //Tell the kernel to process events in SQ
+ int ret = io_uring_enter(s->ring_fd, 1,1,
+ IORING_ENTER_GETEVENTS);
+ if(ret < 0) {
+ perror("io_uring_enter");
+ return -1;
+ }
+
+ //Now we need to read the output from kernel from the CQ
+ while (true) {
+ unsigned head = *cring->head;
+ tail = *cring->tail;
+ read_barrier();
+
+ if (head == tail) {
+ /* It means the buffer is empty.
+ * If we are here, then something went wrong and
+ * kernel didn't return CQE with user_data == OPEN_TAG for some reason
+ */
+ fprintf(stderr, "open_with_uring error: kernel didn't return fd");
+ return -1;
+ }
+
+ index = head & *cring->ring_mask;
+ struct io_uring_cqe *cqe = &cring->cqes[index];
+
+ unsigned long long tag = cqe->user_data;
+ int res = cqe->res;
+
+ write_barrier();
+ *cring->head = head + 1;
+
+ if (tag == OPEN_TAG) {
+ if (res < 0) {
+ errno = -res;
+ perror("IORING_OP_OPENAT");
+ return -1;
+ }
+ return res;
+ }
+ }
+}
+
/*
* io_uring requires a lot of setup which looks pretty hairy, but isn't all
* that difficult to understand. Because of all this boilerplate code,
@@ -155,7 +231,7 @@ int app_setup_uring(struct submitter *s) {
/* Map in the submission and completion queue ring buffers.
* Older kernels only map in the submission queue, though.
* */
- sq_ptr = mmap(0, sring_sz, PROT_READ | PROT_WRITE,
+ sq_ptr = mmap(0, sring_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE,
s->ring_fd, IORING_OFF_SQ_RING);
if (sq_ptr == MAP_FAILED) {
@@ -167,7 +243,7 @@ int app_setup_uring(struct submitter *s) {
cq_ptr = sq_ptr;
} else {
/* Map in the completion queue ring buffer in older kernels separately */
- cq_ptr = mmap(0, cring_sz, PROT_READ | PROT_WRITE,
+ cq_ptr = mmap(0, cring_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE,
s->ring_fd, IORING_OFF_CQ_RING);
if (cq_ptr == MAP_FAILED) {
@@ -266,8 +342,8 @@ void read_from_cq(struct submitter *s) {
int submit_to_sq(char *file_path, struct submitter *s) {
struct file_info *fi;
- int file_fd = open(file_path, O_WRONLY|O_CREAT, 0666);
- if (file_fd < 0 ) {
+ int file_fd = open_with_uring(file_path, s);
+ if (file_fd < 0) {
perror("open");
return 1;
}
@@ -317,7 +393,7 @@ int submit_to_sq(char *file_path, struct submitter *s) {
*/
fi->iovecs[current_block].iov_len = bytes_remaining;
fi->iovecs[current_block].iov_base = bark;
-
+
/* Add our submission queue entry to the tail of the SQE ring buffer */
next_tail = tail = *sring->tail;
@@ -336,7 +412,7 @@ int submit_to_sq(char *file_path, struct submitter *s) {
tail = next_tail;
/* Update the tail so the kernel can see it. */
- if(*sring->tail != tail) {
+ if (*sring->tail != tail) {
*sring->tail = tail;
write_barrier();
}
@@ -347,9 +423,9 @@ int submit_to_sq(char *file_path, struct submitter *s) {
* io_uring_enter() call to wait until min_complete events (the 3rd param)
* complete.
* */
- int ret = io_uring_enter(s->ring_fd, 1,1,
- IORING_ENTER_GETEVENTS);
- if(ret < 0) {
+ int ret = io_uring_enter(s->ring_fd, 1, 1,
+ IORING_ENTER_GETEVENTS);
+ if (ret < 0) {
perror("io_uring_enter");
return 1;
}
@@ -372,13 +448,13 @@ int main(int argc, char *argv[]) {
}
memset(s, 0, sizeof(*s));
- if(app_setup_uring(s)) {
+ if (app_setup_uring(s)) {
fprintf(stderr, "Unable to setup uring!\n");
return 1;
}
for (int i = 1; i < argc; i++) {
- if(submit_to_sq(argv[i], s)) {
+ if (submit_to_sq(argv[i], s)) {
fprintf(stderr, "Error writting file\n");
return 1;
}
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [OE-core] [PATCH] io_uring-writev: open output file through io_uring
2026-08-31 8:02 [PATCH] io_uring-writev: open output file through io_uring frezidok1
@ 2026-09-01 5:34 ` Mathieu Dubois-Briand
2026-09-01 5:48 ` Dmitry Sakhonchik
0 siblings, 1 reply; 3+ messages in thread
From: Mathieu Dubois-Briand @ 2026-09-01 5:34 UTC (permalink / raw)
To: frezidok1, openembedded-core; +Cc: martin.jansa
On Mon Aug 31, 2026 at 10:02 AM CEST, Dmitry Sakhonchik via lists.openembedded.org wrote:
> From: Dmitry Sakhonchik <frezidok1@gmail.com>
>
> The existing test creates the output file with open(), which ends up
> using openat() and is therefore intercepted by pseudo before the actual
> io_uring write operation happens.
>
> Use IORING_OP_OPENAT to create the output file through io_uring as well.
> This makes the test successfully bypass pseudo
>
> io-uring-writev.bb: wrynose doesn't support "S = ${WORKDIR}" anymore, fix it
>
> [YOCTO #15244]
>
> Signed-off-by: Dmitry Sakhonchik <frezidok1@gmail.com>
> ---
Hi Dmitry,
I suspect this was targeting Martin's branch and not master? Otherwise
we are missing the commits adding the io-uring-writev recipes.
Thanks,
Mathieu
--
Mathieu Dubois-Briand, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [OE-core] [PATCH] io_uring-writev: open output file through io_uring
2026-09-01 5:34 ` [OE-core] " Mathieu Dubois-Briand
@ 2026-09-01 5:48 ` Dmitry Sakhonchik
0 siblings, 0 replies; 3+ messages in thread
From: Dmitry Sakhonchik @ 2026-09-01 5:48 UTC (permalink / raw)
To: Mathieu Dubois-Briand; +Cc: openembedded-core, martin.jansa
[-- Attachment #1: Type: text/plain, Size: 1210 bytes --]
Hi.
Yes, it’s for Martin’s branch, he’s already merged it. I just couldn’t
figure out how to specify a branch I am applying to.
Вт, 1 сент. 2026 г. в 08:35, Mathieu Dubois-Briand <
mathieu.dubois-briand@bootlin.com>:
> On Mon Aug 31, 2026 at 10:02 AM CEST, Dmitry Sakhonchik via
> lists.openembedded.org wrote:
> > From: Dmitry Sakhonchik <frezidok1@gmail.com>
> >
> > The existing test creates the output file with open(), which ends up
> > using openat() and is therefore intercepted by pseudo before the actual
> > io_uring write operation happens.
> >
> > Use IORING_OP_OPENAT to create the output file through io_uring as well.
> > This makes the test successfully bypass pseudo
> >
> > io-uring-writev.bb: wrynose doesn't support "S = ${WORKDIR}" anymore,
> fix it
> >
> > [YOCTO #15244]
> >
> > Signed-off-by: Dmitry Sakhonchik <frezidok1@gmail.com>
> > ---
>
> Hi Dmitry,
>
> I suspect this was targeting Martin's branch and not master? Otherwise
> we are missing the commits adding the io-uring-writev recipes.
>
> Thanks,
> Mathieu
>
> --
> Mathieu Dubois-Briand, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>
>
[-- Attachment #2: Type: text/html, Size: 2101 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-01 5:48 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 8:02 [PATCH] io_uring-writev: open output file through io_uring frezidok1
2026-09-01 5:34 ` [OE-core] " Mathieu Dubois-Briand
2026-09-01 5:48 ` Dmitry Sakhonchik
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.