1/************************************************************************************* 2* 3* Copyright (c) International Business Machines Corp., 2003 4* 5* This program is free software; you can redistribute it and/or modify 6* it under the terms of the GNU General Public License as published by 7* the Free Software Foundation; either version 2 of the License, or 8* (at your option) any later version. 9* 10* This program is distributed in the hope that it will be useful, 11* but WITHOUT ANY WARRANTY; without even the implied warranty of 12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13* the GNU General Public License for more details. 14* 15* You should have received a copy of the GNU General Public License 16* along with this program; if not, write to the Free Software 17* Foundation, 18* 19* FILE : aio_tio 20* USAGE : ./aio_tio 21* 22* DESCRIPTION : This program will test Asynchronous I/O for 2.5 Kernel infrastructure 23* REQUIREMENTS: 24* 1) libaio-0.3.92 or up for 2.5 kernal 25* 2) glibc 2.1.91 or up 26* HISTORY : 27* 11/03/2003 Kai Zhao (ltcd3@cn.ibm.com) 28* 29* CODE COVERAGE: 30* 68.3% - fs/aio.c 31* 32************************************************************************************/ 33 34#include "config.h" 35#include "common.h" 36#include "test.h" 37#include <string.h> 38#include <errno.h> 39 40#if HAVE_LIBAIO_H 41 42#define AIO_MAXIO 32 43#define AIO_BLKSIZE (64*1024) 44 45static int alignment = 512; 46static int wait_count = 0; 47 48/* 49 * write work done 50 */ 51static void work_done(io_context_t ctx, struct iocb *iocb, long res, long res2) 52{ 53 54 if (res2 != 0) { 55 io_error("aio write", res2); 56 } 57 58 if (res != iocb->u.c.nbytes) { 59 fprintf(stderr, "write missed bytes expect %lu got %ld\n", 60 iocb->u.c.nbytes, res2); 61 exit(1); 62 } 63 wait_count--; 64} 65 66/* 67 * io_wait_run() - wait for an io_event and then call the callback. 68 */ 69int io_wait_run(io_context_t ctx, struct timespec *to) 70{ 71 struct io_event events[AIO_MAXIO]; 72 struct io_event *ep; 73 int ret, n; 74 75 /* 76 * get up to aio_maxio events at a time. 77 */ 78 ret = n = io_getevents(ctx, 1, AIO_MAXIO, events, to); 79 80 /* 81 * Call the callback functions for each event. 82 */ 83 for (ep = events; n-- > 0; ep++) { 84 io_callback_t cb = (io_callback_t) ep->data; 85 struct iocb *iocb = ep->obj; 86 cb(ctx, iocb, ep->res, ep->res2); 87 } 88 return ret; 89} 90 91int io_tio(char *pathname, int flag, int n, int operation) 92{ 93 int res, fd = 0, i = 0; 94 void *bufptr = NULL; 95 off_t offset = 0; 96 struct timespec timeout; 97 98 io_context_t myctx; 99 struct iocb iocb_array[AIO_MAXIO]; 100 struct iocb *iocbps[AIO_MAXIO]; 101 102 fd = open(pathname, flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 103 if (fd <= 0) { 104 printf("open for %s failed: %s\n", pathname, strerror(errno)); 105 return -1; 106 } 107 108 res = io_queue_init(n, &myctx); 109 //printf (" res = %d \n", res); 110 111 for (i = 0; i < AIO_MAXIO; i++) { 112 113 switch (operation) { 114 case IO_CMD_PWRITE: 115 if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) { 116 perror(" posix_memalign failed "); 117 return -1; 118 } 119 memset(bufptr, 0, AIO_BLKSIZE); 120 121 io_prep_pwrite(&iocb_array[i], fd, bufptr, 122 AIO_BLKSIZE, offset); 123 io_set_callback(&iocb_array[i], work_done); 124 iocbps[i] = &iocb_array[i]; 125 offset += AIO_BLKSIZE; 126 127 break; 128 case IO_CMD_PREAD: 129 if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) { 130 perror(" posix_memalign failed "); 131 return -1; 132 } 133 memset(bufptr, 0, AIO_BLKSIZE); 134 135 io_prep_pread(&iocb_array[i], fd, bufptr, 136 AIO_BLKSIZE, offset); 137 io_set_callback(&iocb_array[i], work_done); 138 iocbps[i] = &iocb_array[i]; 139 offset += AIO_BLKSIZE; 140 break; 141 case IO_CMD_POLL: 142 case IO_CMD_NOOP: 143 break; 144 default: 145 tst_resm(TFAIL, 146 "Command failed; opcode returned: %d\n", 147 operation); 148 return -1; 149 break; 150 } 151 } 152 153 do { 154 res = io_submit(myctx, AIO_MAXIO, iocbps); 155 } while (res == -EAGAIN); 156 if (res < 0) { 157 io_error("io_submit tio", res); 158 } 159 160 /* 161 * We have submitted all the i/o requests. Wait for at least one to complete 162 * and call the callbacks. 163 */ 164 wait_count = AIO_MAXIO; 165 166 timeout.tv_sec = 30; 167 timeout.tv_nsec = 0; 168 169 switch (operation) { 170 case IO_CMD_PREAD: 171 case IO_CMD_PWRITE: 172 { 173 while (wait_count) { 174 res = io_wait_run(myctx, &timeout); 175 if (res < 0) 176 io_error("io_wait_run", res); 177 } 178 } 179 break; 180 } 181 182 close(fd); 183 184 for (i = 0; i < AIO_MAXIO; i++) { 185 if (iocb_array[i].u.c.buf != NULL) { 186 free(iocb_array[i].u.c.buf); 187 } 188 } 189 190 io_queue_release(myctx); 191 192 return 0; 193} 194 195int test_main(void) 196{ 197 int status = 0; 198 199 tst_resm(TINFO, "Running test 1\n"); 200 status = io_tio("file1", 201 O_TRUNC | O_DIRECT | O_WRONLY | O_CREAT | O_LARGEFILE, 202 AIO_MAXIO, IO_CMD_PWRITE); 203 if (status) { 204 return status; 205 } 206 207 tst_resm(TINFO, "Running test 2\n"); 208 status = io_tio("file1", O_RDONLY | O_DIRECT | O_LARGEFILE, 209 AIO_MAXIO, IO_CMD_PREAD); 210 if (status) { 211 return status; 212 } 213 214 tst_resm(TINFO, "Running test 3\n"); 215 status = io_tio("file1", O_TRUNC | O_RDWR, AIO_MAXIO, IO_CMD_PWRITE); 216 if (status) { 217 return status; 218 } 219 220 tst_resm(TINFO, "Running test 4\n"); 221 status = io_tio("file1", O_RDWR, AIO_MAXIO, IO_CMD_PREAD); 222 if (status) { 223 return status; 224 } 225 226 tst_resm(TINFO, "Running test 5\n"); 227 status = io_tio("file1", O_TRUNC | O_WRONLY, AIO_MAXIO, IO_CMD_PWRITE); 228 if (status) { 229 return status; 230 } 231 232 tst_resm(TINFO, "Running test 6 \n"); 233 status = io_tio("file1", O_RDONLY, AIO_MAXIO, IO_CMD_PREAD); 234 if (status) { 235 return status; 236 } 237 238 return status; 239} 240 241#endif 242