* [LTP] [PATCH] lio_listio_2-1: Rewrite test
@ 2026-01-15 17:18 Martin Doucha
2026-01-15 22:32 ` Petr Vorel
0 siblings, 1 reply; 3+ messages in thread
From: Martin Doucha @ 2026-01-15 17:18 UTC (permalink / raw)
To: ltp
The test schedules multiple async writes into a file and then hopes that
at least one will block long enough that a variable can be checked before
the completion signal arrives. Use a socket pair instead of file
to force async writes to block indefinitely. Then drain the socket after
the first signal check and wait for the signal.
Add cleanup helper function that will flush socket buffers, free allocated
memory and close the sockets. Also make setup and cleanup simpler
by statically allocating the aiocb structure array.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
Another race condition fix by filling socket pair buffers until they
block. Tested on kernel v4.4 and v6.12.
.../conformance/interfaces/lio_listio/2-1.c | 133 +++++++++++-------
1 file changed, 81 insertions(+), 52 deletions(-)
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/2-1.c b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/2-1.c
index efcd5b3fc..b21c6d04d 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/2-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/2-1.c
@@ -13,30 +13,33 @@
*
* method:
*
- * - open a file for writing
+ * - open a socket pair
* - submit a list of writes to lio_listio in LIO_NOWAIT mode
* - check that upon return some I/Os are still running
+ * - drain the sockets
+ * - check that I/O finish signal was received
*
*/
-#include <sys/stat.h>
#include <aio.h>
#include <errno.h>
-#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/socket.h>
#include "posixtest.h"
#include "tempfile.h"
#define TNAME "lio_listio/2-1.c"
-#define NUM_AIOCBS 256
-#define BUF_SIZE 1024
+#define NUM_AIOCBS 8
+static int fds[2];
+static struct aiocb aiocbs[NUM_AIOCBS];
+static char *bufs;
static volatile int received_all;
static void sigrt2_handler(int signum PTS_ATTRIBUTE_UNUSED,
@@ -46,54 +49,81 @@ static void sigrt2_handler(int signum PTS_ATTRIBUTE_UNUSED,
received_all = 1;
}
-int main(void)
+static void read_all(void)
+{
+ int i, ret;
+
+ for (i = 0; i < NUM_AIOCBS; i++) {
+ if (!aiocbs[i].aio_buf)
+ break;
+
+ ret = aio_error(&aiocbs[i]);
+
+ /* flush written data from the socket */
+ if (ret == 0 || ret == EINPROGRESS) {
+ read(fds[1], (void *)aiocbs[i].aio_buf,
+ aiocbs[i].aio_nbytes);
+ aiocbs[i].aio_buf = NULL;
+ }
+ }
+}
+
+static void cleanup(void)
{
- char tmpfname[PATH_MAX];
- int fd;
+ read_all();
+ free(bufs);
+ close(fds[0]);
+ close(fds[1]);
+}
- struct aiocb *aiocbs[NUM_AIOCBS];
- char *bufs;
+int main(void)
+{
+ struct aiocb *liocbs[NUM_AIOCBS];
struct sigaction action;
struct sigevent event;
int errors = 0;
int ret;
int err;
int i;
+ int bufsize;
+ socklen_t argsize = sizeof(bufsize);
if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
exit(PTS_UNSUPPORTED);
- PTS_GET_TMP_FILENAME(tmpfname, "pts_lio_listio_2_1");
- unlink(tmpfname);
-
- fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
-
- if (fd == -1) {
- printf(TNAME " Error at open(): %s\n", strerror(errno));
- exit(PTS_UNRESOLVED);
+ ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds);
+ if (ret == -1) {
+ printf(TNAME " Error creating sockets(): %s\n",
+ strerror(errno));
+ return PTS_UNRESOLVED;
}
- unlink(tmpfname);
+ ret = getsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &bufsize, &argsize);
+ if (ret == -1) {
+ printf(TNAME " Error reading socket buffer size: %s\n",
+ strerror(errno));
+ cleanup();
+ return PTS_UNRESOLVED;
+ }
- bufs = malloc(NUM_AIOCBS * BUF_SIZE);
+ /* Socket buffer size is twice the maximum message size */
+ bufsize /= 2;
+ bufs = malloc(NUM_AIOCBS * bufsize);
if (bufs == NULL) {
printf(TNAME " Error at malloc(): %s\n", strerror(errno));
- close(fd);
+ cleanup();
exit(PTS_UNRESOLVED);
}
/* Queue up a bunch of aio writes */
for (i = 0; i < NUM_AIOCBS; i++) {
-
- aiocbs[i] = malloc(sizeof(struct aiocb));
- memset(aiocbs[i], 0, sizeof(struct aiocb));
-
- aiocbs[i]->aio_fildes = fd;
- aiocbs[i]->aio_offset = i * BUF_SIZE;
- aiocbs[i]->aio_buf = &bufs[i * BUF_SIZE];
- aiocbs[i]->aio_nbytes = BUF_SIZE;
- aiocbs[i]->aio_lio_opcode = LIO_WRITE;
+ liocbs[i] = &aiocbs[i];
+ aiocbs[i].aio_fildes = fds[0];
+ aiocbs[i].aio_offset = i * bufsize;
+ aiocbs[i].aio_buf = &bufs[i * bufsize];
+ aiocbs[i].aio_nbytes = bufsize;
+ aiocbs[i].aio_lio_opcode = LIO_WRITE;
}
/* Use SIGRTMIN+2 for list completion */
@@ -108,53 +138,52 @@ int main(void)
sigaction(SIGRTMIN + 2, &action, NULL);
/* Submit request list */
- ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);
+ ret = lio_listio(LIO_NOWAIT, liocbs, NUM_AIOCBS, &event);
if (ret) {
printf(TNAME " Error at lio_listio() %d: %s\n", errno,
- strerror(errno));
- for (i = 0; i < NUM_AIOCBS; i++)
- free(aiocbs[i]);
- free(bufs);
- close(fd);
+ strerror(errno));
+ /* Clear the aiocbs or cleanup() will get stuck */
+ memset(aiocbs, 0, NUM_AIOCBS * sizeof(struct aiocb));
+ cleanup();
exit(PTS_FAIL);
}
if (received_all != 0) {
printf(TNAME
- " Error lio_listio() waited for list completion\n");
- for (i = 0; i < NUM_AIOCBS; i++)
- free(aiocbs[i]);
- free(bufs);
- close(fd);
+ " Error lio_listio() signaled completion too early\n");
+ cleanup();
exit(PTS_FAIL);
}
- while (received_all == 0)
+ read_all();
+
+ for (i = 0; i < 5 && !received_all; i++)
sleep(1);
+ if (received_all == 0) {
+ printf(TNAME " Test did not receive I/O completion signal\n");
+ cleanup();
+ exit(PTS_FAIL);
+ }
+
/* Check return code and free things */
for (i = 0; i < NUM_AIOCBS; i++) {
- err = aio_error(aiocbs[i]);
- ret = aio_return(aiocbs[i]);
+ err = aio_error(&aiocbs[i]);
+ ret = aio_return(&aiocbs[i]);
- if ((err != 0) && (ret != BUF_SIZE)) {
+ if ((err != 0) && (ret != bufsize)) {
printf(TNAME " req %d: error = %d - return = %d\n", i,
- err, ret);
+ err, ret);
errors++;
}
-
- free(aiocbs[i]);
}
- free(bufs);
-
- close(fd);
+ cleanup();
if (errors != 0)
exit(PTS_FAIL);
printf(TNAME " PASSED\n");
-
return PTS_PASS;
}
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [LTP] [PATCH] lio_listio_2-1: Rewrite test
2026-01-15 17:18 [LTP] [PATCH] lio_listio_2-1: Rewrite test Martin Doucha
@ 2026-01-15 22:32 ` Petr Vorel
2026-01-16 12:24 ` Petr Vorel
0 siblings, 1 reply; 3+ messages in thread
From: Petr Vorel @ 2026-01-15 22:32 UTC (permalink / raw)
To: Martin Doucha; +Cc: ltp
Hi Martin,
LGTM, thank you!
Reviewed-by: Petr Vorel <pvorel@suse.cz>
> The test schedules multiple async writes into a file and then hopes that
> at least one will block long enough that a variable can be checked before
> the completion signal arrives. Use a socket pair instead of file
> to force async writes to block indefinitely. Then drain the socket after
> the first signal check and wait for the signal.
> Add cleanup helper function that will flush socket buffers, free allocated
> memory and close the sockets. Also make setup and cleanup simpler
> by statically allocating the aiocb structure array.
> Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> ---
> Another race condition fix by filling socket pair buffers until they
> block. Tested on kernel v4.4 and v6.12.
Tested on 6.17. (I was able to trigger "Error lio_listio() waited for list
completion" failure without the patch when running in loop, not with the patch).
Kind regards,
Petr
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [LTP] [PATCH] lio_listio_2-1: Rewrite test
2026-01-15 22:32 ` Petr Vorel
@ 2026-01-16 12:24 ` Petr Vorel
0 siblings, 0 replies; 3+ messages in thread
From: Petr Vorel @ 2026-01-16 12:24 UTC (permalink / raw)
To: Martin Doucha, ltp
Hi Martin,
Thanks, merged!
Kind regards,
Petr
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-01-16 12:24 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-15 17:18 [LTP] [PATCH] lio_listio_2-1: Rewrite test Martin Doucha
2026-01-15 22:32 ` Petr Vorel
2026-01-16 12:24 ` Petr Vorel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox