static int64_t blockdev_aio_readv(struct file_disk *fdisk, struct spdk_io_channel *ch, struct blockdev_aio_task *aio_task, struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t offset) { struct iocb *iocb = &aio_task->iocb; struct blockdev_aio_io_channel *aio_ch = spdk_io_channel_get_ctx(ch); int rc; io_prep_preadv(iocb, fdisk->fd, iov, iovcnt, offset); iocb->data = aio_task; aio_task->len = nbytes; SPDK_TRACELOG(SPDK_TRACE_AIO, "read %d iovs size %lu to off: %#lx\n", iovcnt, nbytes, offset); rc = io_submit(aio_ch->io_ctx, 1, &iocb); if (rc < 0) { spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_FAILED); SPDK_ERRLOG("%s: io_submit returned %d\n", __func__, rc); return -1; } return nbytes; }
int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, off_t offset, int ev, void *param) { struct iocb *ios[1] = { iocb }; io_prep_preadv(iocb, fd, iov, iovcnt, offset); io_set_eventfd(iocb, ev); iocb->data = param; return io_submit(ctx, 1, ios); }
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int type) { struct qemu_laio_state *s = aio_ctx; struct qemu_laiocb *laiocb; struct iocb *iocbs; off_t offset = sector_num * 512; laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque); if (!laiocb) return NULL; laiocb->nbytes = nb_sectors * 512; laiocb->ctx = s; laiocb->ret = -EINPROGRESS; laiocb->is_read = (type == QEMU_AIO_READ); laiocb->qiov = qiov; iocbs = &laiocb->iocb; switch (type) { case QEMU_AIO_WRITE: io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset); break; case QEMU_AIO_READ: io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset); break; /* Currently Linux kernel does not support other operations */ default: fprintf(stderr, "%s: invalid AIO request type 0x%x.\n", __func__, type); goto out_free_aiocb; } io_set_eventfd(&laiocb->iocb, s->efd); s->count++; if (io_submit(s->ctx, 1, &iocbs) < 0) goto out_dec_count; return &laiocb->common; out_dec_count: s->count--; out_free_aiocb: qemu_aio_release(laiocb); return NULL; }
BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockCompletionFunc *cb, void *opaque, int type) { struct qemu_laio_state *s = aio_ctx; struct qemu_laiocb *laiocb; struct iocb *iocbs; off_t offset = sector_num * 512; laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque); laiocb->nbytes = nb_sectors * 512; laiocb->ctx = s; laiocb->ret = -EINPROGRESS; laiocb->is_read = (type == QEMU_AIO_READ); laiocb->qiov = qiov; iocbs = &laiocb->iocb; switch (type) { case QEMU_AIO_WRITE: io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset); break; case QEMU_AIO_READ: io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset); break; /* Currently Linux kernel does not support other operations */ default: fprintf(stderr, "%s: invalid AIO request type 0x%x.\n", __func__, type); goto out_free_aiocb; } io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e)); if (!s->io_q.plugged) { if (io_submit(s->ctx, 1, &iocbs) < 0) { goto out_free_aiocb; } } else { ioq_enqueue(s, iocbs); } return &laiocb->common; out_free_aiocb: qemu_aio_unref(laiocb); return NULL; }
void AsyncIOOp::preadv(int fd, const iovec* iov, int iovcnt, off_t start) { init(); io_prep_preadv(&iocb_, fd, iov, iovcnt, start); }