static void dma_bdrv_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; target_phys_addr_t cur_addr, cur_len; void *mem; dbs->acb = NULL; dbs->sector_num += dbs->iov.size / 512; dma_bdrv_unmap(dbs); qemu_iovec_reset(&dbs->iov); if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { dbs->common.cb(dbs->common.opaque, ret); qemu_iovec_destroy(&dbs->iov); qemu_aio_release(dbs); return; } while (dbs->sg_cur_index < dbs->sg->nsg) { cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte; mem = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->is_write); if (!mem) break; qemu_iovec_add(&dbs->iov, mem, cur_len); dbs->sg_cur_byte += cur_len; if (dbs->sg_cur_byte == dbs->sg->sg[dbs->sg_cur_index].len) { dbs->sg_cur_byte = 0; ++dbs->sg_cur_index; } } if (dbs->iov.size == 0) { cpu_register_map_client(dbs, continue_after_map_failure); return; } if (dbs->is_write) { dbs->acb = bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov, dbs->iov.size / 512, dma_bdrv_cb, dbs); } else { dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov, dbs->iov.size / 512, dma_bdrv_cb, dbs); } if (!dbs->acb) { dma_bdrv_unmap(dbs); qemu_iovec_destroy(&dbs->iov); return; } }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != 1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_merged_requests * to be able to merge requests. */ qemu_iovec_destroy(&req->qiov); } if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); if (virtio_blk_handle_rw_error(req, -ret, is_read)) { continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } }
static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks, sectors_per_chunk; trace_mirror_iteration_done(s, op->sector_num, op->nb_sectors, ret); s->in_flight--; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; chunk_num = op->sector_num / sectors_per_chunk; nb_chunks = op->nb_sectors / sectors_per_chunk; bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (s->cow_bitmap && ret >= 0) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } qemu_iovec_destroy(&op->qiov); g_slice_free(MirrorOp, op); qemu_coroutine_enter(s->common.co, NULL); }
static void aio_write_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; struct timeval t2; gettimeofday(&t2, NULL); if (ret < 0) { printf("aio_write failed: %s\n", strerror(-ret)); goto out; } if (ctx->qflag) { goto out; } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, ctx->t1); print_report("wrote", &t2, ctx->offset, ctx->qiov.size, ctx->qiov.size, 1, ctx->Cflag); out: qemu_io_free(ctx->buf); qemu_iovec_destroy(&ctx->qiov); g_free(ctx); }
static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque) { VirtIOBlockDataPlane *s = opaque; VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb); struct virtio_blk_inhdr hdr; int len; if (likely(ret >= 0)) { hdr.status = VIRTIO_BLK_S_OK; len = ret; } else { hdr.status = VIRTIO_BLK_S_IOERR; len = 0; } trace_virtio_blk_data_plane_complete_request(s, req->head, ret); if (req->read_qiov) { assert(req->bounce_iov); qemu_iovec_from_buf(req->read_qiov, 0, req->bounce_iov->iov_base, len); qemu_iovec_destroy(req->read_qiov); g_slice_free(QEMUIOVector, req->read_qiov); } if (req->bounce_iov) { qemu_vfree(req->bounce_iov->iov_base); g_slice_free(struct iovec, req->bounce_iov); }
static int coroutine_fn raw_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags) { void *buf = NULL; BlockDriver *drv; QEMUIOVector local_qiov; int ret; if (bs->probed && sector_num == 0) { /* As long as these conditions are true, we can't get partial writes to * the probe buffer and can just directly check the request. */ QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512); QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512); if (nb_sectors == 0) { /* qemu_iovec_to_buf() would fail, but we want to return success * instead of -EINVAL in this case. */ return 0; } buf = qemu_try_blockalign(bs->file->bs, 512); if (!buf) { ret = -ENOMEM; goto fail; } ret = qemu_iovec_to_buf(qiov, 0, buf, 512); if (ret != 512) { ret = -EINVAL; goto fail; } drv = bdrv_probe_all(buf, 512, NULL); if (drv != bs->drv) { ret = -EPERM; goto fail; } /* Use the checked buffer, a malicious guest might be overwriting its * original buffer in the background. */ qemu_iovec_init(&local_qiov, qiov->niov + 1); qemu_iovec_add(&local_qiov, buf, 512); qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512); qiov = &local_qiov; } BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); ret = bdrv_co_do_pwritev(bs->file->bs, sector_num * BDRV_SECTOR_SIZE, nb_sectors * BDRV_SECTOR_SIZE, qiov, flags); fail: if (qiov == &local_qiov) { qemu_iovec_destroy(&local_qiov); } qemu_vfree(buf); return ret; }
static void blk_sync_complete(void *opaque, int ret) { QEMUIOVector *iov = opaque; qemu_iovec_destroy(iov); g_free(iov); /* do nothing. Masters do not directly interact with the backing store, * only the working copy so no mutexing required. */ }
static void dma_complete(DMAAIOCB *dbs, int ret) { trace_dma_complete(dbs, ret, dbs->common.cb); dma_blk_unmap(dbs); if (dbs->common.cb) { dbs->common.cb(dbs->common.opaque, ret); } qemu_iovec_destroy(&dbs->iov); if (dbs->bh) { qemu_bh_delete(dbs->bh); dbs->bh = NULL; } qemu_aio_unref(dbs); }
static void blkverify_aio_bh(void *opaque) { BlkverifyAIOCB *acb = opaque; qemu_bh_delete(acb->bh); if (acb->buf) { qemu_iovec_destroy(&acb->raw_qiov); qemu_vfree(acb->buf); } acb->common.cb(acb->common.opaque, acb->ret); if (acb->finished) { *acb->finished = true; } qemu_aio_release(acb); }
static void dma_complete(DMAAIOCB *dbs, int ret) { dma_bdrv_unmap(dbs); if (dbs->common.cb) { dbs->common.cb(dbs->common.opaque, ret); } qemu_iovec_destroy(&dbs->iov); if (dbs->bh) { qemu_bh_delete(dbs->bh); dbs->bh = NULL; } if (!dbs->in_cancel) { /* Requests may complete while dma_aio_cancel is in progress. In * this case, the AIOCB should not be released because it is still * referenced by dma_aio_cancel. */ qemu_aio_release(dbs); } }
static int blk_free(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); struct ioreq *ioreq; while (!QLIST_EMPTY(&blkdev->freelist)) { ioreq = QLIST_FIRST(&blkdev->freelist); QLIST_REMOVE(ioreq, list); qemu_iovec_destroy(&ioreq->v); qemu_free(ioreq); } qemu_free(blkdev->params); qemu_free(blkdev->mode); qemu_free(blkdev->type); qemu_free(blkdev->dev); qemu_free(blkdev->devtype); qemu_bh_delete(blkdev->bh); return 0; }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != 1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_merged_requests * to be able to merge requests. */ qemu_iovec_destroy(&req->qiov); } if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); /* Note that memory may be dirtied on read failure. If the * virtio request is not completed here, as is the case for * BLOCK_ERROR_ACTION_STOP, the memory may not be copied * correctly during live migration. While this is ugly, * it is acceptable because the device is free to write to * the memory until the request is completed (which will * happen on the other side of the migration). */ if (virtio_blk_handle_rw_error(req, -ret, is_read)) { /* Break the link in case the next request is added to the * restart queue and is going to be parsed from the ring again. */ req->mr_next = NULL; continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; VirtIOBlock *s = next->dev; VirtIODevice *vdev = VIRTIO_DEVICE(s); aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(vdev, req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != -1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_requests to be * able to merge requests. */ qemu_iovec_destroy(&req->qiov); } if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); /* Note that memory may be dirtied on read failure. If the * virtio request is not completed here, as is the case for * BLOCK_ERROR_ACTION_STOP, the memory may not be copied * correctly during live migration. While this is ugly, * it is acceptable because the device is free to write to * the memory until the request is completed (which will * happen on the other side of the migration). */ if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) { continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } aio_context_release(blk_get_aio_context(s->conf.conf.blk)); }
static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks, sectors_per_chunk; trace_mirror_iteration_done(s, op->sector_num, op->nb_sectors, ret); s->in_flight--; s->sectors_in_flight -= op->nb_sectors; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; chunk_num = op->sector_num / sectors_per_chunk; nb_chunks = op->nb_sectors / sectors_per_chunk; bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (ret >= 0) { if (s->cow_bitmap) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } s->common.offset += (uint64_t)op->nb_sectors * BDRV_SECTOR_SIZE; } qemu_iovec_destroy(&op->qiov); g_slice_free(MirrorOp, op); /* Enter coroutine when it is not sleeping. The coroutine sleeps to * rate-limit itself. The coroutine will eventually resume since there is * a sleep timeout so don't wake it early. */ if (s->common.busy) { qemu_coroutine_enter(s->common.co, NULL); } }
static void aio_read_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; struct timeval t2; gettimeofday(&t2, NULL); if (ret < 0) { printf("readv failed: %s\n", strerror(-ret)); goto out; } if (ctx->Pflag) { void *cmp_buf = g_malloc(ctx->qiov.size); memset(cmp_buf, ctx->pattern, ctx->qiov.size); if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { printf("Pattern verification failed at offset %" PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); } g_free(cmp_buf); } if (ctx->qflag) { goto out; } if (ctx->vflag) { dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, ctx->t1); print_report("read", &t2, ctx->offset, ctx->qiov.size, ctx->qiov.size, 1, ctx->Cflag); out: qemu_io_free(ctx->buf); qemu_iovec_destroy(&ctx->qiov); g_free(ctx); }
void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane) { XenBlockRequest *request; if (!dataplane) { return; } while (!QLIST_EMPTY(&dataplane->freelist)) { request = QLIST_FIRST(&dataplane->freelist); QLIST_REMOVE(request, list); qemu_iovec_destroy(&request->v); qemu_vfree(request->buf); g_free(request); } qemu_bh_delete(dataplane->bh); if (dataplane->iothread) { object_unref(OBJECT(dataplane->iothread)); } g_free(dataplane); }
static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks; trace_mirror_iteration_done(s, op->offset, op->bytes, ret); s->in_flight--; s->bytes_in_flight -= op->bytes; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } chunk_num = op->offset / s->granularity; nb_chunks = DIV_ROUND_UP(op->bytes, s->granularity); bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (ret >= 0) { if (s->cow_bitmap) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } if (!s->initial_zeroing_ongoing) { block_job_progress_update(&s->common, op->bytes); } } qemu_iovec_destroy(&op->qiov); g_free(op); if (s->waiting_for_io) { qemu_coroutine_enter(s->common.co); } }
static int multiwrite_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, qflag = 0; int c, cnt; char **buf; int64_t offset, first_offset = 0; /* Some compilers get confused and warn if this is not initialized. */ int total = 0; int nr_iov; int nr_reqs; int pattern = 0xcd; QEMUIOVector *qiovs; int i; BlockRequest *reqs; while ((c = getopt(argc, argv, "CqP:")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'q': qflag = 1; break; case 'P': pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; default: return command_usage(&writev_cmd); } } if (optind > argc - 2) { return command_usage(&writev_cmd); } nr_reqs = 1; for (i = optind; i < argc; i++) { if (!strcmp(argv[i], ";")) { nr_reqs++; } } reqs = g_malloc0(nr_reqs * sizeof(*reqs)); buf = g_malloc0(nr_reqs * sizeof(*buf)); qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); for (i = 0; i < nr_reqs && optind < argc; i++) { int j; /* Read the offset of the request */ offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric offset argument -- %s\n", argv[optind]); goto out; } optind++; if (offset & 0x1ff) { printf("offset %lld is not sector aligned\n", (long long)offset); goto out; } if (i == 0) { first_offset = offset; } /* Read lengths for qiov entries */ for (j = optind; j < argc; j++) { if (!strcmp(argv[j], ";")) { break; } } nr_iov = j - optind; /* Build request */ buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern); if (buf[i] == NULL) { goto out; } reqs[i].qiov = &qiovs[i]; reqs[i].sector = offset >> 9; reqs[i].nb_sectors = reqs[i].qiov->size >> 9; optind = j + 1; pattern++; } /* If there were empty requests at the end, ignore them */ nr_reqs = i; gettimeofday(&t1, NULL); cnt = do_aio_multiwrite(reqs, nr_reqs, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("aio_multiwrite failed: %s\n", strerror(-cnt)); goto out; } if (qflag) { goto out; } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); out: for (i = 0; i < nr_reqs; i++) { qemu_io_free(buf[i]); if (reqs[i].qiov != NULL) { qemu_iovec_destroy(&qiovs[i]); } } g_free(buf); g_free(reqs); g_free(qiovs); return 0; }
static int writev_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, qflag = 0; int c, cnt; char *buf; int64_t offset; /* Some compilers get confused and warn if this is not initialized. */ int total = 0; int nr_iov; int pattern = 0xcd; QEMUIOVector qiov; while ((c = getopt(argc, argv, "CqP:")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'q': qflag = 1; break; case 'P': pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; default: return command_usage(&writev_cmd); } } if (optind > argc - 2) { return command_usage(&writev_cmd); } offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } optind++; if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); return 0; } nr_iov = argc - optind; buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); if (buf == NULL) { return 0; } gettimeofday(&t1, NULL); cnt = do_aio_writev(&qiov, offset, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("writev failed: %s\n", strerror(-cnt)); goto out; } if (qflag) { goto out; } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); out: qemu_iovec_destroy(&qiov); qemu_io_free(buf); return 0; }
static int readv_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, qflag = 0, vflag = 0; int c, cnt; char *buf; int64_t offset; /* Some compilers get confused and warn if this is not initialized. */ int total = 0; int nr_iov; QEMUIOVector qiov; int pattern = 0; int Pflag = 0; while ((c = getopt(argc, argv, "CP:qv")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'P': Pflag = 1; pattern = parse_pattern(optarg); if (pattern < 0) { return 0; } break; case 'q': qflag = 1; break; case 'v': vflag = 1; break; default: return command_usage(&readv_cmd); } } if (optind > argc - 2) { return command_usage(&readv_cmd); } offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); return 0; } optind++; if (offset & 0x1ff) { printf("offset %" PRId64 " is not sector aligned\n", offset); return 0; } nr_iov = argc - optind; buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); if (buf == NULL) { return 0; } gettimeofday(&t1, NULL); cnt = do_aio_readv(&qiov, offset, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("readv failed: %s\n", strerror(-cnt)); goto out; } if (Pflag) { void *cmp_buf = g_malloc(qiov.size); memset(cmp_buf, pattern, qiov.size); if (memcmp(buf, cmp_buf, qiov.size)) { printf("Pattern verification failed at offset %" PRId64 ", %zd bytes\n", offset, qiov.size); } g_free(cmp_buf); } if (qflag) { goto out; } if (vflag) { dump_buffer(buf, offset, qiov.size); } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); out: qemu_iovec_destroy(&qiov); qemu_io_free(buf); return 0; }
void usb_packet_cleanup(USBPacket *p) { qemu_iovec_destroy(&p->iov); }
static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { BDRVVHDXState *s = bs->opaque; int ret = 0; VHDXSectorInfo sinfo; uint64_t bytes_done = 0; QEMUIOVector hd_qiov; qemu_iovec_init(&hd_qiov, qiov->niov); qemu_co_mutex_lock(&s->lock); while (nb_sectors > 0) { /* We are a differencing file, so we need to inspect the sector bitmap * to see if we have the data or not */ if (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) { /* not supported yet */ ret = -ENOTSUP; goto exit; } else { vhdx_block_translate(s, sector_num, nb_sectors, &sinfo); qemu_iovec_reset(&hd_qiov); qemu_iovec_concat(&hd_qiov, qiov, bytes_done, sinfo.bytes_avail); /* check the payload block state */ switch (s->bat[sinfo.bat_idx] & VHDX_BAT_STATE_BIT_MASK) { case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */ case PAYLOAD_BLOCK_UNDEFINED: /* fall through */ case PAYLOAD_BLOCK_UNMAPPED: /* fall through */ case PAYLOAD_BLOCK_ZERO: /* return zero */ qemu_iovec_memset(&hd_qiov, 0, 0, sinfo.bytes_avail); break; case PAYLOAD_BLOCK_FULL_PRESENT: qemu_co_mutex_unlock(&s->lock); ret = bdrv_co_readv(bs->file, sinfo.file_offset >> BDRV_SECTOR_BITS, sinfo.sectors_avail, &hd_qiov); qemu_co_mutex_lock(&s->lock); if (ret < 0) { goto exit; } break; case PAYLOAD_BLOCK_PARTIALLY_PRESENT: /* we don't yet support difference files, fall through * to error */ default: ret = -EIO; goto exit; break; } nb_sectors -= sinfo.sectors_avail; sector_num += sinfo.sectors_avail; bytes_done += sinfo.bytes_avail; } } ret = 0; exit: qemu_co_mutex_unlock(&s->lock); qemu_iovec_destroy(&hd_qiov); return ret; }
static coroutine_fn int block_crypto_co_writev(BlockDriverState *bs, int64_t sector_num, int remaining_sectors, QEMUIOVector *qiov) { BlockCrypto *crypto = bs->opaque; int cur_nr_sectors; /* number of sectors in current iteration */ uint64_t bytes_done = 0; uint8_t *cipher_data = NULL; QEMUIOVector hd_qiov; int ret = 0; size_t payload_offset = qcrypto_block_get_payload_offset(crypto->block) / 512; qemu_iovec_init(&hd_qiov, qiov->niov); /* Bounce buffer so we have a linear mem region for * entire sector. XXX optimize so we avoid bounce * buffer in case that qiov->niov == 1 */ cipher_data = qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512, qiov->size)); if (cipher_data == NULL) { ret = -ENOMEM; goto cleanup; } while (remaining_sectors) { cur_nr_sectors = remaining_sectors; if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) { cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS; } qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_nr_sectors * 512); if (qcrypto_block_encrypt(crypto->block, sector_num, cipher_data, cur_nr_sectors * 512, NULL) < 0) { ret = -EIO; goto cleanup; } qemu_iovec_reset(&hd_qiov); qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512); ret = bdrv_co_writev(bs->file, payload_offset + sector_num, cur_nr_sectors, &hd_qiov); if (ret < 0) { goto cleanup; } remaining_sectors -= cur_nr_sectors; sector_num += cur_nr_sectors; bytes_done += cur_nr_sectors * 512; } cleanup: qemu_iovec_destroy(&hd_qiov); qemu_vfree(cipher_data); return ret; }
void usb_packet_cleanup(USBPacket *p) { assert(!usb_packet_is_inflight(p)); qemu_iovec_destroy(&p->iov); }
static int multiwrite_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, qflag = 0; int c, cnt; char **buf; int64_t offset, first_offset = 0; int total = 0; int nr_iov; int nr_reqs; int pattern = 0xcd; QEMUIOVector *qiovs; int i; BlockRequest *reqs; while ((c = getopt(argc, argv, "CqP:")) != EOF) { switch (c) { case 'C': Cflag = 1; break; case 'q': qflag = 1; break; case 'P': pattern = parse_pattern(optarg); if (pattern < 0) return 0; break; default: return command_usage(&writev_cmd); } } if (optind > argc - 2) return command_usage(&writev_cmd); nr_reqs = 1; for (i = optind; i < argc; i++) { if (!strcmp(argv[i], ";")) { nr_reqs++; } } reqs = qemu_malloc(nr_reqs * sizeof(*reqs)); buf = qemu_malloc(nr_reqs * sizeof(*buf)); qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs)); for (i = 0; i < nr_reqs; i++) { int j; offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric offset argument -- %s\n", argv[optind]); return 0; } optind++; if (offset & 0x1ff) { printf("offset %lld is not sector aligned\n", (long long)offset); return 0; } if (i == 0) { first_offset = offset; } for (j = optind; j < argc; j++) { if (!strcmp(argv[j], ";")) { break; } } nr_iov = j - optind; reqs[i].qiov = &qiovs[i]; buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern); reqs[i].sector = offset >> 9; reqs[i].nb_sectors = reqs[i].qiov->size >> 9; optind = j + 1; offset += reqs[i].qiov->size; pattern++; } gettimeofday(&t1, NULL); cnt = do_aio_multiwrite(reqs, nr_reqs, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("aio_multiwrite failed: %s\n", strerror(-cnt)); goto out; } if (qflag) goto out; t2 = tsub(t2, t1); print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); out: for (i = 0; i < nr_reqs; i++) { qemu_io_free(buf[i]); qemu_iovec_destroy(&qiovs[i]); } qemu_free(buf); qemu_free(reqs); qemu_free(qiovs); return 0; }