Signed-off-by: Max Reitz <mre...@redhat.com> --- block/backup.c | 9 +++++---- blockdev.c | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/block/backup.c b/block/backup.c index 715e1d3be8..88435f883d 100644 --- a/block/backup.c +++ b/block/backup.c @@ -502,6 +502,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, { int ret; BlockDriverInfo bdi; + bool target_does_cow = bdrv_backing_chain_next(target); /* * If there is no backing file on the target, we cannot rely on COW if our @@ -509,7 +510,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, * targets with a backing file, try to avoid COW if possible. */ ret = bdrv_get_info(target, &bdi); - if (ret == -ENOTSUP && !target->backing) { + if (ret == -ENOTSUP && !target_does_cow) { /* Cluster size is not defined */ warn_report("The target block device doesn't provide " "information about the block size and it doesn't have a " @@ -518,14 +519,14 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, "this default, the backup may be unusable", BACKUP_CLUSTER_SIZE_DEFAULT); return BACKUP_CLUSTER_SIZE_DEFAULT; - } else if (ret < 0 && !target->backing) { + } else if (ret < 0 && !target_does_cow) { error_setg_errno(errp, -ret, "Couldn't determine the cluster size of the target image, " "which has no backing file"); error_append_hint(errp, "Aborting, since this may create an unusable destination image\n"); return ret; - } else if (ret < 0 && target->backing) { + } else if (ret < 0 && target_does_cow) { /* Not fatal; just trudge on ahead. */ return BACKUP_CLUSTER_SIZE_DEFAULT; } @@ -569,7 +570,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, return NULL; } - if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) { + if (compress && !bdrv_supports_compressed_writes(target)) { error_setg(errp, "Compression is not supported for this drive %s", bdrv_get_device_name(target)); return NULL; diff --git a/blockdev.c b/blockdev.c index 68e8d33447..605e7b0994 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3500,7 +3500,13 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, /* 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); + /* + * Backup will not replace the source by the target, so none + * of the filters skipped here will be removed (in contrast to + * mirror). Therefore, we can skip all of them when looking + * for the first COW relationship. + */ + source = bdrv_filtered_cow_bs(bdrv_skip_rw_filters(bs)); if (!source) { backup->sync = MIRROR_SYNC_MODE_FULL; } @@ -3520,9 +3526,14 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, if (backup->mode != NEW_IMAGE_MODE_EXISTING) { assert(backup->format); if (source) { - bdrv_refresh_filename(source); - bdrv_img_create(backup->target, backup->format, source->filename, - source->drv->format_name, NULL, + /* Implicit filters should not appear in the filename */ + BlockDriverState *explicit_backing = + bdrv_skip_implicit_filters(source); + + bdrv_refresh_filename(explicit_backing); + bdrv_img_create(backup->target, backup->format, + explicit_backing->filename, + explicit_backing->drv->format_name, NULL, size, flags, false, &local_err); } else { bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL, -- 2.21.0