blob: dea4d5b2b1ebb3a62c00074ef038ffd2d691ea22 [file] [log] [blame]
/*************************************************************************************
*
* Copyright (c) International Business Machines Corp., 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation,
*
* FILE : aio_tio
* USAGE : ./aio_tio
*
* DESCRIPTION : This program will test Asynchronous I/O for 2.5 Kernel infrastructure
* REQUIREMENTS:
* 1) libaio-0.3.92 or up for 2.5 kernal
* 2) glibc 2.1.91 or up
* HISTORY :
* 11/03/2003 Kai Zhao (ltcd3@cn.ibm.com)
*
* CODE COVERAGE:
* 68.3% - fs/aio.c
*
************************************************************************************/
#include "config.h"
#include "common.h"
#include "test.h"
#include <string.h>
#include <errno.h>
#if HAVE_LIBAIO_H
#define AIO_MAXIO 32
#define AIO_BLKSIZE (64*1024)
static int alignment = 512;
static int wait_count = 0;
/*
* write work done
*/
static void work_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
if (res2 != 0) {
io_error("aio write", res2);
}
if (res != iocb->u.c.nbytes) {
fprintf(stderr, "write missed bytes expect %lu got %ld\n",
iocb->u.c.nbytes, res2);
exit(1);
}
wait_count --;
}
/*
* io_wait_run() - wait for an io_event and then call the callback.
*/
int io_wait_run(io_context_t ctx, struct timespec *to)
{
struct io_event events[AIO_MAXIO];
struct io_event *ep;
int ret, n;
/*
* get up to aio_maxio events at a time.
*/
ret = n = io_getevents(ctx, 1, AIO_MAXIO, events, to);
/*
* Call the callback functions for each event.
*/
for (ep = events ; n-- > 0 ; ep++) {
io_callback_t cb = (io_callback_t)ep->data ; struct iocb *iocb = ep->obj ; cb(ctx, iocb, ep->res, ep->res2);
}
return ret;
}
int io_tio(char *pathname, int flag, int n, int operation)
{
int res, fd = 0, i = 0;
void * bufptr = NULL;
off_t offset = 0;
struct timespec timeout;
io_context_t myctx;
struct iocb iocb_array[AIO_MAXIO];
struct iocb *iocbps[AIO_MAXIO];
fd = open (pathname, flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd <= 0) {
printf("open for %s failed: %s\n", pathname, strerror(errno));
return -1;
}
res = io_queue_init(n, &myctx);
//printf (" res = %d \n", res);
for (i = 0 ; i < AIO_MAXIO ; i ++) {
switch (operation) {
case IO_CMD_FSYNC :
case IO_CMD_FDSYNC :
case IO_CMD_PWRITE :
if (posix_memalign (&bufptr, alignment, AIO_BLKSIZE)) {
perror (" posix_memalign failed ");
return -1;
}
memset (bufptr, 0, AIO_BLKSIZE);
io_prep_pwrite (&iocb_array[i], fd, bufptr ,
AIO_BLKSIZE, offset);
io_set_callback(&iocb_array[i], work_done);
iocbps[i] = &iocb_array[i];
offset += AIO_BLKSIZE;
break;
case IO_CMD_PREAD :
if (posix_memalign (&bufptr, alignment, AIO_BLKSIZE)) {
perror (" posix_memalign failed ");
return -1;
}
memset (bufptr, 0, AIO_BLKSIZE);
io_prep_pread (&iocb_array[i], fd, bufptr ,
AIO_BLKSIZE, offset);
io_set_callback(&iocb_array[i], work_done);
iocbps[i] = &iocb_array[i];
offset += AIO_BLKSIZE;
break;
case IO_CMD_POLL :
case IO_CMD_NOOP :
break;
default:
tst_resm (TFAIL,
"Command failed; opcode returned: %d\n",
operation);
return -1;
break;
}
}
do {
res = io_submit(myctx, AIO_MAXIO, iocbps);
} while (res == -EAGAIN);
if (res < 0) {
io_error("io_submit tio", res);
}
/*
* We have submitted all the i/o requests. Wait for at least one to complete
* and call the callbacks.
*/
wait_count = AIO_MAXIO;
timeout.tv_sec = 30;
timeout.tv_nsec = 0;
switch (operation) {
case IO_CMD_PREAD :
case IO_CMD_PWRITE :
{
while (wait_count) {
res = io_wait_run(myctx, &timeout);
if (res < 0)
io_error("io_wait_run", res);
}
}
break;
case IO_CMD_FSYNC :
for (i = 0 ; i < AIO_MAXIO ; i ++) {
res = io_fsync(myctx, iocbps[i], work_done, fd);
if (res < 0) {
io_error("io_fsync write", res);
}
}
break;
case IO_CMD_FDSYNC :
for (i = 0 ; i < AIO_MAXIO ; i ++) {
res = io_fdsync(myctx, iocbps[i], work_done, fd);
if (res < 0) {
io_error("io_fsync write", res);
}
}
break;
}
close (fd);
for (i = 0 ; i < AIO_MAXIO ; i ++) {
if (iocb_array[i].u.c.buf != NULL) {
free (iocb_array[i].u.c.buf);
}
}
io_queue_release (myctx);
return 0;
}
int test_main(void)
{
int status = 0 ;
tst_resm(TINFO, "Running test 1\n");
status = io_tio("file1",
O_TRUNC | O_DIRECT | O_WRONLY | O_CREAT | O_LARGEFILE,
AIO_MAXIO, IO_CMD_PWRITE);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 2\n");
status = io_tio("file1", O_RDONLY | O_DIRECT | O_LARGEFILE,
AIO_MAXIO, IO_CMD_PREAD);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 3\n");
status = io_tio("file1", O_TRUNC | O_RDWR,
AIO_MAXIO, IO_CMD_PWRITE);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 4\n");
status = io_tio("file1", O_RDWR,
AIO_MAXIO, IO_CMD_PREAD);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 5\n");
status = io_tio("file1", O_TRUNC | O_WRONLY,
AIO_MAXIO, IO_CMD_PWRITE);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 6 \n");
status = io_tio("file1", O_RDONLY,
AIO_MAXIO, IO_CMD_PREAD);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 7 \n");
status = io_tio("file2",
O_TRUNC | O_DIRECT | O_WRONLY | O_CREAT | O_LARGEFILE,
AIO_MAXIO, IO_CMD_FSYNC);
if (status) {
return status;
}
tst_resm(TINFO, "Running test 8 \n");
status = io_tio("file2",
O_TRUNC | O_DIRECT | O_WRONLY | O_CREAT | O_LARGEFILE,
AIO_MAXIO, IO_CMD_FDSYNC);
if (status) {
return status;
}
return status;
}
#endif