11/*
22 * Copyright (c) 2004, Bull SA. All rights reserved.
3+ * Copyright (c) 2025 SUSE LLC
34 * Created by: Laurent.Vivier@bull.net
45 * This file is licensed under the GPL license. For the full content
56 * of this license, see the COPYING file at the top level of this
1314 *
1415 * method:
1516 *
16- * - open a file for writing
17+ * - open a socket pair
1718 * - submit a list of writes to lio_listio in LIO_NOWAIT mode
1819 * - check that upon return some I/Os are still running
20+ * - drain the sockets
21+ * - check that I/O finish signal was received
1922 *
2023 */
2124
22- #include <sys/stat.h>
2325#include <aio.h>
2426#include <errno.h>
25- #include <fcntl.h>
2627#include <signal.h>
2728#include <stdio.h>
2829#include <stdlib.h>
2930#include <string.h>
3031#include <unistd.h>
32+ #include <sys/socket.h>
3133
3234#include "posixtest.h"
3335#include "tempfile.h"
3436
3537#define TNAME "lio_listio/2-1.c"
3638
37- #define NUM_AIOCBS 256
38- #define BUF_SIZE 1024
39+ #define NUM_AIOCBS 8
3940
41+ static int fds [2 ];
42+ static struct aiocb aiocbs [NUM_AIOCBS ];
43+ static char * bufs ;
4044static volatile int received_all ;
4145
4246static void sigrt2_handler (int signum PTS_ATTRIBUTE_UNUSED ,
@@ -46,54 +50,81 @@ static void sigrt2_handler(int signum PTS_ATTRIBUTE_UNUSED,
4650 received_all = 1 ;
4751}
4852
49- int main (void )
53+ static void read_all (void )
54+ {
55+ int i , ret ;
56+
57+ for (i = 0 ; i < NUM_AIOCBS ; i ++ ) {
58+ if (!aiocbs [i ].aio_buf )
59+ break ;
60+
61+ ret = aio_error (& aiocbs [i ]);
62+
63+ /* flush written data from the socket */
64+ if (ret == 0 || ret == EINPROGRESS ) {
65+ read (fds [1 ], (void * )aiocbs [i ].aio_buf ,
66+ aiocbs [i ].aio_nbytes );
67+ aiocbs [i ].aio_buf = NULL ;
68+ }
69+ }
70+ }
71+
72+ static void cleanup (void )
5073{
51- char tmpfname [PATH_MAX ];
52- int fd ;
74+ read_all ();
75+ free (bufs );
76+ close (fds [0 ]);
77+ close (fds [1 ]);
78+ }
5379
54- struct aiocb * aiocbs [NUM_AIOCBS ];
55- char * bufs ;
80+ int main (void )
81+ {
82+ struct aiocb * liocbs [NUM_AIOCBS ];
5683 struct sigaction action ;
5784 struct sigevent event ;
5885 int errors = 0 ;
5986 int ret ;
6087 int err ;
6188 int i ;
89+ int bufsize ;
90+ socklen_t argsize = sizeof (bufsize );
6291
6392 if (sysconf (_SC_ASYNCHRONOUS_IO ) < 200112L )
6493 exit (PTS_UNSUPPORTED );
6594
66- PTS_GET_TMP_FILENAME (tmpfname , "pts_lio_listio_2_1" );
67- unlink (tmpfname );
68-
69- fd = open (tmpfname , O_CREAT | O_RDWR | O_EXCL , S_IRUSR | S_IWUSR );
70-
71- if (fd == -1 ) {
72- printf (TNAME " Error at open(): %s\n" , strerror (errno ));
73- exit (PTS_UNRESOLVED );
95+ ret = socketpair (AF_UNIX , SOCK_DGRAM , 0 , fds );
96+ if (ret == -1 ) {
97+ printf (TNAME " Error creating sockets(): %s\n" ,
98+ strerror (errno ));
99+ return PTS_UNRESOLVED ;
74100 }
75101
76- unlink (tmpfname );
102+ ret = getsockopt (fds [0 ], SOL_SOCKET , SO_SNDBUF , & bufsize , & argsize );
103+ if (ret == -1 ) {
104+ printf (TNAME " Error reading socket buffer size: %s\n" ,
105+ strerror (errno ));
106+ cleanup ();
107+ return PTS_UNRESOLVED ;
108+ }
77109
78- bufs = malloc (NUM_AIOCBS * BUF_SIZE );
110+ /* Socket buffer size is twice the maximum message size */
111+ bufsize /= 2 ;
112+ bufs = malloc (NUM_AIOCBS * bufsize );
79113
80114 if (bufs == NULL ) {
81115 printf (TNAME " Error at malloc(): %s\n" , strerror (errno ));
82- close ( fd );
116+ cleanup ( );
83117 exit (PTS_UNRESOLVED );
84118 }
85119
86120 /* Queue up a bunch of aio writes */
87121 for (i = 0 ; i < NUM_AIOCBS ; i ++ ) {
88-
89- aiocbs [i ] = malloc (sizeof (struct aiocb ));
90- memset (aiocbs [i ], 0 , sizeof (struct aiocb ));
91-
92- aiocbs [i ]-> aio_fildes = fd ;
93- aiocbs [i ]-> aio_offset = i * BUF_SIZE ;
94- aiocbs [i ]-> aio_buf = & bufs [i * BUF_SIZE ];
95- aiocbs [i ]-> aio_nbytes = BUF_SIZE ;
96- aiocbs [i ]-> aio_lio_opcode = LIO_WRITE ;
122+ liocbs [i ] = & aiocbs [i ];
123+ aiocbs [i ].aio_fildes = fds [0 ];
124+ aiocbs [i ].aio_offset = i * bufsize ;
125+ aiocbs [i ].aio_buf = & bufs [i * bufsize ];
126+ aiocbs [i ].aio_nbytes = bufsize ;
127+ aiocbs [i ].aio_lio_opcode = LIO_WRITE ;
97128 }
98129
99130 /* Use SIGRTMIN+2 for list completion */
@@ -108,53 +139,52 @@ int main(void)
108139 sigaction (SIGRTMIN + 2 , & action , NULL );
109140
110141 /* Submit request list */
111- ret = lio_listio (LIO_NOWAIT , aiocbs , NUM_AIOCBS , & event );
142+ ret = lio_listio (LIO_NOWAIT , liocbs , NUM_AIOCBS , & event );
112143
113144 if (ret ) {
114145 printf (TNAME " Error at lio_listio() %d: %s\n" , errno ,
115- strerror (errno ));
116- for (i = 0 ; i < NUM_AIOCBS ; i ++ )
117- free (aiocbs [i ]);
118- free (bufs );
119- close (fd );
146+ strerror (errno ));
147+ /* Clear the aiocbs or cleanup() will get stuck */
148+ memset (aiocbs , 0 , NUM_AIOCBS * sizeof (struct aiocb ));
149+ cleanup ();
120150 exit (PTS_FAIL );
121151 }
122152
123153 if (received_all != 0 ) {
124154 printf (TNAME
125- " Error lio_listio() waited for list completion\n" );
126- for (i = 0 ; i < NUM_AIOCBS ; i ++ )
127- free (aiocbs [i ]);
128- free (bufs );
129- close (fd );
155+ " Error lio_listio() signaled completion too early\n" );
156+ cleanup ();
130157 exit (PTS_FAIL );
131158 }
132159
133- while (received_all == 0 )
160+ read_all ();
161+
162+ for (i = 0 ; i < 5 && !received_all ; i ++ )
134163 sleep (1 );
135164
165+ if (received_all == 0 ) {
166+ printf (TNAME " Test did not receive I/O completion signal\n" );
167+ cleanup ();
168+ exit (PTS_FAIL );
169+ }
170+
136171 /* Check return code and free things */
137172 for (i = 0 ; i < NUM_AIOCBS ; i ++ ) {
138- err = aio_error (aiocbs [i ]);
139- ret = aio_return (aiocbs [i ]);
173+ err = aio_error (& aiocbs [i ]);
174+ ret = aio_return (& aiocbs [i ]);
140175
141- if ((err != 0 ) && (ret != BUF_SIZE )) {
176+ if ((err != 0 ) && (ret != bufsize )) {
142177 printf (TNAME " req %d: error = %d - return = %d\n" , i ,
143- err , ret );
178+ err , ret );
144179 errors ++ ;
145180 }
146-
147- free (aiocbs [i ]);
148181 }
149182
150- free (bufs );
151-
152- close (fd );
183+ cleanup ();
153184
154185 if (errors != 0 )
155186 exit (PTS_FAIL );
156187
157188 printf (TNAME " PASSED\n" );
158-
159189 return PTS_PASS ;
160190}
0 commit comments