/* * aio_bug.c * * Copyright (C) 2014, Dan Aloni, Kernelim Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_IOS 128 const int max_events = 32; const int io_size = 0x1000; io_context_t io_ctx; struct iocb io[MAX_IOS]; struct iocb *iops[MAX_IOS]; struct iovec iovecs[MAX_IOS]; struct io_event events[MAX_IOS]; char *data; long submitted = 0; long completed = 0; long pending = 0; void prune(void) { int ret; ret = io_getevents(io_ctx, pending, MAX_IOS, events, NULL); if (ret > 0) { printf("Completed: %d\n", ret); completed += ret; pending -= ret; } } int main(int argc, char **argv) { int ret; int fd; const char *filename = "aio_bug_temp"; long i, to_submit; struct iocb **iocb_sub; ret = io_setup(max_events, &io_ctx); assert(!ret); unlink(filename); fd = open(filename, O_CREAT | O_RDWR | O_DIRECT, 0644); assert(fd >= 0); ret = ftruncate(fd, MAX_IOS * io_size); assert(!ret); data = mmap(NULL, io_size * MAX_IOS, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); assert(data != MAP_FAILED); for (i = 0; i < MAX_IOS; i++) { iops[i] = &io[i]; io[i].data = io; iovecs[i].iov_base = &data[io_size * i]; iovecs[i].iov_len = io_size; io_prep_preadv(&io[i], fd, &iovecs[i], 1, 0); } to_submit = MAX_IOS; iocb_sub = iops; while (submitted < MAX_IOS) { printf("Submitting: %ld\n", to_submit); ret = io_submit(io_ctx, to_submit, iocb_sub); if (ret >= 0) { printf("Submitted: %d\n", ret); submitted += ret; iocb_sub += ret; pending += ret; to_submit -= ret; } else { if (ret == -EAGAIN) { printf("Submitted too much, that's okay\n"); prune(); } } } prune(); io_destroy(io_ctx); close(fd); printf("Verifying...\n"); assert(completed == submitted); printf("OK\n"); return 0; } /* * * Good output: * * Submitting: 128 * Submitted: 126 * Submitting: 2 * Submitted too much, that's okay * Completed: 126 * Submitting: 2 * Submitted: 2 * Completed: 2 * Verifying... * OK * * Bad output: * * Submitting: 128 * Submitted: 128 * * */