diff mbox series

[02/13] block: Freeze the backing chain for the duration of the commit job

Message ID 2da7b388a740d1f1b7f40e1182fc821f8abb8fbb.1547739122.git.berto@igalia.com (mailing list archive)
State New, archived
Headers show
Series Add a 'x-blockdev-reopen' QMP command | expand

Commit Message

Alberto Garcia Jan. 17, 2019, 3:33 p.m. UTC
Signed-off-by: Alberto Garcia <berto@igalia.com>
---
 block/commit.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Kevin Wolf Feb. 12, 2019, 2:54 p.m. UTC | #1
Am 17.01.2019 um 16:33 hat Alberto Garcia geschrieben:
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> ---
>  block/commit.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/block/commit.c b/block/commit.c
> index 53148e610b..8824d135e0 100644
> --- a/block/commit.c
> +++ b/block/commit.c
> @@ -73,6 +73,8 @@ static int commit_prepare(Job *job)
>  {
>      CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
>  
> +    bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
> +
>      /* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
>       * the normal backing chain can be restored. */
>      blk_unref(s->base);
> @@ -89,6 +91,8 @@ static void commit_abort(Job *job)
>      CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
>      BlockDriverState *top_bs = blk_bs(s->top);
>  
> +    bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);

commit_abort() will run if commit_prepare() returned an error, so we may
end up unfreezing twice. Maybe move it into the 'if (s->base)' block a
few lines down.

>      /* Make sure commit_top_bs and top stay around until bdrv_replace_node() */
>      bdrv_ref(top_bs);
>      bdrv_ref(s->commit_top_bs);
> @@ -336,6 +340,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
>          }
>      }
>  
> +    if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
> +        goto fail;
> +    }

Don't error paths need to unfreeze after this?

Kevin
Alberto Garcia Feb. 14, 2019, 3:21 p.m. UTC | #2
On Tue 12 Feb 2019 03:54:15 PM CET, Kevin Wolf wrote:
>> @@ -336,6 +340,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
>>          }
>>      }
>>  
>> +    if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
>> +        goto fail;
>> +    }
>
> Don't error paths need to unfreeze after this?

Yes, and while debugging this I realized that the error path is wrong:

    if (commit_top_bs) {
        bdrv_replace_node(commit_top_bs, top, &error_abort);
    }
    job_early_fail(&s->common.job);

Doing bdrv_replace_node() here before job_early_fail() fails with

Unexpected error in bdrv_check_update_perm() at block.c:1920:
Conflicts with use by commit job 'virtio0' as 'intermediate node', which does not allow 'consistent read' on <node-name>
Aborted

I'll write a separate patch for this problem.

Berto
Kevin Wolf Feb. 14, 2019, 3:45 p.m. UTC | #3
Am 14.02.2019 um 16:21 hat Alberto Garcia geschrieben:
> On Tue 12 Feb 2019 03:54:15 PM CET, Kevin Wolf wrote:
> >> @@ -336,6 +340,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
> >>          }
> >>      }
> >>  
> >> +    if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
> >> +        goto fail;
> >> +    }
> >
> > Don't error paths need to unfreeze after this?
> 
> Yes, and while debugging this I realized that the error path is wrong:
> 
>     if (commit_top_bs) {
>         bdrv_replace_node(commit_top_bs, top, &error_abort);
>     }
>     job_early_fail(&s->common.job);
> 
> Doing bdrv_replace_node() here before job_early_fail() fails with
> 
> Unexpected error in bdrv_check_update_perm() at block.c:1920:
> Conflicts with use by commit job 'virtio0' as 'intermediate node', which does not allow 'consistent read' on <node-name>
> Aborted

Oh, good point. And it seems to have been wrong even since permissions
were introduced to the commit job in 8dfba279776.

> I'll write a separate patch for this problem.

And a test case! :-)

(That is, if the errors can even be triggered reliably without modifying
the code.)

Kevin
diff mbox series

Patch

diff --git a/block/commit.c b/block/commit.c
index 53148e610b..8824d135e0 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -73,6 +73,8 @@  static int commit_prepare(Job *job)
 {
     CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
 
+    bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
+
     /* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
      * the normal backing chain can be restored. */
     blk_unref(s->base);
@@ -89,6 +91,8 @@  static void commit_abort(Job *job)
     CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
     BlockDriverState *top_bs = blk_bs(s->top);
 
+    bdrv_unfreeze_backing_chain(s->commit_top_bs, s->base_bs);
+
     /* Make sure commit_top_bs and top stay around until bdrv_replace_node() */
     bdrv_ref(top_bs);
     bdrv_ref(s->commit_top_bs);
@@ -336,6 +340,10 @@  void commit_start(const char *job_id, BlockDriverState *bs,
         }
     }
 
+    if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
+        goto fail;
+    }
+
     ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
     if (ret < 0) {
         goto fail;