From cd4b6761ea2f504c993ba2b817f152ee0c0dadd4 Mon Sep 17 00:00:00 2001 From: alessandronardin Date: Thu, 20 Jun 2024 11:06:44 +0200 Subject: [PATCH] cpukit/posix/aio*: Corrected aio_return() and aio_error() behaviour Added field to the aio control block to track when a result is retrieved and modified code accordingly. Updated documentation for aio_return() and aio_error(). Updated test psxaio01 to make it compatible with specifications. Closes #5039 --- cpukit/include/aio.h | 42 ++++- cpukit/include/rtems/posix/aio_misc.h | 6 - cpukit/posix/src/aio_error.c | 9 +- cpukit/posix/src/aio_fsync.c | 10 +- cpukit/posix/src/aio_misc.c | 4 +- cpukit/posix/src/aio_read.c | 12 +- cpukit/posix/src/aio_return.c | 17 +- cpukit/posix/src/aio_write.c | 11 +- testsuites/psxtests/psxaio01/init.c | 192 +++++++++------------- testsuites/psxtests/psxaio01/psxaio01.scn | 12 -- 10 files changed, 150 insertions(+), 165 deletions(-) diff --git a/cpukit/include/aio.h b/cpukit/include/aio.h index 3c86547ff2..fbea82ae08 100644 --- a/cpukit/include/aio.h +++ b/cpukit/include/aio.h @@ -71,9 +71,11 @@ extern "C" { /** All requested operations have been canceled */ #define AIO_CANCELED 0 + /** Some operations could not be canceled since they are in progress */ #define AIO_NOTCANCELED 1 -/** + +/** * None of the requested operations could be canceled since * they are already complete */ @@ -81,6 +83,7 @@ extern "C" { /** Calling process is to be suspendes until the operation is complete */ #define LIO_WAIT 0 + /** * Calling process is to continue execution while the operation is performed * and no notification shall be given when the operation is completed @@ -89,13 +92,25 @@ extern "C" { /** No transfer is requested */ #define LIO_NOP 0 + /** Request a read() */ #define LIO_READ 1 + /** Request a write() */ #define LIO_WRITE 2 + /** Needed by aio_fsync() */ #define LIO_SYNC 3 +/* + * Constants to track return status + */ + +/** The aio operation return value has been retrieved */ +#define AIO_RETURNED 0 + +/** The aio operation return value has not been retrieved */ +#define AIO_NOTRETURNED 1 /** * @brief Asynchronous I/O Control Block @@ -122,10 +137,12 @@ struct aiocb { /** @name private */ + /** @brief Field used for aio_return() */ + int return_status; /** @brief Field used for aio_error() */ - int error_code; + int error_code; /** @brief Filed used for aio_return() */ - ssize_t return_value; + ssize_t return_value; }; /** @@ -142,7 +159,7 @@ struct aiocb { * - EAGAIN not enough memory * - EINVAL the starting position of the file is past the maximum offset * for this file. - * + * - EINVAL aiocbp is a NULL pointer */ int aio_read( struct aiocb *aiocbp @@ -160,7 +177,7 @@ int aio_read( * - EBADF FD not opened for write * - EINVAL invalid aio_reqprio or aio_offset or aio_nbytes * - EAGAIN not enough memory - * + * - EINVAL aiocbp is a NULL pointer */ int aio_write( struct aiocb *aiocbp @@ -183,10 +200,13 @@ int lio_listio( * * 6.7.5 Retrieve Error of Asynchronous I/O Operation, P1003.1b-1993, p. 161 * - * @param[in] aiocbp is a pointer to the asynchronous I/O control block + * @param[in,out] aiocbp is a pointer to the asynchronous I/O control block * * @retval 0 The operation has completed succesfully. * @retval EINPROGRESS The operation has not yet completed. + * @retval EINVAL The return status for the request associated with aiocbp + * has already been retrieved. + * @retval EINVAL aiocbp is a NULL pointer. * @return The error status as described for the various operations. */ int aio_error( @@ -200,12 +220,17 @@ int aio_error( * 6.7.6 Retrieve Return Status of Asynchronous I/O Operation, * P1003.1b-1993, p. 162 * - * @param[in] aiocbp is a pointer to the asynchronous I/O control block + * @param[in,out] aiocbp is a pointer to the asynchronous I/O control block * + * @retval -1 The operation returned with an error. errno is set to indicate + * the error,as described for the various operations. + * @retval EINVAL The return status for the request associated with aiocbp + * has already been retrieved. + * @retval EINVAL aiocbp is a NULL pointer. * @return The operation return status, stored in aiocbp->return_value */ ssize_t aio_return( - const struct aiocb *aiocbp + struct aiocb *aiocbp ); /** @@ -258,6 +283,7 @@ int aio_suspend( * by the aiocbp argument is not a valid file descriptor. * - EINVAL A value of op other than O_SYNC was specified. * The current implemetation only supports O_SYNC. + * - EINVAL aiocbp is a NULL pointer. */ int aio_fsync( int op, diff --git a/cpukit/include/rtems/posix/aio_misc.h b/cpukit/include/rtems/posix/aio_misc.h index 9af10a5026..f292000393 100644 --- a/cpukit/include/rtems/posix/aio_misc.h +++ b/cpukit/include/rtems/posix/aio_misc.h @@ -38,7 +38,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #ifndef _AIO_MISC_H #define _AIO_MISC_H @@ -201,11 +200,6 @@ int rtems_aio_remove_req( #define AIO_printf(_x) #endif -#define rtems_aio_set_errno_return_minus_one( _error, _aiocbp ) \ - do { (_aiocbp)->error_code = (_error); \ - (_aiocbp)->return_value = -1; \ - rtems_set_errno_and_return_minus_one(_error);} while(0) - #ifdef __cplusplus } #endif diff --git a/cpukit/posix/src/aio_error.c b/cpukit/posix/src/aio_error.c index e849f89ea0..1a9b92f4b8 100644 --- a/cpukit/posix/src/aio_error.c +++ b/cpukit/posix/src/aio_error.c @@ -45,9 +45,14 @@ #include -int -aio_error( const struct aiocb *aiocbp ) +int aio_error( const struct aiocb *aiocbp ) { + if ( aiocbp == NULL ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( aiocbp->return_status == AIO_RETURNED ) + rtems_set_errno_and_return_minus_one( EINVAL ); + return aiocbp->error_code; } diff --git a/cpukit/posix/src/aio_fsync.c b/cpukit/posix/src/aio_fsync.c index 55ef259469..ca4a1dc2f6 100644 --- a/cpukit/posix/src/aio_fsync.c +++ b/cpukit/posix/src/aio_fsync.c @@ -46,7 +46,6 @@ #include #include - int aio_fsync( int op, struct aiocb *aiocbp @@ -55,8 +54,11 @@ int aio_fsync( rtems_aio_request *req; int mode; + if ( aiocbp == NULL ) + rtems_set_errno_and_return_minus_one( EINVAL ); + if ( op != O_SYNC ) - rtems_aio_set_errno_return_minus_one( EINVAL, aiocbp ); + rtems_set_errno_and_return_minus_one( EINVAL ); mode = fcntl( aiocbp->aio_fildes, F_GETFL ); if ( @@ -65,11 +67,11 @@ int aio_fsync( ((mode & O_ACCMODE) == O_RDWR) ) ) - rtems_aio_set_errno_return_minus_one( EBADF, aiocbp ); + rtems_set_errno_and_return_minus_one( EBADF ); req = malloc( sizeof( rtems_aio_request ) ); if ( req == NULL ) - rtems_aio_set_errno_return_minus_one( EAGAIN, aiocbp ); + rtems_set_errno_and_return_minus_one( EAGAIN ); req->aiocbp = aiocbp; req->aiocbp->aio_lio_opcode = LIO_SYNC; diff --git a/cpukit/posix/src/aio_misc.c b/cpukit/posix/src/aio_misc.c index b14605bf6f..14fe6b7945 100644 --- a/cpukit/posix/src/aio_misc.c +++ b/cpukit/posix/src/aio_misc.c @@ -38,7 +38,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include #include #include @@ -283,6 +282,7 @@ rtems_aio_enqueue( rtems_aio_request *req ) req->policy = policy; req->aiocbp->error_code = EINPROGRESS; req->aiocbp->return_value = 0; + req->aiocbp->return_status = AIO_NOTRETURNED; if ( aio_request_queue.idle_threads == 0 && @@ -515,7 +515,7 @@ static void rtems_aio_handle_helper( rtems_aio_request *req ) req->aiocbp->aio_nbytes, req->aiocbp->aio_offset ); break; - + case LIO_SYNC: AIO_printf( "sync\n" ); result = fsync( req->aiocbp->aio_fildes ); diff --git a/cpukit/posix/src/aio_read.c b/cpukit/posix/src/aio_read.c index 7dbb809ee8..cf206d5317 100644 --- a/cpukit/posix/src/aio_read.c +++ b/cpukit/posix/src/aio_read.c @@ -48,12 +48,14 @@ #include #include - int aio_read( struct aiocb *aiocbp ) { rtems_aio_request *req; int mode; + if ( aiocbp == NULL ) + rtems_set_errno_and_return_minus_one( EINVAL ); + mode = fcntl( aiocbp->aio_fildes, F_GETFL ); if ( !( @@ -61,17 +63,17 @@ int aio_read( struct aiocb *aiocbp ) (( mode&O_ACCMODE ) == O_RDWR ) ) ) - rtems_aio_set_errno_return_minus_one( EBADF, aiocbp ); + rtems_set_errno_and_return_minus_one( EBADF ); if ( aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX ) - rtems_aio_set_errno_return_minus_one( EINVAL, aiocbp ); + rtems_set_errno_and_return_minus_one( EINVAL ); if ( aiocbp->aio_offset < 0 ) - rtems_aio_set_errno_return_minus_one( EINVAL, aiocbp ); + rtems_set_errno_and_return_minus_one( EINVAL ); req = malloc( sizeof( rtems_aio_request ) ); if ( req == NULL ) - rtems_aio_set_errno_return_minus_one( EAGAIN, aiocbp ); + rtems_set_errno_and_return_minus_one( EAGAIN ); req->aiocbp = aiocbp; req->aiocbp->aio_lio_opcode = LIO_READ; diff --git a/cpukit/posix/src/aio_return.c b/cpukit/posix/src/aio_return.c index 356e7d1937..d4189609d9 100644 --- a/cpukit/posix/src/aio_return.c +++ b/cpukit/posix/src/aio_return.c @@ -36,19 +36,26 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include - #include -ssize_t -aio_return( const struct aiocb *aiocbp ) +ssize_t aio_return( struct aiocb *aiocbp ) { - return aiocbp->return_value; + if ( aiocbp == NULL ) + rtems_set_errno_and_return_minus_one( ENOENT ); + + if ( aiocbp->return_status == AIO_RETURNED ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + aiocbp->return_status = AIO_RETURNED; + if ( aiocbp->return_status < 0 ) + rtems_set_errno_and_return_minus_one( aiocbp->error_code ); + else + return aiocbp->return_value; } diff --git a/cpukit/posix/src/aio_write.c b/cpukit/posix/src/aio_write.c index aadbb613c8..27992e7694 100644 --- a/cpukit/posix/src/aio_write.c +++ b/cpukit/posix/src/aio_write.c @@ -51,6 +51,9 @@ aio_write( struct aiocb *aiocbp ) rtems_aio_request *req; int mode; + if ( aiocbp == NULL ) + rtems_set_errno_and_return_minus_one( EINVAL ); + mode = fcntl( aiocbp->aio_fildes, F_GETFL ); if ( !( @@ -58,17 +61,17 @@ aio_write( struct aiocb *aiocbp ) ( ( mode&O_ACCMODE ) == O_RDWR ) ) ) - rtems_aio_set_errno_return_minus_one( EBADF, aiocbp ); + rtems_set_errno_and_return_minus_one( EBADF ); if ( aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX ) - rtems_aio_set_errno_return_minus_one( EINVAL, aiocbp ); + rtems_set_errno_and_return_minus_one( EINVAL ); if ( aiocbp->aio_offset < 0 ) - rtems_aio_set_errno_return_minus_one( EINVAL, aiocbp ); + rtems_set_errno_and_return_minus_one( EINVAL ); req = malloc( sizeof( rtems_aio_request ) ); if ( req == NULL ) - rtems_aio_set_errno_return_minus_one( EAGAIN, aiocbp ); + rtems_set_errno_and_return_minus_one( EAGAIN ); req->aiocbp = aiocbp; req->aiocbp->aio_lio_opcode = LIO_WRITE; diff --git a/testsuites/psxtests/psxaio01/init.c b/testsuites/psxtests/psxaio01/init.c index d9b5c8d54f..f6c29b39cc 100644 --- a/testsuites/psxtests/psxaio01/init.c +++ b/testsuites/psxtests/psxaio01/init.c @@ -47,176 +47,134 @@ const char rtems_test_name[] = "PSXAIO 1"; #define WRONG_FD 404 /* forward declarations to avoid warnings */ -struct aiocb *create_aiocb(int fd); -void free_aiocb(struct aiocb *aiocbp); +struct aiocb *create_aiocb( int fd ); +void free_aiocb( struct aiocb *aiocbp ); -struct aiocb * -create_aiocb (int fd) +struct aiocb *create_aiocb( int fd ) { struct aiocb *aiocbp; - aiocbp = malloc (sizeof (struct aiocb)); - memset (aiocbp, 0, sizeof (struct aiocb)); - aiocbp->aio_buf = malloc (BUFSIZE * sizeof (char)); + aiocbp = malloc( sizeof( struct aiocb ) ); + memset( aiocbp, 0, sizeof( struct aiocb ) ); + aiocbp->aio_buf = malloc( BUFSIZE * sizeof( char ) ); aiocbp->aio_nbytes = BUFSIZE; aiocbp->aio_offset = 0; aiocbp->aio_reqprio = 0; aiocbp->aio_fildes = fd; - return aiocbp; } -void -free_aiocb (struct aiocb *aiocbp) +void free_aiocb( struct aiocb *aiocbp ) { free ((char*) aiocbp->aio_buf); free (aiocbp); } -void * -POSIX_Init (void *argument) +void *POSIX_Init( void *argument ) { int result, fd; struct aiocb *aiocbp; int status; - rtems_aio_init (); + rtems_aio_init(); - status = mkdir ("/tmp", S_IRWXU); - rtems_test_assert (!status); + status = mkdir( "/tmp", S_IRWXU ); + rtems_test_assert( !status ); - fd = open ("/tmp/aio_fildes", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); - rtems_test_assert ( fd != -1); + fd = open( "/tmp/aio_fildes", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO ); + rtems_test_assert( fd != -1 ); TEST_BEGIN(); - puts (" Init: EBADF TESTS "); - - aiocbp = create_aiocb (WRONG_FD); - status = aio_write (aiocbp); - rtems_test_assert (status == -1); + aiocbp = create_aiocb( WRONG_FD ); /* Bad file descriptor */ - puts ("Init: aio_write() - EBADF "); - - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EBADF); - - status = aio_read (aiocbp); - rtems_test_assert (status == -1); - - /* Bad file descriptor */ - puts ("Init: aio_read() - EBADF "); - - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EBADF); - - status = aio_cancel (WRONG_FD, NULL); - rtems_test_assert (status == -1); - - /* Bad file descriptor */ - puts ("Init: aio_cancel() - EBADF "); - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EBADF); + result = aio_write( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EBADF ); - status = aio_fsync (O_SYNC, aiocbp); - rtems_test_assert (status == -1); - /* Bad file descriptor */ - puts ("Init: aio_fsync() - EBADF "); - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EBADF); + result = aio_read( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EBADF ); + + /* Bad file descriptor */ - free_aiocb (aiocbp); + result = aio_cancel( WRONG_FD, NULL ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EBADF ); + + /* Bad file descriptor */ + + result = aio_fsync( O_SYNC, aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EBADF ); + + free_aiocb( aiocbp ); + + aiocbp = create_aiocb( fd ); + aiocbp->aio_offset = -1; /* Invalid offset */ - puts ("Init: aio_write() - EINVAL [aio_offset]"); - aiocbp = create_aiocb (fd); - aiocbp->aio_offset = -1; - status = aio_write (aiocbp); - rtems_test_assert (status == -1); + result = aio_write( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); + /* Invalid offset */ - /* Invalid offset */ - puts ("Init: aio_read() - EINVAL [aio_offset]"); + result = aio_read( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); - status = aio_read (aiocbp); - rtems_test_assert (status == -1); + free_aiocb( aiocbp ); - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); - - free_aiocb (aiocbp); + aiocbp = create_aiocb( fd ); + aiocbp->aio_reqprio = AIO_PRIO_DELTA_MAX + 1; /* Invalid request priority */ - puts ("Init: aio_write() - EINVAL [aio_reqprio]"); - aiocbp = create_aiocb (fd); - aiocbp->aio_reqprio = AIO_PRIO_DELTA_MAX + 1; - status = aio_write (aiocbp); - rtems_test_assert (status == -1); - - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); + result = aio_write( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); /* Invalid request priority */ - puts ("Init: aio_read() - EINVAL [aio_reqprio]"); - status = aio_read (aiocbp); - rtems_test_assert (status == -1); - - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); - - /* Invalid request aio_cancel */ - puts ("Init: aio_cancel() - EINVAL "); - - status = aio_cancel (WRONG_FD, aiocbp); - rtems_test_assert (status == -1); - - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); + result = aio_read( aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); /* Invalid operation to aio_fsync */ - puts ("Init: aio_fsync() - EINVAL "); - status = aio_fsync (-1, aiocbp); - rtems_test_assert (status == -1); - result = aio_return (aiocbp); - rtems_test_assert (result == -1); - status = aio_error (aiocbp); - rtems_test_assert (status == EINVAL); + result = aio_fsync( -1, aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); - free_aiocb (aiocbp); + /* Invalid request aio_cancel */ + + aiocbp->aio_fildes = WRONG_FD; + result = aio_cancel( fd, aiocbp ); + status = errno; + rtems_test_assert( result == -1 ); + rtems_test_assert( status == EINVAL ); + + free_aiocb( aiocbp ); TEST_END(); - close (fd); - rtems_test_exit (0); + close( fd ); + rtems_test_exit( 0 ); return NULL; - } diff --git a/testsuites/psxtests/psxaio01/psxaio01.scn b/testsuites/psxtests/psxaio01/psxaio01.scn index c5ed646360..6306bf6b9b 100644 --- a/testsuites/psxtests/psxaio01/psxaio01.scn +++ b/testsuites/psxtests/psxaio01/psxaio01.scn @@ -1,14 +1,2 @@ *** BEGIN OF TEST PSXAIO 1 *** -Init: EBADF TESTS -Init: aio_write() - EBADF -Init: aio_read() - EBADF -Init: aio_cancel() - EBADF -Init: aio_fsync() - EBADF -Init: aio_write() - EINVAL [aio_offset] -Init: aio_read() - EINVAL [aio_offset] -Init: aio_write() - EINVAL [aio_reqprio] -Init: aio_read() - EINVAL [aio_reqprio] -Init: aio_cancel() - EINVAL -Init: aio_fsync() - EINVAL - *** END OF TEST PSXAIO 1 *** \ No newline at end of file