diff mbox

[06/11] qmp: Add an implementation wrapper for qmp_drive_backup

Message ID 1425528911-10300-7-git-send-email-jsnow@redhat.com
State New
Headers show

Commit Message

John Snow March 5, 2015, 4:15 a.m. UTC
We'd like to be able to specify the callback given to backup_start
manually in the case of transactions, so split apart qmp_drive_backup
into an implementation and a wrapper.

Switch drive_backup_prepare to use the new wrapper, but don't overload
the callback and closure yet.

This is kind of gross, but we need to forward-declare the wrapper for
the drive_backup transaction to be able to use. I could try moving
the transaction blocks lower instead, but I wanted (for v1, at least)
to minimize code movement so that the core changes were easiest to see.

If anyone has suggestions on organization, please suggest them.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 blockdev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 58 insertions(+), 19 deletions(-)

Comments

Max Reitz March 17, 2015, 6:51 p.m. UTC | #1
On 2015-03-04 at 23:15, John Snow wrote:
> We'd like to be able to specify the callback given to backup_start
> manually in the case of transactions, so split apart qmp_drive_backup
> into an implementation and a wrapper.
>
> Switch drive_backup_prepare to use the new wrapper, but don't overload
> the callback and closure yet.
>
> This is kind of gross, but we need to forward-declare the wrapper for
> the drive_backup transaction to be able to use. I could try moving
> the transaction blocks lower instead, but I wanted (for v1, at least)
> to minimize code movement so that the core changes were easiest to see.
>
> If anyone has suggestions on organization, please suggest them.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>   blockdev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++----------------
>   1 file changed, 58 insertions(+), 19 deletions(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index 3153ee7..9e3b9e9 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1449,6 +1449,19 @@ void undo_transaction_wrapper(BlkTransactionState *common)
>       blk_put_transaction_state(common);
>   }
>   
> +static void _drive_backup(const char *device, const char *target,

Please don't use leading underscores. (Please.)

Just call it do_drive_backup() or something.

Other than that, I'm okay with a forward-declaration; if you want to 
move it, but I'd be fine with moving the code, too.

With _drive_backup() being called do_drive_backup():

Reviewed-by: Max Reitz <mreitz@redhat.com>

> +                          bool has_format, const char *format,
> +                          enum MirrorSyncMode sync,
> +                          bool has_mode, enum NewImageMode mode,
> +                          bool has_speed, int64_t speed,
> +                          bool has_bitmap, const char *bitmap,
> +                          bool has_on_source_error,
> +                          BlockdevOnError on_source_error,
> +                          bool has_on_target_error,
> +                          BlockdevOnError on_target_error,
> +                          BlockCompletionFunc *cb, void *opaque,
> +                          Error **errp);
> +
>   /* internal snapshot private data */
>   typedef struct InternalSnapshotState {
>       BlkTransactionState common;
> @@ -1768,15 +1781,16 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
>       state->aio_context = bdrv_get_aio_context(bs);
>       aio_context_acquire(state->aio_context);
>   
> -    qmp_drive_backup(backup->device, backup->target,
> -                     backup->has_format, backup->format,
> -                     backup->sync,
> -                     backup->has_mode, backup->mode,
> -                     backup->has_speed, backup->speed,
> -                     backup->has_bitmap, backup->bitmap,
> -                     backup->has_on_source_error, backup->on_source_error,
> -                     backup->has_on_target_error, backup->on_target_error,
> -                     &local_err);
> +    _drive_backup(backup->device, backup->target,
> +                  backup->has_format, backup->format,
> +                  backup->sync,
> +                  backup->has_mode, backup->mode,
> +                  backup->has_speed, backup->speed,
> +                  backup->has_bitmap, backup->bitmap,
> +                  backup->has_on_source_error, backup->on_source_error,
> +                  backup->has_on_target_error, backup->on_target_error,
> +                  NULL, NULL,
> +                  &local_err);
>       if (local_err) {
>           error_propagate(errp, local_err);
>           return;
> @@ -2717,15 +2731,18 @@ out:
>       aio_context_release(aio_context);
>   }
>   
> -void qmp_drive_backup(const char *device, const char *target,
> -                      bool has_format, const char *format,
> -                      enum MirrorSyncMode sync,
> -                      bool has_mode, enum NewImageMode mode,
> -                      bool has_speed, int64_t speed,
> -                      bool has_bitmap, const char *bitmap,
> -                      bool has_on_source_error, BlockdevOnError on_source_error,
> -                      bool has_on_target_error, BlockdevOnError on_target_error,
> -                      Error **errp)
> +static void _drive_backup(const char *device, const char *target,
> +                          bool has_format, const char *format,
> +                          enum MirrorSyncMode sync,
> +                          bool has_mode, enum NewImageMode mode,
> +                          bool has_speed, int64_t speed,
> +                          bool has_bitmap, const char *bitmap,
> +                          bool has_on_source_error,
> +                          BlockdevOnError on_source_error,
> +                          bool has_on_target_error,
> +                          BlockdevOnError on_target_error,
> +                          BlockCompletionFunc *cb, void *opaque,
> +                          Error **errp)
>   {
>       BlockDriverState *bs;
>       BlockDriverState *target_bs;
> @@ -2837,9 +2854,15 @@ void qmp_drive_backup(const char *device, const char *target,
>           }
>       }
>   
> +    if (cb == NULL) {
> +        cb = block_job_cb;
> +    }
> +    if (opaque == NULL) {
> +        opaque = bs;
> +    }
>       backup_start(bs, target_bs, speed, sync, bmap,
>                    on_source_error, on_target_error,
> -                 block_job_cb, bs, &local_err);
> +                 cb, opaque, &local_err);
>       if (local_err != NULL) {
>           bdrv_unref(target_bs);
>           error_propagate(errp, local_err);
> @@ -2850,6 +2873,22 @@ out:
>       aio_context_release(aio_context);
>   }
>   
> +void qmp_drive_backup(const char *device, const char *target,
> +                      bool has_format, const char *format,
> +                      enum MirrorSyncMode sync,
> +                      bool has_mode, enum NewImageMode mode,
> +                      bool has_speed, int64_t speed,
> +                      bool has_bitmap, const char *bitmap,
> +                      bool has_on_source_error, BlockdevOnError on_source_error,
> +                      bool has_on_target_error, BlockdevOnError on_target_error,
> +                      Error **errp)
> +{
> +    _drive_backup(device, target, has_format, format, sync, has_mode, mode,
> +                  has_speed, speed, has_bitmap, bitmap, has_on_source_error,
> +                  on_source_error, has_on_target_error, on_target_error,
> +                  NULL, NULL, errp);
> +}
> +
>   BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
>   {
>       return bdrv_named_nodes_list();
John Snow March 17, 2015, 7:16 p.m. UTC | #2
On 03/17/2015 02:51 PM, Max Reitz wrote:
> On 2015-03-04 at 23:15, John Snow wrote:
>> We'd like to be able to specify the callback given to backup_start
>> manually in the case of transactions, so split apart qmp_drive_backup
>> into an implementation and a wrapper.
>>
>> Switch drive_backup_prepare to use the new wrapper, but don't overload
>> the callback and closure yet.
>>
>> This is kind of gross, but we need to forward-declare the wrapper for
>> the drive_backup transaction to be able to use. I could try moving
>> the transaction blocks lower instead, but I wanted (for v1, at least)
>> to minimize code movement so that the core changes were easiest to see.
>>
>> If anyone has suggestions on organization, please suggest them.
>>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>   blockdev.c | 77
>> ++++++++++++++++++++++++++++++++++++++++++++++----------------
>>   1 file changed, 58 insertions(+), 19 deletions(-)
>>
>> diff --git a/blockdev.c b/blockdev.c
>> index 3153ee7..9e3b9e9 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -1449,6 +1449,19 @@ void
>> undo_transaction_wrapper(BlkTransactionState *common)
>>       blk_put_transaction_state(common);
>>   }
>> +static void _drive_backup(const char *device, const char *target,
>
> Please don't use leading underscores. (Please.)
>
> Just call it do_drive_backup() or something.
>
> Other than that, I'm okay with a forward-declaration; if you want to
> move it, but I'd be fine with moving the code, too.
>
> With _drive_backup() being called do_drive_backup():
>
> Reviewed-by: Max Reitz <mreitz@redhat.com>
>

Moving the code around might be better, it just makes for a much noisier 
patch. I made my decisions for v1 to keep code disturbed the least.

Once more critiques roll in I will decide what to do.

I'll replace with "do_drive_backup" unless you can think of a nice 
three-letter word to replace "do" so that I don't even have to perturb 
the alignment context ;)

