@@ -1841,17 +1841,8 @@ typedef struct DriveBackupState {
BlockJob *job;
} DriveBackupState;
-static void do_drive_backup(const char *job_id, 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,
- BlockJobTxn *txn, Error **errp);
+static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
+ Error **errp);
static void drive_backup_prepare(BlkActionState *common, Error **errp)
{
@@ -1874,16 +1865,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
bdrv_drained_begin(bs);
state->bs = bs;
- do_drive_backup(backup->has_job_id ? backup->job_id : NULL,
- 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,
- common->block_job_txn, &local_err);
+ do_drive_backup(backup, common->block_job_txn, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -3134,17 +3116,7 @@ out:
aio_context_release(aio_context);
}
-static void do_drive_backup(const char *job_id, 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,
- BlockJobTxn *txn, Error **errp)
+static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp)
{
BlockDriverState *bs;
BlockDriverState *target_bs;
@@ -3156,20 +3128,23 @@ static void do_drive_backup(const char *job_id, const char *device,
int flags;
int64_t size;
- if (!has_speed) {
- speed = 0;
+ if (!backup->has_speed) {
+ backup->speed = 0;
}
- if (!has_on_source_error) {
- on_source_error = BLOCKDEV_ON_ERROR_REPORT;
+ if (!backup->has_on_source_error) {
+ backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
}
- if (!has_on_target_error) {
- on_target_error = BLOCKDEV_ON_ERROR_REPORT;
+ if (!backup->has_on_target_error) {
+ backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
}
- if (!has_mode) {
- mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+ if (!backup->has_mode) {
+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+ }
+ if (!backup->has_job_id) {
+ backup->job_id = NULL;
}
- bs = qmp_get_root_bs(device, errp);
+ bs = qmp_get_root_bs(backup->device, errp);
if (!bs) {
return;
}
@@ -3177,8 +3152,9 @@ static void do_drive_backup(const char *job_id, const char *device,
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
- if (!has_format) {
- format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
+ if (!backup->has_format) {
+ backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
+ NULL : (char*) bs->drv->format_name;
}
/* Early check to avoid creating target */
@@ -3190,13 +3166,13 @@ static void do_drive_backup(const char *job_id, const char *device,
/* See if we have a backing HD we can use to create our new image
* on top of. */
- if (sync == MIRROR_SYNC_MODE_TOP) {
+ if (backup->sync == MIRROR_SYNC_MODE_TOP) {
source = backing_bs(bs);
if (!source) {
- sync = MIRROR_SYNC_MODE_FULL;
+ backup->sync = MIRROR_SYNC_MODE_FULL;
}
}
- if (sync == MIRROR_SYNC_MODE_NONE) {
+ if (backup->sync == MIRROR_SYNC_MODE_NONE) {
source = bs;
}
@@ -3206,14 +3182,14 @@ static void do_drive_backup(const char *job_id, const char *device,
goto out;
}
- if (mode != NEW_IMAGE_MODE_EXISTING) {
- assert(format);
+ if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
+ assert(backup->format);
if (source) {
- bdrv_img_create(target, format, source->filename,
+ bdrv_img_create(backup->target, backup->format, source->filename,
source->drv->format_name, NULL,
size, flags, &local_err, false);
} else {
- bdrv_img_create(target, format, NULL, NULL, NULL,
+ bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
size, flags, &local_err, false);
}
}
@@ -3223,29 +3199,29 @@ static void do_drive_backup(const char *job_id, const char *device,
goto out;
}
- if (format) {
+ if (backup->format) {
options = qdict_new();
- qdict_put(options, "driver", qstring_from_str(format));
+ qdict_put(options, "driver", qstring_from_str(backup->format));
}
- target_bs = bdrv_open(target, NULL, options, flags, errp);
+ target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
if (!target_bs) {
goto out;
}
bdrv_set_aio_context(target_bs, aio_context);
- if (has_bitmap) {
- bmap = bdrv_find_dirty_bitmap(bs, bitmap);
+ if (backup->has_bitmap) {
+ bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
if (!bmap) {
- error_setg(errp, "Bitmap '%s' could not be found", bitmap);
+ error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
bdrv_unref(target_bs);
goto out;
}
}
- backup_start(job_id, bs, target_bs, speed, sync, bmap,
- on_source_error, on_target_error,
+ backup_start(backup->job_id, bs, target_bs, backup->speed, backup->sync,
+ bmap, backup->on_source_error, backup->on_target_error,
block_job_cb, bs, txn, &local_err);
bdrv_unref(target_bs);
if (local_err != NULL) {
@@ -3257,24 +3233,9 @@ out:
aio_context_release(aio_context);
}
-void qmp_drive_backup(bool has_job_id, const char *job_id,
- 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)
+void qmp_drive_backup(DriveBackup *arg, Error **errp)
{
- return do_drive_backup(has_job_id ? job_id : NULL, 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, errp);
+ return do_drive_backup(arg, NULL, errp);
}
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
@@ -1109,8 +1109,16 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
const char *format = qdict_get_try_str(qdict, "format");
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
bool full = qdict_get_try_bool(qdict, "full", false);
- enum NewImageMode mode;
Error *err = NULL;
+ DriveBackup backup = {
+ .device = (char *)device,
+ .target = (char *)filename,
+ .has_format = !!format,
+ .format = (char *)format,
+ .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
+ .has_mode = true,
+ .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
+ };
if (!filename) {
error_setg(&err, QERR_MISSING_PARAMETER, "target");
@@ -1118,16 +1126,7 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
return;
}
- if (reuse) {
- mode = NEW_IMAGE_MODE_EXISTING;
- } else {
- mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
- }
-
- qmp_drive_backup(false, NULL, device, filename, !!format, format,
- full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
- true, mode, false, 0, false, NULL,
- false, 0, false, 0, &err);
+ qmp_drive_backup(&backup, &err);
hmp_handle_error(mon, &err);
}
@@ -1091,7 +1091,8 @@
#
# Since 1.6
##
-{ 'command': 'drive-backup', 'data': 'DriveBackup' }
+{ 'command': 'drive-backup', 'boxed': true,
+ 'data': 'DriveBackup' }
##
# @blockdev-backup