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 o2test_aio_pread(struct o2test_aio *o2a, int fd, void *buf, size_t count, off_t offset) { int ret = 0; struct iocb *iocbs[] = { o2a->o2a_iocbs[o2a->o2a_cr_event] }; if (o2a->o2a_cr_event >= o2a->o2a_nr_events) { fprintf(stderr, "current aio context didn't support %d " "requests\n", o2a->o2a_cr_event); return -1; } io_prep_pread(o2a->o2a_iocbs[o2a->o2a_cr_event], fd, buf, count, offset); ret = io_submit(o2a->o2a_ctx, 1, iocbs); if (ret != 1) { ret = errno; fprintf(stderr, "error %s during %s\n", strerror(errno), "io_submit"); ret = -1; } o2a->o2a_cr_event++; return ret; }
//return eventfd int AIORead(std::string path,void *buf,int epfd=-1) { m_filefd = openFile(path); if (-1 == m_filefd) { return -1; } m_ctx = 0; if (io_setup(8192, &m_ctx)) { perror("io_setup"); return -1; } if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) { perror("posix_memalign"); return 5; } printf("buf: %p\n", buf); for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) { iocbps[i] = &iocbp->iocb; io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE); io_set_eventfd(&iocbp->iocb, efd); io_set_callback(&iocbp->iocb, aio_callback); iocbp->nth_request = i + 1; } if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) { perror("io_submit"); return 6; } }
int init_iocb(int n, int iosize) { void *buf; int i; if ((iocb_free = malloc(n * sizeof(struct iocb *))) == 0) { return -1; } for (i = 0; i < n; i++) { if (!(iocb_free[i] = (struct iocb *) malloc(sizeof(struct iocb)))) return -1; if (posix_memalign(&buf, alignment, iosize)) return -1; if (debug > 1) { printf("buf allocated at 0x%p, align:%d\n", buf, alignment); } if (zero) { /* * We are writing zero's to dstfd */ memset(buf, 0, iosize); } io_prep_pread(iocb_free[i], -1, buf, iosize, 0); } iocb_free_count = i; return 0; }
ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, long long offset, int thread_id) { FILE_DESCRIPTOR fd = files[file_id]; #ifdef HAVE_MMAP void *start; long long page_addr; long long page_offset; #endif #ifdef HAVE_LIBAIO struct iocb iocb; #else (void)thread_id; /* unused */ #endif if (file_io_mode == FILE_IO_MODE_SYNC) return pread(fd, buf, count, offset); #ifdef HAVE_LIBAIO else if (file_io_mode == FILE_IO_MODE_ASYNC) { /* Use asynchronous read */ io_prep_pread(&iocb, fd, buf, count, offset); if (file_submit_or_wait(&iocb, FILE_OP_TYPE_READ, count, thread_id)) return 0; return count; } #endif #ifdef HAVE_MMAP else if (file_io_mode == FILE_IO_MODE_MMAP) { # if SIZEOF_SIZE_T == 4 /* Create file mapping for each I/O operation on 32-bit platforms */ page_addr = offset & file_page_mask; page_offset = offset - page_addr; start = mmap(NULL, count + page_offset, PROT_READ, MAP_SHARED, fd, page_addr); if (start == MAP_FAILED) return 0; memcpy(buffer, (char *)start + page_offset, count); munmap(start, count + page_offset); return count; # else (void)start; /* unused */ (void)page_addr; /* unused */ (void)page_offset; /* unused */ /* We already have all files mapped on 64-bit platforms */ memcpy(buffer, (char *)mmaps[file_id] + offset, count); return count; # endif } #endif /* HAVE_MMAP */ return 1; /* Unknown I/O mode */ }
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; }
/* Submits the read IO request */ void SubmitRead(int offset){ int x; struct iocb iocbr; struct iocb *iocbrp=&iocbr; /* Init iocb structure */ io_prep_pread(&iocbr,filedes,buffer,BUFFERSIZE,BUFFERSIZE*offset); iocbr.data=(void*)buffer; x=io_submit(context,1,&iocbrp); /* Submit the request */ if(x<0) printf("Error while submitting read request\n %d",x); }
int aio_read(int fd, void *buffer, size_t length, off_t offset, aio_callback_t cb){ struct iocb iocb; struct iocb *piocb = &iocb; int resp; io_prep_pread(&iocb, fd, buffer, length, offset); iocb.data = cb; io_set_eventfd(&iocb, aio_fd); resp = io_submit(aio_ctx,1, &piocb); return resp; }
static int sector_io(struct sbd_context *st, int sector, void *data, int rw) { struct timespec timeout; struct io_event event; struct iocb *ios[1] = { &st->io }; long r; timeout.tv_sec = timeout_io; timeout.tv_nsec = 0; memset(&st->io, 0, sizeof(struct iocb)); if (rw) { io_prep_pwrite(&st->io, st->devfd, data, sector_size, sector_size * sector); } else { io_prep_pread(&st->io, st->devfd, data, sector_size, sector_size * sector); } if (io_submit(st->ioctx, 1, ios) != 1) { cl_log(LOG_ERR, "Failed to submit IO request! (rw=%d)", rw); return -1; } errno = 0; r = io_getevents(st->ioctx, 1L, 1L, &event, &timeout); if (r < 0 ) { cl_log(LOG_ERR, "Failed to retrieve IO events (rw=%d)", rw); return -1; } else if (r < 1L) { cl_log(LOG_INFO, "Cancelling IO request due to timeout (rw=%d)", rw); r = io_cancel(st->ioctx, ios[0], &event); if (r) { DBGLOG(LOG_INFO, "Could not cancel IO request (rw=%d)", rw); /* Doesn't really matter, debugging information. */ } return -1; } else if (r > 1L) { cl_log(LOG_ERR, "More than one IO was returned (r=%ld)", r); return -1; } /* IO is happy */ if (event.res == sector_size) { return 0; } else { cl_log(LOG_ERR, "Short IO (rw=%d, res=%lu, sector_size=%d)", rw, event.res, sector_size); return -1; } }
void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count) { u64 offset; offset = sector * (s64)m_blocksize + m_dataoffset; u32 bytesToRead = count * m_blocksize; struct iocb iocb; struct iocb* iocbs = &iocb; io_prep_pread(&iocb, m_fd, pBuffer, bytesToRead, offset); io_submit(m_aio_context, 1, &iocbs); }
/* * build an aio iocb for an operation, based on oper->rw and the * last offset used. This finds the struct io_unit that will be attached * to the iocb, and things are ready for submission to aio after this * is called. * * returns null on error */ static struct io_unit *build_iocb(struct thread_info *t, struct io_oper *oper) { struct io_unit *io; off_t rand_byte; io = find_iou(t, oper); if (!io) { fprintf(stderr, "unable to find io unit\n"); return NULL; } switch(oper->rw) { case WRITE: io_prep_pwrite(&io->iocb,oper->fd, io->buf, oper->reclen, oper->last_offset); oper->last_offset += oper->reclen; break; case READ: io_prep_pread(&io->iocb,oper->fd, io->buf, oper->reclen, oper->last_offset); oper->last_offset += oper->reclen; break; case RREAD: rand_byte = random_byte_offset(oper); oper->last_offset = rand_byte; io_prep_pread(&io->iocb,oper->fd, io->buf, oper->reclen, rand_byte); break; case RWRITE: rand_byte = random_byte_offset(oper); oper->last_offset = rand_byte; io_prep_pwrite(&io->iocb,oper->fd, io->buf, oper->reclen, rand_byte); break; } return io; }
int file_aio_read(int fd, void *start, int size, long long offset) { struct iocb *cb = malloc(sizeof(struct iocb)); /* remaind to free */ if(!cb) { printf("file_aio_write %s\n", strerror(errno)); return -1; } io_prep_pread(cb, fd, start, size, offset); io_set_callback(cb, read_done); return io_submit(*aio_queue, 1, &cb); }
void random_io(int fd, off_t ionum, int access_size, int num_requests) { // (1) io_context_tの初期化 io_context_t ctx; memset(&ctx, 0, sizeof(io_context_t)); int r = io_setup(num_requests, &ctx); assert(r == 0); // (2) iocbs(I/O要求)の構築 struct iocb **iocbs = new struct iocb*[num_requests]; char **bufs = new char*[num_requests]; for (int i = 0; i < num_requests; i++) { iocbs[i] = new struct iocb(); posix_memalign((void **)&bufs[i], 512, access_size); off_t block_number = rand() % ionum; io_prep_pread(iocbs[i], fd, bufs[i], access_size, block_number * access_size); io_set_callback(iocbs[i], read_done); } // (3) I/O要求を投げる r = io_submit(ctx, num_requests, iocbs); assert(r == num_requests); // (4) 完了したI/O要求を待ち、終わったものについてはcallbackを呼び出す int cnt = 0; while (true) { struct io_event events[32]; int n = io_getevents(ctx, 1, 32, events, NULL); if (n > 0) cnt += n; for (int i = 0; i < n; i++) { struct io_event *ev = events + i; io_callback_t callback = (io_callback_t)ev->data; struct iocb *iocb = ev->obj; callback(ctx, iocb, ev->res, ev->res2); } if (n == 0 || cnt == num_requests) break; } for (int i = 0; i < num_requests; i++) { delete iocbs[i]; free(bufs[i]); } delete[] iocbs; delete[] bufs; }
aiom_cb_t * mb_aiom_prep_pread (mb_aiom_t *aiom, int fd, void *buf, size_t count, long long offset) { aiom_cb_t *aiom_cb; if (NULL == (aiom_cb = mb_res_pool_pop(aiom->cbpool))) { return NULL; } io_prep_pread(&aiom_cb->iocb, fd, buf, count, offset); GETTIMEOFDAY(&aiom_cb->submit_time); aiom->pending[aiom->nr_pending++] = aiom_cb; return aiom_cb; }
void RandomAccessFileDevice::prepareTransfer(RandomAccessRequest &request) { assert(request.pDevice == this); #ifdef USE_AIO_H int aio_lio_opcode = (request.type == RandomAccessRequest::READ) ? LIO_READ : LIO_WRITE; FileSize cbOffset = request.cbOffset; for (RandomAccessRequest::BindingListIter bindingIter(request.bindingList); bindingIter; ++bindingIter) { RandomAccessRequestBinding *pBinding = bindingIter; pBinding->aio_fildes = handle; pBinding->aio_lio_opcode = aio_lio_opcode; // TODO: initialize constant fields below only once pBinding->aio_buf = pBinding->getBuffer(); pBinding->aio_nbytes = pBinding->getBufferSize(); pBinding->aio_reqprio = 0; pBinding->aio_offset = cbOffset; cbOffset += pBinding->aio_nbytes; } assert(cbOffset == request.cbOffset + request.cbTransfer); #endif #ifdef USE_LIBAIO_H FileSize cbOffset = request.cbOffset; for (RandomAccessRequest::BindingListIter bindingIter(request.bindingList); bindingIter; ++bindingIter) { RandomAccessRequestBinding *pBinding = bindingIter; if (request.type == RandomAccessRequest::READ) { io_prep_pread( pBinding, handle, pBinding->getBuffer(), pBinding->getBufferSize(), cbOffset); } else { io_prep_pwrite( pBinding, handle, pBinding->getBuffer(), pBinding->getBufferSize(), cbOffset); } cbOffset += pBinding->getBufferSize(); } assert(cbOffset == request.cbOffset + request.cbTransfer); #endif }
static void aiobe_pread(struct device* dev, void* buf, size_t size, off64_t offset, dev_callback_t cb, void* cookie) { int ret; struct aiobe_request* req=(struct aiobe_request*)malloc(sizeof(struct aiobe_request)); struct iocb* iocb = &req->iocb; memset(req, 0, sizeof(*req)); io_prep_pread(iocb, D(dev)->fd, buf, size, offset); req->cb=cb; req->cookie=cookie; iocb->data=req; ret=io_submit(D(dev)->ctx, 1, &iocb); if (ret!=1) aiobe_complete(req, -1); }
int aioperf_libaio_read(aioperf_io_task_t *io_task) { struct iocb *libaio_req = NULL; aioperf_repository_t *repository = NULL; aioperf_conf_info_t *conf_info = NULL; unsigned long left_size = 0; unsigned int count = 0; repository = io_task->repository; conf_info = repository->conf_info; left_size = io_task->file_size - io_task->offset; if (!(libaio_req = (struct iocb *)aioperf_memory_pool_alloc(repository->pool, sizeof(struct iocb)))) { printf("alloc error\n"); return AIOPERF_ERROR; } if (!(io_task->buf = (char *)aioperf_memory_memalign(512, conf_info->buf_size))) { printf("memory memalign error\n"); } io_task->data = libaio_req; if (left_size > conf_info->buf_size) { count = conf_info->buf_size; } else { count = left_size; } io_prep_pread(libaio_req, io_task->fd, io_task->buf, count, io_task->offset); libaio_req->data = io_task; io_set_eventfd(libaio_req, io_task->repository->signal_fd); if (io_submit(*(io_context_t *)repository->mgr->data, 1, &libaio_req) < 0) { printf("io_submit error\n"); } return AIOPERF_OK; }
int aio_enqueue( int fd, char *buf, unsigned long size, unsigned long start_addr, OPERATION_TYPE op ) { int rtn; int queue_id; struct iocb *cb; int i; retry: queue_id = find_and_set_id(); if(queue_id == -1){ PRINT("Qbusy "); usleep(10); goto retry; } my_iocbp[queue_id].qid = queue_id; cb = &my_iocbp[queue_id].iocbp; switch (op){ case WG_READ: io_prep_pread(cb, fd, buf, size, start_addr); break; case WG_WRITE: io_prep_pwrite(cb, fd, buf, size, start_addr); break; default: PRINT("Error not supported I/O operation file:%s, line:%d\n", __func__, __LINE__); exit(1); } rtn = io_submit(context, 1, &cb); if(rtn<0){ PRINT("Error on I/O submission, line:%d, errno:%d\n", __LINE__, rtn); exit(1); } pthread_mutex_lock(&aio_req_num_mutex); req_num++; pthread_mutex_unlock(&aio_req_num_mutex); return rtn; }
JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_submitRead (JNIEnv * env, jclass clazz, jint fileHandle, jobject contextPointer, jlong position, jint size, jobject bufferRead, jobject callback) { struct io_control * theControl = getIOControl(env, contextPointer); if (theControl == NULL) { return; } struct iocb * iocb = getIOCB(theControl); if (iocb == NULL) { throwIOException(env, "Not enough space in libaio queue"); return; } io_prep_pread(iocb, fileHandle, getBuffer(env, bufferRead), (size_t)size, position); // The GlobalRef will be deleted when poll is called. this is done so // the vm wouldn't crash if the Callback passed by the user is GCed between submission // and callback. // also as the real intention is to hold the reference until the life cycle is complete iocb->data = (void *) (*env)->NewGlobalRef(env, callback); submit(env, theControl, iocb); }
inline void prep_aio (struct iocb *this_iocb, const struct trace_entry *request) { struct object *obj = getobj (request->item->obj); char *ptr; if (request->rwType == 'R') io_prep_pread (this_iocb, lfs_n.fd, obj->obj_data->data, request->bytecount, request->startbyte); else if (request->rwType == 'W') { ptr = request->item->_ptr = getshmptr (request->item->shmid); if (ptr == NULL) { lfs_printf ("pre_aio failed"); assert (0); return; } lfs_printf ("prep_aio write\n"); io_prep_pwrite (this_iocb, lfs_n.fd, ptr, request->bytecount, request->startbyte); } }
static int vdev_file_io_start(zio_t *zio) { vdev_t *vd = zio->io_vd; vdev_file_t *vf = vd->vdev_tsd; #ifdef LINUX_AIO struct iocb *iocbp = &zio->io_aio; #endif ssize_t resid; int error; if (zio->io_type == ZIO_TYPE_IOCTL) { zio_vdev_io_bypass(zio); /* XXPOLICY */ if (!vdev_readable(vd)) { zio->io_error = ENXIO; return (ZIO_PIPELINE_CONTINUE); } switch (zio->io_cmd) { case DKIOCFLUSHWRITECACHE: if (zfs_nocacheflush) break; /* This doesn't actually do much with O_DIRECT... */ zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, kcred, NULL); dprintf("fsync(%s) = %d\n", vdev_description(vd), zio->io_error); if (vd->vdev_nowritecache) { zio->io_error = ENOTSUP; break; } /* Flush the write cache */ error = flushwc(vf->vf_vnode); dprintf("flushwc(%s) = %d\n", vdev_description(vd), error); if (error) { #ifdef _KERNEL cmn_err(CE_WARN, "Failed to flush write cache " "on device '%s'. Data on pool '%s' may be lost " "if power fails. No further warnings will " "be given.", vdev_description(vd), spa_name(vd->vdev_spa)); #endif vd->vdev_nowritecache = B_TRUE; zio->io_error = error; } break; default: zio->io_error = ENOTSUP; } return (ZIO_PIPELINE_CONTINUE); } /* * In the kernel, don't bother double-caching, but in userland, * we want to test the vdev_cache code. */ if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio) == 0) return (ZIO_PIPELINE_STOP); if ((zio = vdev_queue_io(zio)) == NULL) return (ZIO_PIPELINE_STOP); /* XXPOLICY */ if (zio->io_type == ZIO_TYPE_WRITE) error = vdev_writeable(vd) ? vdev_error_inject(vd, zio) : ENXIO; else error = vdev_readable(vd) ? vdev_error_inject(vd, zio) : ENXIO; error = (vd->vdev_remove_wanted || vd->vdev_is_failing) ? ENXIO : error; if (error) { zio->io_error = error; zio_interrupt(zio); return (ZIO_PIPELINE_STOP); } #ifdef LINUX_AIO if (zio->io_aio_ctx && zio->io_aio_ctx->zac_enabled) { if (zio->io_type == ZIO_TYPE_READ) io_prep_pread(&zio->io_aio, vf->vf_vnode->v_fd, zio->io_data, zio->io_size, zio->io_offset); else io_prep_pwrite(&zio->io_aio, vf->vf_vnode->v_fd, zio->io_data, zio->io_size, zio->io_offset); zio->io_aio.data = zio; do { error = io_submit(zio->io_aio_ctx->zac_ctx, 1, &iocbp); } while (error == -EINTR); if (error < 0) { zio->io_error = -error; zio_interrupt(zio); } else VERIFY(error == 1); return (ZIO_PIPELINE_STOP); } #endif zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data, zio->io_size, zio->io_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); if (resid != 0 && zio->io_error == 0) zio->io_error = ENOSPC; zio_interrupt(zio); return (ZIO_PIPELINE_STOP); }
static int check_state(int fd, struct directio_context *ct, int sync, int timeout_secs) { struct timespec timeout = { .tv_nsec = 5 }; struct io_event event; struct stat sb; int rc = PATH_UNCHECKED; long r; if (fstat(fd, &sb) == 0) { LOG(4, "called for %x", (unsigned) sb.st_rdev); } if (sync > 0) { LOG(4, "called in synchronous mode"); timeout.tv_sec = timeout_secs; timeout.tv_nsec = 0; } if (!ct->running) { struct iocb *ios[1] = { &ct->io }; LOG(3, "starting new request"); memset(&ct->io, 0, sizeof(struct iocb)); io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0); if (io_submit(ct->ioctx, 1, ios) != 1) { LOG(3, "io_submit error %i", errno); return PATH_UNCHECKED; } } ct->running++; errno = 0; r = io_getevents(ct->ioctx, 1L, 1L, &event, &timeout); if (r < 0 ) { LOG(3, "async io getevents returned %li (errno=%s)", r, strerror(errno)); ct->running = 0; rc = PATH_UNCHECKED; } else if (r < 1L) { if (ct->running > timeout_secs || sync) { struct iocb *ios[1] = { &ct->io }; LOG(3, "abort check on timeout"); r = io_cancel(ct->ioctx, ios[0], &event); /* * Only reset ct->running if we really * could abort the pending I/O */ if (r) LOG(3, "io_cancel error %i", errno); else ct->running = 0; rc = PATH_DOWN; } else { LOG(3, "async io pending"); rc = PATH_PENDING; } } else { LOG(3, "io finished %lu/%lu", event.res, event.res2); ct->running = 0; rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN; } return rc; } int libcheck_check (struct checker * c) { int ret; struct directio_context * ct = (struct directio_context *)c->context; if (!ct) return PATH_UNCHECKED; ret = check_state(c->fd, ct, c->sync, c->timeout); switch (ret) { case PATH_UNCHECKED: MSG(c, MSG_DIRECTIO_UNKNOWN); break; case PATH_DOWN: MSG(c, MSG_DIRECTIO_DOWN); break; case PATH_UP: MSG(c, MSG_DIRECTIO_UP); break; case PATH_PENDING: MSG(c, MSG_DIRECTIO_PENDING); break; default: break; } return ret; }
/* 一次提交多个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 main(int argc, char **argv) { int i, j, sec, usec; int failflag=0; int bflag=0, nflag=0, Fflag=0; char *optb, *optn, *optF; char *msg; /* for parse_opts */ struct io_event event; static struct timespec ts; struct timeval stv, etv; option_t options[] = { { "b:", &bflag, &optb }, { "n:", &nflag, &optn }, { "F:", &Fflag, &optF }, { NULL, NULL, NULL} }; msg = parse_opts(argc, argv, options, &help); if (msg != (char *) NULL) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); tst_exit(); } bufsize = (bflag ? atoi(optb):8192); nr = (nflag ? atoi(optn):10); if (Fflag) { sprintf(fname, optF); } else { sprintf(fname, "aiofile"); } setup(); /* TEST 1 */ pos = 0; gettimeofday(&stv, NULL); io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); for (i = 0; i< nr; i++) { ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 1: io_submit failed - retval=%d, " "errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 1: %d writes in %3d.%06d sec", nr, sec, usec); } /* TEST 2 */ pos = 0; failflag=0; gettimeofday(&stv, NULL); io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); for (i = 0; i< nr; i++) { ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 2: io_submit failed - retval=%d, " "errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 2: %d reads in %3d.%06d sec", nr, sec, usec); } /* TEST 3 */ pos = 0; failflag=0; gettimeofday(&stv, NULL); for (i = 0; i< nr; i++) { io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 3: io_submit failed - retval=%d, " "errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 3: %d prep,writes in %3d.%06d sec", nr, sec, usec); } /* TEST 4 */ pos = 0; failflag=0; gettimeofday(&stv, NULL); for (i = 0; i< nr; i++) { io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 4: io_submit failed - retval=%d, " "errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 4: %d prep,reads in %3d.%06d sec", nr, sec, usec); } /* TEST 5 */ pos = 0; failflag=0; gettimeofday(&stv, NULL); for (i = 0; i< nr; i++) { io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 5: write io_submit failed - " "retval=%d, errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 5: read io_submit failed - " "retval=%d, errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 5: %d reads and writes in %3d.%06d sec", nr, sec, usec); } /* TEST 6 */ pos = 0; failflag=0; gettimeofday(&stv, NULL); for (i = 0; i< nr; i++) { io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 6: write io_submit failed - " "retval=%d, errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); ts.tv_sec = 30; ts.tv_nsec = 0; do { TEST(io_submit(io_ctx, 1, iocbs)); } while (TEST_RETURN == -EAGAIN); if (TEST_RETURN < 0) { TEST_ERROR_LOG(TEST_ERRNO); tst_resm(TFAIL, "Test 6: read io_submit failed - " "retval=%d, errno=%d", TEST_RETURN, TEST_ERRNO); failflag=1; continue; } while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1); for (j = 0; j < bufsize; j++) { if (srcbuf[j] != dstbuf[j]) tst_resm(TFAIL, "Test 6: compare failed - " "read: %c, " "actual: %c", dstbuf[j], srcbuf[j]); break; } gettimeofday(&etv, NULL); } if (!failflag) { sec = etv.tv_sec - stv.tv_sec; usec = etv.tv_usec - stv.tv_usec; if (usec < 0) { usec += 1000000; sec--; } tst_resm(TPASS, "Test 6: %d read,write,verify in %d.%06d sec", i, sec, usec); } cleanup(); tst_exit(); }
int main(int argc, char *argv[]) { int efd, fd, epfd; io_context_t ctx; struct timespec tms; struct io_event events[NUM_EVENTS]; struct custom_iocb iocbs[NUM_EVENTS]; struct iocb *iocbps[NUM_EVENTS]; struct custom_iocb *iocbp; int i, j, r; void *buf; struct epoll_event epevent; // TODO:Used to record event? efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (efd == -1) { perror("eventfd"); return 2; } // File Open Operation fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644); if (fd == -1) { perror("open"); return 3; } // Init the file size first. ftruncate(fd, TEST_FILE_SIZE); ctx = 0; // 1. io_setup: Create an asynchronous I/O context capable of receiving // at least nr_events. // 2. 8192: It could receive at least 8192 events?? if (io_setup(8192, &ctx)) { perror("io_setup"); return 4; } // Allocate RD_WR_SIZE bytes, and places the address of the allocated memory // in *buf. The address of the allocated memory will be a multiple of ALIGN_SIZE, if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) { perror("posix_memalign"); return 5; } printf("buf: %p\n", buf); for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) { iocbps[i] = &iocbp->iocb; // An inline convenience function designed to facilitate the initialization of the iocb for // an asynchronous read operation. When the function finished, the iocbp->iocb will be: // iocb->u.c.nbytes= RD_WR_SIZE // iocb->aio_fildes = fd // iocb->u.c.buf = buf // iocb->u.c.offset = i * RD_WR_SIZE io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE); io_set_eventfd(&iocbp->iocb, efd); // Set up io completion callback function. io_set_callback(&iocbp->iocb, aio_callback); iocbp->nth_request = i + 1; } // Submit asynchronous I/O blocks for processing. It will queue NUM_EVENTS // I/O request blocks for processing in the AIO context ctx. // iocbps is an array of nr AIO control blocks, which will be submitted to context ctx. if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) { perror("io_submit"); return 6; } // Open an epoll file descriptor ( epoll is I/O event notification facility). // It will returns a file descriptor referring to the new epoll instance. epfd = epoll_create(1); if (epfd == -1) { perror("epoll_create"); return 7; } epevent.events = EPOLLIN | EPOLLET; epevent.data.ptr = NULL; // epoll_ctl: Control interface for an epoll descriptor. // EPOLL_CTL_ADD: the operation that will be performanced // efd: The target file descriptor that the operation will be performed for. // epevent: describle the object linked to the fle descriptor efd. if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent)) { perror("epoll_ctl"); return 8; } i = 0; while (i < NUM_EVENTS) { uint64_t finished_aio; // epoll_wait: wait for an I/O event on an epoll file descriptor // epfd: the file descriptor that the epoll instance refer to. // epevent: points to the events that will be available for the caller. // 1: at most 1 are returned by the function // -1: specifies the minimum number of milliseconds that epoll_wait() will block. // -1 causes epoll_wait to block indefinitely. if (epoll_wait(epfd, &epevent, 1, -1) != 1) { perror("epoll_wait"); return 9; } if (read(efd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio)) { perror("read"); return 10; } printf("finished io number: %"PRIu64"\n", finished_aio); while (finished_aio > 0) { tms.tv_sec = 0; tms.tv_nsec = 0; // read asynchronous I/O events from the completion queue. r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms); if (r > 0) { for (j = 0; j < r; ++j) { ((io_callback_t)(events[j].data))(ctx, events[j].obj, events[j].res, events[j].res2); } i += r; finished_aio -= r; } } } close(epfd); free(buf); // destroy an asynchronous I/O context io_destroy(ctx); close(fd); close(efd); remove(TEST_FILE); return 0; }
int main(int argc, char *argv[]) { int fd, rc, j, k, nbytes = NBYTES, maxevents = NBUF; char *buf[NBUF], *filename = "/dev/mycdrv"; struct iocb *iocbray[NBUF], *iocb; off_t offset; io_context_t ctx = 0; struct io_event events[2 * NBUF]; struct timespec timeout = { 0, 0 }; /* open or create the file and fill it with a pattern */ if (argc > 1) filename = argv[1]; printf("opening %s\n", filename); /* notice opening with these flags won't hurt a device node! */ if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) < 0) { printf("couldn't open %s, ABORTING\n", filename); exit(-1); } /* write initial data out, clear buffers, allocate iocb's */ for (j = 0; j < NBUF; j++) { /* no need to zero iocbs; will be done in io_prep_pread */ iocbray[j] = malloc(sizeof(struct iocb)); buf[j] = malloc(nbytes); sprintf(buf[j], "%4d%4d%4d%4d%4d%4d%4d%4d", j, j, j, j, j, j, j, j); write(fd, buf[j], nbytes); memset(buf[j], 0, nbytes); } printf("\n"); /* prepare the context */ rc = io_setup(maxevents, &ctx); printf(" rc from io_setup = %d\n", rc); /* (async) read the data from the file */ printf(" reading initial data from the file:\n"); for (j = 0; j < NBUF; j++) { iocb = iocbray[j]; offset = j * nbytes; io_prep_pread(iocb, fd, (void *)buf[j], nbytes, offset); rc = io_submit(ctx, 1, &iocb); } /* sync up and print out the readin data */ while ((rc = io_getevents(ctx, NBUF, NBUF, events, &timeout)) > 0) { printf(" rc from io_getevents on the read = %d\n\n", rc); } printbufs(buf, nbytes); /* filling in the buffers before the write */ for (j = 0; j < NBUF; j++) { char *tmp = buf[j]; for (k = 0; k < nbytes; k++) { sprintf((tmp + k), "%1d", j); } } /* write the changed buffers out */ printf(" writing new data to the file:\n"); for (j = 0; j < NBUF; j++) { iocb = iocbray[j]; offset = j * nbytes; io_prep_pwrite(iocb, fd, buf[j], nbytes, offset); rc = io_submit(ctx, 1, &iocb); } /* sync up again */ while ((rc = io_getevents(ctx, NBUF, NBUF, events, &timeout)) > 0) { printf(" rc from io_getevents on the write = %d\n\n", rc); } printbufs(buf, nbytes); /* clean up */ rc = io_destroy(ctx); close(fd); exit(0); }
int main() { size_t i; /* Attempt to read the MBR magic number from the device as a sanity check */ FILE *file = fopen("/dev/sdd", "r"); if (file == NULL) FATAL("Unable to open the device"); for (i = 0; i < SZ; i++) dest[0][i] = JUNK_VAL; size_t nr = fread(dest[0], SZ, 1, file); if (nr != 1) FATAL("Unable to read from the device"); fclose(file); if(dest[0][MAG_NUM_OFFSET1] != MAG_NUM_VAL1 || dest[0][MAG_NUM_OFFSET2] != MAG_NUM_VAL2) printf("Warning: Magic number not found during sanity check\n"); /* Open the device again, but get ready to use async IO this time */ int fd = open("/dev/sdd", O_NONBLOCK | O_DIRECT | O_RDWR, 0); if (fd < 0) FATAL("Error opening file"); /* Now use *real* asynchronous IO to read multiple chunks in parallel */ io_context_t ctx; memset(&ctx, 0, sizeof(ctx)); IO_RUN (__LINE__, io_queue_init, maxEvents, &ctx); /* This is the read job we asynchronously run */ struct iocb job_data[NUM_JOBS]; struct iocb *job = job_data; struct iocb *q[NUM_JOBS]; for (i = 0; i < SZ; i++) dest[0][i] = JUNK_VAL; for (i = 0; i < NUM_JOBS; i++,job++) { if (i & 1) io_prep_pread(job, fd, dest[i], SZ, i * SZ); else io_prep_pwrite(job, fd, dest[i], SZ, i * SZ); q[i] = job; } /* Issue it now */ job = job_data; IO_RUN (__LINE__, io_submit, ctx, NUM_JOBS, q); /* Wait for it */ struct timespec timeout; timeout.tv_sec = 5; timeout.tv_nsec = 0; struct io_event evts[NUM_JOBS]; IO_RUN (__LINE__, io_getevents, ctx, NUM_JOBS, NUM_JOBS, evts, &timeout); for (i = 0; i < NUM_JOBS; i++) { /* Confirm that the IOs completed successfully */ check(ctx, evts[i].obj, evts[i].res, evts[i].res2); } /* Only checking the first buffer, since the other ones were read from other locations */ if(dest[0][MAG_NUM_OFFSET1] != MAG_NUM_VAL1 || dest[0][MAG_NUM_OFFSET2] != MAG_NUM_VAL2) printf("Warning: Magic number not found during async read\n"); close(fd); io_destroy(ctx); return 0; }
static void *aio_out_thread (void *param) { char *name = (char *) param; int status; io_context_t ctx = 0; struct iocb *queue, *iocb; unsigned i; status = sink_open (name); if (status < 0) return 0; sink_fd = status; pthread_cleanup_push (close_fd, &sink_fd); /* initialize i/o queue */ status = io_setup (aio_out, &ctx); if (status < 0) { perror ("aio_out_thread, io_setup"); return 0; } pthread_cleanup_push (queue_release, &ctx); if (aio_out == 0) aio_out = 1; queue = alloca (aio_out * sizeof *iocb); /* populate and (re)run the queue */ for (i = 0, iocb = queue; i < aio_out; i++, iocb++) { char *buf = malloc (iosize); if (!buf) { fprintf(stderr, "%s can't get buffer[%d]\n", __FUNCTION__, i); return 0; } /* data can be processed in out_complete() */ io_prep_pread (iocb, sink_fd, buf, iosize, 0); io_set_callback (iocb, out_complete); iocb->key = USB_DIR_OUT; status = io_submit (ctx, 1, &iocb); if (status < 0) { perror (__FUNCTION__); break; } aio_out_pending++; if (verbose > 2) fprintf(stderr, "%s submit uiocb %p\n", __FUNCTION__, iocb); } status = io_run (ctx, &aio_out_pending); if (status < 0) perror ("aio_out_thread, io_run"); /* clean up */ fflush (stderr); pthread_cleanup_pop (1); pthread_cleanup_pop (1); return 0; }
void AsyncIOOp::pread(int fd, void* buf, size_t size, off_t start) { init(); io_prep_pread(&iocb_, fd, buf, size, start); }
int main(int argc, char *argv[]) { // 每次读入32K字节 const int buffer_size = 0x8000; // 最大事件数 32 const int nr_events = 32; int rt; io_context_t ctx ={0}; // 初使化 io_context_t rt = io_setup(nr_events, &ctx); if ( rt != 0 ) perror("io_setup error"); // 依次读取参数作为文件名加入提交到ctx int pagesize = sysconf(_SC_PAGESIZE); int i = 1; for ( i=1; i<argc; ++i) { struct iocb *cb = (struct iocb*)malloc(sizeof(struct iocb)); void *buffer; // 要使用O_DIRECT, 必须要对齐 posix_memalign(&buffer, pagesize, buffer_size); io_prep_pread(cb, open(argv[i], O_RDONLY | O_DIRECT), buffer, buffer_size, 0); rt = io_submit(ctx, 1, &cb); if (rt < 0) perror("io_submit ");; } printf("io_prep_pread over \n"); struct io_event events[nr_events]; struct iocb *cbs[nr_events]; int remain = argc - 1; int n = 0; // 接收数据最小返回的请求数为1,最大为nr_events while (remain && (n = io_getevents(ctx, 1, nr_events, events, 0))) { int nr_cbs = 0; int i = 0 ; for (i=0; i<n; ++i) { struct io_event event = events[i]; struct iocb *cb = event.obj; // event.res为unsigned //printf("%d receive %d bytes\n", cb->aio_fildes, event.res); if (event.res > buffer_size) { printf("%s\n", strerror(-event.res)); } if (event.res != buffer_size || event.res2 != 0) { --remain; printf("if %s",cb->u.c.buf); // 释放buffer, fd 与 cb free(cb->u.c.buf); close(cb->aio_fildes); free(cb); } else { printf("else%s",cb->u.c.buf); // 更新cb的offset cb->u.c.offset += event.res; cbs[nr_cbs++] = cb; } } if (nr_cbs) { // 继续接收数据 io_submit(ctx, nr_cbs, cbs); } } return 0; }