>> +                          bool has_format, const char *format,
>> +                          enum MirrorSyncMode sync,
>> +                          bool has_mode, enum NewImageMode mode,
>> +                          bool has_speed, int64_t speed,
>> +                          bool has_bitmap, const char *bitmap,
>> +                          bool has_on_source_error,
>> +                          BlockdevOnError on_source_error,
>> +                          bool has_on_target_error,
>> +                          BlockdevOnError on_target_error,
>> +                          BlockCompletionFunc *cb, void *opaque,
>> +                          Error **errp);
>> +
>>   /* internal snapshot private data */
>>   typedef struct InternalSnapshotState {
>>       BlkTransactionState common;
>> @@ -1768,15 +1781,16 @@ static void
>> drive_backup_prepare(BlkTransactionState *common, Error **errp)
>>       state->aio_context = bdrv_get_aio_context(bs);
>>       aio_context_acquire(state->aio_context);
>> -    qmp_drive_backup(backup->device, backup->target,
>> -                     backup->has_format, backup->format,
>> -                     backup->sync,
>> -                     backup->has_mode, backup->mode,
>> -                     backup->has_speed, backup->speed,
>> -                     backup->has_bitmap, backup->bitmap,
>> -                     backup->has_on_source_error,
>> backup->on_source_error,
>> -                     backup->has_on_target_error,
>> backup->on_target_error,
>> -                     &local_err);
>> +    _drive_backup(backup->device, backup->target,
>> +                  backup->has_format, backup->format,
>> +                  backup->sync,
>> +                  backup->has_mode, backup->mode,
>> +                  backup->has_speed, backup->speed,
>> +                  backup->has_bitmap, backup->bitmap,
>> +                  backup->has_on_source_error, backup->on_source_error,
>> +                  backup->has_on_target_error, backup->on_target_error,
>> +                  NULL, NULL,
>> +                  &local_err);
>>       if (local_err) {
>>           error_propagate(errp, local_err);
>>           return;
>> @@ -2717,15 +2731,18 @@ out:
>>       aio_context_release(aio_context);
>>   }
>> -void qmp_drive_backup(const char *device, const char *target,
>> -                      bool has_format, const char *format,
>> -                      enum MirrorSyncMode sync,
>> -                      bool has_mode, enum NewImageMode mode,
>> -                      bool has_speed, int64_t speed,
>> -                      bool has_bitmap, const char *bitmap,
>> -                      bool has_on_source_error, BlockdevOnError
>> on_source_error,
>> -                      bool has_on_target_error, BlockdevOnError
>> on_target_error,
>> -                      Error **errp)
>> +static void _drive_backup(const char *device, const char *target,
>> +                          bool has_format, const char *format,
>> +                          enum MirrorSyncMode sync,
>> +                          bool has_mode, enum NewImageMode mode,
>> +                          bool has_speed, int64_t speed,
>> +                          bool has_bitmap, const char *bitmap,
>> +                          bool has_on_source_error,
>> +                          BlockdevOnError on_source_error,
>> +                          bool has_on_target_error,
>> +                          BlockdevOnError on_target_error,
>> +                          BlockCompletionFunc *cb, void *opaque,
>> +                          Error **errp)
>>   {
>>       BlockDriverState *bs;
>>       BlockDriverState *target_bs;
>> @@ -2837,9 +2854,15 @@ void qmp_drive_backup(const char *device, const
>> char *target,
>>           }
>>       }
>> +    if (cb == NULL) {
>> +        cb = block_job_cb;
>> +    }
>> +    if (opaque == NULL) {
>> +        opaque = bs;
>> +    }
>>       backup_start(bs, target_bs, speed, sync, bmap,
>>                    on_source_error, on_target_error,
>> -                 block_job_cb, bs, &local_err);
>> +                 cb, opaque, &local_err);
>>       if (local_err != NULL) {
>>           bdrv_unref(target_bs);
>>           error_propagate(errp, local_err);
>> @@ -2850,6 +2873,22 @@ out:
>>       aio_context_release(aio_context);
>>   }
>> +void qmp_drive_backup(const char *device, const char *target,
>> +                      bool has_format, const char *format,
>> +                      enum MirrorSyncMode sync,
>> +                      bool has_mode, enum NewImageMode mode,
>> +                      bool has_speed, int64_t speed,
>> +                      bool has_bitmap, const char *bitmap,
>> +                      bool has_on_source_error, BlockdevOnError
>> on_source_error,
>> +                      bool has_on_target_error, BlockdevOnError
>> on_target_error,
>> +                      Error **errp)
>> +{
>> +    _drive_backup(device, target, has_format, format, sync, has_mode,
>> mode,
>> +                  has_speed, speed, has_bitmap, bitmap,
>> has_on_source_error,
>> +                  on_source_error, has_on_target_error, on_target_error,
>> +                  NULL, NULL, errp);
>> +}
>> +
>>   BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
>>   {
>>       return bdrv_named_nodes_list();
>
Max Reitz March 17, 2015, 7:33 p.m. UTC | #3
On 2015-03-17 at 15:16, John Snow wrote:
>
>
> On 03/17/2015 02:51 PM, Max Reitz wrote:
>> On 2015-03-04 at 23:15, John Snow wrote:
>>> We'd like to be able to specify the callback given to backup_start
>>> manually in the case of transactions, so split apart qmp_drive_backup
>>> into an implementation and a wrapper.
>>>
>>> Switch drive_backup_prepare to use the new wrapper, but don't overload
>>> the callback and closure yet.
>>>
>>> This is kind of gross, but we need to forward-declare the wrapper for
>>> the drive_backup transaction to be able to use. I could try moving
>>> the transaction blocks lower instead, but I wanted (for v1, at least)
>>> to minimize code movement so that the core changes were easiest to see.
>>>
>>> If anyone has suggestions on organization, please suggest them.
>>>
>>> Signed-off-by: John Snow <jsnow@redhat.com>
>>> ---
>>>   blockdev.c | 77
>>> ++++++++++++++++++++++++++++++++++++++++++++++----------------
>>>   1 file changed, 58 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/blockdev.c b/blockdev.c
>>> index 3153ee7..9e3b9e9 100644
>>> --- a/blockdev.c
>>> +++ b/blockdev.c
>>> @@ -1449,6 +1449,19 @@ void
>>> undo_transaction_wrapper(BlkTransactionState *common)
>>>       blk_put_transaction_state(common);
>>>   }
>>> +static void _drive_backup(const char *device, const char *target,
>>
>> Please don't use leading underscores. (Please.)
>>
>> Just call it do_drive_backup() or something.
>>
>> Other than that, I'm okay with a forward-declaration; if you want to
>> move it, but I'd be fine with moving the code, too.
>>
>> With _drive_backup() being called do_drive_backup():
>>
>> Reviewed-by: Max Reitz <mreitz@redhat.com>
>>
>
> Moving the code around might be better, it just makes for a much 
> noisier patch. I made my decisions for v1 to keep code disturbed the 
> least.
>
> Once more critiques roll in I will decide what to do.
>
> I'll replace with "do_drive_backup" unless you can think of a nice 
> three-letter word to replace "do" so that I don't even have to perturb 
> the alignment context ;)

