static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { RawAIOCB *acb; /* * If O_DIRECT is used and the buffer is not aligned fall back * to synchronous IO. */ BDRVRawState *s = bs->opaque; if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) { QEMUBH *bh; acb = qemu_aio_get(bs, cb, opaque); acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors); bh = qemu_bh_new(raw_aio_em_cb, acb); qemu_bh_schedule(bh); return &acb->common; } acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); if (!acb) return NULL; if (qemu_paio_write(&acb->aiocb) < 0) { raw_aio_remove(acb); return NULL; } return &acb->common; }
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; RawAIOCB *acb; if (fd_open(bs) < 0) return NULL; acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); if (!acb) return NULL; acb->aiocb.aio_fildes = s->fd; acb->aiocb.ev_signo = SIGUSR2; acb->aiocb.aio_offset = 0; acb->aiocb.aio_flags = 0; acb->next = posix_aio_state->first_aio; posix_aio_state->first_aio = acb; acb->aiocb.aio_ioctl_buf = buf; acb->aiocb.aio_ioctl_cmd = req; if (qemu_paio_ioctl(&acb->aiocb) < 0) { raw_aio_remove(acb); return NULL; } return &acb->common; }
static void raw_aio_cancel(BlockDriverAIOCB *blockacb) { int ret; RawAIOCB *acb = (RawAIOCB *)blockacb; ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); if (ret == QEMU_PAIO_NOTCANCELED) { /* fail safe: if the aio could not be canceled, we wait for it */ while (qemu_paio_error(&acb->aiocb) == EINPROGRESS); } raw_aio_remove(acb); }
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { RawAIOCB *acb; acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque); if (!acb) return NULL; if (qemu_paio_write(&acb->aiocb) < 0) { raw_aio_remove(acb); return NULL; } return &acb->common; }