block: simplify drive-backup

Now that we can support boxed commands, use it to greatly reduce the
number of parameters (and likelihood of getting out of sync) when
adjusting drive-backup parameters.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Pavel Butsykin 2016-07-22 11:17:50 +03:00 committed by Kevin Wolf
parent 3ea1a09111
commit 81206a8987
3 changed files with 48 additions and 87 deletions

View File

@ -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)

21
hmp.c
View File

@ -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);
}

View File

@ -1091,7 +1091,8 @@
#
# Since 1.6
##
{ 'command': 'drive-backup', 'data': 'DriveBackup' }
{ 'command': 'drive-backup', 'boxed': true,
'data': 'DriveBackup' }
##
# @blockdev-backup