static void do_drive_backup(DriveBackup *backup, BlockJobTxn *txn, Error **errp) { BlockDriverState *bs; BlockDriverState *target_bs; BlockDriverState *source = NULL; BdrvDirtyBitmap *bmap = NULL; AioContext *aio_context; QDict *options = NULL; Error *local_err = NULL; int flags; int64_t size; if (!backup->has_speed) { backup->speed = 0; } if (!backup->has_on_source_error) { backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT; } if (!backup->has_on_target_error) { backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT; } 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(backup->device, errp); if (!bs) { return; } aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); if (!backup->has_format) { backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ? NULL : (char*) bs->drv->format_name; } /* Early check to avoid creating target */ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { goto out; } flags = bs->open_flags | BDRV_O_RDWR; /* See if we have a backing HD we can use to create our new image * on top of. */ if (backup->sync == MIRROR_SYNC_MODE_TOP) { source = backing_bs(bs); if (!source) { backup->sync = MIRROR_SYNC_MODE_FULL; } } if (backup->sync == MIRROR_SYNC_MODE_NONE) { source = bs; } size = bdrv_getlength(bs); if (size < 0) { error_setg_errno(errp, -size, "bdrv_getlength failed"); goto out; } if (backup->mode != NEW_IMAGE_MODE_EXISTING) { assert(backup->format); if (source) { bdrv_img_create(backup->target, backup->format, source->filename, source->drv->format_name, NULL, size, flags, &local_err, false); } else { bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL, size, flags, &local_err, false); } } if (local_err) { error_propagate(errp, local_err); goto out; } if (backup->format) { options = qdict_new(); qdict_put(options, "driver", qstring_from_str(backup->format)); } target_bs = bdrv_open(backup->target, NULL, options, flags, errp); if (!target_bs) { goto out; } bdrv_set_aio_context(target_bs, aio_context); if (backup->has_bitmap) { 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; } } 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) { error_propagate(errp, local_err); goto out; } out: aio_context_release(aio_context); }