[PATCH v8 29/43] mirror: Deal with filters

2020-09-01 Thread Max Reitz
This includes some permission limiting (for example, we only need to
take the RESIZE permission for active commits where the base is smaller
than the top).

base_overlay is introduced so we can query bdrv_is_allocated_above() on
it - we cannot do that with base itself, because a filter's block_status
is the same as its child node, so if there are filters on base,
bdrv_is_allocated_above() on base would return information including
base.

Use this opportunity to rename qmp_drive_mirror()'s "source" BDS to
"target_backing_bs", because that is what it really refers to.

Signed-off-by: Max Reitz 
---
 qapi/block-core.json |   6 ++-
 block/mirror.c   | 118 +--
 blockdev.c   |  32 
 3 files changed, 118 insertions(+), 38 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index f8f42cc836..8d180b584c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1948,7 +1948,8 @@
 #
 # @replaces: with sync=full graph node name to be replaced by the new
 #image when a whole image copy is done. This can be used to repair
-#broken Quorum files. (Since 2.1)
+#broken Quorum files.  By default, @device is replaced, although
+#implicitly created filters on it are kept. (Since 2.1)
 #
 # @mode: whether and how QEMU should create a new image, default is
 #'absolute-paths'.
@@ -2259,7 +2260,8 @@
 #
 # @replaces: with sync=full graph node name to be replaced by the new
 #image when a whole image copy is done. This can be used to repair
-#broken Quorum files.
+#broken Quorum files.  By default, @device is replaced, although
+#implicitly created filters on it are kept.
 #
 # @speed:  the maximum speed, in bytes per second
 #
diff --git a/block/mirror.c b/block/mirror.c
index e8e8844afc..f16b0d62bc 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -42,6 +42,7 @@ typedef struct MirrorBlockJob {
 BlockBackend *target;
 BlockDriverState *mirror_top_bs;
 BlockDriverState *base;
+BlockDriverState *base_overlay;
 
 /* The name of the graph node to replace */
 char *replaces;
@@ -677,8 +678,10 @@ static int mirror_exit_common(Job *job)
  &error_abort);
 if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
 BlockDriverState *backing = s->is_none_mode ? src : s->base;
-if (backing_bs(target_bs) != backing) {
-bdrv_set_backing_hd(target_bs, backing, &local_err);
+BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs);
+
+if (bdrv_cow_bs(unfiltered_target) != backing) {
+bdrv_set_backing_hd(unfiltered_target, backing, &local_err);
 if (local_err) {
 error_report_err(local_err);
 local_err = NULL;
@@ -740,7 +743,7 @@ static int mirror_exit_common(Job *job)
  * valid.
  */
 block_job_remove_all_bdrv(bjob);
-bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
+bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
 
 /* We just changed the BDS the job BB refers to (with either or both of the
  * bdrv_replace_node() calls), so switch the BB back so the cleanup does
@@ -786,7 +789,6 @@ static void coroutine_fn mirror_throttle(MirrorBlockJob *s)
 static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 {
 int64_t offset;
-BlockDriverState *base = s->base;
 BlockDriverState *bs = s->mirror_top_bs->backing->bs;
 BlockDriverState *target_bs = blk_bs(s->target);
 int ret;
@@ -837,7 +839,8 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 return 0;
 }
 
-ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count);
+ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes,
+  &count);
 if (ret < 0) {
 return ret;
 }
@@ -936,7 +939,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
 } else {
 s->target_cluster_size = BDRV_SECTOR_SIZE;
 }
-if (backing_filename[0] && !target_bs->backing &&
+if (backing_filename[0] && !bdrv_backing_chain_next(target_bs) &&
 s->granularity < s->target_cluster_size) {
 s->buf_size = MAX(s->buf_size, s->target_cluster_size);
 s->cow_bitmap = bitmap_new(length);
@@ -1116,8 +1119,9 @@ static void mirror_complete(Job *job, Error **errp)
 if (s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) {
 int ret;
 
-assert(!target->backing);
-ret = bdrv_open_backing_file(target, NULL, "backing", errp);
+assert(!bdrv_backing_chain_next(target));
+ret = bdrv_open_backing_file(bdrv_skip_filters(target), NULL,
+ "backing", errp);
 if (ret < 0) {
 return;
 }
@@ -1555,8 +1559,8 @@ stat

Re: [PATCH v8 29/43] mirror: Deal with filters

2020-09-02 Thread Kevin Wolf
Am 01.09.2020 um 16:34 hat Max Reitz geschrieben:
> This includes some permission limiting (for example, we only need to
> take the RESIZE permission for active commits where the base is smaller
> than the top).
> 
> base_overlay is introduced so we can query bdrv_is_allocated_above() on
> it - we cannot do that with base itself, because a filter's block_status
> is the same as its child node, so if there are filters on base,
> bdrv_is_allocated_above() on base would return information including
> base.
> 
> Use this opportunity to rename qmp_drive_mirror()'s "source" BDS to
> "target_backing_bs", because that is what it really refers to.
> 
> Signed-off-by: Max Reitz 

I see that you decided not to fix the missing freeze of the backing
chain on the source side. I'm willing to view this as a pre-existing
issue that shouldn't stop this series, but are you going to send a
separate patch for it?

Kevin




Re: [PATCH v8 29/43] mirror: Deal with filters

2020-09-02 Thread Max Reitz
On 02.09.20 10:53, Kevin Wolf wrote:
> Am 01.09.2020 um 16:34 hat Max Reitz geschrieben:
>> This includes some permission limiting (for example, we only need to
>> take the RESIZE permission for active commits where the base is smaller
>> than the top).
>>
>> base_overlay is introduced so we can query bdrv_is_allocated_above() on
>> it - we cannot do that with base itself, because a filter's block_status
>> is the same as its child node, so if there are filters on base,
>> bdrv_is_allocated_above() on base would return information including
>> base.
>>
>> Use this opportunity to rename qmp_drive_mirror()'s "source" BDS to
>> "target_backing_bs", because that is what it really refers to.
>>
>> Signed-off-by: Max Reitz 
> 
> I see that you decided not to fix the missing freeze of the backing
> chain on the source side. I'm willing to view this as a pre-existing
> issue

Yes, that’s how I regarded it.

> that shouldn't stop this series, but are you going to send a
> separate patch for it?

Why not.

Max



signature.asc
Description: OpenPGP digital signature