int aio_read_random(char* file_name) { int ret = 0; int fd = -1; fd = ::open(file_name, O_RDONLY); fprintf(stdout, "open %s, fd %d\n", file_name, fd); int64_t file_length = ::lseek(fd, 0, SEEK_END); int piece_num = (file_length + PIECE_LEN - 1)/ PIECE_LEN; int bitfield_size = (piece_num + 8 - 1)/8; u_int8_t* bitfield = (u_int8_t*)malloc(bitfield_size); memset(bitfield, 0, bitfield_size); fprintf(stdout, "file_length=%ld, piece_num=%d, bitfield_size=%d\n", file_length, piece_num, bitfield_size); io_context_t myctx; memset(&myctx, 0, sizeof(myctx)); io_queue_init(AIO_MAXIO, &myctx); while(1) { // read piece by random int piece_index = rand_index(piece_num); int piece_pos = bitfield_find_unset(bitfield, piece_num, piece_index); if(piece_pos == -1) { break; } //printf("read piece=%d\n", piece_pos); struct iocb* io2 = (struct iocb*)malloc(sizeof(struct iocb)); memset(io2, 0, sizeof(struct iocb)); u_int8_t* buff = NULL; posix_memalign((void **)&buff, getpagesize(), PIECE_LEN); io_prep_pread(io2, fd, buff, PIECE_LEN, PIECE_LEN*piece_pos); io2->data = (void*)piece_pos; io_submit(myctx, 1, &io2); struct io_event events[AIO_MAXIO]; int num = io_getevents(myctx, 0, AIO_MAXIO, events, NULL); //printf("io_request completed %d\n", num); for(int i=0;i<num;i++) { struct iocb *objp = events[i].obj; int finish_piece_pos = (int)(long)objp->data; //printf("done_piece=%d, res=%ld, res2=%ld\n", finish_piece_pos, events[i].res, events[i].res2); //cb(myctx, io2, events[i].res, events[i].res2); bitfield_set_one(bitfield, piece_num, finish_piece_pos); free(objp->u.c.buf); free(objp); } } close(fd); fd = -1; return 0; }
int file_async_init(void) { unsigned int i; if (file_io_mode != FILE_IO_MODE_ASYNC) return 0; file_async_backlog = sb_get_value_int("file-async-backlog"); if (file_async_backlog <= 0) { log_text(LOG_FATAL, "Invalid value of file-async-backlog: %d", file_async_backlog); return 1; } aio_ctxts = (sb_aio_context_t *)calloc(sb_globals.num_threads, sizeof(sb_aio_context_t)); for (i = 0; i < sb_globals.num_threads; i++) { if (io_queue_init(file_async_backlog, &aio_ctxts[i].io_ctxt)) { log_errno(LOG_FATAL, "io_queue_init() failed!"); return 1; } aio_ctxts[i].events = (struct io_event *)malloc(file_async_backlog * sizeof(struct io_event)); if (aio_ctxts[i].events == NULL) { log_errno(LOG_FATAL, "Failed to allocate async I/O context!"); return 1; } } return 0; }
AsyncFile::AsyncFile(std::string & _fileName, AIOController * _controller, int _maxIO) : aioContext(0), events(0), fileHandle(0), controller(_controller), pollerRunning(0) { ::pthread_mutex_init(&fileMutex,0); ::pthread_mutex_init(&pollerMutex,0); maxIO = _maxIO; fileName = _fileName; if (io_queue_init(maxIO, &aioContext)) { throw AIOException(NATIVE_ERROR_CANT_INITIALIZE_AIO, "Can't initialize aio, out of AIO Handlers"); } fileHandle = ::open(fileName.data(), O_RDWR | O_CREAT | O_DIRECT, 0666); if (fileHandle < 0) { io_queue_release(aioContext); throw AIOException(NATIVE_ERROR_CANT_OPEN_CLOSE_FILE, "Can't open file"); } #ifdef DEBUG fprintf (stderr,"File Handle %d", fileHandle); #endif events = (struct io_event *)malloc (maxIO * sizeof (struct io_event)); if (events == 0) { throw AIOException (NATIVE_ERROR_CANT_ALLOCATE_QUEUE, "Can't allocate ioEvents"); } }
/* * do async DIO writes to a sparse file */ void aiodio_sparse(char *filename, int align, int writesize, int filesize, int num_aio) { int fd; int i; int w; static struct sigaction s; struct iocb **iocbs; off_t offset; io_context_t myctx; struct io_event event; int aio_inflight; s.sa_sigaction = sig_term_func; s.sa_flags = SA_SIGINFO; sigaction(SIGTERM, &s, 0); if ((num_aio * writesize) > filesize) { num_aio = filesize / writesize; } memset(&myctx, 0, sizeof(myctx)); io_queue_init(num_aio, &myctx); iocbs = (struct iocb **)malloc(sizeof(struct iocb *) * num_aio); for (i = 0; i < num_aio; i++) { if ((iocbs[i] = (struct iocb *)malloc(sizeof(struct iocb))) == 0) { perror("cannot malloc iocb"); return; } } WITH_SIGNALS_BLOCKED( fd = open(filename, O_DIRECT|O_WRONLY|O_CREAT|O_EXCL, 0600); if (fd > 0) filename1=filename; );
void AsyncIO::initializeContext() { if (!ctxSet_.load(std::memory_order_acquire)) { std::lock_guard<std::mutex> lock(initMutex_); if (!ctxSet_.load(std::memory_order_relaxed)) { int rc = io_queue_init(capacity_, &ctx_); // returns negative errno if (rc == -EAGAIN) { long aio_nr, aio_max; std::unique_ptr<FILE, int(*)(FILE*)> fp(fopen("/proc/sys/fs/aio-nr", "r"), fclose); PCHECK(fp); CHECK_EQ(fscanf(fp.get(), "%ld", &aio_nr), 1); std::unique_ptr<FILE, int(*)(FILE*)> aio_max_fp(fopen("/proc/sys/fs/aio-max-nr", "r"), fclose); PCHECK(aio_max_fp); CHECK_EQ(fscanf(aio_max_fp.get(), "%ld", &aio_max), 1); LOG(ERROR) << "No resources for requested capacity of " << capacity_; LOG(ERROR) << "aio_nr " << aio_nr << ", aio_max_nr " << aio_max; } checkKernelError(rc, "AsyncIO: io_queue_init failed"); DCHECK(ctx_); ctxSet_.store(true, std::memory_order_release); } } }
void AsyncIO::initializeContext() { if (!ctx_) { int rc = io_queue_init(capacity_, &ctx_); // returns negative errno checkKernelError(rc, "AsyncIO: io_queue_init failed"); DCHECK(ctx_); } }
static errcode_t unix_vec_read_blocks(io_channel *channel, struct io_vec_unit *ivus, int count) { int i; int ret; io_context_t io_ctx; struct iocb *iocb = NULL, **iocbs = NULL; struct io_event *events = NULL; int64_t offset; int submitted, completed = 0; ret = OCFS2_ET_NO_MEMORY; iocb = malloc((sizeof(struct iocb) * count)); iocbs = malloc((sizeof(struct iocb *) * count)); events = malloc((sizeof(struct io_event) * count)); if (!iocb || !iocbs || !events) goto out; memset(&io_ctx, 0, sizeof(io_ctx)); ret = io_queue_init(count, &io_ctx); if (ret) return ret; for (i = 0; i < count; ++i) { offset = ivus[i].ivu_blkno * channel->io_blksize; io_prep_pread(&(iocb[i]), channel->io_fd, ivus[i].ivu_buf, ivus[i].ivu_buflen, offset); iocbs[i] = &iocb[i]; } resubmit: ret = io_submit(io_ctx, count - completed, &iocbs[completed]); if (!ret && (count - completed)) ret = OCFS2_ET_SHORT_READ; if (ret < 0) goto out; submitted = ret; ret = io_getevents(io_ctx, submitted, submitted, events, NULL); if (ret < 0) goto out; completed += submitted; if (completed < count) goto resubmit; out: if (ret >= 0) ret = 0; if (!ret) channel->io_bytes_read += (count * channel->io_blksize); free(iocb); free(iocbs); free(events); io_queue_release(io_ctx); return ret; }
void aio_setup(io_context_t *io_ctx, int n) { int res = io_queue_init(n, io_ctx); if (res != 0) { fprintf(stderr, "io_queue_setup(%d) returned %d (%s)\n", n, res, strerror(-res)); exit(3); } }
static bool init_aio_linux(struct vfs_handle_struct *handle) { struct tevent_timer *te = NULL; if (event_fd != -1) { /* Already initialized. */ return true; } /* Schedule a shutdown event for 30 seconds from now. */ te = tevent_add_timer(handle->conn->sconn->ev_ctx, NULL, timeval_current_ofs(30, 0), aio_linux_housekeeping, NULL); if (te == NULL) { goto fail; } event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (event_fd == -1) { goto fail; } aio_read_event = tevent_add_fd(server_event_context(), NULL, event_fd, TEVENT_FD_READ, aio_linux_done, NULL); if (aio_read_event == NULL) { goto fail; } if (io_queue_init(lp_aio_max_threads(), &io_ctx)) { goto fail; } DEBUG(10,("init_aio_linux: initialized with up to %d events\n", (int)lp_aio_max_threads())); return true; fail: DEBUG(10,("init_aio_linux: initialization failed\n")); TALLOC_FREE(te); TALLOC_FREE(aio_read_event); if (event_fd != -1) { close(event_fd); event_fd = -1; } memset(&io_ctx, '\0', sizeof(io_ctx)); return false; }
static void setup(void) { int ret; tst_sig(NOFORK, DEF_HANDLER, cleanup); /* Pause if option was specified */ TEST_PAUSE; tst_tmpdir(); /* 创建aiofile文件 */ if ((fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) tst_brkm(TFAIL, cleanup, "failed to open %s " "file, errno: %d", fname, errno); stat(fname, &s); /* 分配iocbs数组 */ if ((iocbs = malloc(sizeof(int) * nr)) == NULL) tst_brkm(TFAIL, cleanup, "malloc for iocbs failed - " "errno: %d", errno); /* 分配iocb对象 */ if ((iocbs[0] = malloc(sizeof(struct iocb))) == NULL) tst_brkm(TFAIL, cleanup, "malloc for iocbs elements failed - " "errno: %d", errno); if (S_ISCHR(s.st_mode)) { if ((ret = posix_memalign((void **)&srcbuf, bufsize, bufsize)) != 0) /* 分配源buf */ tst_brkm(TFAIL, cleanup, "posix_memalign for srcbuf " "failed - errno: %d", errno); if ((ret = posix_memalign((void **)&dstbuf, bufsize, bufsize)) != 0) /* 分配目标buf */ tst_brkm(TFAIL, cleanup, "posix_memalign for dstbuf " "failed - errno: %d", errno); } else { if ((srcbuf = malloc(sizeof(char) * bufsize)) == NULL) tst_brkm(TFAIL, cleanup, "malloc for srcbuf " "failed - errno: %d", errno); if ((dstbuf = malloc(sizeof(char) * bufsize)) == NULL) tst_brkm(TFAIL, cleanup, "malloc for dstbuf " "failed - errno: %d", errno); } memset((void *)srcbuf, 65, bufsize); /* 源buf赋值 */ if ((ret = io_queue_init(1, &io_ctx)) != 0) /* 初始化IO上下文对象 */ tst_brkm(TFAIL, cleanup, "io_queue_init failed: %s", strerror(ret)); }
static int io_async_sendfile_init(struct iothread *t) { memset(&aio_ctx, 0, sizeof(aio_ctx)); if ( io_queue_init(AIO_QUEUE_SIZE, &aio_ctx) ) { fprintf(stderr, "io_queue_init: %s\n", os_err()); return 0; } aio_iocbs = hgang_new(sizeof(struct iocb), 0); if ( NULL == aio_iocbs ) return 0; efd = nbio_eventfd_new(0, aio_event, NULL); if ( NULL == efd ) return 0; nbio_eventfd_add(t, efd); return 1; }
int aiobe_open(struct device* dev, const char* path, int flags, mode_t mode) { int i; dev->ops = &aiobe_device_ops; dev->data = malloc(sizeof(struct aiobe_data)); int ret = open(path, flags, mode); if (ret<0) { free(dev->data); return -1; } D(dev)->fd = ret; if (io_queue_init(1000, &D(dev)->ctx)) { close(D(dev)->fd); free(dev->data); return -1; } for(i=0;i<10;i++) pthread_create(&D(dev)->cbt[i], NULL, aiobe_thread, dev); return 0; }
/* * append to the end of a file using AIO DIRECT. */ void aiodio_append(char *filename) { int fd; void *bufptr; int i; int w; struct iocb iocb_array[NUM_AIO]; struct iocb *iocbs[NUM_AIO]; off_t offset = 0; io_context_t myctx; struct io_event event; struct timespec timeout; fd = open(filename, O_DIRECT|O_WRONLY|O_CREAT, 0666); if (fd < 0) { perror("cannot create file"); return; } memset(&myctx, 0, sizeof(myctx)); io_queue_init(NUM_AIO, &myctx); for (i = 0; i < NUM_AIO; i++ ) { if (posix_memalign(&bufptr, 4096, AIO_SIZE)) { perror("cannot malloc aligned memory"); return; } memset(bufptr, 0, AIO_SIZE); io_prep_pwrite(&iocb_array[i], fd, bufptr, AIO_SIZE, offset); iocbs[i] = &iocb_array[i]; offset += AIO_SIZE; } /* * Start the 1st NUM_AIO requests */ if ((w = io_submit(myctx, NUM_AIO, iocbs)) < 0) { fprintf(stderr, "io_submit write returned %d\n", w); } /* * As AIO requests finish, keep issuing more AIOs. */ for (; i < 1000; i++) { int n = 0; struct iocb *iocbp; n = io_getevents(myctx, 1, 1, &event, &timeout); if (n > 0) { iocbp = (struct iocb *)event.obj; if( n > 0){ io_prep_pwrite(iocbp, fd, iocbp->u.c.buf, AIO_SIZE, offset); offset += AIO_SIZE; if ((w = io_submit(myctx, 1, &iocbp)) < 0) { fprintf(stderr, "write %d returned %d\n", i, w); } } } } }
/* 一次提交多个io请求的操作 */ 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_aio(char* src_file, char* dst_file) { int length = sizeof("abcdefg"); char* content = (char*)malloc(length); io_context_t myctx; int rc; char* buff = NULL; int offset = 0; int num, i, tmp; if((srcfd=open(src_file, O_CREAT|O_RDWR, 0666))<0) { printf("open srcfile error\n"); exit(1); } printf("srcfd=%d\n", srcfd); lseek(srcfd, 0, SEEK_SET); write(srcfd, "abcdefg", length); lseek(srcfd, 0, SEEK_SET); read(srcfd, content, length); printf("write in the srcfile successful, content is [%s]\n", content); if((odsfd=open(dst_file, O_CREAT|O_RDWR, 0666))<0) { close(srcfd); printf("open odsfile error\n"); exit(1); } memset(&myctx, 0, sizeof(myctx)); io_queue_init(AIO_MAXIO, &myctx); struct iocb *io = (struct iocb*)malloc(sizeof(struct iocb)); int iosize = AIO_BLKSIZE; tmp = posix_memalign((void **)&buff, getpagesize(), AIO_BLKSIZE); if(tmp < 0) { printf("posix_memalign error\n"); exit(1); } if(NULL == io) { printf("io out of memeory\n"); exit(1); } io_prep_pread(io, srcfd, buff, iosize, offset); io_set_callback(io, rd_done); printf("START...\n\n"); rc = io_submit(myctx, 1, &io); if(rc < 0) printf("io_submit read error\n"); printf("\nsubmit %d read request\n", rc); //m_io_queue_run(myctx); struct io_event events[AIO_MAXIO]; io_callback_t cb; int finish_count = 0; while(1) { num = io_getevents(myctx, 0, AIO_MAXIO, events, NULL); printf("\n%d io_request completed\n\n", num); for(i=0;i<num;i++) { cb = (io_callback_t)events[i].data; struct iocb *io = events[i].obj; printf("events[%d].data = %lX, res = %ld, res2 = %ld\n", i, cb, events[i].res, events[i].res2); cb(myctx, io, events[i].res, events[i].res2); } finish_count += num; if(finish_count >= 2) { break; } } return 0; }
static int io_tio(char *pathname, int flag, int operation) { int res, fd = 0, i = 0; void *bufptr = NULL; off_t offset = 0; struct timespec timeout; struct stat fi_stat; size_t alignment; io_context_t myctx; struct iocb iocb_array[AIO_MAXIO]; struct iocb *iocbps[AIO_MAXIO]; fd = SAFE_OPEN(pathname, flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* determine the alignment from the blksize of the underlying device */ SAFE_FSTAT(fd, &fi_stat); alignment = fi_stat.st_blksize; res = io_queue_init(AIO_MAXIO, &myctx); for (i = 0; i < AIO_MAXIO; i++) { switch (operation) { case IO_CMD_PWRITE: if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) { tst_brk(TBROK | TERRNO, "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)) { tst_brk(TBROK | TERRNO, "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; default: tst_res(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 them 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; } SAFE_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 main(int argc, char **argv) { io_context_t ctx; struct iocb iocb; struct iocb *iocbs[1]; struct io_event event; struct stat st; char *ptr, *buf, one[PATH_MAX], two[PATH_MAX]; size_t buflen, ptrlen; long rc; int fd1, fd2; if ((argc < 2) || (strcmp(argv[1],"-h") == 0)) { printf("Usage: partial_aio_direct <filename>\n"); exit(1); } snprintf(one, sizeof(one), "%s-1", argv[1]); snprintf(two, sizeof(two), "%s-2", argv[1]); unlink(one); unlink(two); fd1 = open(one, O_CREAT|O_RDWR|O_DIRECT, 0644); if (fd1 < 0) { perror("open"); exit(1); } fd2 = open(two, O_CREAT|O_RDWR|O_DIRECT, 0644); if (fd2 < 0) { perror("open"); exit(1); } if (fstat(fd1, &st)) { perror("open"); exit(1); } if (ftruncate(fd1, st.st_blksize)) { perror("ftruncate()"); exit(1); } if (ftruncate(fd2, st.st_blksize)) { perror("ftruncate()"); exit(1); } if (ftruncate(fd1, st.st_blksize * 2)) { perror("ftruncate()"); exit(1); } if (ftruncate(fd2, st.st_blksize * 2)) { perror("ftruncate()"); exit(1); } /* assumes this is a power of two */ buflen = st.st_blksize * 2; ptrlen = st.st_blksize * 4; /* some slop */ ptr = calloc(1, ptrlen); if (ptr == NULL) { perror("calloc"); exit(1); } /* align buf to the next natural buflen alignment after ptr */ buf = align_pow2(ptr, st.st_blksize); rc = io_queue_init(100, &ctx); if (rc) { printf("queue_init: %ld\n", rc); exit(1); } io_prep_pwrite(&iocb, fd1, buf, buflen, 0); memset(ptr, 0x42, ptrlen); printf("saw block size %lu, writing with buflen %lu\n", st.st_blksize, buflen); iocbs[0] = &iocb; rc = io_submit(ctx, 1, iocbs); if (rc != 1) { printf("submit: %ld\n", rc); exit(1); } rc = io_getevents(ctx, 1, 1, &event, NULL); printf("got %ld: data %p iocb %p res %ld res2 %ld\n", rc, event.data, event.obj, event.res, event.res2); return 0; }
/** * Everything that is allocated here will be freed at deleteContext when the class is unloaded. */ JNIEXPORT jobject JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_newContext(JNIEnv* env, jobject thisObject, jint queueSize) { io_context_t libaioContext; int i = 0; #ifdef DEBUG fprintf (stdout, "Initializing context\n"); #endif int res = io_queue_init(queueSize, &libaioContext); if (res) { // Error, so need to release whatever was done before free(libaioContext); throwRuntimeExceptionErrorNo(env, "Cannot initialize queue:", res); return NULL; } struct iocb ** iocb = (struct iocb **)malloc((sizeof(struct iocb *) * (size_t)queueSize)); if (iocb == NULL) { throwOutOfMemoryError(env); return NULL; } for (i = 0; i < queueSize; i++) { iocb[i] = (struct iocb *)malloc(sizeof(struct iocb)); if (iocb[i] == NULL) { // it's unlikely this would happen at this point // for that reason I'm not cleaning up individual IOCBs here // we could increase support here with a cleanup of any previously allocated iocb // But I'm afraid of adding not needed complexity here throwOutOfMemoryError(env); return NULL; } } struct io_control * theControl = (struct io_control *) malloc(sizeof(struct io_control)); if (theControl == NULL) { throwOutOfMemoryError(env); return NULL; } res = pthread_mutex_init(&(theControl->iocbLock), 0); if (res) { free(theControl); free(libaioContext); throwRuntimeExceptionErrorNo(env, "Can't initialize mutext:", res); return NULL; } res = pthread_mutex_init(&(theControl->pollLock), 0); if (res) { free(theControl); free(libaioContext); throwRuntimeExceptionErrorNo(env, "Can't initialize mutext:", res); return NULL; } struct io_event * events = (struct io_event *)malloc(sizeof(struct io_event) * (size_t)queueSize); theControl->ioContext = libaioContext; theControl->events = events; theControl->iocb = iocb; theControl->queueSize = queueSize; theControl->iocbPut = 0; theControl->iocbGet = 0; theControl->used = 0; theControl->thisObject = (*env)->NewGlobalRef(env, thisObject); return (*env)->NewDirectByteBuffer(env, theControl, sizeof(struct io_control)); }
int main(int argc, char * argv[]) { int sg_fd, k, ok; unsigned char inqCmdBlk [INQ_CMD_LEN] = {0x12, 0, 0, 0, INQ_REPLY_LEN, 0}; unsigned char turCmdBlk [TUR_CMD_LEN] = {0x00, 0, 0, 0, 0, 0}; unsigned char inqBuff[INQ_REPLY_LEN]; sg_io_hdr_t io_hdr; char * file_name = 0; char ebuff[EBUFF_SZ]; unsigned char sense_buffer[32]; int do_extra = 0; for (k = 1; k < argc; ++k) { if (0 == memcmp("-x", argv[k], 2)) do_extra = 1; else if (*argv[k] == '-') { printf("Unrecognized switch: %s\n", argv[k]); file_name = 0; break; } else if (0 == file_name) file_name = argv[k]; else { printf("too many arguments\n"); file_name = 0; break; } } if (0 == file_name) { printf("Usage: 'sg_simple_aio [-x] <sg_device>'\n"); return 1; } /* An access mode of O_RDWR is required for write()/read() interface */ if ((sg_fd = open(file_name, O_RDWR)) < 0) { snprintf(ebuff, EBUFF_SZ, "sg_simple_aio: error opening file: %s", file_name); perror(ebuff); return 1; } /* Just to be safe, check we have a new sg device by trying an ioctl */ if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { printf("sg_simple_aio: %s doesn't seem to be an new sg device\n", file_name); close(sg_fd); return 1; } /* Prepare INQUIRY command */ memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); io_hdr.interface_id = 'S'; io_hdr.cmd_len = sizeof(inqCmdBlk); /* io_hdr.iovec_count = 0; */ /* memset takes care of this */ io_hdr.mx_sb_len = sizeof(sense_buffer); io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; io_hdr.dxfer_len = INQ_REPLY_LEN; io_hdr.dxferp = inqBuff; io_hdr.cmdp = inqCmdBlk; io_hdr.sbp = sense_buffer; io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */ /* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */ /* io_hdr.pack_id = 0; */ /* io_hdr.usr_ptr = NULL; */ #if 1 { struct iocb a_iocb; struct iocb * iocb_arr[1]; io_context_t io_ctx; int res; if (0 != (res = io_queue_init(1, &io_ctx))) { printf("io_queue_init: failed %s\n", strerror(-res)); close(sg_fd); return 1; } iocb_arr[0] = &a_iocb; io_prep_pwrite(iocb_arr[0], sg_fd, &io_hdr, sizeof(io_hdr), 0); io_set_callback(iocb_arr[0], my_io_callback); res = io_submit(io_ctx, 1, iocb_arr); if (1 != res) { printf("io_submit: returned %d\n", res); close(sg_fd); return 1; } } #else if (write(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) { perror("sg_simple_aio: Inquiry write error"); close(sg_fd); return 1; } #endif /* sleep(3); */ if (read(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) { perror("sg_simple_aio: Inquiry read error"); close(sg_fd); return 1; } /* now for the error processing */ ok = 0; switch (sg_err_category3(&io_hdr)) { case SG_LIB_CAT_CLEAN: ok = 1; break; case SG_LIB_CAT_RECOVERED: printf("Recovered error on INQUIRY, continuing\n"); ok = 1; break; default: /* won't bother decoding other categories */ sg_chk_n_print3("INQUIRY command error", &io_hdr); break; } if (ok) { /* output result if it is available */ char * p = (char *)inqBuff; int f = (int)*(p + 7); printf("Some of the INQUIRY command's results:\n"); printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32); printf("[wide=%d sync=%d cmdque=%d sftre=%d]\n", !!(f & 0x20), !!(f & 0x10), !!(f & 2), !!(f & 1)); /* Extra info, not necessary to look at */ if (do_extra) printf("INQUIRY duration=%u millisecs, resid=%d, msg_status=%d\n", io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status); } /* Prepare TEST UNIT READY command */ memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); io_hdr.interface_id = 'S'; io_hdr.cmd_len = sizeof(turCmdBlk); io_hdr.mx_sb_len = sizeof(sense_buffer); io_hdr.dxfer_direction = SG_DXFER_NONE; io_hdr.cmdp = turCmdBlk; io_hdr.sbp = sense_buffer; io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { perror("sg_simple_aio: Test Unit Ready SG_IO ioctl error"); close(sg_fd); return 1; } /* now for the error processing */ ok = 0; switch (sg_err_category3(&io_hdr)) { case SG_LIB_CAT_CLEAN: ok = 1; break; case SG_LIB_CAT_RECOVERED: printf("Recovered error on Test Unit Ready, continuing\n"); ok = 1; break; default: /* won't bother decoding other categories */ sg_chk_n_print3("Test Unit Ready command error", &io_hdr); break; } if (ok) printf("Test Unit Ready successful so unit is ready!\n"); else printf("Test Unit Ready failed so unit may _not_ be ready!\n"); if (do_extra) printf("TEST UNIT READY duration=%u millisecs, resid=%d, msg_status=%d\n", io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status); close(sg_fd); return 0; }
int main(int argc, char *const *argv) { struct stat st; off_t length = 0, offset = 0; io_context_t myctx; int c; extern char *optarg; extern int optind, opterr, optopt; while ((c = getopt(argc, argv, "a:b:df:n:s:wzD:")) != -1) { char *endp; switch (c) { case 'a': /* alignment of data buffer */ alignment = strtol(optarg, &endp, 0); alignment = (long)scale_by_kmg((long long)alignment, *endp); break; case 'f': /* use these open flags */ if (strcmp(optarg, "LARGEFILE") == 0 || strcmp(optarg, "O_LARGEFILE") == 0) { source_open_flag |= O_LARGEFILE; dest_open_flag |= O_LARGEFILE; } else if (strcmp(optarg, "TRUNC") == 0 || strcmp(optarg, "O_TRUNC") == 0) { dest_open_flag |= O_TRUNC; } else if (strcmp(optarg, "SYNC") == 0 || strcmp(optarg, "O_SYNC") == 0) { dest_open_flag |= O_SYNC; } else if (strcmp(optarg, "DIRECT") == 0 || strcmp(optarg, "O_DIRECT") == 0) { source_open_flag |= O_DIRECT; dest_open_flag |= O_DIRECT; } else if (strncmp(optarg, "CREAT", 5) == 0 || strncmp(optarg, "O_CREAT", 5) == 0) { dest_open_flag |= O_CREAT; } break; case 'd': debug++; break; case 'D': delay.tv_usec = atoi(optarg); break; case 'b': /* block size */ aio_blksize = strtol(optarg, &endp, 0); aio_blksize = (long)scale_by_kmg((long long)aio_blksize, *endp); break; case 'n': /* num io */ aio_maxio = strtol(optarg, &endp, 0); break; case 's': /* size to transfer */ length = strtoll(optarg, &endp, 0); length = scale_by_kmg(length, *endp); break; case 'w': /* no write */ no_write = 1; break; case 'z': /* write zero's */ zero = 1; break; default: usage(); } } argc -= optind; argv += optind; #ifndef DEBUG if (argc < 1) { usage(); } #else source_open_flag |= O_DIRECT; dest_open_flag |= O_DIRECT; aio_blksize = 1; aio_maxio=1; srcname = "junkdata"; dstname = "ff2"; #endif if (!zero) { #ifndef DEBUG if ((srcfd = open(srcname = *argv, source_open_flag)) < 0) { #else if ((srcfd = open(srcname, source_open_flag)) < 0) { #endif perror(srcname); exit(1); } argv++; argc--; length = 1073741824; #if 0 if (fstat(srcfd, &st) < 0) { perror("fstat"); exit(1); } if (length == 0) length = st.st_size; #endif } if (!no_write) { /* * We are either copying or writing zeros to dstname */ #ifndef DEBUG if (argc < 1) { usage(); } if ((dstfd = open(dstname = *argv, dest_open_flag, 0666)) < 0) { #else if ((dstfd = open(dstname, dest_open_flag, 0666)) < 0) { #endif perror(dstname); exit(1); } if (zero) { /* * get size of dest, if we are zeroing it. * TODO: handle devices. */ if (fstat(dstfd, &st) < 0) { perror("fstat"); exit(1); } if (length == 0) length = st.st_size; } } /* initialize state machine */ memset(&myctx, 0, sizeof(myctx)); io_queue_init(aio_maxio, &myctx); tocopy = howmany(length, aio_blksize); if (init_iocb(aio_maxio, aio_blksize) < 0) { fprintf(stderr, "Error allocating the i/o buffers\n"); exit(1); } while (tocopy > 0) { int i, rc; /* Submit as many reads as once as possible upto aio_maxio */ int n = MIN(MIN(aio_maxio - busy, aio_maxio), howmany(length - offset, aio_blksize)); if (n > 0) { struct iocb *ioq[n]; for (i = 0; i < n; i++) { struct iocb *io = alloc_iocb(); int iosize = MIN(length - offset, aio_blksize); if (zero) { /* * We are writing zero's to dstfd */ io_prep_pwrite(io, dstfd, io->u.c.buf, iosize, offset); io_set_callback(io, wr_done); } else { io_prep_pread(io, srcfd, io->u.c.buf, iosize, offset); io_set_callback(io, rd_done); } ioq[i] = io; offset += iosize; } rc = io_submit(myctx, n, ioq); if (rc < 0) io_error("io_submit", rc); busy += n; if (debug > 1) printf("io_submit(%d) busy:%d\n", n, busy); if (delay.tv_usec) { struct timeval t = delay; (void)select(0,0,0,0,&t); } } /* * We have submitted all the i/o requests. Wait for at least one to complete * and call the callbacks. */ count_io_q_waits++; rc = io_wait_run(myctx, 0); if (rc < 0) io_error("io_wait_run", rc); if (debug > 1) { printf("io_wait_run: rc == %d\n", rc); printf("busy:%d aio_maxio:%d tocopy:%d\n", busy, aio_maxio, tocopy); } } if (srcfd != -1) close(srcfd); if (dstfd != -1) close(dstfd); exit(0); }
int main(int argc, char **argv) { int run_time = 30; int op = O_RDONLY; int qd = 4; int end_of_device = 0; int opt, i, j, max_req, rc, ios_ready, in_flight, count; unsigned long arena_size; unsigned long seed = time(NULL); unsigned long mix_seed = time(NULL); unsigned long random_range = 0; unsigned char *arena; struct iocb *iocbs; struct iocb *ioptr; struct iocb **iolist; struct iocb **iolist_ptr; struct io_event *events; struct timespec start, end, now; unsigned long total_data, total_writes, total_count; int min_data, max_data; io_context_t ioctx; double mbs, actual_time; struct option options[] = { { "help", no_argument, NULL, 'h' }, { "write", optional_argument, NULL, 'w' }, { "loop", no_argument, NULL, 'l' }, { "mixseed", required_argument, NULL, 'm' }, { "qd", required_argument, NULL, 'q' }, { "random", optional_argument, NULL, 'r' }, { "range", required_argument, NULL, 'a' }, { "size", required_argument, NULL, 's' }, { "time", required_argument, NULL, 't' }, { NULL } }; req_size = 1024 * 1024; write_pct = 0.0; for (;;) { opt = getopt_long(argc, argv, "hwlq:s:t:", options, NULL); if (opt == -1) break; switch (opt) { case 'w': op = O_RDWR; write_pct = 1.0; if (optarg) write_pct = strtod(optarg, NULL) / 100.0; if (write_pct < 1.0) random_offsets = 1; break; case 'l': loop_at_end = 1; break; case 'm': mix_seed = strtoul(optarg, NULL, 0); break; case 'q': qd = atoi(optarg); break; case 't': run_time = atoi(optarg); break; case 's': req_size = strtoul(optarg, NULL, 0); break; case 'r': random_offsets = 1; if (optarg) seed = strtoul(optarg, NULL, 0); else seed = time(NULL); break; case 'a': random_range = strtoul(optarg, NULL, 0); break; case 'h': case '?': default: usage(argv[0]); break; } } if (run_time < 1) { fprintf(stderr, "%s: run time must be at least 1 second\n", argv[0]); exit(1); } if (qd < 0 || qd > 64) { fprintf(stderr, "%s: queue depth must be between 1 and 64\n", argv[0]); exit(1); } if (req_size < 4096 || req_size > (16 * 1024 * 1024)) { fprintf(stderr, "%s: request size must be between 4K and 16M\n", argv[0]); exit(1); } /* Always do a multiple of a page for direct IO. */ req_size &= ~4095; if (random_range) { random_range /= req_size; if (random_range < 2) { fprintf(stderr, "%s: random range gives no " "randomness\n", argv[0]); exit(1); } } if (optind == argc) { fprintf(stderr, "%s: need devices to benchmark\n", argv[0]); exit(1); } ndev = argc - optind; devs = malloc(ndev * sizeof(*devs)); if (!ndev) { fprintf(stderr, "%s: no memory for devices\n", argv[0]); exit(1); } for (i = 0; i < ndev; i++) { devs[i].replace = -1; devs[i].io_base = NULL; devs[i].offset = 0; devs[i].count = 0; devs[i].writes = 0; devs[i].status = ' '; devs[i].name = argv[optind++]; devs[i].fd = open(devs[i].name, op|O_DIRECT|O_SYNC); if (devs[i].fd < 0) { fprintf(stderr, "%s: opening ", argv[0]); perror(devs[i].name); exit(1); } devs[i].size = lseek(devs[i].fd, 0, SEEK_END); if (devs[i].size < 0) { fprintf(stderr, "%s: lseek ", argv[0]); perror(devs[i].name); exit(1); } if (random_offsets) { unsigned long t = seed + i; devs[i].random_range = devs[i].size / req_size; if (random_range && devs[i].random_range > random_range) devs[i].random_range = random_range; devs[i].off_rand_state[2] = t >> 16; devs[i].off_rand_state[1] = t & 0xffff; devs[i].off_rand_state[0] = 0x330e; t = mix_seed + i; devs[i].rw_rand_state[2] = t >> 16; devs[i].rw_rand_state[1] = t & 0xffff; devs[i].rw_rand_state[0] = 0x330e; } } /* The arena needs to be big enough to host the maximum number of * requests possible, plus an extra set of requests to pass around * the devices to fairly share any memory fragmentation seen. */ max_req = ndev * qd; arena_size = (max_req + qd) * req_size; arena = mmap(NULL, arena_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_POPULATE|MAP_PRIVATE, -1, 0); if (arena == MAP_FAILED) { fprintf(stderr, "%s: unable to allocate arena\n", argv[0]); exit(1); } memset(arena, 0, arena_size); iocbs = malloc(max_req * sizeof(*iocbs)); if (!iocbs) { fprintf(stderr, "%s: no memory for IOCBs\n", argv[0]); exit(1); } iolist = malloc(max_req * sizeof(*iocbs)); if (!iolist) { fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]); exit(1); } events = malloc(max_req * sizeof(*events)); if (!iolist) { fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]); exit(1); } rc = io_queue_init(max_req, &ioctx); if (rc < 0) { fprintf(stderr, "%s: unable to initialize IO context: %s\n", argv[0], strerror(-rc)); exit(1); } /* Prepopulate our IO requests */ ios_ready = 0; ioptr = iocbs; iolist_ptr = iolist; for (i = 0; i < qd; i++) { for (j = 0; j < ndev; j++) { if (!devs[j].io_base) devs[j].io_base = ioptr; /* Initial iocb prep, will be overwritten in * prepare_request() with proper offset and operation. */ io_prep_pwrite(ioptr, devs[j].fd, arena, req_size, 0); ioptr->data = &devs[j]; arena += req_size; if (prepare_request(&devs[j], ioptr)) { fprintf(stderr, "Premature end of device for " "%s\n", devs[j].name); exit(1); } *iolist_ptr++ = ioptr++; ios_ready++; } } /* Populate the replacement list */ buf_dev = 0; buf_next = NULL; buf_ready = NULL; for (i = 0; i < qd; i++) { buf_p = (struct buf_list *) arena; buf_p->next = buf_ready; buf_ready = buf_p; arena += req_size; } clock_gettime(CLOCK_MONOTONIC_HR, &now); end.tv_sec = now.tv_sec + run_time; end.tv_nsec = now.tv_nsec; devs[0].replace = 0; in_flight = 0; clock_gettime(CLOCK_MONOTONIC_HR, &start); /* Prime the IO pump with our prepared requests */ rc = io_submit(ioctx, ios_ready, iolist); if (rc < 0) { fprintf(stderr, "%s: io_submit() failed: %s\n", argv[0], strerror(-rc)); exit(1); } in_flight += ios_ready; iolist_ptr = iolist; ios_ready = 0; /* Main IO loop */ while (time_before(&now, &end) && !end_of_device) { count = io_getevents(ioctx, 1, in_flight, events, NULL); if (count <= 0) { fprintf(stderr, "%s: io_getevents() failed: " "%s\n", argv[0], strerror(-rc)); exit(1); } for (i = 0; i < count && !end_of_device; i++) { struct iocb *iocb = events[i].obj; struct dev_info *dev = iocb->data; if (events[i].res2) { fprintf(stderr, "%s: got error for %s:" " %lu\n", argv[0], dev->name, events[i].res2); exit(1); } end_of_device = prepare_request(dev, iocb); if (!end_of_device) { *iolist_ptr++ = iocb; ios_ready++; } in_flight--; } /* If we're here, then odds are good we have IO to submit. * Check just in case something woke us up other than an * IO completion. */ if (ios_ready) { rc = io_submit(ioctx, ios_ready, iolist); if (rc < 0) { fprintf(stderr, "%s: io_submit() failed: %s\n", argv[0], strerror(-rc)); exit(1); } in_flight += ios_ready; iolist_ptr = iolist; ios_ready = 0; } clock_gettime(CLOCK_MONOTONIC_HR, &now); } if (end_of_device) { actual_time = now.tv_nsec - start.tv_nsec; actual_time /= 10e9; actual_time += now.tv_sec - start.tv_sec; } else actual_time = run_time; /* Ok, test time is finished, drain outstanding requests */ while (in_flight) { count = io_getevents(ioctx, 1, in_flight, events, NULL); if (count <= 0) { fprintf(stderr, "%s: draining io_getevents() failed: " "%s\n", argv[0], strerror(-rc)); exit(1); } for (i = 0; i < count; i++) { struct iocb *iocb = events[i].obj; struct dev_info *dev = iocb->data; if (events[i].res2) { fprintf(stderr, "%s: draining got error for %s:" " %lu\n", argv[0], dev->name, events[i].res2); exit(1); } in_flight--; } } /* Find the targets that wrote the min and max data so we can * calculate the skew. */ min_data = max_data = 0; total_data = total_writes = total_count= 0; for (i = 0; i < ndev; i++) { if (devs[i].count < devs[min_data].count) min_data = i; if (devs[i].count > devs[max_data].count) max_data = i; total_data += devs[i].count * req_size; total_writes += devs[i].writes; total_count += devs[i].count; } devs[min_data].status = 'm'; devs[max_data].status = 'M'; printf("run time: %.6f seconds%s\n", actual_time, end_of_device ? " (end of device reached)" : ""); printf("queue depth: %d\n", qd); printf("operation: %s ", random_offsets ? "random" : "sequential"); if (write_pct >= 1.0) printf("write\n"); else if (write_pct == 0.0) printf("read\n"); else { printf("mixed (goal %.02f%% writes)\n", write_pct * 100); printf("random request seed: %lu\n", mix_seed); } if (random_offsets) printf("random offset seed: %lu\n", seed); if (random_range) printf("random range: %lu bytes\n", random_range * req_size); printf("request size: %lu bytes\n\n", req_size); for (i = 0; i < ndev; i++) { mbs = ((double) devs[i].count * req_size) / actual_time; mbs /= 1024 * 1024; printf("%c %s: %lu %.2f MB/s", devs[i].status, devs[i].name, devs[i].count * req_size, mbs); if (write_pct != 0.0 && write_pct < 1.0) { printf(" %02.f%% writes", 100.0 * devs[i].writes / devs[i].count); } printf("\n"); } mbs = (double) total_data / actual_time; mbs /= 1024 * 1024; printf("total: %lu %.2f MB/s", total_data, mbs); mbs = (double) (devs[max_data].count - devs[min_data].count); mbs *= req_size; mbs /= actual_time; mbs /= 1024 * 1024; printf(" skew %.2f MB/s", mbs); if (write_pct != 0.0 && write_pct < 1.0) printf(" %02.f%% writes", 100.0 * total_writes / total_count); printf("\n"); return 0; }
void loop_aio(int fd, void *buf) { int res; unsigned int elapsed; /* i/o context initialization */ io_context_t myctx; memset(&myctx, 0, sizeof(myctx)); if ((res = io_queue_init(maxinflight, &myctx))) io_error("io_queue_init", res); copied = 0; inflight = 0; if (opt_verbose) printf("[run %d] start\n", runid); while (copied < mycount) { struct iocb *ioq[maxsubmit]; int tosubmit = 0; unsigned long long int index; struct iocb *iocb; struct timeval tv1, tv2; /* filling a context with io queries */ while (copied + inflight + tosubmit < mycount && inflight + tosubmit < maxinflight && tosubmit < maxsubmit) { /* Simultaneous asynchronous operations using the same iocb produce undefined results. */ iocb = calloc(1, sizeof(struct iocb)); if (mode_rnd) index = (mydevsize / myiosize) * random() / RAND_MAX; else index = copied + inflight + tosubmit; if (mode_write) io_prep_pwrite(iocb, fd, buf, myiosize, index * myiosize); else io_prep_pread(iocb, fd, buf, myiosize, index * myiosize); io_set_callback(iocb, io_done); ioq[tosubmit] = iocb; tosubmit += 1; } /* if there are available slots for submitting queries, do it */ if (tosubmit) { /* submit io and check elapsed time */ gettimeofday(&tv1, NULL); if ((res = io_submit(myctx, tosubmit, ioq)) != tosubmit) { printf("only %d io submitted\n", res); io_error("io_submit write", res); } gettimeofday(&tv2, NULL); elapsed = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000; if (elapsed > 200) printf("warning: io_submit() took %d ms, this is suspicious, maybe nr_request is too low.\n", elapsed); /* inflight io += newly submitted io */ inflight += tosubmit; } /* handle completed io events */ if ((res = io_queue_run(myctx)) < 0) io_error("io_queue_run", res); if (inflight == maxinflight || (inflight && copied + inflight == mycount)) { struct io_event event; if ((res = io_getevents(myctx, 1, 1, &event, NULL)) < 0) io_error("io_getevents", res); if (res != 1) errx(1, "no events?"); ((io_callback_t)event.obj->data)(myctx, event.obj, event.res, event.res2); } } io_queue_release(myctx); }
int main(int argc, char *const *argv) { int srcfd; struct stat st; off_t length = 0, offset = 0; io_context_t myctx; if (argc != 2 || argv[1][0] == '-') { fprintf(stderr, "Usage: aioread SOURCE"); exit(1); } if ((srcfd = open(srcname = argv[1], O_RDONLY)) < 0) { perror(srcname); exit(1); } if (fstat(srcfd, &st) < 0) { perror("fstat"); exit(1); } length = st.st_size; /* initialize state machine */ memset(&myctx, 0, sizeof(myctx)); io_queue_init(AIO_MAXIO, &myctx); tocopy = howmany(length, AIO_BLKSIZE); printf("tocopy: %ld times\n", tocopy); int i, j; for (i = 0; i < AIO_MAXIO; i ++) memset(&aiobuf[i], '\0', sizeof(struct mybuf)); int ps = getpagesize(); while (tocopy > 0) { rc; /* Submit as many reads as once as possible upto AIO_MAXIO */ int n = MIN(MIN(AIO_MAXIO - busy, AIO_MAXIO / 2), \ howmany(length - offset, AIO_BLKSIZE)); if (n > 0) { struct iocb *ioq[n]; for (i = 0; i < n; i++) { struct iocb *io = (struct iocb *) malloc(sizeof(struct iocb)); int iosize = MIN(length - offset, AIO_BLKSIZE); for (j = 0; j < AIO_MAXIO; j ++) { } char *buf; posix_memalign(&buf, ps, iosize); if (NULL == buf || NULL == io) { fprintf(stderr, "out of memory\n"); exit(1); } io_prep_pread(io, srcfd, buf, iosize, offset); io_set_callback(io, rd_done); ioq[i] = io; offset += iosize; } rc = io_submit(myctx, n, ioq); if (rc < 0) io_error("io_submit", rc); busy += n; } // Handle IO’s that have completed rc = io_queue_run(myctx); if (rc < 0) io_error("io_queue_run", rc); // if we have maximum number of i/o’s in flight // then wait for one to complete if (busy == AIO_MAXIO) { rc = io_queue_wait(myctx, NULL); if (rc < 0) io_error("io_queue_wait", rc); } } close(srcfd); exit(0); }