Well, you're still prepending "static", so I think you won't get around 
perturbing the context :-)

Max

>>> +                          bool has_format, const char *format,
>>> +                          enum MirrorSyncMode sync,
>>> +                          bool has_mode, enum NewImageMode mode,
>>> +                          bool has_speed, int64_t speed,
>>> +                          bool has_bitmap, const char *bitmap,
>>> +                          bool has_on_source_error,
>>> +                          BlockdevOnError on_source_error,
>>> +                          bool has_on_target_error,
>>> +                          BlockdevOnError on_target_error,
>>> +                          BlockCompletionFunc *cb, void *opaque,
>>> +                          Error **errp);
>>> +
>>>   /* internal snapshot private data */
>>>   typedef struct InternalSnapshotState {
>>>       BlkTransactionState common;
>>> @@ -1768,15 +1781,16 @@ static void
>>> drive_backup_prepare(BlkTransactionState *common, Error **errp)
>>>       state->aio_context = bdrv_get_aio_context(bs);
>>>       aio_context_acquire(state->aio_context);
>>> -    qmp_drive_backup(backup->device, backup->target,
>>> -                     backup->has_format, backup->format,
>>> -                     backup->sync,
>>> -                     backup->has_mode, backup->mode,
>>> -                     backup->has_speed, backup->speed,
>>> -                     backup->has_bitmap, backup->bitmap,
>>> -                     backup->has_on_source_error,
>>> backup->on_source_error,
>>> -                     backup->has_on_target_error,
>>> backup->on_target_error,
>>> -                     &local_err);
>>> +    _drive_backup(backup->device, backup->target,
>>> +                  backup->has_format, backup->format,
>>> +                  backup->sync,
>>> +                  backup->has_mode, backup->mode,
>>> +                  backup->has_speed, backup->speed,
>>> +                  backup->has_bitmap, backup->bitmap,
>>> +                  backup->has_on_source_error, 
>>> backup->on_source_error,
>>> +                  backup->has_on_target_error, 
>>> backup->on_target_error,
>>> +                  NULL, NULL,
>>> +                  &local_err);
>>>       if (local_err) {
>>>           error_propagate(errp, local_err);
>>>           return;
>>> @@ -2717,15 +2731,18 @@ out:
>>>       aio_context_release(aio_context);
>>>   }
>>> -void qmp_drive_backup(const char *device, const char *target,
>>> -                      bool has_format, const char *format,
>>> -                      enum MirrorSyncMode sync,
>>> -                      bool has_mode, enum NewImageMode mode,
>>> -                      bool has_speed, int64_t speed,
>>> -                      bool has_bitmap, const char *bitmap,
>>> -                      bool has_on_source_error, BlockdevOnError
>>> on_source_error,
>>> -                      bool has_on_target_error, BlockdevOnError
>>> on_target_error,
>>> -                      Error **errp)
>>> +static void _drive_backup(const char *device, const char *target,
>>> +                          bool has_format, const char *format,
>>> +                          enum MirrorSyncMode sync,
>>> +                          bool has_mode, enum NewImageMode mode,
>>> +                          bool has_speed, int64_t speed,
>>> +                          bool has_bitmap, const char *bitmap,
>>> +                          bool has_on_source_error,
>>> +                          BlockdevOnError on_source_error,
>>> +                          bool has_on_target_error,
>>> +                          BlockdevOnError on_target_error,
>>> +                          BlockCompletionFunc *cb, void *opaque,
>>> +                          Error **errp)
>>>   {
>>>       BlockDriverState *bs;
>>>       BlockDriverState *target_bs;
>>> @@ -2837,9 +2854,15 @@ void qmp_drive_backup(const char *device, const
>>> char *target,
>>>           }
>>>       }
>>> +    if (cb == NULL) {
>>> +        cb = block_job_cb;
>>> +    }
>>> +    if (opaque == NULL) {
>>> +        opaque = bs;
>>> +    }
>>>       backup_start(bs, target_bs, speed, sync, bmap,
>>>                    on_source_error, on_target_error,
>>> -                 block_job_cb, bs, &local_err);
>>> +                 cb, opaque, &local_err);
>>>       if (local_err != NULL) {
>>>           bdrv_unref(target_bs);
>>>           error_propagate(errp, local_err);
>>> @@ -2850,6 +2873,22 @@ out:
>>>       aio_context_release(aio_context);
>>>   }
>>> +void qmp_drive_backup(const char *device, const char *target,
>>> +                      bool has_format, const char *format,
>>> +                      enum MirrorSyncMode sync,
>>> +                      bool has_mode, enum NewImageMode mode,
>>> +                      bool has_speed, int64_t speed,
>>> +                      bool has_bitmap, const char *bitmap,
>>> +                      bool has_on_source_error, BlockdevOnError
>>> on_source_error,
>>> +                      bool has_on_target_error, BlockdevOnError
>>> on_target_error,
>>> +                      Error **errp)
>>> +{
>>> +    _drive_backup(device, target, has_format, format, sync, has_mode,
>>> mode,
>>> +                  has_speed, speed, has_bitmap, bitmap,
>>> has_on_source_error,
>>> +                  on_source_error, has_on_target_error, 
>>> on_target_error,
>>> +                  NULL, NULL, errp);
>>> +}
>>> +
>>>   BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
>>>   {
>>>       return bdrv_named_nodes_list();
>>
>
Eric Blake March 17, 2015, 8:15 p.m. UTC | #4
On 03/17/2015 01:16 PM, John Snow wrote:

>> Other than that, I'm okay with a forward-declaration; if you want to
>> move it, but I'd be fine with moving the code, too.
>>
>> With _drive_backup() being called do_drive_backup():
>>
>> Reviewed-by: Max Reitz <mreitz@redhat.com>
>>
> 
> Moving the code around might be better, it just makes for a much noisier
> patch. I made my decisions for v1 to keep code disturbed the least.
> 
> Once more critiques roll in I will decide what to do.

I like avoiding forward declarations for non-recursive static functions
(aka topological sorting); but if you do code motion, do it in a
separate patch from the other changes.
diff mbox

Patch

diff --git a/blockdev.c b/blockdev.c
index 3153ee7..9e3b9e9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1449,6 +1449,19 @@  void undo_transaction_wrapper(BlkTransactionState *common)
     blk_put_transaction_state(common);
 }
 
