/************************************************************************************* * * 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> #ifdef HAVE_LIBAIO #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_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; } 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; } return status; } #endif