* [LTP] [PATCH v1] io_submit04: Add test case for RWF_NOWAIT flag @ 2023-10-29 1:27 Wei Gao via ltp 2024-02-06 15:59 ` Petr Vorel 2025-10-22 2:05 ` [LTP] [PATCH v2] " Wei Gao via ltp 0 siblings, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2023-10-29 1:27 UTC (permalink / raw) To: ltp Fixs: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + testcases/kernel/syscalls/io_submit/Makefile | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 178 ++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/runtest/syscalls b/runtest/syscalls index c7a0b2301..5e7fa0403 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -656,6 +656,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/Makefile b/testcases/kernel/syscalls/io_submit/Makefile index ce4f13b72..c29d2060c 100644 --- a/testcases/kernel/syscalls/io_submit/Makefile +++ b/testcases/kernel/syscalls/io_submit/Makefile @@ -6,5 +6,6 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk LDLIBS += $(AIO_LIBS) +LDFLAGS += -pthread include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..9622ff796 --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Wei Gao <wegao@suse.com> + */ + +/*\ + * [Description] + * + * Similarily to the preadv2, this is a basic test for io_submit + * RWF_NOWAIT flag, we are attempting to force io_submit return + * EAGAIN with thread concurently running threads. + * + */ + +#include <linux/aio_abi.h> + +#include "config.h" +#include "tst_test.h" +#include "tst_safe_pthread.h" +#include "lapi/syscalls.h" + +#define TEST_FILE "test_file" +#define MODE 0777 +#define BUF_LEN 1000000 +#define MNTPOINT "mntpoint" + +static char *w_buf; +static char *r_buf; +static int fd; +static aio_context_t ctx; +static struct iocb iocb; +static struct iocb *iocbs[] = {&iocb}; +static volatile int stop; + +static inline void io_prep_option(struct iocb *cb, int fd, void *buf, + size_t count, long long offset, unsigned int opcode) +{ + memset(cb, 0, sizeof(*cb)); + cb->aio_fildes = fd; + cb->aio_lio_opcode = opcode; + cb->aio_buf = (uint64_t)r_buf; + cb->aio_offset = offset; + cb->aio_nbytes = count; + cb->aio_rw_flags = RWF_NOWAIT; +} + +static void write_test(void) +{ + SAFE_LSEEK(fd, 0, SEEK_SET); + SAFE_WRITE(SAFE_WRITE_ALL, fd, r_buf, BUF_LEN); +} + +static void *writer_thread(void *unused) +{ + while (!stop) + write_test(); + + return unused; +} + +static void drop_caches(void) +{ + SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3"); +} + +static void *cache_dropper(void *unused) +{ + unsigned int drop_cnt = 0; + + while (!stop) { + drop_caches(); + drop_cnt++; + } + + tst_res(TINFO, "Cache dropped %u times", drop_cnt); + + return unused; +} + +static unsigned int io_submit(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + + TST_EXP_VAL_SILENT(tst_syscall(__NR_io_submit, ctx, 1, iocbs), 1); + + TST_EXP_VAL_SILENT(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, + &timeout), 1); + + if (evbuf.res == -EAGAIN) + return 1; + else + return 0; +} + +static void *nowait_reader(void *unused LTP_ATTRIBUTE_UNUSED) +{ + unsigned int eagains_cnt = 0; + + while (!stop) { + if (eagains_cnt >= 100) + stop = 1; + eagains_cnt = eagains_cnt + io_submit(); + } + + return (void *)(long)eagains_cnt; +} + +static void setup(void) +{ + + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); + + fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, MODE); + + memset(w_buf, 'a', BUF_LEN); + memset(r_buf, 'b', BUF_LEN); + + io_prep_option(&iocb, fd, r_buf, BUF_LEN, 0, IOCB_CMD_PREAD); +} + +static void cleanup(void) +{ + if (fd > 0) + SAFE_CLOSE(fd); + + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + + +static void run(void) +{ + + pthread_t reader, dropper, writer; + void *eagains; + + stop = 0; + + SAFE_PTHREAD_CREATE(&dropper, NULL, cache_dropper, NULL); + SAFE_PTHREAD_CREATE(&reader, NULL, nowait_reader, NULL); + SAFE_PTHREAD_CREATE(&writer, NULL, writer_thread, NULL); + + while (!stop && tst_remaining_runtime()) + usleep(100000); + + stop = 1; + + SAFE_PTHREAD_JOIN(reader, &eagains); + SAFE_PTHREAD_JOIN(dropper, NULL); + SAFE_PTHREAD_JOIN(writer, NULL); + + if (eagains) + tst_res(TPASS, "Got some EAGAIN"); + else + tst_res(TFAIL, "Haven't got EAGAIN"); + +} + +static struct tst_test test = { + .needs_tmpdir = 1, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .max_runtime = 60, + .mntpoint = MNTPOINT, + .mount_device = 1, + .all_filesystems = 1, + .bufs = (struct tst_buffers []) { + {&w_buf, .size = BUF_LEN}, + {&r_buf, .size = BUF_LEN}, + {} + } +}; -- 2.35.3 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v1] io_submit04: Add test case for RWF_NOWAIT flag 2023-10-29 1:27 [LTP] [PATCH v1] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp @ 2024-02-06 15:59 ` Petr Vorel 2025-10-22 2:05 ` [LTP] [PATCH v2] " Wei Gao via ltp 1 sibling, 0 replies; 22+ messages in thread From: Petr Vorel @ 2024-02-06 15:59 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > Fixs: #467 Fixes: #467 +++ b/testcases/kernel/syscalls/io_submit/Makefile @@ -6,5 +6,6 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk LDLIBS += $(AIO_LIBS) BTW Only io_submit01.c uses libaio, but all files are linked against -laio because Makefile does not prefix that setup with io_submit01. +LDFLAGS += -pthread So for the same reason I would prefix this for this test only: io_submit04: LDFLAGS += -pthread ... > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > @@ -0,0 +1,178 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2023 Wei Gao <wegao@suse.com> > + */ > + > +/*\ > + * [Description] > + * > + * Similarily to the preadv2, this is a basic test for io_submit s/Similarily/Similarly/ But I would remove "Similarily to the preadv2" > + * RWF_NOWAIT flag, we are attempting to force io_submit return > + * EAGAIN with thread concurently running threads. > + * nit: empty blank line. > + */ ... > +static void *writer_thread(void *unused) > +{ > + while (!stop) > + write_test(); > + > + return unused; > +} > + > +static void drop_caches(void) > +{ > + SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3"); > +} > + > +static void *cache_dropper(void *unused) > +{ > + unsigned int drop_cnt = 0; > + > + while (!stop) { > + drop_caches(); > + drop_cnt++; > + } > + > + tst_res(TINFO, "Cache dropped %u times", drop_cnt); > + > + return unused; > +} > + > +static unsigned int io_submit(void) > +{ > + struct io_event evbuf; > + struct timespec timeout = { .tv_sec = 1 }; > + > + TST_EXP_VAL_SILENT(tst_syscall(__NR_io_submit, ctx, 1, iocbs), 1); It fails with EOPNOTSUPP on TMPDIR on tmpfs (e.g. on Tumbleweed). # ./io_submit04 ... tst_supported_fs_types.c:49: TINFO: mkfs is not needed for tmpfs tst_test.c:1701: TINFO: === Testing on ext2 === tst_test.c:1117: TINFO: Formatting /dev/loop0 with ext2 opts='' extra opts='' mke2fs 1.47.0 (5-Feb-2023) tst_test.c:1131: TINFO: Mounting /dev/loop0 to /tmp/LTP_io_bhotMR/mntpoint fstyp=ext2 flags=0 io_submit04.c:85: TFAIL: tst_syscall(__NR_io_submit, ctx, 1, iocbs) retval -1 != 1: EOPNOTSUPP (95) io_submit04.c:87: TFAIL: tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout) retval 0 != 1: SUCCESS (0) io_submit04.c:85: TFAIL: tst_syscall(__NR_io_submit, ctx, 1, iocbs) retval -1 != 1: EOPNOTSUPP (95) io_submit04.c:87: TFAIL: tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout) retval 0 != 1: SUCCESS (0) io_submit04.c:85: TFAIL: tst_syscall(__NR_io_submit, ctx, 1, iocbs) retval -1 != 1: EOPNOTSUPP (95) io_submit04.c:87: TFAIL: tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout) retval 0 != 1: SUCCESS (0) First, it would make sense to quit this filesystem test on first error, because it does not make sense to run test 100x when it fails. But that will need to redesign way how you test it, otherwise cleanup breaks. Why? Because .mntpoint = MNTPOINT does not mean it will cd into the directory. You need to add: SAFE_CHDIR(MNTPOINT); (This need is a bit confusing, I don't remember the reason why test does not do it.) And if you add it, you finds that it fails on various filesystems, you need to add: .skip_filesystems = (const char *const[]) { "vfat", "exfat", "ntfs", "tmpfs", NULL }, Maybe even fuse would be problematic, but not sure (on my system ntfs was actually tested via fuse). And make check warning: $ make check-io_submit04 CHECK testcases/kernel/syscalls/io_submit/io_submit04.c io_submit04.c:63: WARNING: Prefer using '"%s...", __func__' to using 'drop_caches', this function's name, in a string make: [../../../../include/mk/rules.mk:56: check-io_submit04] Error 1 (ignored) > + > + TST_EXP_VAL_SILENT(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, > + &timeout), 1); > + > + if (evbuf.res == -EAGAIN) > + return 1; > + else > + return 0; nit: return evbuf.res == -EAGAIN > +} ... > +static inline void io_prep_option(struct iocb *cb, int fd, void *buf, > + size_t count, long long offset, unsigned int opcode) > +{ > + memset(cb, 0, sizeof(*cb)); > + cb->aio_fildes = fd; > + cb->aio_lio_opcode = opcode; > + cb->aio_buf = (uint64_t)r_buf; Compile warning (I guess it's not a first time I ask to pay attention to the compile warnings): io_submit04.c: In function ‘io_prep_option’: io_submit04.c:35:66: warning: unused parameter ‘buf’ [-Wunused-parameter] 35 | static inline void io_prep_option(struct iocb *cb, int fd, void *buf, => maybe use actually the parameter buf, instead of using the static r_buf? cb->aio_buf = (uint64_t)buf; Or, you may just remove void *buf, as r_buf is static anyway and used in the setup. > + cb->aio_offset = offset; > + cb->aio_nbytes = count; > + cb->aio_rw_flags = RWF_NOWAIT; > +} > + ... > +static void setup(void) > +{ > + nit: empty line ^ > + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); I guess this should tst_brk() if failed, right? Therefore just: if (!tst_syscall(__NR_io_setup, 1, &ctx)) tst_brk(TBROK, ...); > + > + fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, MODE); > + > + memset(w_buf, 'a', BUF_LEN); > + memset(r_buf, 'b', BUF_LEN); > + > + io_prep_option(&iocb, fd, r_buf, BUF_LEN, 0, IOCB_CMD_PREAD); NOTE: Here you pass r_buf > +} > + > +static void cleanup(void) > +{ > + if (fd > 0) > + SAFE_CLOSE(fd); > + > + if (tst_syscall(__NR_io_destroy, ctx)) > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); Maybe just tst_res(TWARN | TERRNO, ...) because it's in a cleanup function? > +} > + > + > +static void run(void) > +{ > + > + pthread_t reader, dropper, writer; > + void *eagains; > + > + stop = 0; > + > + SAFE_PTHREAD_CREATE(&dropper, NULL, cache_dropper, NULL); > + SAFE_PTHREAD_CREATE(&reader, NULL, nowait_reader, NULL); > + SAFE_PTHREAD_CREATE(&writer, NULL, writer_thread, NULL); > + > + while (!stop && tst_remaining_runtime()) > + usleep(100000); > + > + stop = 1; I'm not really sure about this stop = 1 setup, which is done also on nowait_reader(). This is probably obvious to the other reviewers. > + > + SAFE_PTHREAD_JOIN(reader, &eagains); > + SAFE_PTHREAD_JOIN(dropper, NULL); > + SAFE_PTHREAD_JOIN(writer, NULL); > + > + if (eagains) > + tst_res(TPASS, "Got some EAGAIN"); > + else > + tst_res(TFAIL, "Haven't got EAGAIN"); > + > +} -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v2] io_submit04: Add test case for RWF_NOWAIT flag 2023-10-29 1:27 [LTP] [PATCH v1] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp 2024-02-06 15:59 ` Petr Vorel @ 2025-10-22 2:05 ` Wei Gao via ltp 2025-12-18 13:21 ` Andrea Cervesato via ltp 2025-12-24 8:49 ` [LTP] [PATCH v3] " Wei Gao via ltp 1 sibling, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2025-10-22 2:05 UTC (permalink / raw) To: ltp Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 87 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/runtest/syscalls b/runtest/syscalls index 4b284f279..655a46e91 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -693,6 +693,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..5c9c4065a --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test iocb RWF_* flags support: RWF_NOWAIT + * + * Checks if an asynchronous read operation with RWF_NOWAIT on a blocking + * resource (empty pipe) fails immediately with -EAGAIN. + */ + +#include <linux/aio_abi.h> + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" + +static int fd[2]; +static char buf[100]; + +static aio_context_t ctx; +static struct iocb iocb; +static struct iocb *iocbs[] = {&iocb}; + +static inline void io_prep_option(struct iocb *cb, int fd, void *buf, + size_t count, long long offset, unsigned int opcode) +{ + memset(cb, 0, sizeof(*cb)); + cb->aio_fildes = fd; + cb->aio_lio_opcode = opcode; + cb->aio_buf = (uint64_t)buf; + cb->aio_offset = offset; + cb->aio_nbytes = count; + cb->aio_rw_flags = RWF_NOWAIT; +} + +static void setup(void) +{ + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); + SAFE_PIPE(fd); + io_prep_option(&iocb, fd[0], buf, sizeof(buf), 0, IOCB_CMD_PREAD); +} + +static void cleanup(void) +{ + if (fd[0]) + SAFE_CLOSE(fd[0]); + + if (fd[1]) + SAFE_CLOSE(fd[1]); + + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == nr) + tst_res(TPASS, "io_submit() pass"); + else + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); + + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); + + if (evbuf.res == -EAGAIN) + tst_res(TINFO, "io_submit RWF_NOWAIT flag check pass"); + else + tst_res(TFAIL | TTERRNO, "io_submit expect EAGAIN, but get %s", strerror(-evbuf.res)); + +} + +static struct tst_test test = { + .test_all = run, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .setup = setup, + .cleanup = cleanup, +}; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v2] io_submit04: Add test case for RWF_NOWAIT flag 2025-10-22 2:05 ` [LTP] [PATCH v2] " Wei Gao via ltp @ 2025-12-18 13:21 ` Andrea Cervesato via ltp 2025-12-24 8:49 ` [LTP] [PATCH v3] " Wei Gao via ltp 1 sibling, 0 replies; 22+ messages in thread From: Andrea Cervesato via ltp @ 2025-12-18 13:21 UTC (permalink / raw) To: Wei Gao, ltp Hi! please take a look at the CI, we have a compile issue on opensuse 42.2 https://github.com/linux-test-project/ltp/actions/runs/18703432408/job/53336553104 We probably need a fallback attribute on `struct iocb` -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2025-10-22 2:05 ` [LTP] [PATCH v2] " Wei Gao via ltp 2025-12-18 13:21 ` Andrea Cervesato via ltp @ 2025-12-24 8:49 ` Wei Gao via ltp 2026-01-05 12:53 ` Andrea Cervesato via ltp 2026-01-07 6:10 ` [LTP] [PATCH v4] " Wei Gao via ltp 1 sibling, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2025-12-24 8:49 UTC (permalink / raw) To: ltp Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- configure.ac | 1 + include/lapi/aio_abi.h | 44 ++++++++++ runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 86 +++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 include/lapi/aio_abi.h create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/configure.ac b/configure.ac index a0ebbb34d..ee46e3f24 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ ]) AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h new file mode 100644 index 000000000..bd8c2965b --- /dev/null +++ b/include/lapi/aio_abi.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +#ifndef LAPI_AIO_ABI_H__ +#define LAPI_AIO_ABI_H__ + +#include <endian.h> +#include <linux/aio_abi.h> + +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0x00000008 +#endif + +struct iocb_fallback { + uint64_t aio_data; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t aio_key; + uint32_t aio_rw_flags; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint32_t aio_rw_flags; + uint32_t aio_key; +#else +#error edit for your odd byteorder. +#endif + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; +}; + +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS +typedef struct iocb_fallback iocb; +#else +typedef struct iocb iocb; +#endif + +#endif /* LAPI_AIO_ABI_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index a1ef7548b..18182a2d6 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -696,6 +696,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..bae89828a --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test iocb RWF_* flags support: RWF_NOWAIT + * + * Checks if an asynchronous read operation with RWF_NOWAIT on a blocking + * resource (empty pipe) fails immediately with -EAGAIN. + */ + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/aio_abi.h" + +static int fd[2]; +static char buf[100]; + +static aio_context_t ctx; +static iocb cb; +static iocb *iocbs[] = {&cb}; + +static inline void io_prep_option(iocb *cb, int fd, void *buf, + size_t count, long long offset, unsigned int opcode) +{ + memset(cb, 0, sizeof(*cb)); + cb->aio_fildes = fd; + cb->aio_lio_opcode = opcode; + cb->aio_buf = (uint64_t)buf; + cb->aio_offset = offset; + cb->aio_nbytes = count; + cb->aio_rw_flags = RWF_NOWAIT; +} + +static void setup(void) +{ + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); + SAFE_PIPE(fd); + io_prep_option(&cb, fd[0], buf, sizeof(buf), 0, IOCB_CMD_PREAD); +} + +static void cleanup(void) +{ + if (fd[0]) + SAFE_CLOSE(fd[0]); + + if (fd[1]) + SAFE_CLOSE(fd[1]); + + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == nr) + tst_res(TPASS, "io_submit() pass"); + else + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); + + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); + + if (evbuf.res == -EAGAIN) + tst_res(TINFO, "io_submit RWF_NOWAIT flag check pass"); + else + tst_res(TFAIL | TTERRNO, "io_submit expect EAGAIN, but get %s", strerror(-evbuf.res)); + +} + +static struct tst_test test = { + .test_all = run, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .setup = setup, + .cleanup = cleanup, +}; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2025-12-24 8:49 ` [LTP] [PATCH v3] " Wei Gao via ltp @ 2026-01-05 12:53 ` Andrea Cervesato via ltp 2026-01-06 6:26 ` Wei Gao via ltp 2026-01-07 6:10 ` [LTP] [PATCH v4] " Wei Gao via ltp 1 sibling, 1 reply; 22+ messages in thread From: Andrea Cervesato via ltp @ 2026-01-05 12:53 UTC (permalink / raw) To: Wei Gao, ltp Hi! On Wed Dec 24, 2025 at 9:49 AM CET, Wei Gao wrote: > Fixes: #467 > Signed-off-by: Wei Gao <wegao@suse.com> > --- > configure.ac | 1 + > include/lapi/aio_abi.h | 44 ++++++++++ > runtest/syscalls | 1 + > .../kernel/syscalls/io_submit/.gitignore | 1 + > .../kernel/syscalls/io_submit/io_submit04.c | 86 +++++++++++++++++++ > 5 files changed, 133 insertions(+) > create mode 100644 include/lapi/aio_abi.h > create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c > > diff --git a/configure.ac b/configure.ac > index a0ebbb34d..ee46e3f24 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ > ]) > AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) > > +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > new file mode 100644 > index 000000000..bd8c2965b > --- /dev/null > +++ b/include/lapi/aio_abi.h > @@ -0,0 +1,44 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +#ifndef LAPI_AIO_ABI_H__ > +#define LAPI_AIO_ABI_H__ > + > +#include <endian.h> > +#include <linux/aio_abi.h> > + > +#ifndef RWF_NOWAIT > +# define RWF_NOWAIT 0x00000008 > +#endif > + > +struct iocb_fallback { > + uint64_t aio_data; > +#if __BYTE_ORDER == __LITTLE_ENDIAN > + uint32_t aio_key; > + uint32_t aio_rw_flags; > +#elif __BYTE_ORDER == __BIG_ENDIAN > + uint32_t aio_rw_flags; > + uint32_t aio_key; > +#else > +#error edit for your odd byteorder. > +#endif > + uint16_t aio_lio_opcode; > + int16_t aio_reqprio; > + uint32_t aio_fildes; > + uint64_t aio_buf; > + uint64_t aio_nbytes; > + int64_t aio_offset; > + uint64_t aio_reserved2; > + uint32_t aio_flags; > + uint32_t aio_resfd; > +}; > + > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > +typedef struct iocb_fallback iocb; > +#else > +typedef struct iocb iocb; > +#endif > + > +#endif /* LAPI_AIO_ABI_H__ */ > diff --git a/runtest/syscalls b/runtest/syscalls > index a1ef7548b..18182a2d6 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -696,6 +696,7 @@ io_setup02 io_setup02 > io_submit01 io_submit01 > io_submit02 io_submit02 > io_submit03 io_submit03 > +io_submit04 io_submit04 > > keyctl01 keyctl01 > keyctl02 keyctl02 > diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore > index 60b07970a..abe962e1c 100644 > --- a/testcases/kernel/syscalls/io_submit/.gitignore > +++ b/testcases/kernel/syscalls/io_submit/.gitignore > @@ -1,3 +1,4 @@ > /io_submit01 > /io_submit02 > /io_submit03 > +/io_submit04 > diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c > new file mode 100644 > index 000000000..bae89828a > --- /dev/null > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > @@ -0,0 +1,86 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +/*\ > + * Test iocb RWF_* flags support: RWF_NOWAIT > + * > + * Checks if an asynchronous read operation with RWF_NOWAIT on a blocking > + * resource (empty pipe) fails immediately with -EAGAIN. We can write it better: /*\ * Test RWF_NOWAIT support in io_submit(), verifying that an * asynchronous read operation on a blocking resource (empty pipe) * will cause -EAGAIN. This is done by checking that io_getevents() * syscall returns immediately and io_event.res is equal to -EAGAIN. */ > + */ > + > +#include "config.h" > +#include "tst_test.h" > +#include "lapi/syscalls.h" > +#include "lapi/aio_abi.h" > + > +static int fd[2]; > +static char buf[100]; > + > +static aio_context_t ctx; > +static iocb cb; > +static iocb *iocbs[] = {&cb}; Data that is passed to syscalls should be initialized via tst_test.bufs > + > +static inline void io_prep_option(iocb *cb, int fd, void *buf, > + size_t count, long long offset, unsigned int opcode) > +{ > + memset(cb, 0, sizeof(*cb)); > + cb->aio_fildes = fd; > + cb->aio_lio_opcode = opcode; > + cb->aio_buf = (uint64_t)buf; > + cb->aio_offset = offset; > + cb->aio_nbytes = count; > + cb->aio_rw_flags = RWF_NOWAIT; > +} > + > +static void setup(void) > +{ > + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); > + SAFE_PIPE(fd); > + io_prep_option(&cb, fd[0], buf, sizeof(buf), 0, IOCB_CMD_PREAD); > +} > + > +static void cleanup(void) > +{ > + if (fd[0]) > + SAFE_CLOSE(fd[0]); > + > + if (fd[1]) > + SAFE_CLOSE(fd[1]); > + > + if (tst_syscall(__NR_io_destroy, ctx)) > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); > +} > + > +static void run(void) > +{ > + struct io_event evbuf; > + struct timespec timeout = { .tv_sec = 1 }; > + long nr = 1; > + > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > + > + if (TST_RET == nr) > + tst_res(TPASS, "io_submit() pass"); > + else > + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); Our goal is to verify that io_getevents() returns EAGAIN, so we can just: if (TST_RET != nr) { tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); return; } We return because if io_submit() fails there's nothing to do more. > + > + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); > + > + if (evbuf.res == -EAGAIN) > + tst_res(TINFO, "io_submit RWF_NOWAIT flag check pass"); Why TINFO if we are testing this feature? Also the message is not giving any information of io_getevents(). We can just (look below)... > + else > + tst_res(TFAIL | TTERRNO, "io_submit expect EAGAIN, but get %s", strerror(-evbuf.res)); > + > +} if (evbuf.res == -EAGAIN) tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); else tst_res(TFAIL | TTERRNO, "io_getevents() returned with %s instead of EAGAIN", strerror(-evbuf.res)); > + > +static struct tst_test test = { > + .test_all = run, > + .needs_kconfigs = (const char *[]) { > + "CONFIG_AIO=y", > + NULL > + }, > + .setup = setup, > + .cleanup = cleanup, > +}; -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-05 12:53 ` Andrea Cervesato via ltp @ 2026-01-06 6:26 ` Wei Gao via ltp 2026-01-06 8:39 ` Andrea Cervesato via ltp 2026-01-06 8:39 ` Petr Vorel 0 siblings, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-01-06 6:26 UTC (permalink / raw) To: Andrea Cervesato; +Cc: ltp On Mon, Jan 05, 2026 at 01:53:50PM +0100, Andrea Cervesato wrote: > Hi! > > On Wed Dec 24, 2025 at 9:49 AM CET, Wei Gao wrote: > > Fixes: #467 > > Signed-off-by: Wei Gao <wegao@suse.com> > > --- > > configure.ac | 1 + > > include/lapi/aio_abi.h | 44 ++++++++++ > > runtest/syscalls | 1 + > > .../kernel/syscalls/io_submit/.gitignore | 1 + > > .../kernel/syscalls/io_submit/io_submit04.c | 86 +++++++++++++++++++ > > 5 files changed, 133 insertions(+) > > create mode 100644 include/lapi/aio_abi.h > > create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c > > > > diff --git a/configure.ac b/configure.ac > > index a0ebbb34d..ee46e3f24 100644 > > --- a/configure.ac > > +++ b/configure.ac > > @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ > > ]) > > AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) > > > > +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) > > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > > new file mode 100644 > > index 000000000..bd8c2965b > > --- /dev/null > > +++ b/include/lapi/aio_abi.h > > @@ -0,0 +1,44 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > > + */ > > + > > +#ifndef LAPI_AIO_ABI_H__ > > +#define LAPI_AIO_ABI_H__ > > + > > +#include <endian.h> > > +#include <linux/aio_abi.h> > > + > > +#ifndef RWF_NOWAIT > > +# define RWF_NOWAIT 0x00000008 > > +#endif > > + > > +struct iocb_fallback { > > + uint64_t aio_data; > > +#if __BYTE_ORDER == __LITTLE_ENDIAN > > + uint32_t aio_key; > > + uint32_t aio_rw_flags; > > +#elif __BYTE_ORDER == __BIG_ENDIAN > > + uint32_t aio_rw_flags; > > + uint32_t aio_key; > > +#else > > +#error edit for your odd byteorder. > > +#endif > > + uint16_t aio_lio_opcode; > > + int16_t aio_reqprio; > > + uint32_t aio_fildes; > > + uint64_t aio_buf; > > + uint64_t aio_nbytes; > > + int64_t aio_offset; > > + uint64_t aio_reserved2; > > + uint32_t aio_flags; > > + uint32_t aio_resfd; > > +}; > > + > > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > > +typedef struct iocb_fallback iocb; > > +#else > > +typedef struct iocb iocb; > > +#endif > > + > > +#endif /* LAPI_AIO_ABI_H__ */ > > diff --git a/runtest/syscalls b/runtest/syscalls > > index a1ef7548b..18182a2d6 100644 > > --- a/runtest/syscalls > > +++ b/runtest/syscalls > > @@ -696,6 +696,7 @@ io_setup02 io_setup02 > > io_submit01 io_submit01 > > io_submit02 io_submit02 > > io_submit03 io_submit03 > > +io_submit04 io_submit04 > > > > keyctl01 keyctl01 > > keyctl02 keyctl02 > > diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore > > index 60b07970a..abe962e1c 100644 > > --- a/testcases/kernel/syscalls/io_submit/.gitignore > > +++ b/testcases/kernel/syscalls/io_submit/.gitignore > > @@ -1,3 +1,4 @@ > > /io_submit01 > > /io_submit02 > > /io_submit03 > > +/io_submit04 > > diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c > > new file mode 100644 > > index 000000000..bae89828a > > --- /dev/null > > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > > @@ -0,0 +1,86 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > > + */ > > + > > +/*\ > > + * Test iocb RWF_* flags support: RWF_NOWAIT > > + * > > + * Checks if an asynchronous read operation with RWF_NOWAIT on a blocking > > + * resource (empty pipe) fails immediately with -EAGAIN. > > We can write it better: > > /*\ > * Test RWF_NOWAIT support in io_submit(), verifying that an > * asynchronous read operation on a blocking resource (empty pipe) > * will cause -EAGAIN. This is done by checking that io_getevents() > * syscall returns immediately and io_event.res is equal to -EAGAIN. > */ > > > + */ > > + > > +#include "config.h" > > +#include "tst_test.h" > > +#include "lapi/syscalls.h" > > +#include "lapi/aio_abi.h" > > + > > +static int fd[2]; > > +static char buf[100]; > > + > > +static aio_context_t ctx; > > +static iocb cb; > > +static iocb *iocbs[] = {&cb}; > > Data that is passed to syscalls should be initialized via tst_test.bufs > > > + > > +static inline void io_prep_option(iocb *cb, int fd, void *buf, > > + size_t count, long long offset, unsigned int opcode) > > +{ > > + memset(cb, 0, sizeof(*cb)); > > + cb->aio_fildes = fd; > > + cb->aio_lio_opcode = opcode; > > + cb->aio_buf = (uint64_t)buf; > > + cb->aio_offset = offset; > > + cb->aio_nbytes = count; > > + cb->aio_rw_flags = RWF_NOWAIT; > > +} > > + > > +static void setup(void) > > +{ > > + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); > > + SAFE_PIPE(fd); > > + io_prep_option(&cb, fd[0], buf, sizeof(buf), 0, IOCB_CMD_PREAD); > > +} > > + > > +static void cleanup(void) > > +{ > > + if (fd[0]) > > + SAFE_CLOSE(fd[0]); > > + > > + if (fd[1]) > > + SAFE_CLOSE(fd[1]); > > + > > + if (tst_syscall(__NR_io_destroy, ctx)) > > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); > > +} > > + > > +static void run(void) > > +{ > > + struct io_event evbuf; > > + struct timespec timeout = { .tv_sec = 1 }; > > + long nr = 1; > > + > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > + > > + if (TST_RET == nr) > > + tst_res(TPASS, "io_submit() pass"); > > + else > > + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > > Our goal is to verify that io_getevents() returns EAGAIN, so we can just: > > if (TST_RET != nr) { > tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > return; > } > > We return because if io_submit() fails there's nothing to do more. tst_res(TBROK will trigger error such as : make[1]: Leaving directory '/home/wegao/ltp/lib' In file included from ../../../../include/tst_test.h:20, from io_submit04.c:14: io_submit04.c: In function ‘run’: ../../../../include/tst_common.h:80:32: error: size of unnamed array is negative 80 | do { ((void)sizeof(char[1 - 2 * !!(condition)])); } while (0) | ^ ../../../../include/tst_common.h:83:9: note: in expansion of macro ‘TST_BUILD_BUG_ON’ 83 | TST_BUILD_BUG_ON(condition) | ^~~~~~~~~~~~~~~~ ../../../../include/tst_test.h:71:17: note: in expansion of macro ‘TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN’ 71 | TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(\ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ io_submit04.c:63:17: note: in expansion of macro ‘tst_res’ 63 | tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", | ^~~~~~~ make: *** [../../../../include/mk/rules.mk:48: io_submit04] Error 1 -bash: ./io_submit04: No such file or directory So i suppose we need use "tst_brk(TBROK" without return, correct? > > > + > > + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); > > + > > + if (evbuf.res == -EAGAIN) > > + tst_res(TINFO, "io_submit RWF_NOWAIT flag check pass"); > > Why TINFO if we are testing this feature? Also the message is not giving > any information of io_getevents(). We can just (look below)... > > > + else > > + tst_res(TFAIL | TTERRNO, "io_submit expect EAGAIN, but get %s", strerror(-evbuf.res)); > > + > > +} > > if (evbuf.res == -EAGAIN) > tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); > else > tst_res(TFAIL | TTERRNO, "io_getevents() returned with %s instead of EAGAIN", strerror(-evbuf.res)); > > > + > > +static struct tst_test test = { > > + .test_all = run, > > + .needs_kconfigs = (const char *[]) { > > + "CONFIG_AIO=y", > > + NULL > > + }, > > + .setup = setup, > > + .cleanup = cleanup, > > +}; > > -- > Andrea Cervesato > SUSE QE Automation Engineer Linux > andrea.cervesato@suse.com > -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-06 6:26 ` Wei Gao via ltp @ 2026-01-06 8:39 ` Andrea Cervesato via ltp 2026-01-06 8:39 ` Petr Vorel 1 sibling, 0 replies; 22+ messages in thread From: Andrea Cervesato via ltp @ 2026-01-06 8:39 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > > We return because if io_submit() fails there's nothing to do more. > tst_res(TBROK will trigger error such as : > make[1]: Leaving directory '/home/wegao/ltp/lib' > In file included from ../../../../include/tst_test.h:20, > from io_submit04.c:14: > io_submit04.c: In function ‘run’: > ../../../../include/tst_common.h:80:32: error: size of unnamed array is negative > 80 | do { ((void)sizeof(char[1 - 2 * !!(condition)])); } while (0) > | ^ > ../../../../include/tst_common.h:83:9: note: in expansion of macro ‘TST_BUILD_BUG_ON’ > 83 | TST_BUILD_BUG_ON(condition) > | ^~~~~~~~~~~~~~~~ > ../../../../include/tst_test.h:71:17: note: in expansion of macro ‘TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN’ > 71 | TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(\ > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > io_submit04.c:63:17: note: in expansion of macro ‘tst_res’ > 63 | tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > | ^~~~~~~ > make: *** [../../../../include/mk/rules.mk:48: io_submit04] Error 1 > -bash: ./io_submit04: No such file or directory > > So i suppose we need use "tst_brk(TBROK" without return, correct? Yes, sorry, christmas vacation is hitting :-) -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-06 6:26 ` Wei Gao via ltp 2026-01-06 8:39 ` Andrea Cervesato via ltp @ 2026-01-06 8:39 ` Petr Vorel 2026-01-07 8:53 ` Jan Stancek via ltp 1 sibling, 1 reply; 22+ messages in thread From: Petr Vorel @ 2026-01-06 8:39 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi all, ... > > > +static void run(void) > > > +{ > > > + struct io_event evbuf; > > > + struct timespec timeout = { .tv_sec = 1 }; > > > + long nr = 1; > > > + > > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > > + > > > + if (TST_RET == nr) > > > + tst_res(TPASS, "io_submit() pass"); > > > + else > > > + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > > Our goal is to verify that io_getevents() returns EAGAIN, so we can just: > > if (TST_RET != nr) { > > tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > > return; > > } > > We return because if io_submit() fails there's nothing to do more. > tst_res(TBROK will trigger error such as : > make[1]: Leaving directory '/home/wegao/ltp/lib' > In file included from ../../../../include/tst_test.h:20, > from io_submit04.c:14: > io_submit04.c: In function ‘run’: > ../../../../include/tst_common.h:80:32: error: size of unnamed array is negative > 80 | do { ((void)sizeof(char[1 - 2 * !!(condition)])); } while (0) > | ^ > ../../../../include/tst_common.h:83:9: note: in expansion of macro ‘TST_BUILD_BUG_ON’ > 83 | TST_BUILD_BUG_ON(condition) > | ^~~~~~~~~~~~~~~~ > ../../../../include/tst_test.h:71:17: note: in expansion of macro ‘TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN’ > 71 | TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(\ > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > io_submit04.c:63:17: note: in expansion of macro ‘tst_res’ > 63 | tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > | ^~~~~~~ > make: *** [../../../../include/mk/rules.mk:48: io_submit04] Error 1 > -bash: ./io_submit04: No such file or directory > So i suppose we need use "tst_brk(TBROK" without return, correct? Yes, that's a macro which enforces using TBROK only with tst_brk(). @Cyril @Li @Jan I wonder if we still need this enforcement after Cyril's change a1f82704c2 ("lib/tst_test.c: Fix tst_brk() handling") Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v3] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-06 8:39 ` Petr Vorel @ 2026-01-07 8:53 ` Jan Stancek via ltp 0 siblings, 0 replies; 22+ messages in thread From: Jan Stancek via ltp @ 2026-01-07 8:53 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Tue, Jan 6, 2026 at 9:39 AM Petr Vorel <pvorel@suse.cz> wrote: > > Hi all, > > ... > > > > +static void run(void) > > > > +{ > > > > + struct io_event evbuf; > > > > + struct timespec timeout = { .tv_sec = 1 }; > > > > + long nr = 1; > > > > + > > > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > > > + > > > > + if (TST_RET == nr) > > > > + tst_res(TPASS, "io_submit() pass"); > > > > + else > > > > + tst_res(TFAIL | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > > > > Our goal is to verify that io_getevents() returns EAGAIN, so we can just: > > > > if (TST_RET != nr) { > > > tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", TST_RET, nr); > > > return; > > > } > > > > We return because if io_submit() fails there's nothing to do more. > > tst_res(TBROK will trigger error such as : > > make[1]: Leaving directory '/home/wegao/ltp/lib' > > In file included from ../../../../include/tst_test.h:20, > > from io_submit04.c:14: > > io_submit04.c: In function ‘run’: > > ../../../../include/tst_common.h:80:32: error: size of unnamed array is negative > > 80 | do { ((void)sizeof(char[1 - 2 * !!(condition)])); } while (0) > > | ^ > > ../../../../include/tst_common.h:83:9: note: in expansion of macro ‘TST_BUILD_BUG_ON’ > > 83 | TST_BUILD_BUG_ON(condition) > > | ^~~~~~~~~~~~~~~~ > > ../../../../include/tst_test.h:71:17: note: in expansion of macro ‘TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN’ > > 71 | TST_RES_SUPPORTS_TCONF_TDEBUG_TFAIL_TINFO_TPASS_TWARN(\ > > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > io_submit04.c:63:17: note: in expansion of macro ‘tst_res’ > > 63 | tst_res(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > > | ^~~~~~~ > > make: *** [../../../../include/mk/rules.mk:48: io_submit04] Error 1 > > -bash: ./io_submit04: No such file or directory > > > So i suppose we need use "tst_brk(TBROK" without return, correct? > > Yes, that's a macro which enforces using TBROK only with tst_brk(). > > @Cyril @Li @Jan I wonder if we still need this enforcement after Cyril's change > a1f82704c2 ("lib/tst_test.c: Fix tst_brk() handling") Looking at differences between tst_res_() and tst_vbrk_() , vbrk_ has some additional cleanup calls so they don't look to be exactly identical. I'd keep it to encourage usage of tst_brk() if you need to abort the test (from any context: library, test, test children). -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v4] io_submit04: Add test case for RWF_NOWAIT flag 2025-12-24 8:49 ` [LTP] [PATCH v3] " Wei Gao via ltp 2026-01-05 12:53 ` Andrea Cervesato via ltp @ 2026-01-07 6:10 ` Wei Gao via ltp 2026-02-18 12:21 ` Andrea Cervesato via ltp 2026-03-17 7:43 ` [LTP] [PATCH v5] " Wei Gao via ltp 1 sibling, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-01-07 6:10 UTC (permalink / raw) To: ltp Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- configure.ac | 1 + include/lapi/aio_abi.h | 44 +++++++++ runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 94 +++++++++++++++++++ 5 files changed, 141 insertions(+) create mode 100644 include/lapi/aio_abi.h create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/configure.ac b/configure.ac index a0ebbb34d..ee46e3f24 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ ]) AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h new file mode 100644 index 000000000..bd8c2965b --- /dev/null +++ b/include/lapi/aio_abi.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +#ifndef LAPI_AIO_ABI_H__ +#define LAPI_AIO_ABI_H__ + +#include <endian.h> +#include <linux/aio_abi.h> + +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0x00000008 +#endif + +struct iocb_fallback { + uint64_t aio_data; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t aio_key; + uint32_t aio_rw_flags; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint32_t aio_rw_flags; + uint32_t aio_key; +#else +#error edit for your odd byteorder. +#endif + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; +}; + +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS +typedef struct iocb_fallback iocb; +#else +typedef struct iocb iocb; +#endif + +#endif /* LAPI_AIO_ABI_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index a1ef7548b..18182a2d6 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -696,6 +696,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..d085d3238 --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test RWF_NOWAIT support in io_submit(), verifying that an + * asynchronous read operation on a blocking resource (empty pipe) + * will cause -EAGAIN. This is done by checking that io_getevents() + * syscall returns immediately and io_event.res is equal to -EAGAIN. + */ + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/aio_abi.h" + + +#define BUF_SIZE 100 + +static int fd[2]; + +static aio_context_t ctx; +static char *buf; +static iocb *cb; +static iocb **iocbs; + +static void setup(void) +{ + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); + SAFE_PIPE(fd); + + cb->aio_fildes = fd[0]; + cb->aio_lio_opcode = IOCB_CMD_PREAD; + cb->aio_buf = (uint64_t)buf; + cb->aio_offset = 0; + cb->aio_nbytes = BUF_SIZE; + cb->aio_rw_flags = RWF_NOWAIT; + + iocbs[0] = cb; +} + +static void cleanup(void) +{ + if (fd[0]) + SAFE_CLOSE(fd[0]); + + if (fd[1]) + SAFE_CLOSE(fd[1]); + + if (ctx) + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == -1 && errno == EOPNOTSUPP) { + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); + } else if (TST_RET != nr) { + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", + TST_RET, nr); + } + + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); + + if (evbuf.res == -EAGAIN) + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); + else + tst_res(TFAIL | TTERRNO, "io_getevents() returned with %s instead of EAGAIN", + strerror(-evbuf.res)); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .bufs = (struct tst_buffers []) { + {&buf, .size = BUF_SIZE}, + {&cb, .size = sizeof(iocb)}, + {&iocbs, .size = sizeof(iocb *)}, + {}, + } +}; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v4] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-07 6:10 ` [LTP] [PATCH v4] " Wei Gao via ltp @ 2026-02-18 12:21 ` Andrea Cervesato via ltp 2026-03-05 4:41 ` Wei Gao via ltp 2026-03-17 7:43 ` [LTP] [PATCH v5] " Wei Gao via ltp 1 sibling, 1 reply; 22+ messages in thread From: Andrea Cervesato via ltp @ 2026-02-18 12:21 UTC (permalink / raw) To: Wei Gao, ltp Hi! On Wed Jan 7, 2026 at 7:10 AM CET, Wei Gao wrote: > Fixes: #467 > Signed-off-by: Wei Gao <wegao@suse.com> > --- > configure.ac | 1 + > include/lapi/aio_abi.h | 44 +++++++++ > runtest/syscalls | 1 + > .../kernel/syscalls/io_submit/.gitignore | 1 + > .../kernel/syscalls/io_submit/io_submit04.c | 94 +++++++++++++++++++ > 5 files changed, 141 insertions(+) > create mode 100644 include/lapi/aio_abi.h > create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c > > diff --git a/configure.ac b/configure.ac > index a0ebbb34d..ee46e3f24 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ > ]) > AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) > > +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > new file mode 100644 > index 000000000..bd8c2965b > --- /dev/null > +++ b/include/lapi/aio_abi.h > @@ -0,0 +1,44 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +#ifndef LAPI_AIO_ABI_H__ > +#define LAPI_AIO_ABI_H__ > + > +#include <endian.h> > +#include <linux/aio_abi.h> > + > +#ifndef RWF_NOWAIT > +# define RWF_NOWAIT 0x00000008 > +#endif > + > +struct iocb_fallback { > + uint64_t aio_data; > +#if __BYTE_ORDER == __LITTLE_ENDIAN > + uint32_t aio_key; > + uint32_t aio_rw_flags; > +#elif __BYTE_ORDER == __BIG_ENDIAN > + uint32_t aio_rw_flags; > + uint32_t aio_key; > +#else > +#error edit for your odd byteorder. > +#endif > + uint16_t aio_lio_opcode; > + int16_t aio_reqprio; > + uint32_t aio_fildes; > + uint64_t aio_buf; > + uint64_t aio_nbytes; > + int64_t aio_offset; > + uint64_t aio_reserved2; > + uint32_t aio_flags; > + uint32_t aio_resfd; > +}; checkpatch.pl reports you are using too many spaces for indentation in here. > + > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > +typedef struct iocb_fallback iocb; Why not just define here the iocb, instead of having iocb_fallback defined before? > +#else > +typedef struct iocb iocb; And this would not be needed then. > +#endif > + > +#endif /* LAPI_AIO_ABI_H__ */ > diff --git a/runtest/syscalls b/runtest/syscalls > index a1ef7548b..18182a2d6 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -696,6 +696,7 @@ io_setup02 io_setup02 > io_submit01 io_submit01 > io_submit02 io_submit02 > io_submit03 io_submit03 > +io_submit04 io_submit04 > > keyctl01 keyctl01 > keyctl02 keyctl02 > diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore > index 60b07970a..abe962e1c 100644 > --- a/testcases/kernel/syscalls/io_submit/.gitignore > +++ b/testcases/kernel/syscalls/io_submit/.gitignore > @@ -1,3 +1,4 @@ > /io_submit01 > /io_submit02 > /io_submit03 > +/io_submit04 > diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c > new file mode 100644 > index 000000000..d085d3238 > --- /dev/null > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > @@ -0,0 +1,94 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +/*\ > + * Test RWF_NOWAIT support in io_submit(), verifying that an > + * asynchronous read operation on a blocking resource (empty pipe) > + * will cause -EAGAIN. This is done by checking that io_getevents() > + * syscall returns immediately and io_event.res is equal to -EAGAIN. > + */ > + > +#include "config.h" > +#include "tst_test.h" > +#include "lapi/syscalls.h" > +#include "lapi/aio_abi.h" > + > + nit: double blank-line is not needed. > +#define BUF_SIZE 100 > + > +static int fd[2]; fd should be initialized to -1 and compared to this value in the cleanup() before closing. zero is a valid value for file descriptors (stdin). > + > +static aio_context_t ctx; > +static char *buf; > +static iocb *cb; > +static iocb **iocbs; > + > +static void setup(void) > +{ > + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); We need to break the test here if io_setup fails. Silently failing it will keep test running. > + SAFE_PIPE(fd); > + > + cb->aio_fildes = fd[0]; > + cb->aio_lio_opcode = IOCB_CMD_PREAD; > + cb->aio_buf = (uint64_t)buf; > + cb->aio_offset = 0; > + cb->aio_nbytes = BUF_SIZE; > + cb->aio_rw_flags = RWF_NOWAIT; > + > + iocbs[0] = cb; > +} > + > +static void cleanup(void) > +{ > + if (fd[0]) > + SAFE_CLOSE(fd[0]); > + > + if (fd[1]) > + SAFE_CLOSE(fd[1]); > + > + if (ctx) > + if (tst_syscall(__NR_io_destroy, ctx)) > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); > +} > + > +static void run(void) > +{ > + struct io_event evbuf; > + struct timespec timeout = { .tv_sec = 1 }; > + long nr = 1; > + > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > + > + if (TST_RET == -1 && errno == EOPNOTSUPP) { > + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); > + } else if (TST_RET != nr) { > + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > + TST_RET, nr); > + } > + > + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); Return value is ignored. > + > + if (evbuf.res == -EAGAIN) > + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); > + else > + tst_res(TFAIL | TTERRNO, "io_getevents() returned with %s instead of EAGAIN", TTERRNO is not needed. > + strerror(-evbuf.res)); > +} > + > +static struct tst_test test = { > + .test_all = run, > + .setup = setup, > + .cleanup = cleanup, > + .needs_kconfigs = (const char *[]) { > + "CONFIG_AIO=y", > + NULL > + }, > + .bufs = (struct tst_buffers []) { > + {&buf, .size = BUF_SIZE}, > + {&cb, .size = sizeof(iocb)}, > + {&iocbs, .size = sizeof(iocb *)}, > + {}, > + } > +}; -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v4] io_submit04: Add test case for RWF_NOWAIT flag 2026-02-18 12:21 ` Andrea Cervesato via ltp @ 2026-03-05 4:41 ` Wei Gao via ltp 0 siblings, 0 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-03-05 4:41 UTC (permalink / raw) To: Andrea Cervesato; +Cc: ltp On Wed, Feb 18, 2026 at 01:21:46PM +0100, Andrea Cervesato wrote: > Hi! > > On Wed Jan 7, 2026 at 7:10 AM CET, Wei Gao wrote: > > Fixes: #467 > > Signed-off-by: Wei Gao <wegao@suse.com> > > --- > > > + > > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > > +typedef struct iocb_fallback iocb; > > Why not just define here the iocb, instead of having iocb_fallback > defined before? This way can avoid complie failure on old system such as: https://github.com/coolgw/ltp/actions/runs/22699554704/job/65813365426 make[4]: *** [io_submit04] Error 1 make[4]: *** Waiting for unfinished jobs.... ../../../../include/mk/rules.mk:48: recipe for target 'io_submit04' failed CC testcases/kernel/syscalls/io_submit/io_submit01 CC testcases/kernel/syscalls/io_submit/io_submit02 CC testcases/kernel/syscalls/io_submit/io_submit03 make[3]: *** [all] Error 2 ../../../include/mk/generic_trunk_target.inc:92: recipe for target 'all' failed make[2]: *** [all] Error 2 ../../include/mk/generic_trunk_target.inc:92: recipe for target 'all' failed make[1]: *** [all] Error 2 ../include/mk/generic_trunk_target.inc:92: recipe for target 'all' failed make[1]: Leaving directory '/__w/ltp/ltp/testcases' Makefile:85: recipe for target 'testcases-all' failed make: *** [testcases-all] Error 2 Error: Process completed with exit code 2 This kind of fallback also mentioned/used in following patch: https://patchwork.ozlabs.org/project/ltp/patch/20251211015915.1086-1-wegao@suse.com/ > > > +#else > > +typedef struct iocb iocb; > > And this would not be needed then. > > > +#endif > > + > > +#endif /* LAPI_AIO_ABI_H__ */ > > diff --git a/runtest/syscalls b/runtest/syscalls > > index a1ef7548b..18182a2d6 100644 > > --- a/runtest/syscalls > > +++ b/runtest/syscalls > > @@ -696,6 +696,7 @@ io_setup02 io_setup02 > > io_submit01 io_submit01 > > io_submit02 io_submit02 > > io_submit03 io_submit03 > > +io_submit04 io_submit04 > > > > keyctl01 keyctl01 > > keyctl02 keyctl02 > > diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore > > index 60b07970a..abe962e1c 100644 > > --- a/testcases/kernel/syscalls/io_submit/.gitignore > > +++ b/testcases/kernel/syscalls/io_submit/.gitignore > > @@ -1,3 +1,4 @@ > > /io_submit01 > > /io_submit02 > > /io_submit03 > > +/io_submit04 > > diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c > > new file mode 100644 > > index 000000000..d085d3238 > > --- /dev/null > > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > > @@ -0,0 +1,94 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > > + */ > > + > > +/*\ > > + * Test RWF_NOWAIT support in io_submit(), verifying that an > > + * asynchronous read operation on a blocking resource (empty pipe) > > + * will cause -EAGAIN. This is done by checking that io_getevents() > > + * syscall returns immediately and io_event.res is equal to -EAGAIN. > > + */ > > + > > +#include "config.h" > > +#include "tst_test.h" > > +#include "lapi/syscalls.h" > > +#include "lapi/aio_abi.h" > > + > > + > > nit: double blank-line is not needed. > > > +#define BUF_SIZE 100 > > + > > +static int fd[2]; > > fd should be initialized to -1 and compared to this value in the > cleanup() before closing. zero is a valid value for file descriptors > (stdin). > > > + > > +static aio_context_t ctx; > > +static char *buf; > > +static iocb *cb; > > +static iocb **iocbs; > > + > > +static void setup(void) > > +{ > > + TST_EXP_PASS_SILENT(tst_syscall(__NR_io_setup, 1, &ctx)); > > We need to break the test here if io_setup fails. Silently failing it > will keep test running. > > > + SAFE_PIPE(fd); > > + > > + cb->aio_fildes = fd[0]; > > + cb->aio_lio_opcode = IOCB_CMD_PREAD; > > + cb->aio_buf = (uint64_t)buf; > > + cb->aio_offset = 0; > > + cb->aio_nbytes = BUF_SIZE; > > + cb->aio_rw_flags = RWF_NOWAIT; > > + > > + iocbs[0] = cb; > > +} > > + > > +static void cleanup(void) > > +{ > > + if (fd[0]) > > + SAFE_CLOSE(fd[0]); > > + > > + if (fd[1]) > > + SAFE_CLOSE(fd[1]); > > + > > + if (ctx) > > + if (tst_syscall(__NR_io_destroy, ctx)) > > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); > > +} > > + > > +static void run(void) > > +{ > > + struct io_event evbuf; > > + struct timespec timeout = { .tv_sec = 1 }; > > + long nr = 1; > > + > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > + > > + if (TST_RET == -1 && errno == EOPNOTSUPP) { > > + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); > > + } else if (TST_RET != nr) { > > + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > > + TST_RET, nr); > > + } > > + > > + tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout); > > Return value is ignored. > > > + > > + if (evbuf.res == -EAGAIN) > > + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); > > + else > > + tst_res(TFAIL | TTERRNO, "io_getevents() returned with %s instead of EAGAIN", > > TTERRNO is not needed. > > > + strerror(-evbuf.res)); > > +} > > + > > +static struct tst_test test = { > > + .test_all = run, > > + .setup = setup, > > + .cleanup = cleanup, > > + .needs_kconfigs = (const char *[]) { > > + "CONFIG_AIO=y", > > + NULL > > + }, > > + .bufs = (struct tst_buffers []) { > > + {&buf, .size = BUF_SIZE}, > > + {&cb, .size = sizeof(iocb)}, > > + {&iocbs, .size = sizeof(iocb *)}, > > + {}, > > + } > > +}; > > > > > -- > Andrea Cervesato > SUSE QE Automation Engineer Linux > andrea.cervesato@suse.com > -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v5] io_submit04: Add test case for RWF_NOWAIT flag 2026-01-07 6:10 ` [LTP] [PATCH v4] " Wei Gao via ltp 2026-02-18 12:21 ` Andrea Cervesato via ltp @ 2026-03-17 7:43 ` Wei Gao via ltp 2026-03-17 9:54 ` Andrea Cervesato via ltp 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp 1 sibling, 2 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-03-17 7:43 UTC (permalink / raw) To: ltp v4->v5: - Initialize fd to -1 - Replaces silent macros with explicit error checks - Verifies that io_getevents actually returns the expected event - Remove duplicate TTERRNO Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- configure.ac | 1 + include/lapi/aio_abi.h | 44 +++++++++ runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 99 +++++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 include/lapi/aio_abi.h create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/configure.ac b/configure.ac index 7fa614dcb..61462d192 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ ]) AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h new file mode 100644 index 000000000..bd8c2965b --- /dev/null +++ b/include/lapi/aio_abi.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +#ifndef LAPI_AIO_ABI_H__ +#define LAPI_AIO_ABI_H__ + +#include <endian.h> +#include <linux/aio_abi.h> + +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0x00000008 +#endif + +struct iocb_fallback { + uint64_t aio_data; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t aio_key; + uint32_t aio_rw_flags; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint32_t aio_rw_flags; + uint32_t aio_key; +#else +#error edit for your odd byteorder. +#endif + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; +}; + +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS +typedef struct iocb_fallback iocb; +#else +typedef struct iocb iocb; +#endif + +#endif /* LAPI_AIO_ABI_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 2179e007c..9812b1bfe 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -699,6 +699,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..9b7b52995 --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test RWF_NOWAIT support in io_submit(), verifying that an + * asynchronous read operation on a blocking resource (empty pipe) + * will cause -EAGAIN. This is done by checking that io_getevents() + * syscall returns immediately and io_event.res is equal to -EAGAIN. + */ + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/aio_abi.h" + +#define BUF_SIZE 100 + +static int fd[2] = {-1, -1}; +static aio_context_t ctx; +static char *buf; +static iocb *cb; +static iocb **iocbs; + +static void setup(void) +{ + if (tst_syscall(__NR_io_setup, 1, &ctx)) + tst_brk(TBROK | TERRNO, "io_setup failed"); + + SAFE_PIPE(fd); + + cb->aio_fildes = fd[0]; + cb->aio_lio_opcode = IOCB_CMD_PREAD; + cb->aio_buf = (uint64_t)buf; + cb->aio_offset = 0; + cb->aio_nbytes = BUF_SIZE; + cb->aio_rw_flags = RWF_NOWAIT; + + iocbs[0] = cb; +} + +static void cleanup(void) +{ + if (fd[0]) + SAFE_CLOSE(fd[0]); + + if (fd[1]) + SAFE_CLOSE(fd[1]); + + if (ctx) + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == -1 && errno == EOPNOTSUPP) { + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); + } else if (TST_RET != nr) { + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", + TST_RET, nr); + } + + TEST(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout)); + + if (TST_RET != 1) { + tst_res(TFAIL | TTERRNO, "io_getevents() failed to get 1 event"); + return; + } + + if (evbuf.res == -EAGAIN) + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); + else + tst_res(TFAIL, "io_getevents() returned with %s instead of EAGAIN", + strerror(-evbuf.res)); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .bufs = (struct tst_buffers []) { + {&buf, .size = BUF_SIZE}, + {&cb, .size = sizeof(iocb)}, + {&iocbs, .size = sizeof(iocb *)}, + {}, + } +}; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v5] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-17 7:43 ` [LTP] [PATCH v5] " Wei Gao via ltp @ 2026-03-17 9:54 ` Andrea Cervesato via ltp 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp 1 sibling, 0 replies; 22+ messages in thread From: Andrea Cervesato via ltp @ 2026-03-17 9:54 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Thanks for the patch. I have a few issues to address before this can be merged. > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > +struct iocb_fallback { > + uint64_t aio_data; > +#if __BYTE_ORDER == __LITTLE_ENDIAN > + uint32_t aio_key; > + uint32_t aio_rw_flags; The struct body uses spaces for indentation instead of tabs. Please convert to tabs to match the kernel coding style used in other lapi headers. > +static void cleanup(void) > +{ > + if (fd[0]) > + SAFE_CLOSE(fd[0]); > + > + if (fd[1]) > + SAFE_CLOSE(fd[1]); fd is initialised to {-1, -1}. The check `if (fd[0])` is truthy for -1, so if setup() aborts before SAFE_PIPE() (e.g. io_setup fails), cleanup will call SAFE_CLOSE(-1) which fails with EBADF and triggers a spurious TBROK. Use the standard LTP pattern: if (fd[0] != -1) SAFE_CLOSE(fd[0]); if (fd[1] != -1) SAFE_CLOSE(fd[1]); > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > + > + if (TST_RET == -1 && errno == EOPNOTSUPP) { After the TEST() macro, use TST_ERR instead of bare errno: if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { Regards, -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v6] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-17 7:43 ` [LTP] [PATCH v5] " Wei Gao via ltp 2026-03-17 9:54 ` Andrea Cervesato via ltp @ 2026-03-17 11:46 ` Wei Gao via ltp 2026-03-20 12:54 ` Andrea Cervesato via ltp ` (3 more replies) 1 sibling, 4 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-03-17 11:46 UTC (permalink / raw) To: ltp v5-v6: - Changed fd checks to != -1 in cleanup function - Replaced errno with TST_ERR for LTP macro consistency - cleanup format issue for aio_abi.h Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- configure.ac | 1 + include/lapi/aio_abi.h | 44 +++++++++ runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 99 +++++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 include/lapi/aio_abi.h create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/configure.ac b/configure.ac index 7fa614dcb..61462d192 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ ]) AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h new file mode 100644 index 000000000..ac78e5500 --- /dev/null +++ b/include/lapi/aio_abi.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +#ifndef LAPI_AIO_ABI_H__ +#define LAPI_AIO_ABI_H__ + +#include <endian.h> +#include <linux/aio_abi.h> + +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0x00000008 +#endif + +struct iocb_fallback { + uint64_t aio_data; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t aio_key; + uint32_t aio_rw_flags; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint32_t aio_rw_flags; + uint32_t aio_key; +#else +#error edit for your odd byteorder. +#endif + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; +}; + +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS +typedef struct iocb_fallback iocb; +#else +typedef struct iocb iocb; +#endif + +#endif /* LAPI_AIO_ABI_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 2179e007c..9812b1bfe 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -699,6 +699,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..3b8842da0 --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test RWF_NOWAIT support in io_submit(), verifying that an + * asynchronous read operation on a blocking resource (empty pipe) + * will cause -EAGAIN. This is done by checking that io_getevents() + * syscall returns immediately and io_event.res is equal to -EAGAIN. + */ + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/aio_abi.h" + +#define BUF_SIZE 100 + +static int fd[2] = {-1, -1}; +static aio_context_t ctx; +static char *buf; +static iocb *cb; +static iocb **iocbs; + +static void setup(void) +{ + if (tst_syscall(__NR_io_setup, 1, &ctx)) + tst_brk(TBROK | TERRNO, "io_setup failed"); + + SAFE_PIPE(fd); + + cb->aio_fildes = fd[0]; + cb->aio_lio_opcode = IOCB_CMD_PREAD; + cb->aio_buf = (uint64_t)buf; + cb->aio_offset = 0; + cb->aio_nbytes = BUF_SIZE; + cb->aio_rw_flags = RWF_NOWAIT; + + iocbs[0] = cb; +} + +static void cleanup(void) +{ + if (fd[0] != -1) + SAFE_CLOSE(fd[0]); + + if (fd[1] != -1) + SAFE_CLOSE(fd[1]); + + if (ctx) + if (tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); + } else if (TST_RET != nr) { + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", + TST_RET, nr); + } + + TEST(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout)); + + if (TST_RET != 1) { + tst_res(TFAIL | TTERRNO, "io_getevents() failed to get 1 event"); + return; + } + + if (evbuf.res == -EAGAIN) + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); + else + tst_res(TFAIL, "io_getevents() returned with %s instead of EAGAIN", + strerror(-evbuf.res)); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .bufs = (struct tst_buffers []) { + {&buf, .size = BUF_SIZE}, + {&cb, .size = sizeof(iocb)}, + {&iocbs, .size = sizeof(iocb *)}, + {}, + } +}; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v6] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp @ 2026-03-20 12:54 ` Andrea Cervesato via ltp 2026-03-27 18:17 ` Petr Vorel ` (2 subsequent siblings) 3 siblings, 0 replies; 22+ messages in thread From: Andrea Cervesato via ltp @ 2026-03-20 12:54 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > v5-v6: > - Changed fd checks to != -1 in cleanup function > - Replaced errno with TST_ERR for LTP macro consistency > - cleanup format issue for aio_abi.h This can't be the body of the commit. It should be after --- as a patch comment. We can fix the commit message once patch merged. Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com> Regards, -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v6] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp 2026-03-20 12:54 ` Andrea Cervesato via ltp @ 2026-03-27 18:17 ` Petr Vorel 2026-03-30 8:08 ` Wei Gao via ltp 2026-04-04 1:00 ` Wei Gao via ltp 2026-03-31 11:18 ` [LTP] [PATCH v7] fanotify22.c: handle multiple asynchronous error events Wei Gao via ltp 2026-04-04 1:13 ` [LTP] [PATCH v7] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp 3 siblings, 2 replies; 22+ messages in thread From: Petr Vorel @ 2026-03-27 18:17 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, all, > +++ b/configure.ac > @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ > ]) > AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) > +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) FYI I double checked this is from 4.13 9830f4be159b2 ("fs: Use RWF_* flags for AIO operations") So we need it, but it'd be worth to double check how the test run on 4.4 (if it TCONF). Also maybe add a comment in the code or at least mention it in the commit message. When we drop old SLES we will be able to remove this. @Andrea: any hint for your agents to check supported versions https://linux-test-project.readthedocs.io/en/latest/users/supported_systems.html#kernel-version and whether it needs to have fallback in lapi and configure.ac? Also we may ask not to add .min_kver which would be too old. > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > new file mode 100644 > index 000000000..ac78e5500 > --- /dev/null > +++ b/include/lapi/aio_abi.h > @@ -0,0 +1,44 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +#ifndef LAPI_AIO_ABI_H__ > +#define LAPI_AIO_ABI_H__ > + > +#include <endian.h> > +#include <linux/aio_abi.h> > + > +#ifndef RWF_NOWAIT > +# define RWF_NOWAIT 0x00000008 And this as well. b745fafaf70c0 ("fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT") > +#endif > + > +struct iocb_fallback { > + uint64_t aio_data; > +#if __BYTE_ORDER == __LITTLE_ENDIAN > + uint32_t aio_key; > + uint32_t aio_rw_flags; > +#elif __BYTE_ORDER == __BIG_ENDIAN > + uint32_t aio_rw_flags; > + uint32_t aio_key; > +#else > +#error edit for your odd byteorder. > +#endif > + uint16_t aio_lio_opcode; > + int16_t aio_reqprio; > + uint32_t aio_fildes; > + uint64_t aio_buf; > + uint64_t aio_nbytes; > + int64_t aio_offset; > + uint64_t aio_reserved2; > + uint32_t aio_flags; > + uint32_t aio_resfd; > +}; > + > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > +typedef struct iocb_fallback iocb; > +#else > +typedef struct iocb iocb; > +#endif > + > +#endif /* LAPI_AIO_ABI_H__ */ ... > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > @@ -0,0 +1,99 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > + */ > + > +/*\ > + * Test RWF_NOWAIT support in io_submit(), verifying that an > + * asynchronous read operation on a blocking resource (empty pipe) > + * will cause -EAGAIN. This is done by checking that io_getevents() Please :manpage:`io_getevents(2)` (to have link to https://man7.org/linux/man-pages/man2/io_getevents.2.html in docs). @Andrea: ^ to agents? > + * syscall returns immediately and io_event.res is equal to -EAGAIN. > + */ > + > +#include "config.h" > +#include "tst_test.h" > +#include "lapi/syscalls.h" > +#include "lapi/aio_abi.h" > + > +#define BUF_SIZE 100 > + > +static int fd[2] = {-1, -1}; nit: Andrea (I guess you asked for it), because we hardly close STDOUT in the test 0 is always used. I see it a bit overkill using -1 (using 0 as the default would almost always work). > +static aio_context_t ctx; > +static char *buf; > +static iocb *cb; > +static iocb **iocbs; > + > +static void setup(void) > +{ > + if (tst_syscall(__NR_io_setup, 1, &ctx)) > + tst_brk(TBROK | TERRNO, "io_setup failed"); > + > + SAFE_PIPE(fd); > + > + cb->aio_fildes = fd[0]; > + cb->aio_lio_opcode = IOCB_CMD_PREAD; > + cb->aio_buf = (uint64_t)buf; > + cb->aio_offset = 0; > + cb->aio_nbytes = BUF_SIZE; > + cb->aio_rw_flags = RWF_NOWAIT; > + > + iocbs[0] = cb; > +} > + > +static void cleanup(void) > +{ > + if (fd[0] != -1) > + SAFE_CLOSE(fd[0]); > + > + if (fd[1] != -1) > + SAFE_CLOSE(fd[1]); > + > + if (ctx) > + if (tst_syscall(__NR_io_destroy, ctx)) > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); Upper if would require { } brackets, but let's simplify: if (ctx && tst_syscall(__NR_io_destroy, ctx)) tst_brk(TBROK | TERRNO, "io_destroy() failed"); > +} > + > +static void run(void) > +{ > + struct io_event evbuf; > + struct timespec timeout = { .tv_sec = 1 }; > + long nr = 1; > + > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > + > + if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { > + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); > + } else if (TST_RET != nr) { > + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > + TST_RET, nr); > + } Maybe move this to setup()? > + > + TEST(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout)); > + > + if (TST_RET != 1) { > + tst_res(TFAIL | TTERRNO, "io_getevents() failed to get 1 event"); > + return; > + } > + > + if (evbuf.res == -EAGAIN) Did you please check this on 32bit? > + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); > + else > + tst_res(TFAIL, "io_getevents() returned with %s instead of EAGAIN", > + strerror(-evbuf.res)); > +} The rest LGTM. Kind regards, Petr > + > +static struct tst_test test = { > + .test_all = run, > + .setup = setup, > + .cleanup = cleanup, > + .needs_kconfigs = (const char *[]) { > + "CONFIG_AIO=y", > + NULL > + }, > + .bufs = (struct tst_buffers []) { > + {&buf, .size = BUF_SIZE}, > + {&cb, .size = sizeof(iocb)}, > + {&iocbs, .size = sizeof(iocb *)}, > + {}, > + } > +}; -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v6] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-27 18:17 ` Petr Vorel @ 2026-03-30 8:08 ` Wei Gao via ltp 2026-04-04 1:00 ` Wei Gao via ltp 1 sibling, 0 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-03-30 8:08 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Mar 27, 2026 at 07:17:10PM +0100, Petr Vorel wrote: > Hi Wei, all, > > > +++ b/configure.ac > > @@ -172,6 +172,7 @@ AC_CHECK_FUNCS_ONCE([ \ > > ]) > > AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) > > > +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) > FYI I double checked this is from 4.13 > 9830f4be159b2 ("fs: Use RWF_* flags for AIO operations") > > So we need it, but it'd be worth to double check how the test run on 4.4 (if it > TCONF). Also maybe add a comment in the code or at least mention it in the > commit message. When we drop old SLES we will be able to remove this. I found a 12-SP5 JeOS old img with kernel 4.12, the test result show TCONF, i think 4.4 also can show TCONF. https://download.opensuse.org/repositories/SUSE:/Templates:/Images:/SLE-12-SP5/images/SLES12-SP5-JeOS.x86_64-12.5-kvm-and-xen-Build1.614.qcow2 linux:~/ltp/testcases/kernel/syscalls/io_submit # uname -r 4.12.14-122.231-default linux:~/ltp/testcases/kernel/syscalls/io_submit # cat /etc/os-release NAME="SLES" VERSION="12-SP5" VERSION_ID="12.5" PRETTY_NAME="SUSE Linux Enterprise Server 12 SP5" ID="sles" ANSI_COLOR="0;32" CPE_NAME="cpe:/o:suse:sles:12:sp5" linux:~/ltp/testcases/kernel/syscalls/io_submit # ./io_submit04 tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz' tst_buffers.c:57: TINFO: Test is using guarded buffers tst_test.c:2059: TINFO: LTP version: 20260130 tst_test.c:2062: TINFO: Tested kernel: 4.12.14-122.231-default #1 SMP Wed Oct 2 17:30:21 UTC 2024 (5f0ddca) x86_64 tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz' tst_kconfig.c:678: TINFO: CONFIG_FAULT_INJECTION kernel option detected which might slow the execution tst_test.c:1889: TINFO: Overall timeout per run is 0h 02m 00s io_submit04.c:65: TCONF: RWF_NOWAIT not supported by kernel > > @Andrea: any hint for your agents to check supported versions > https://linux-test-project.readthedocs.io/en/latest/users/supported_systems.html#kernel-version > and whether it needs to have fallback in lapi and configure.ac? > Also we may ask not to add .min_kver which would be too old. > > > AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) > > AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) > > AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) > > diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h > > new file mode 100644 > > index 000000000..ac78e5500 > > --- /dev/null > > +++ b/include/lapi/aio_abi.h > > @@ -0,0 +1,44 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > > + */ > > + > > +#ifndef LAPI_AIO_ABI_H__ > > +#define LAPI_AIO_ABI_H__ > > + > > +#include <endian.h> > > +#include <linux/aio_abi.h> > > + > > +#ifndef RWF_NOWAIT > > +# define RWF_NOWAIT 0x00000008 > And this as well. > b745fafaf70c0 ("fs: Introduce RWF_NOWAIT and FMODE_AIO_NOWAIT") > > > +#endif > > + > > +struct iocb_fallback { > > + uint64_t aio_data; > > +#if __BYTE_ORDER == __LITTLE_ENDIAN > > + uint32_t aio_key; > > + uint32_t aio_rw_flags; > > +#elif __BYTE_ORDER == __BIG_ENDIAN > > + uint32_t aio_rw_flags; > > + uint32_t aio_key; > > +#else > > +#error edit for your odd byteorder. > > +#endif > > + uint16_t aio_lio_opcode; > > + int16_t aio_reqprio; > > + uint32_t aio_fildes; > > + uint64_t aio_buf; > > + uint64_t aio_nbytes; > > + int64_t aio_offset; > > + uint64_t aio_reserved2; > > + uint32_t aio_flags; > > + uint32_t aio_resfd; > > +}; > > + > > +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS > > +typedef struct iocb_fallback iocb; > > +#else > > +typedef struct iocb iocb; > > +#endif > > + > > +#endif /* LAPI_AIO_ABI_H__ */ > ... > > > +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c > > @@ -0,0 +1,99 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2025 Wei Gao <wegao@suse.com> > > + */ > > + > > +/*\ > > + * Test RWF_NOWAIT support in io_submit(), verifying that an > > + * asynchronous read operation on a blocking resource (empty pipe) > > + * will cause -EAGAIN. This is done by checking that io_getevents() > Please :manpage:`io_getevents(2)` > (to have link to https://man7.org/linux/man-pages/man2/io_getevents.2.html in > docs). > > @Andrea: ^ to agents? > > > + * syscall returns immediately and io_event.res is equal to -EAGAIN. > > + */ > > + > > +#include "config.h" > > +#include "tst_test.h" > > +#include "lapi/syscalls.h" > > +#include "lapi/aio_abi.h" > > + > > +#define BUF_SIZE 100 > > + > > +static int fd[2] = {-1, -1}; > nit: Andrea (I guess you asked for it), because we hardly close STDOUT in the > test 0 is always used. I see it a bit overkill using -1 (using 0 as the default > would almost always work). > Though is nit, i need final decision, @Petr @Andrea > > +static aio_context_t ctx; > > +static char *buf; > > +static iocb *cb; > > +static iocb **iocbs; > > + > > +static void setup(void) > > +{ > > + if (tst_syscall(__NR_io_setup, 1, &ctx)) > > + tst_brk(TBROK | TERRNO, "io_setup failed"); > > + > > + SAFE_PIPE(fd); > > + > > + cb->aio_fildes = fd[0]; > > + cb->aio_lio_opcode = IOCB_CMD_PREAD; > > + cb->aio_buf = (uint64_t)buf; > > + cb->aio_offset = 0; > > + cb->aio_nbytes = BUF_SIZE; > > + cb->aio_rw_flags = RWF_NOWAIT; > > + > > + iocbs[0] = cb; > > +} > > + > > +static void cleanup(void) > > +{ > > + if (fd[0] != -1) > > + SAFE_CLOSE(fd[0]); > > + > > + if (fd[1] != -1) > > + SAFE_CLOSE(fd[1]); > > + > > + if (ctx) > > + if (tst_syscall(__NR_io_destroy, ctx)) > > + tst_brk(TBROK | TERRNO, "io_destroy() failed"); > Upper if would require { } brackets, but let's simplify: > > if (ctx && tst_syscall(__NR_io_destroy, ctx)) > tst_brk(TBROK | TERRNO, "io_destroy() failed"); > > > +} > > + > > +static void run(void) > > +{ > > + struct io_event evbuf; > > + struct timespec timeout = { .tv_sec = 1 }; > > + long nr = 1; > > + > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > + > > + if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { > > + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); > > + } else if (TST_RET != nr) { > > + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > > + TST_RET, nr); > > + } > > Maybe move this to setup()? > > > + > > + TEST(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout)); > > + > > + if (TST_RET != 1) { > > + tst_res(TFAIL | TTERRNO, "io_getevents() failed to get 1 event"); > > + return; > > + } > > + > > + if (evbuf.res == -EAGAIN) > Did you please check this on 32bit? Test on 32bit compat mode show error, this need further invetigation why root@wintermute:~/ltp32/testcases/kernel/syscalls/io_submit# ./io_submit04 tst_buffers.c:57: TINFO: Test is using guarded buffers tst_test.c:2025: TINFO: LTP version: 20250130-546-g13dbd838c tst_test.c:2028: TINFO: Tested kernel: 7.0.0-rc2-g5ee8dbf54602 #32 SMP PREEMPT_DYNAMIC Tue Mar 24 17:42:54 CST 2026 x86_64 tst_kconfig.c:71: TINFO: Couldn't locate kernel config! tst_test.c:1846: TINFO: Overall timeout per run is 0h 00m 30s io_submit04.c:67: TBROK: io_submit() returns -1, expected 1: EFAULT (14) > > > + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); > > + else > > + tst_res(TFAIL, "io_getevents() returned with %s instead of EAGAIN", > > + strerror(-evbuf.res)); > > +} > > The rest LGTM. > > Kind regards, > Petr > > > + > > +static struct tst_test test = { > > + .test_all = run, > > + .setup = setup, > > + .cleanup = cleanup, > > + .needs_kconfigs = (const char *[]) { > > + "CONFIG_AIO=y", > > + NULL > > + }, > > + .bufs = (struct tst_buffers []) { > > + {&buf, .size = BUF_SIZE}, > > + {&cb, .size = sizeof(iocb)}, > > + {&iocbs, .size = sizeof(iocb *)}, > > + {}, > > + } > > +}; -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [LTP] [PATCH v6] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-27 18:17 ` Petr Vorel 2026-03-30 8:08 ` Wei Gao via ltp @ 2026-04-04 1:00 ` Wei Gao via ltp 1 sibling, 0 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-04-04 1:00 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Mar 27, 2026 at 07:17:10PM +0100, Petr Vorel wrote: > Hi Wei, all, > > > + struct timespec timeout = { .tv_sec = 1 }; > > + long nr = 1; > > + > > + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); > > + > > + if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { > > + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); > > + } else if (TST_RET != nr) { > > + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", > > + TST_RET, nr); > > + } > > Maybe move this to setup()? Moving io_submit() to setup() breaks multi-iteration testing. Since io_getevents() reaps the request, we should call io_submit() inside the run() loop to re-queue the operation for the next pass. -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 22+ messages in thread
* [LTP] [PATCH v7] fanotify22.c: handle multiple asynchronous error events 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp 2026-03-20 12:54 ` Andrea Cervesato via ltp 2026-03-27 18:17 ` Petr Vorel @ 2026-03-31 11:18 ` Wei Gao via ltp 2026-04-04 1:13 ` [LTP] [PATCH v7] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp 3 siblings, 0 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-03-31 11:18 UTC (permalink / raw) To: ltp; +Cc: Jan Kara, kernel test robot Since the introduction of the asynchronous fserror reporting framework (kernel commit 81d2e13a57c9), fanotify22 has encountered sporadic failures due to the non-deterministic nature of event delivery and merging: 1) tcase3 failure: A race condition occurs when the test reads the notification fd between two events. Use a poll() and read() loop to wait until the expected event. 2) tcase4 failure: The kernel may deliver errors as independent events instead of a single merged event, since different worker kthread can end up generating each event so they won't be merged. As suggested by Jan Kara, this patch introduces a consolidate_events() helper. It iterates through the event buffer, accumulates the error_count from all independent events, and updates the first event's count in-place. Reported-by: kernel test robot <oliver.sang@intel.com> Closes: https://lore.kernel.org/oe-lkp/202602042124.87bd00e3-lkp@intel.com Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- v6->v7: - validation check to accept either error or error2 in check_error_event_info_error .../kernel/syscalls/fanotify/fanotify22.c | 113 +++++++++++++++--- 1 file changed, 96 insertions(+), 17 deletions(-) diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index e8002b160..f5d59b99d 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -28,6 +28,7 @@ #include "tst_test.h" #include <sys/fanotify.h> #include <sys/types.h> +#include <poll.h> #ifdef HAVE_SYS_FANOTIFY_H #include "fanotify.h" @@ -88,7 +89,6 @@ static void trigger_bad_link_lookup(void) ret, BAD_LINK, errno, EUCLEAN); } - static void tcase3_trigger(void) { trigger_bad_link_lookup(); @@ -104,6 +104,7 @@ static void tcase4_trigger(void) static struct test_case { char *name; int error; + int error2; unsigned int error_count; struct fanotify_fid_t *fid; void (*trigger_error)(void); @@ -134,37 +135,79 @@ static struct test_case { .trigger_error = &tcase4_trigger, .error_count = 2, .error = EFSCORRUPTED, + .error2 = ESHUTDOWN, .fid = &bad_file_fid, } }; +static size_t consolidate_events(char *buf, size_t len, const struct test_case *ex) +{ + struct fanotify_event_metadata *metadata, *first = NULL; + struct fanotify_event_info_error *first_info = NULL; + unsigned int total_count = 0; + int event_num = 0; + + for (metadata = (struct fanotify_event_metadata *)buf; + FAN_EVENT_OK(metadata, len); + metadata = FAN_EVENT_NEXT(metadata, len)) { + + event_num++; + struct fanotify_event_info_error *info = get_event_info_error(metadata); + + if (!info) { + tst_res(TFAIL, "Event [%d] missing error info", event_num); + continue; + } + + if (info->error != ex->error && (ex->error2 == 0 || info->error != ex->error2)) { + tst_res(TFAIL, "Event [%d] unexpected errno (%d)", + event_num, info->error); + continue; + } + + if (!first) { + first = metadata; + first_info = info; + } + total_count += info->error_count; + + tst_res(TINFO, "Event [%d]: errno=%d, error_count=%d", + event_num, info->error, info->error_count); + } + + if (first_info) + first_info->error_count = total_count; + + return (first) ? first->event_len : 0; +} + static int check_error_event_info_fid(struct fanotify_event_info_fid *fid, const struct test_case *ex) { struct file_handle *fh = (struct file_handle *) &fid->handle; if (memcmp(&fid->fsid, &ex->fid->fsid, sizeof(fid->fsid))) { - tst_res(TFAIL, "%s: Received bad FSID type (%x...!=%x...)", - ex->name, FSID_VAL_MEMBER(fid->fsid, 0), + tst_res(TFAIL, "Received bad FSID type (%x...!=%x...)", + FSID_VAL_MEMBER(fid->fsid, 0), ex->fid->fsid.val[0]); return 1; } if (fh->handle_type != ex->fid->handle.handle_type) { - tst_res(TFAIL, "%s: Received bad file_handle type (%d!=%d)", - ex->name, fh->handle_type, ex->fid->handle.handle_type); + tst_res(TFAIL, "Received bad file_handle type (%d!=%d)", + fh->handle_type, ex->fid->handle.handle_type); return 1; } if (fh->handle_bytes != ex->fid->handle.handle_bytes) { - tst_res(TFAIL, "%s: Received bad file_handle len (%d!=%d)", - ex->name, fh->handle_bytes, ex->fid->handle.handle_bytes); + tst_res(TFAIL, "Received bad file_handle len (%d!=%d)", + fh->handle_bytes, ex->fid->handle.handle_bytes); return 1; } if (memcmp(fh->f_handle, ex->fid->handle.f_handle, fh->handle_bytes)) { - tst_res(TFAIL, "%s: Received wrong handle. " - "Expected (%x...) got (%x...) ", ex->name, + tst_res(TFAIL, "Received wrong handle. " + "Expected (%x...) got (%x...) ", *(int *)ex->fid->handle.f_handle, *(int *)fh->f_handle); return 1; } @@ -177,14 +220,15 @@ static int check_error_event_info_error(struct fanotify_event_info_error *info_e int fail = 0; if (info_error->error_count != ex->error_count) { - tst_res(TFAIL, "%s: Unexpected error_count (%d!=%d)", - ex->name, info_error->error_count, ex->error_count); + tst_res(TFAIL, "Unexpected error_count (%d!=%d)", + info_error->error_count, ex->error_count); fail++; } - if (info_error->error != ex->error) { - tst_res(TFAIL, "%s: Unexpected error code value (%d!=%d)", - ex->name, info_error->error, ex->error); + if (info_error->error != ex->error && + (ex->error2 == 0 || info_error->error != ex->error2)) { + tst_res(TFAIL, "Unexpected error code value (%d!=%d)", + info_error->error, ex->error); fail++; } @@ -248,19 +292,54 @@ static void check_event(char *buf, size_t len, const struct test_case *ex) static void do_test(unsigned int i) { const struct test_case *tcase = &testcases[i]; - size_t read_len; + size_t read_len = 0; + struct pollfd pfd; + unsigned int accumulated_count = 0; + + tst_res(TINFO, "Test case: %s", tcase->name); SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD|FAN_MARK_FILESYSTEM, FAN_FS_ERROR, AT_FDCWD, MOUNT_PATH); tcase->trigger_error(); - read_len = SAFE_READ(0, fd_notify, event_buf, BUF_SIZE); + pfd.fd = fd_notify; + pfd.events = POLLIN; + + while (accumulated_count < tcase->error_count) { + if (poll(&pfd, 1, 5000) <= 0) { + tst_res(TFAIL, "Timeout waiting for events"); + goto out; + } + + if (BUF_SIZE - read_len < FAN_EVENT_METADATA_LEN) + tst_brk(TBROK, "Insufficient buffer space for next event"); + + char *current_pos = event_buf + read_len; + ssize_t ret = SAFE_READ(0, fd_notify, current_pos, BUF_SIZE - read_len); + + struct fanotify_event_metadata *m = + (struct fanotify_event_metadata *)current_pos; + while (FAN_EVENT_OK(m, ret)) { + struct fanotify_event_info_error *e = get_event_info_error(m); + + if (e) + accumulated_count += e->error_count; + + read_len += m->event_len; + m = FAN_EVENT_NEXT(m, ret); + } + } + + read_len = consolidate_events(event_buf, read_len, tcase); + + check_event(event_buf, read_len, tcase); + +out: SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_REMOVE|FAN_MARK_FILESYSTEM, FAN_FS_ERROR, AT_FDCWD, MOUNT_PATH); - check_event(event_buf, read_len, tcase); /* Unmount and mount the filesystem to get it out of the error state */ SAFE_UMOUNT(MOUNT_PATH); SAFE_MOUNT(tst_device->dev, MOUNT_PATH, tst_device->fs_type, 0, NULL); -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
* [LTP] [PATCH v7] io_submit04: Add test case for RWF_NOWAIT flag 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp ` (2 preceding siblings ...) 2026-03-31 11:18 ` [LTP] [PATCH v7] fanotify22.c: handle multiple asynchronous error events Wei Gao via ltp @ 2026-04-04 1:13 ` Wei Gao via ltp 3 siblings, 0 replies; 22+ messages in thread From: Wei Gao via ltp @ 2026-04-04 1:13 UTC (permalink / raw) To: ltp Fixes: #467 Signed-off-by: Wei Gao <wegao@suse.com> --- v6->v7: - Fix 32bit issue, use TST_PTR_TO_UINT convert buf - Updated the comment header to use the :manpage: - Simplify logic in cleanup() configure.ac | 1 + include/lapi/aio_abi.h | 44 +++++++++ runtest/syscalls | 1 + .../kernel/syscalls/io_submit/.gitignore | 1 + .../kernel/syscalls/io_submit/io_submit04.c | 99 +++++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 include/lapi/aio_abi.h create mode 100644 testcases/kernel/syscalls/io_submit/io_submit04.c diff --git a/configure.ac b/configure.ac index e5d3ce063..812f17d8b 100644 --- a/configure.ac +++ b/configure.ac @@ -173,6 +173,7 @@ AC_CHECK_FUNCS_ONCE([ \ ]) AC_CHECK_FUNCS(mkdtemp,[],AC_MSG_ERROR(mkdtemp() not found!)) +AC_CHECK_MEMBERS([struct iocb.aio_rw_flags],,,[#include <linux/aio_abi.h>]) AC_CHECK_MEMBERS([struct fanotify_event_info_fid.fsid.__val],,,[#include <sys/fanotify.h>]) AC_CHECK_MEMBERS([struct perf_event_mmap_page.aux_head],,,[#include <linux/perf_event.h>]) AC_CHECK_MEMBERS([struct sigaction.sa_sigaction],[],[],[#include <signal.h>]) diff --git a/include/lapi/aio_abi.h b/include/lapi/aio_abi.h new file mode 100644 index 000000000..ac78e5500 --- /dev/null +++ b/include/lapi/aio_abi.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +#ifndef LAPI_AIO_ABI_H__ +#define LAPI_AIO_ABI_H__ + +#include <endian.h> +#include <linux/aio_abi.h> + +#ifndef RWF_NOWAIT +# define RWF_NOWAIT 0x00000008 +#endif + +struct iocb_fallback { + uint64_t aio_data; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t aio_key; + uint32_t aio_rw_flags; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint32_t aio_rw_flags; + uint32_t aio_key; +#else +#error edit for your odd byteorder. +#endif + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; +}; + +#ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS +typedef struct iocb_fallback iocb; +#else +typedef struct iocb iocb; +#endif + +#endif /* LAPI_AIO_ABI_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 6ba0227a8..d72fceb5e 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -699,6 +699,7 @@ io_setup02 io_setup02 io_submit01 io_submit01 io_submit02 io_submit02 io_submit03 io_submit03 +io_submit04 io_submit04 keyctl01 keyctl01 keyctl02 keyctl02 diff --git a/testcases/kernel/syscalls/io_submit/.gitignore b/testcases/kernel/syscalls/io_submit/.gitignore index 60b07970a..abe962e1c 100644 --- a/testcases/kernel/syscalls/io_submit/.gitignore +++ b/testcases/kernel/syscalls/io_submit/.gitignore @@ -1,3 +1,4 @@ /io_submit01 /io_submit02 /io_submit03 +/io_submit04 diff --git a/testcases/kernel/syscalls/io_submit/io_submit04.c b/testcases/kernel/syscalls/io_submit/io_submit04.c new file mode 100644 index 000000000..d68bde909 --- /dev/null +++ b/testcases/kernel/syscalls/io_submit/io_submit04.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Wei Gao <wegao@suse.com> + */ + +/*\ + * Test RWF_NOWAIT support in io_submit(), verifying that an + * asynchronous read operation on a blocking resource (empty pipe) + * will cause -EAGAIN. This is done by checking that io_getevents() + * :manpage:`io_getevents(2)` syscall returns immediately and + * io_event.res is equal to -EAGAIN. + */ + +#include "config.h" +#include "tst_test.h" +#include "lapi/syscalls.h" +#include "lapi/aio_abi.h" + +#define BUF_SIZE 100 + +static int fd[2] = {-1, -1}; +static aio_context_t ctx; +static char *buf; +static iocb *cb; +static iocb **iocbs; + +static void setup(void) +{ + if (tst_syscall(__NR_io_setup, 1, &ctx)) + tst_brk(TBROK | TERRNO, "io_setup failed"); + + SAFE_PIPE(fd); + + cb->aio_fildes = fd[0]; + cb->aio_lio_opcode = IOCB_CMD_PREAD; + cb->aio_buf = TST_PTR_TO_UINT(buf); + cb->aio_offset = 0; + cb->aio_nbytes = BUF_SIZE; + cb->aio_rw_flags = RWF_NOWAIT; + + iocbs[0] = cb; +} + +static void cleanup(void) +{ + if (fd[0] != -1) + SAFE_CLOSE(fd[0]); + + if (fd[1] != -1) + SAFE_CLOSE(fd[1]); + + if (ctx && tst_syscall(__NR_io_destroy, ctx)) + tst_brk(TBROK | TERRNO, "io_destroy() failed"); +} + +static void run(void) +{ + struct io_event evbuf; + struct timespec timeout = { .tv_sec = 1 }; + long nr = 1; + + TEST(tst_syscall(__NR_io_submit, ctx, nr, iocbs)); + + if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) { + tst_brk(TCONF, "RWF_NOWAIT not supported by kernel"); + } else if (TST_RET != nr) { + tst_brk(TBROK | TTERRNO, "io_submit() returns %ld, expected %ld", + TST_RET, nr); + } + + TEST(tst_syscall(__NR_io_getevents, ctx, 1, 1, &evbuf, &timeout)); + + if (TST_RET != 1) { + tst_res(TFAIL | TTERRNO, "io_getevents() failed to get 1 event"); + return; + } + + if (evbuf.res == -EAGAIN) + tst_res(TPASS, "io_getevents() returned EAGAIN on read event"); + else + tst_res(TFAIL, "io_getevents() returned with %s instead of EAGAIN", + strerror(-evbuf.res)); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_kconfigs = (const char *[]) { + "CONFIG_AIO=y", + NULL + }, + .bufs = (struct tst_buffers []) { + {&buf, .size = BUF_SIZE}, + {&cb, .size = sizeof(iocb)}, + {&iocbs, .size = sizeof(iocb *)}, + {}, + } +}; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-04-04 1:14 UTC | newest] Thread overview: 22+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-10-29 1:27 [LTP] [PATCH v1] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp 2024-02-06 15:59 ` Petr Vorel 2025-10-22 2:05 ` [LTP] [PATCH v2] " Wei Gao via ltp 2025-12-18 13:21 ` Andrea Cervesato via ltp 2025-12-24 8:49 ` [LTP] [PATCH v3] " Wei Gao via ltp 2026-01-05 12:53 ` Andrea Cervesato via ltp 2026-01-06 6:26 ` Wei Gao via ltp 2026-01-06 8:39 ` Andrea Cervesato via ltp 2026-01-06 8:39 ` Petr Vorel 2026-01-07 8:53 ` Jan Stancek via ltp 2026-01-07 6:10 ` [LTP] [PATCH v4] " Wei Gao via ltp 2026-02-18 12:21 ` Andrea Cervesato via ltp 2026-03-05 4:41 ` Wei Gao via ltp 2026-03-17 7:43 ` [LTP] [PATCH v5] " Wei Gao via ltp 2026-03-17 9:54 ` Andrea Cervesato via ltp 2026-03-17 11:46 ` [LTP] [PATCH v6] " Wei Gao via ltp 2026-03-20 12:54 ` Andrea Cervesato via ltp 2026-03-27 18:17 ` Petr Vorel 2026-03-30 8:08 ` Wei Gao via ltp 2026-04-04 1:00 ` Wei Gao via ltp 2026-03-31 11:18 ` [LTP] [PATCH v7] fanotify22.c: handle multiple asynchronous error events Wei Gao via ltp 2026-04-04 1:13 ` [LTP] [PATCH v7] io_submit04: Add test case for RWF_NOWAIT flag Wei Gao via ltp
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox