[Qemu-devel] [PATCH] blockdev: fix missed target unref for drive-backup

John Snow posted 1 patch 4 years, 11 months ago
Test docker-mingw@fedora passed
Test docker-clang@ubuntu passed
Test checkpatch passed
Test asan passed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20190510215212.8413-1-jsnow@redhat.com
Maintainers: Markus Armbruster <armbru@redhat.com>, Max Reitz <mreitz@redhat.com>, Kevin Wolf <kwolf@redhat.com>
There is a newer version of this series
blockdev.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
[Qemu-devel] [PATCH] blockdev: fix missed target unref for drive-backup
Posted by John Snow 4 years, 11 months ago
If the bitmap can't be used for whatever reason, we skip putting down
the reference. Fix that.

In practice, this means that if you attempt to gracefully exit QEMU
after a backup command being rejected, bdrv_close_all will fail and
tell you some unpleasant things via assert().

Reported-by: aihua liang <aliang@redhat.com>
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1703916
Signed-off-by: John Snow <jsnow@redhat.com>
---
 blockdev.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 79fbac8450..278ecdd122 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3525,8 +3525,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
     if (set_backing_hd) {
         bdrv_set_backing_hd(target_bs, source, &local_err);
         if (local_err) {
-            bdrv_unref(target_bs);
-            goto out;
+            goto unref;
         }
     }
 
@@ -3534,11 +3533,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
         bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
         if (!bmap) {
             error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
-            bdrv_unref(target_bs);
-            goto out;
+            goto unref;
         }
         if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
-            goto out;
+            goto unref;
         }
     }
     if (!backup->auto_finalize) {
@@ -3552,12 +3550,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
                             backup->sync, bmap, backup->compress,
                             backup->on_source_error, backup->on_target_error,
                             job_flags, NULL, NULL, txn, &local_err);
-    bdrv_unref(target_bs);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
-        goto out;
     }
 
+unref:
+    bdrv_unref(target_bs);
 out:
     aio_context_release(aio_context);
     return job;
-- 
2.20.1


Re: [Qemu-devel] [PATCH] blockdev: fix missed target unref for drive-backup
Posted by Kevin Wolf 4 years, 11 months ago
Am 10.05.2019 um 23:52 hat John Snow geschrieben:
> If the bitmap can't be used for whatever reason, we skip putting down
> the reference. Fix that.
> 
> In practice, this means that if you attempt to gracefully exit QEMU
> after a backup command being rejected, bdrv_close_all will fail and
> tell you some unpleasant things via assert().
> 
> Reported-by: aihua liang <aliang@redhat.com>
> Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1703916
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  blockdev.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/blockdev.c b/blockdev.c
> index 79fbac8450..278ecdd122 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -3525,8 +3525,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>      if (set_backing_hd) {
>          bdrv_set_backing_hd(target_bs, source, &local_err);
>          if (local_err) {
> -            bdrv_unref(target_bs);
> -            goto out;
> +            goto unref;
>          }
>      }
>  
> @@ -3534,11 +3533,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>          bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
>          if (!bmap) {
>              error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
> -            bdrv_unref(target_bs);
> -            goto out;
> +            goto unref;
>          }
>          if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
> -            goto out;
> +            goto unref;
>          }
>      }
>      if (!backup->auto_finalize) {
> @@ -3552,12 +3550,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>                              backup->sync, bmap, backup->compress,
>                              backup->on_source_error, backup->on_target_error,
>                              job_flags, NULL, NULL, txn, &local_err);
> -    bdrv_unref(target_bs);
>      if (local_err != NULL) {
>          error_propagate(errp, local_err);
> -        goto out;

Please leave a 'goto unref' here so we can later add more code without
modifying unrelated error paths (or, more likely, forgetting to modify
them).

>      }
>  
> +unref:
> +    bdrv_unref(target_bs);
>  out:
>      aio_context_release(aio_context);
>      return job;

With this fixed:
Reviewed-by: Kevin Wolf <kwolf@redhat.com>

Re: [Qemu-devel] [PATCH] blockdev: fix missed target unref for drive-backup
Posted by John Snow 4 years, 11 months ago

On 5/13/19 7:13 AM, Kevin Wolf wrote:
> Am 10.05.2019 um 23:52 hat John Snow geschrieben:
>> If the bitmap can't be used for whatever reason, we skip putting down
>> the reference. Fix that.
>>
>> In practice, this means that if you attempt to gracefully exit QEMU
>> after a backup command being rejected, bdrv_close_all will fail and
>> tell you some unpleasant things via assert().
>>
>> Reported-by: aihua liang <aliang@redhat.com>
>> Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1703916
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>  blockdev.c | 12 +++++-------
>>  1 file changed, 5 insertions(+), 7 deletions(-)
>>
>> diff --git a/blockdev.c b/blockdev.c
>> index 79fbac8450..278ecdd122 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -3525,8 +3525,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>>      if (set_backing_hd) {
>>          bdrv_set_backing_hd(target_bs, source, &local_err);
>>          if (local_err) {
>> -            bdrv_unref(target_bs);
>> -            goto out;
>> +            goto unref;
>>          }
>>      }
>>  
>> @@ -3534,11 +3533,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>>          bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
>>          if (!bmap) {
>>              error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
>> -            bdrv_unref(target_bs);
>> -            goto out;
>> +            goto unref;
>>          }
>>          if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
>> -            goto out;
>> +            goto unref;
>>          }
>>      }
>>      if (!backup->auto_finalize) {
>> @@ -3552,12 +3550,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
>>                              backup->sync, bmap, backup->compress,
>>                              backup->on_source_error, backup->on_target_error,
>>                              job_flags, NULL, NULL, txn, &local_err);
>> -    bdrv_unref(target_bs);
>>      if (local_err != NULL) {
>>          error_propagate(errp, local_err);
>> -        goto out;
> 
> Please leave a 'goto unref' here so we can later add more code without
> modifying unrelated error paths (or, more likely, forgetting to modify
> them).
> 

Oh, that makes sense.

>>      }
>>  
>> +unref:
>> +    bdrv_unref(target_bs);
>>  out:
>>      aio_context_release(aio_context);
>>      return job;
> 
> With this fixed:
> Reviewed-by: Kevin Wolf <kwolf@redhat.com>
> 

Thanks!