static BlockDriverAIOCB * iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; size_t size; int fua = 0; /* set FUA on writes when cache mode is write through */ if (!(bs->open_flags & BDRV_O_CACHE_WB)) { fua = 1; } acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque); trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb); acb->iscsilun = iscsilun; acb->qiov = qiov; acb->canceled = 0; /* XXX we should pass the iovec to write10 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ size = nb_sectors * BDRV_SECTOR_SIZE; acb->buf = g_malloc(size); qemu_iovec_to_buffer(acb->qiov, acb->buf); acb->task = iscsi_write10_task(iscsi, iscsilun->lun, sector_qemu2lun(sector_num, iscsilun), acb->buf, size, iscsilun->block_size, 0, 0, fua, 0, 0, iscsi_aio_write10_cb, acb); if (acb->task == NULL) { error_report("iSCSI: Failed to send write10 command. %s", iscsi_get_error(iscsi)); g_free(acb->buf); qemu_aio_release(acb); return NULL; } iscsi_set_events(iscsilun); return &acb->common; }
static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, RBDAIOCmd cmd) { RBDAIOCB *acb; RADOSCB *rcb; rbd_completion_t c; int64_t off, size; char *buf; int r; BDRVRBDState *s = bs->opaque; acb = qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque); acb->cmd = cmd; acb->qiov = qiov; if (cmd == RBD_AIO_DISCARD || cmd == RBD_AIO_FLUSH) { acb->bounce = NULL; } else { acb->bounce = qemu_blockalign(bs, qiov->size); } acb->ret = 0; acb->error = 0; acb->s = s; acb->bh = NULL; acb->status = -EINPROGRESS; if (cmd == RBD_AIO_WRITE) { qemu_iovec_to_buffer(acb->qiov, acb->bounce); } buf = acb->bounce; off = sector_num * BDRV_SECTOR_SIZE; size = nb_sectors * BDRV_SECTOR_SIZE; s->qemu_aio_count++; /* All the RADOSCB */ rcb = g_malloc(sizeof(RADOSCB)); rcb->done = 0; rcb->acb = acb; rcb->buf = buf; rcb->s = acb->s; rcb->size = size; r = (*librbd.rbd_aio_create_completion)(rcb, (rbd_callback_t) rbd_finish_aiocb, &c); if (r < 0) { goto failed; } switch (cmd) { case RBD_AIO_WRITE: r = (*librbd.rbd_aio_write)(s->image, off, size, buf, c); break; case RBD_AIO_READ: r = (*librbd.rbd_aio_read)(s->image, off, size, buf, c); break; case RBD_AIO_DISCARD: r = (*librbd.rbd_aio_discard)(s->image, off, size, c); break; case RBD_AIO_FLUSH: r = (*librbd.rbd_aio_flush)(s->image, c); break; default: r = -EINVAL; } if (r < 0) { goto failed; } return &acb->common; failed: g_free(rcb); s->qemu_aio_count--; qemu_aio_unref(acb); return NULL; }
static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque, int write) { RBDAIOCB *acb; RADOSCB *rcb; rbd_completion_t c; int64_t off, size; char *buf; int r; BDRVRBDState *s = bs->opaque; acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque); if (!acb) { return NULL; } acb->write = write; acb->qiov = qiov; acb->bounce = qemu_blockalign(bs, qiov->size); acb->ret = 0; acb->error = 0; acb->s = s; acb->cancelled = 0; acb->bh = NULL; if (write) { qemu_iovec_to_buffer(acb->qiov, acb->bounce); } buf = acb->bounce; off = sector_num * BDRV_SECTOR_SIZE; size = nb_sectors * BDRV_SECTOR_SIZE; s->qemu_aio_count++; /* All the RADOSCB */ rcb = g_malloc(sizeof(RADOSCB)); rcb->done = 0; rcb->acb = acb; rcb->buf = buf; rcb->s = acb->s; rcb->size = size; r = rbd_aio_create_completion(rcb, (rbd_callback_t) rbd_finish_aiocb, &c); if (r < 0) { goto failed; } if (write) { r = rbd_aio_write(s->image, off, size, buf, c); } else { r = rbd_aio_read(s->image, off, size, buf, c); } if (r < 0) { goto failed; } return &acb->common; failed: g_free(rcb); s->qemu_aio_count--; qemu_aio_release(acb); return NULL; }