2015-08-26 15:49:07 +03:00
/*
2016-01-06 14:27:15 +03:00
* Copyright ( c ) 2015 - 2016 Dmitry V . Levin < ldv @ altlinux . org >
2015-08-26 15:49:07 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2016-01-02 16:28:43 +03:00
# include "tests.h"
2015-08-26 20:48:40 +03:00
# include <assert.h>
# include <errno.h>
2016-01-11 05:20:04 +03:00
# include <fcntl.h>
2015-08-26 15:49:07 +03:00
# include <inttypes.h>
# include <stdio.h>
2015-12-16 05:00:01 +03:00
# include <time.h>
2015-08-26 15:49:07 +03:00
# include <unistd.h>
# include <sys/syscall.h>
# if defined __NR_io_setup \
& & defined __NR_io_submit \
& & defined __NR_io_getevents \
2015-08-26 20:48:40 +03:00
& & defined __NR_io_cancel \
2015-08-26 15:49:07 +03:00
& & defined __NR_io_destroy
# include <linux / aio_abi.h>
int
main ( void )
{
2016-01-14 01:06:18 +03:00
const unsigned int sizeof_data0 = 4096 ;
const unsigned int sizeof_data1 = 8192 ;
void * data0 = tail_alloc ( sizeof_data0 ) ;
void * data1 = tail_alloc ( sizeof_data1 ) ;
2015-08-26 15:49:07 +03:00
2016-01-14 01:06:18 +03:00
const struct iocb proto_cb [ ] = {
2015-08-26 15:49:07 +03:00
{
2015-08-26 20:48:40 +03:00
. aio_data = 0xfeedface11111111 ,
2015-08-26 15:49:07 +03:00
. aio_reqprio = 11 ,
. aio_buf = ( unsigned long ) data0 ,
2015-08-26 20:48:40 +03:00
. aio_offset = 0xdeface1facefeed ,
2016-01-14 01:06:18 +03:00
. aio_nbytes = sizeof_data0
2015-08-26 15:49:07 +03:00
} ,
{
2015-08-26 20:48:40 +03:00
. aio_data = 0xfeedface22222222 ,
2015-08-26 15:49:07 +03:00
. aio_reqprio = 22 ,
. aio_buf = ( unsigned long ) data1 ,
2015-08-26 20:48:40 +03:00
. aio_offset = 0xdeface2cafef00d ,
2016-01-14 01:06:18 +03:00
. aio_nbytes = sizeof_data1
2015-08-26 15:49:07 +03:00
}
} ;
2016-01-14 01:06:18 +03:00
const struct iocb * cb = tail_memdup ( proto_cb , sizeof ( proto_cb ) ) ;
const struct iovec proto_iov0 [ ] = {
2015-08-26 20:48:40 +03:00
{
. iov_base = data0 ,
2016-01-14 01:06:18 +03:00
. iov_len = sizeof_data0 / 4
2015-08-26 20:48:40 +03:00
} ,
{
2016-01-14 01:06:18 +03:00
. iov_base = data0 + sizeof_data0 / 4 ,
. iov_len = sizeof_data0 / 4 * 3
2015-08-26 20:48:40 +03:00
} ,
} ;
2016-01-14 01:06:18 +03:00
const struct iovec * iov0 = tail_memdup ( proto_iov0 , sizeof ( proto_iov0 ) ) ;
const struct iovec proto_iov1 [ ] = {
2015-08-26 20:48:40 +03:00
{
. iov_base = data1 ,
2016-01-14 01:06:18 +03:00
. iov_len = sizeof_data1 / 4
2015-08-26 20:48:40 +03:00
} ,
{
2016-01-14 01:06:18 +03:00
. iov_base = data1 + sizeof_data1 / 4 ,
. iov_len = sizeof_data1 / 4 * 3
2015-08-26 20:48:40 +03:00
} ,
} ;
2016-01-14 01:06:18 +03:00
const struct iovec * iov1 = tail_memdup ( proto_iov1 , sizeof ( proto_iov1 ) ) ;
const struct iocb proto_cbv [ ] = {
2015-08-26 20:48:40 +03:00
{
. aio_data = 0xfeed11111111face ,
. aio_lio_opcode = 7 ,
. aio_reqprio = 111 ,
2016-01-14 01:06:18 +03:00
. aio_buf = ( unsigned long ) iov0 ,
2015-08-26 20:48:40 +03:00
. aio_offset = 0xdeface1facefeed ,
2016-01-14 01:06:18 +03:00
. aio_nbytes = ARRAY_SIZE ( proto_iov0 )
2015-08-26 20:48:40 +03:00
} ,
{
. aio_data = 0xfeed22222222face ,
. aio_lio_opcode = 7 ,
. aio_reqprio = 222 ,
2016-01-14 01:06:18 +03:00
. aio_buf = ( unsigned long ) iov1 ,
2015-08-26 20:48:40 +03:00
. aio_offset = 0xdeface2cafef00d ,
2016-01-14 01:06:18 +03:00
. aio_nbytes = ARRAY_SIZE ( proto_iov1 )
2015-08-26 20:48:40 +03:00
}
} ;
2016-01-14 01:06:18 +03:00
const struct iocb * cbv = tail_memdup ( proto_cbv , sizeof ( proto_cbv ) ) ;
const struct iocb proto_cbc = {
2015-08-26 20:48:40 +03:00
. aio_data = 0xdeadbeefbadc0ded ,
. aio_reqprio = 99 ,
. aio_fildes = - 42
} ;
2016-01-14 01:06:18 +03:00
const struct iocb * cbc = tail_memdup ( & proto_cbc , sizeof ( proto_cbc ) ) ;
2015-08-26 15:49:07 +03:00
2016-01-14 01:06:18 +03:00
const long proto_cbs [ ] = {
( long ) & cb [ 0 ] , ( long ) & cb [ 1 ]
2015-08-26 15:49:07 +03:00
} ;
2016-01-14 01:06:18 +03:00
const long * cbs = tail_memdup ( proto_cbs , sizeof ( proto_cbs ) ) ;
const long proto_cbvs [ ] = {
2015-08-26 20:48:40 +03:00
( long ) & cbv [ 0 ] , ( long ) & cbv [ 1 ] ,
} ;
2016-01-14 01:06:18 +03:00
const long * cbvs = tail_memdup ( proto_cbvs , sizeof ( proto_cbvs ) ) ;
unsigned long * ctx = tail_alloc ( sizeof ( unsigned long ) ) ;
* ctx = 0 ;
2015-08-26 15:49:07 +03:00
2016-01-14 01:06:18 +03:00
const unsigned int nr = ARRAY_SIZE ( proto_cb ) ;
2015-08-26 15:49:07 +03:00
const unsigned long lnr = ( unsigned long ) ( 0xdeadbeef00000000ULL | nr ) ;
2016-01-14 01:06:18 +03:00
const struct io_event * ev = tail_alloc ( nr * sizeof ( struct io_event ) ) ;
const struct timespec proto_ts = { . tv_nsec = 123456789 } ;
const struct timespec * ts = tail_memdup ( & proto_ts , sizeof ( proto_ts ) ) ;
2015-08-26 15:49:07 +03:00
( void ) close ( 0 ) ;
if ( open ( " /dev/zero " , O_RDONLY ) )
2016-01-06 14:27:15 +03:00
perror_msg_and_skip ( " open: %s " , " /dev/zero " ) ;
2015-08-26 15:49:07 +03:00
2016-01-14 01:06:18 +03:00
if ( syscall ( __NR_io_setup , lnr , ctx ) )
2016-01-06 14:27:15 +03:00
perror_msg_and_skip ( " io_setup " ) ;
2016-01-14 01:06:18 +03:00
printf ( " io_setup(%u, [%lu]) = 0 \n " , nr , * ctx ) ;
2015-08-26 15:49:07 +03:00
2016-01-14 01:06:18 +03:00
if ( syscall ( __NR_io_submit , * ctx , nr , cbs ) ! = ( long ) nr )
2016-01-06 14:27:15 +03:00
perror_msg_and_skip ( " io_submit " ) ;
2015-08-26 15:49:07 +03:00
printf ( " io_submit(%lu, %u, [ "
2015-08-26 20:48:40 +03:00
" {data=%#llx, pread, reqprio=11, fildes=0, "
2015-08-26 15:49:07 +03:00
" buf=%p, nbytes=%u, offset=%lld}, "
2015-08-26 20:48:40 +03:00
" {data=%#llx, pread, reqprio=22, fildes=0, "
2015-08-26 15:49:07 +03:00
" buf=%p, nbytes=%u, offset=%lld} "
" ]) = %u \n " ,
2016-01-14 01:06:18 +03:00
* ctx , nr ,
2015-08-26 15:49:07 +03:00
( unsigned long long ) cb [ 0 ] . aio_data , data0 ,
2016-01-14 01:06:18 +03:00
sizeof_data0 , ( long long ) cb [ 0 ] . aio_offset ,
2015-08-26 15:49:07 +03:00
( unsigned long long ) cb [ 1 ] . aio_data , data1 ,
2016-01-14 01:06:18 +03:00
sizeof_data1 , ( long long ) cb [ 1 ] . aio_offset ,
2015-08-26 15:49:07 +03:00
nr ) ;
2016-01-14 01:06:18 +03:00
assert ( syscall ( __NR_io_getevents , * ctx , nr , nr + 1 , ev , ts ) = = ( long ) nr ) ;
2015-08-26 15:49:07 +03:00
printf ( " io_getevents(%lu, %u, %u, [ "
" {data=%#llx, obj=%p, res=%u, res2=0}, "
" {data=%#llx, obj=%p, res=%u, res2=0} "
" ], {0, 123456789}) = %u \n " ,
2016-01-14 01:06:18 +03:00
* ctx , nr , nr + 1 ,
( unsigned long long ) cb [ 0 ] . aio_data , & cb [ 0 ] , sizeof_data0 ,
( unsigned long long ) cb [ 1 ] . aio_data , & cb [ 1 ] , sizeof_data1 ,
2015-08-26 15:49:07 +03:00
nr ) ;
2016-01-14 01:06:18 +03:00
assert ( syscall ( __NR_io_cancel , * ctx , cbc , ev ) = = - 1 & & EINVAL = = errno ) ;
2015-08-26 20:48:40 +03:00
printf ( " io_cancel(%lu, {data=%#llx, pread, reqprio=99, fildes=-42}, %p) "
2016-01-06 14:27:15 +03:00
" = -1 EINVAL (%m) \n " ,
2016-01-14 01:06:18 +03:00
* ctx , ( unsigned long long ) cbc - > aio_data , ev ) ;
2015-08-26 20:48:40 +03:00
2016-01-14 01:06:18 +03:00
if ( syscall ( __NR_io_submit , * ctx , nr , cbvs ) ! = ( long ) nr )
2016-01-06 14:27:15 +03:00
perror_msg_and_skip ( " io_submit " ) ;
2015-08-26 20:48:40 +03:00
printf ( " io_submit(%lu, %u, [ "
" {data=%#llx, preadv, reqprio=%hd, fildes=0, "
" iovec=[{%p, %u}, {%p, %u}], offset=%lld}, "
" {data=%#llx, preadv, reqprio=%hd, fildes=0, "
" iovec=[{%p, %u}, {%p, %u}], offset=%lld} "
" ]) = %u \n " ,
2016-01-14 01:06:18 +03:00
* ctx , nr ,
2015-08-26 20:48:40 +03:00
( unsigned long long ) cbv [ 0 ] . aio_data , cbv [ 0 ] . aio_reqprio ,
iov0 [ 0 ] . iov_base , ( unsigned int ) iov0 [ 0 ] . iov_len ,
iov0 [ 1 ] . iov_base , ( unsigned int ) iov0 [ 1 ] . iov_len ,
( long long ) cbv [ 0 ] . aio_offset ,
( unsigned long long ) cbv [ 1 ] . aio_data , cbv [ 1 ] . aio_reqprio ,
iov1 [ 0 ] . iov_base , ( unsigned int ) iov1 [ 0 ] . iov_len ,
iov1 [ 1 ] . iov_base , ( unsigned int ) iov1 [ 1 ] . iov_len ,
( long long ) cbv [ 1 ] . aio_offset ,
nr ) ;
2016-01-14 01:06:18 +03:00
assert ( syscall ( __NR_io_destroy , * ctx ) = = 0 ) ;
printf ( " io_destroy(%lu) = 0 \n " , * ctx ) ;
2015-08-26 15:49:07 +03:00
puts ( " +++ exited with 0 +++ " ) ;
return 0 ;
}
# else
2016-01-06 14:27:15 +03:00
SKIP_MAIN_UNDEFINED ( " __NR_io_* " )
2015-08-26 15:49:07 +03:00
# endif