X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3753e255da8f6a654c3e7b650a2d27734bec15f9..da01ff7f38f52791f93fc3ca59afcfbb220f15af:/block/replication.c diff --git a/block/replication.c b/block/replication.c index 3885f04c31..9ed6e0fb04 100644 --- a/block/replication.c +++ b/block/replication.c @@ -13,7 +13,7 @@ */ #include "qemu/osdep.h" -#include "qemu-common.h" +#include "qemu/option.h" #include "block/nbd.h" #include "block/blockjob.h" #include "block/block_int.h" @@ -157,13 +157,17 @@ static void replication_close(BlockDriverState *bs) static void replication_child_perm(BlockDriverState *bs, BdrvChild *c, const BdrvChildRole *role, + BlockReopenQueue *reopen_queue, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { - *nperm = *nshared = BLK_PERM_CONSISTENT_READ \ - | BLK_PERM_WRITE \ - | BLK_PERM_WRITE_UNCHANGED; - + *nperm = BLK_PERM_CONSISTENT_READ; + if ((bs->open_flags & (BDRV_O_INACTIVE | BDRV_O_RDWR)) == BDRV_O_RDWR) { + *nperm |= BLK_PERM_WRITE; + } + *nshared = BLK_PERM_CONSISTENT_READ \ + | BLK_PERM_WRITE \ + | BLK_PERM_WRITE_UNCHANGED; return; } @@ -234,10 +238,14 @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs, } if (job) { - backup_wait_for_overlapping_requests(child->bs->job, sector_num, - remaining_sectors); - backup_cow_request_begin(&req, child->bs->job, sector_num, - remaining_sectors); + uint64_t remaining_bytes = remaining_sectors * BDRV_SECTOR_SIZE; + + backup_wait_for_overlapping_requests(child->bs->job, + sector_num * BDRV_SECTOR_SIZE, + remaining_bytes); + backup_cow_request_begin(&req, child->bs->job, + sector_num * BDRV_SECTOR_SIZE, + remaining_bytes); ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors, qiov); backup_cow_request_end(&req); @@ -252,7 +260,8 @@ out: static coroutine_fn int replication_co_writev(BlockDriverState *bs, int64_t sector_num, int remaining_sectors, - QEMUIOVector *qiov) + QEMUIOVector *qiov, + int flags) { BDRVReplicationState *s = bs->opaque; QEMUIOVector hd_qiov; @@ -260,8 +269,10 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs, BdrvChild *top = bs->file; BdrvChild *base = s->secondary_disk; BdrvChild *target; - int ret, n; + int ret; + int64_t n; + assert(!flags); ret = replication_get_io_status(s); if (ret < 0) { goto out; @@ -279,14 +290,20 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs, */ qemu_iovec_init(&hd_qiov, qiov->niov); while (remaining_sectors > 0) { - ret = bdrv_is_allocated_above(top->bs, base->bs, sector_num, - remaining_sectors, &n); + int64_t count; + + ret = bdrv_is_allocated_above(top->bs, base->bs, + sector_num * BDRV_SECTOR_SIZE, + remaining_sectors * BDRV_SECTOR_SIZE, + &count); if (ret < 0) { goto out1; } + assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)); + n = count >> BDRV_SECTOR_BITS; qemu_iovec_reset(&hd_qiov); - qemu_iovec_concat(&hd_qiov, qiov, bytes_done, n * BDRV_SECTOR_SIZE); + qemu_iovec_concat(&hd_qiov, qiov, bytes_done, count); target = ret ? top : base; ret = bdrv_co_writev(target, sector_num, n, &hd_qiov); @@ -296,7 +313,7 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs, remaining_sectors -= n; sector_num += n; - bytes_done += n * BDRV_SECTOR_SIZE; + bytes_done += count; } out1: @@ -327,12 +344,24 @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp) return; } + if (!s->active_disk->bs->drv) { + error_setg(errp, "Active disk %s is ejected", + s->active_disk->bs->node_name); + return; + } + ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs); if (ret < 0) { error_setg(errp, "Cannot make active disk empty"); return; } + if (!s->hidden_disk->bs->drv) { + error_setg(errp, "Hidden disk %s is ejected", + s->hidden_disk->bs->node_name); + return; + } + ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs); if (ret < 0) { error_setg(errp, "Cannot make hidden disk empty"); @@ -367,6 +396,9 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable, new_secondary_flags = s->orig_secondary_flags; } + bdrv_subtree_drained_begin(s->hidden_disk->bs); + bdrv_subtree_drained_begin(s->secondary_disk->bs); + if (orig_hidden_flags != new_hidden_flags) { reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL, new_hidden_flags); @@ -382,6 +414,9 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable, reopen_queue, &local_err); error_propagate(errp, local_err); } + + bdrv_subtree_drained_end(s->hidden_disk->bs); + bdrv_subtree_drained_end(s->secondary_disk->bs); } static void backup_job_cleanup(BlockDriverState *bs) @@ -496,6 +531,9 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, return; } + /* Must be true, or the bdrv_getlength() calls would have failed */ + assert(s->active_disk->bs->drv && s->hidden_disk->bs->drv); + if (!s->active_disk->bs->drv->bdrv_make_empty || !s->hidden_disk->bs->drv->bdrv_make_empty) { error_setg(errp, @@ -538,7 +576,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, aio_context_release(aio_context); return; } - block_job_start(job); + job_start(&job->job); break; default: aio_context_release(aio_context); @@ -667,7 +705,6 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp) BlockDriver bdrv_replication = { .format_name = "replication", - .protocol_name = "replication", .instance_size = sizeof(BDRVReplicationState), .bdrv_open = replication_open,