+static void _drive_backup(const char *device, const char *target,
+                          bool has_format, const char *format,
+                          enum MirrorSyncMode sync,
+                          bool has_mode, enum NewImageMode mode,
+                          bool has_speed, int64_t speed,
+                          bool has_bitmap, const char *bitmap,
+                          bool has_on_source_error,
+                          BlockdevOnError on_source_error,
+                          bool has_on_target_error,
+                          BlockdevOnError on_target_error,
+                          BlockCompletionFunc *cb, void *opaque,
+                          Error **errp);
+
 /* internal snapshot private data */
 typedef struct InternalSnapshotState {
     BlkTransactionState common;
@@ -1768,15 +1781,16 @@  static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
     state->aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(state->aio_context);
 
-    qmp_drive_backup(backup->device, backup->target,
-                     backup->has_format, backup->format,
-                     backup->sync,
-                     backup->has_mode, backup->mode,
-                     backup->has_speed, backup->speed,
-                     backup->has_bitmap, backup->bitmap,
-                     backup->has_on_source_error, backup->on_source_error,
-                     backup->has_on_target_error, backup->on_target_error,
-                     &local_err);
+    _drive_backup(backup->device, backup->target,
+                  backup->has_format, backup->format,
+                  backup->sync,
+                  backup->has_mode, backup->mode,
+                  backup->has_speed, backup->speed,
+                  backup->has_bitmap, backup->bitmap,
+                  backup->has_on_source_error, backup->on_source_error,
+                  backup->has_on_target_error, backup->on_target_error,
+                  NULL, NULL,
+                  &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -2717,15 +2731,18 @@  out:
     aio_context_release(aio_context);
 }
 
-void qmp_drive_backup(const char *device, const char *target,
-                      bool has_format, const char *format,
-                      enum MirrorSyncMode sync,
-                      bool has_mode, enum NewImageMode mode,
-                      bool has_speed, int64_t speed,
-                      bool has_bitmap, const char *bitmap,
-                      bool has_on_source_error, BlockdevOnError on_source_error,
-                      bool has_on_target_error, BlockdevOnError on_target_error,
-                      Error **errp)
+static void _drive_backup(const char *device, const char *target,
+                          bool has_format, const char *format,
+                          enum MirrorSyncMode sync,
+                          bool has_mode, enum NewImageMode mode,
+                          bool has_speed, int64_t speed,
+                          bool has_bitmap, const char *bitmap,
+                          bool has_on_source_error,
+                          BlockdevOnError on_source_error,
+                          bool has_on_target_error,
+                          BlockdevOnError on_target_error,
+                          BlockCompletionFunc *cb, void *opaque,
+                          Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *target_bs;
@@ -2837,9 +2854,15 @@  void qmp_drive_backup(const char *device, const char *target,
         }
     }
 
+    if (cb == NULL) {
+        cb = block_job_cb;
+    }
+    if (opaque == NULL) {
+        opaque = bs;
+    }
     backup_start(bs, target_bs, speed, sync, bmap,
                  on_source_error, on_target_error,
-                 block_job_cb, bs, &local_err);
+                 cb, opaque, &local_err);
     if (local_err != NULL) {
         bdrv_unref(target_bs);
         error_propagate(errp, local_err);
@@ -2850,6 +2873,22 @@  out:
     aio_context_release(aio_context);
 }
 
+void qmp_drive_backup(const char *device, const char *target,
+                      bool has_format, const char *format,
+                      enum MirrorSyncMode sync,
+                      bool has_mode, enum NewImageMode mode,
+                      bool has_speed, int64_t speed,
+                      bool has_bitmap, const char *bitmap,
+                      bool has_on_source_error, BlockdevOnError on_source_error,
+                      bool has_on_target_error, BlockdevOnError on_target_error,
+                      Error **errp)
+{
+    _drive_backup(device, target, has_format, format, sync, has_mode, mode,
+                  has_speed, speed, has_bitmap, bitmap, has_on_source_error,
+                  on_source_error, has_on_target_error, on_target_error,
+                  NULL, NULL, errp);
+}
+
 BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
 {
     return bdrv_named_nodes_list();