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
This commit is contained in:
alessandronardin
2024-06-20 11:06:44 +02:00
committed by Amar Takhar
parent c4c3e68790
commit cd4b6761ea
10 changed files with 150 additions and 165 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -45,9 +45,14 @@
#include <rtems/seterr.h>
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;
}

View File

@@ -46,7 +46,6 @@
#include <rtems/posix/aio_misc.h>
#include <rtems/seterr.h>
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;

View File

@@ -38,7 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
@@ -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 );

View File

@@ -48,12 +48,14 @@
#include <stdlib.h>
#include <limits.h>
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;

View File

@@ -36,19 +36,26 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <aio.h>
#include <errno.h>
#include <rtems/seterr.h>
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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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 ***