On 2018-02-27 10:34, Fam Zheng wrote: > On Mon, 01/22 23:08, Max Reitz wrote: >> @@ -1151,7 +1285,48 @@ static int coroutine_fn >> bdrv_mirror_top_preadv(BlockDriverState *bs, >> static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, >> uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) >> { >> - return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags); >> + MirrorOp *op = NULL; >> + MirrorBDSOpaque *s = bs->opaque; >> + QEMUIOVector bounce_qiov; >> + void *bounce_buf; >> + int ret = 0; >> + bool copy_to_target; >> + >> + copy_to_target = s->job->ret >= 0 && >> + s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING; >> + >> + if (copy_to_target) { >> + /* The guest might concurrently modify the data to write; but >> + * the data on source and destination must match, so we have >> + * to use a bounce buffer if we are going to write to the >> + * target now. */ >> + bounce_buf = qemu_blockalign(bs, bytes); >> + iov_to_buf_full(qiov->iov, qiov->niov, 0, bounce_buf, bytes); > > Quorum doesn't use a bounce buffer, so I think we can get away without it > too: a > guest concurrently modifying the buffer isn't a concern in practice. > >> + >> + qemu_iovec_init(&bounce_qiov, 1); >> + qemu_iovec_add(&bounce_qiov, bounce_buf, bytes); >> + qiov = &bounce_qiov; >> + >> + op = active_write_prepare(s->job, offset, bytes); >> + } >> + >> + ret = bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags); >> + if (ret < 0) { >> + goto out; >> + } >> + >> + if (copy_to_target) { >> + do_sync_target_write(s->job, offset, bytes, qiov, flags); >> + } >> + >> +out: >> + if (copy_to_target) { >> + active_write_settle(op); >> + >> + qemu_iovec_destroy(&bounce_qiov); >> + qemu_vfree(bounce_buf); >> + } >> + return ret; >> } >> >> static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs) > > Don't you need to update bdrv_mirror_top_pdiscard and bdrv_mirror_top_pwritev > too?
Now that you mention it... Max
signature.asc
Description: OpenPGP digital signature