aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2021-03-26 15:55:08 +0100
committerMax Reitz <mreitz@redhat.com>2021-03-30 13:02:10 +0200
commit484108293d94d80acd5a2f4332eaea5e2605947a (patch)
treeb7027cc72f7680b4d68d40f0eaccd4afa18cc6b0 /block
parent220222a0fecf0fbd9f49633abef552dd019ab9cd (diff)
qcow2: Force preallocation with data-file-raw
Setting the qcow2 data-file-raw bit means that you can ignore the qcow2 metadata when reading from the external data file. It does not mean that you have to ignore it, though. Therefore, the data read must be the same regardless of whether you interpret the metadata or whether you ignore it, and thus the L1/L2 tables must all be present and give a 1:1 mapping. This patch changes 244's output: First, the qcow2 file is larger right after creation, because of metadata preallocation. Second, the qemu-img map output changes: Everything that was not explicitly discarded or zeroed is now a data area. Signed-off-by: Max Reitz <mreitz@redhat.com> Message-Id: <20210326145509.163455-2-mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/qcow2.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/block/qcow2.c b/block/qcow2.c
index 2fb43c6f7e..9727ae8fe3 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3503,6 +3503,28 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
ret = -EINVAL;
goto out;
}
+ if (qcow2_opts->data_file_raw &&
+ qcow2_opts->preallocation == PREALLOC_MODE_OFF)
+ {
+ /*
+ * data-file-raw means that "the external data file can be
+ * read as a consistent standalone raw image without looking
+ * at the qcow2 metadata." It does not say that the metadata
+ * must be ignored, though (and the qcow2 driver in fact does
+ * not ignore it), so the L1/L2 tables must be present and
+ * give a 1:1 mapping, so you get the same result regardless
+ * of whether you look at the metadata or whether you ignore
+ * it.
+ */
+ qcow2_opts->preallocation = PREALLOC_MODE_METADATA;
+
+ /*
+ * Cannot use preallocation with backing files, but giving a
+ * backing file when specifying data_file_raw is an error
+ * anyway.
+ */
+ assert(!qcow2_opts->has_backing_file);
+ }
if (qcow2_opts->data_file) {
if (version < 3) {
@@ -4238,6 +4260,18 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
goto fail;
}
+
+ if (data_file_is_raw(bs) && prealloc == PREALLOC_MODE_OFF) {
+ /*
+ * When creating a qcow2 image with data-file-raw, we enforce
+ * at least prealloc=metadata, so that the L1/L2 tables are
+ * fully allocated and reading from the data file will return
+ * the same data as reading from the qcow2 image. When the
+ * image is grown, we must consequently preallocate the
+ * metadata structures to cover the added area.
+ */
+ prealloc = PREALLOC_MODE_METADATA;
+ }
}
switch (prealloc) {