block/mirror: determine copy_to_target only once
In preparation to allow changing the copy_mode via QMP. When running in an iothread, it could be that copy_mode is changed from the main thread in between reading copy_mode in bdrv_mirror_top_pwritev() and reading copy_mode in bdrv_mirror_top_do_write(), so they might end up disagreeing about whether copy_to_target is true or false. Avoid that scenario by determining copy_to_target only once and passing it to bdrv_mirror_top_do_write() as an argument. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Message-ID: <20231031135431.393137-5-f.ebner@proxmox.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
058cfca564
commit
7b32ad2242
@ -1463,21 +1463,21 @@ bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
|
||||
}
|
||||
|
||||
static bool should_copy_to_target(MirrorBDSOpaque *s)
|
||||
{
|
||||
return s->job && s->job->ret >= 0 &&
|
||||
!job_is_cancelled(&s->job->common.job) &&
|
||||
s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING;
|
||||
}
|
||||
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_mirror_top_do_write(BlockDriverState *bs, MirrorMethod method,
|
||||
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
|
||||
int flags)
|
||||
bool copy_to_target, uint64_t offset, uint64_t bytes,
|
||||
QEMUIOVector *qiov, int flags)
|
||||
{
|
||||
MirrorOp *op = NULL;
|
||||
MirrorBDSOpaque *s = bs->opaque;
|
||||
int ret = 0;
|
||||
bool copy_to_target = false;
|
||||
|
||||
if (s->job) {
|
||||
copy_to_target = s->job->ret >= 0 &&
|
||||
!job_is_cancelled(&s->job->common.job) &&
|
||||
s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING;
|
||||
}
|
||||
|
||||
if (copy_to_target) {
|
||||
op = active_write_prepare(s->job, offset, bytes);
|
||||
@ -1524,17 +1524,10 @@ static int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
||||
{
|
||||
MirrorBDSOpaque *s = bs->opaque;
|
||||
QEMUIOVector bounce_qiov;
|
||||
void *bounce_buf;
|
||||
int ret = 0;
|
||||
bool copy_to_target = false;
|
||||
|
||||
if (s->job) {
|
||||
copy_to_target = s->job->ret >= 0 &&
|
||||
!job_is_cancelled(&s->job->common.job) &&
|
||||
s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING;
|
||||
}
|
||||
bool copy_to_target = should_copy_to_target(bs->opaque);
|
||||
|
||||
if (copy_to_target) {
|
||||
/* The guest might concurrently modify the data to write; but
|
||||
@ -1551,8 +1544,8 @@ bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
flags &= ~BDRV_REQ_REGISTERED_BUF;
|
||||
}
|
||||
|
||||
ret = bdrv_mirror_top_do_write(bs, MIRROR_METHOD_COPY, offset, bytes, qiov,
|
||||
flags);
|
||||
ret = bdrv_mirror_top_do_write(bs, MIRROR_METHOD_COPY, copy_to_target,
|
||||
offset, bytes, qiov, flags);
|
||||
|
||||
if (copy_to_target) {
|
||||
qemu_iovec_destroy(&bounce_qiov);
|
||||
@ -1575,15 +1568,17 @@ static int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
|
||||
flags);
|
||||
bool copy_to_target = should_copy_to_target(bs->opaque);
|
||||
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, copy_to_target,
|
||||
offset, bytes, NULL, flags);
|
||||
}
|
||||
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_mirror_top_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
|
||||
{
|
||||
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, offset, bytes,
|
||||
NULL, 0);
|
||||
bool copy_to_target = should_copy_to_target(bs->opaque);
|
||||
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, copy_to_target,
|
||||
offset, bytes, NULL, 0);
|
||||
}
|
||||
|
||||
static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
|
||||
|
Loading…
Reference in New Issue
Block a user