|
|
ddf19c |
From e56abd782be8bb41bb07c0317d008f95ec9a8ee5 Mon Sep 17 00:00:00 2001
|
|
|
ddf19c |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
ddf19c |
Date: Wed, 3 Jun 2020 16:03:20 +0100
|
|
|
ddf19c |
Subject: [PATCH 21/26] backup: Make sure that source and target size match
|
|
|
ddf19c |
|
|
|
ddf19c |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
ddf19c |
Message-id: <20200603160325.67506-7-kwolf@redhat.com>
|
|
|
ddf19c |
Patchwork-id: 97107
|
|
|
ddf19c |
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 06/11] backup: Make sure that source and target size match
|
|
|
ddf19c |
Bugzilla: 1778593
|
|
|
ddf19c |
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
ddf19c |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
ddf19c |
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
|
ddf19c |
|
|
|
ddf19c |
Since the introduction of a backup filter node in commit 00e30f05d, the
|
|
|
ddf19c |
backup block job crashes when the target image is smaller than the
|
|
|
ddf19c |
source image because it will try to write after the end of the target
|
|
|
ddf19c |
node without having BLK_PERM_RESIZE. (Previously, the BlockBackend layer
|
|
|
ddf19c |
would have caught this and errored out gracefully.)
|
|
|
ddf19c |
|
|
|
ddf19c |
We can fix this and even do better than the old behaviour: Check that
|
|
|
ddf19c |
source and target have the same image size at the start of the block job
|
|
|
ddf19c |
and unshare BLK_PERM_RESIZE. (This permission was already unshared
|
|
|
ddf19c |
before the same commit 00e30f05d, but the BlockBackend that was used to
|
|
|
ddf19c |
make the restriction was removed without a replacement.) This will
|
|
|
ddf19c |
immediately error out when starting the job instead of only when writing
|
|
|
ddf19c |
to a block that doesn't exist in the target.
|
|
|
ddf19c |
|
|
|
ddf19c |
Longer target than source would technically work because we would never
|
|
|
ddf19c |
write to blocks that don't exist, but semantically these are invalid,
|
|
|
ddf19c |
too, because a backup is supposed to create a copy, not just an image
|
|
|
ddf19c |
that starts with a copy.
|
|
|
ddf19c |
|
|
|
ddf19c |
Fixes: 00e30f05de1d19586345ec373970ef4c192c6270
|
|
|
ddf19c |
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1778593
|
|
|
ddf19c |
Cc: qemu-stable@nongnu.org
|
|
|
ddf19c |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ddf19c |
Message-Id: <20200430142755.315494-4-kwolf@redhat.com>
|
|
|
ddf19c |
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
ddf19c |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ddf19c |
(cherry picked from commit 958a04bd32af18d9a207bcc78046e56a202aebc2)
|
|
|
ddf19c |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ddf19c |
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
|
ddf19c |
---
|
|
|
ddf19c |
block/backup-top.c | 14 +++++++++-----
|
|
|
ddf19c |
block/backup.c | 14 +++++++++++++-
|
|
|
ddf19c |
2 files changed, 22 insertions(+), 6 deletions(-)
|
|
|
ddf19c |
|
|
|
ddf19c |
diff --git a/block/backup-top.c b/block/backup-top.c
|
|
|
ddf19c |
index b8d863f..6756091 100644
|
|
|
ddf19c |
--- a/block/backup-top.c
|
|
|
ddf19c |
+++ b/block/backup-top.c
|
|
|
ddf19c |
@@ -143,8 +143,10 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
|
|
ddf19c |
*
|
|
|
ddf19c |
* Share write to target (child_file), to not interfere
|
|
|
ddf19c |
* with guest writes to its disk which may be in target backing chain.
|
|
|
ddf19c |
+ * Can't resize during a backup block job because we check the size
|
|
|
ddf19c |
+ * only upfront.
|
|
|
ddf19c |
*/
|
|
|
ddf19c |
- *nshared = BLK_PERM_ALL;
|
|
|
ddf19c |
+ *nshared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
|
|
|
ddf19c |
*nperm = BLK_PERM_WRITE;
|
|
|
ddf19c |
} else {
|
|
|
ddf19c |
/* Source child */
|
|
|
ddf19c |
@@ -154,7 +156,7 @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
|
|
ddf19c |
if (perm & BLK_PERM_WRITE) {
|
|
|
ddf19c |
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
|
|
|
ddf19c |
}
|
|
|
ddf19c |
- *nshared &= ~BLK_PERM_WRITE;
|
|
|
ddf19c |
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
|
|
|
ddf19c |
}
|
|
|
ddf19c |
}
|
|
|
ddf19c |
|
|
|
ddf19c |
@@ -187,10 +189,12 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
|
|
|
ddf19c |
{
|
|
|
ddf19c |
Error *local_err = NULL;
|
|
|
ddf19c |
BDRVBackupTopState *state;
|
|
|
ddf19c |
- BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
|
|
|
ddf19c |
- filter_node_name,
|
|
|
ddf19c |
- BDRV_O_RDWR, errp);
|
|
|
ddf19c |
+ BlockDriverState *top;
|
|
|
ddf19c |
+
|
|
|
ddf19c |
+ assert(source->total_sectors == target->total_sectors);
|
|
|
ddf19c |
|
|
|
ddf19c |
+ top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name,
|
|
|
ddf19c |
+ BDRV_O_RDWR, errp);
|
|
|
ddf19c |
if (!top) {
|
|
|
ddf19c |
return NULL;
|
|
|
ddf19c |
}
|
|
|
ddf19c |
diff --git a/block/backup.c b/block/backup.c
|
|
|
ddf19c |
index 7c6ddd2..821c9fb 100644
|
|
|
ddf19c |
--- a/block/backup.c
|
|
|
ddf19c |
+++ b/block/backup.c
|
|
|
ddf19c |
@@ -348,7 +348,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
|
ddf19c |
BlockCompletionFunc *cb, void *opaque,
|
|
|
ddf19c |
JobTxn *txn, Error **errp)
|
|
|
ddf19c |
{
|
|
|
ddf19c |
- int64_t len;
|
|
|
ddf19c |
+ int64_t len, target_len;
|
|
|
ddf19c |
BackupBlockJob *job = NULL;
|
|
|
ddf19c |
int64_t cluster_size;
|
|
|
ddf19c |
BdrvRequestFlags write_flags;
|
|
|
ddf19c |
@@ -413,6 +413,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
|
ddf19c |
goto error;
|
|
|
ddf19c |
}
|
|
|
ddf19c |
|
|
|
ddf19c |
+ target_len = bdrv_getlength(target);
|
|
|
ddf19c |
+ if (target_len < 0) {
|
|
|
ddf19c |
+ error_setg_errno(errp, -target_len, "Unable to get length for '%s'",
|
|
|
ddf19c |
+ bdrv_get_device_or_node_name(bs));
|
|
|
ddf19c |
+ goto error;
|
|
|
ddf19c |
+ }
|
|
|
ddf19c |
+
|
|
|
ddf19c |
+ if (target_len != len) {
|
|
|
ddf19c |
+ error_setg(errp, "Source and target image have different sizes");
|
|
|
ddf19c |
+ goto error;
|
|
|
ddf19c |
+ }
|
|
|
ddf19c |
+
|
|
|
ddf19c |
cluster_size = backup_calculate_cluster_size(target, errp);
|
|
|
ddf19c |
if (cluster_size < 0) {
|
|
|
ddf19c |
goto error;
|
|
|
ddf19c |
--
|
|
|
ddf19c |
1.8.3.1
|
|
|
ddf19c |
|