aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2019-02-25 15:16:57 +0100
committerKevin Wolf <kwolf@redhat.com>2019-02-25 15:16:57 +0100
commit1b967e9f348d48788a2ab481d45398b80ce71fa6 (patch)
tree2e82fcbdb5617c9b7741ec4a9676904507356a94 /block/qcow2.c
parent83c68e149a9365a3db6de751f219ad1d79928462 (diff)
parent6a4e88e17966a963ee818daab3d0c9fa6bf73903 (diff)
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block
Block patches: - Fix various issues with bdrv_refresh_filename() - Fix various iotests - Include LUKS overhead in qemu-img measure for qcow2 - A fix for vmdk's image creation interface # gpg: Signature made Mon Feb 25 15:13:43 2019 CET # gpg: using RSA key F407DB0061D5CF40 # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * mreitz/tags/pull-block-2019-02-25: (45 commits) iotests: Skip 211 on insufficient memory vmdk: false positive of compat6 with hwversion not set iotests: add LUKS payload overhead to 178 qemu-img measure test qcow2: include LUKS payload overhead in qemu-img measure iotests.py: s/_/-/g on keys in qmp_log() iotests: Let 045 be run concurrently iotests: Filter SSH paths iotests.py: Filter filename in any string value iotests.py: Add is_str() iotests: Fix 207 to use QMP filters for qmp_log iotests: Fix 232 for LUKS iotests: Remove superfluous rm from 232 iotests: Fix 237 for Python 2.x iotests: Re-add filename filters iotests: Test json:{} filenames of internal BDSs block: BDS options may lack the "driver" option block/null: Generate filename even with latency-ns block/curl: Implement bdrv_refresh_filename() block/curl: Harmonize option defaults block/nvme: Fix bdrv_refresh_filename() ... Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/qcow2.c')
-rw-r--r--block/qcow2.c89
1 files changed, 85 insertions, 4 deletions
diff --git a/block/qcow2.c b/block/qcow2.c
index 65a54c9ac6..1de5e24613 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1474,13 +1474,15 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail;
}
- bs->backing_file[len] = '\0';
- s->image_backing_file = g_strdup(bs->backing_file);
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
}
/* Internal snapshots */
@@ -2518,6 +2520,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
return -EINVAL;
}
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
@@ -4232,6 +4236,60 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
return ret;
}
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
+ size_t headerlen, void *opaque, Error **errp)
+{
+ size_t *headerlenp = opaque;
+
+ /* Stash away the payload size */
+ *headerlenp = headerlen;
+ return 0;
+}
+
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
+ size_t offset, const uint8_t *buf, size_t buflen,
+ void *opaque, Error **errp)
+{
+ /* Discard the bytes, we're not actually writing to an image */
+ return buflen;
+}
+
+/* Determine the number of bytes for the LUKS payload */
+static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
+ Error **errp)
+{
+ QDict *opts_qdict;
+ QDict *cryptoopts_qdict;
+ QCryptoBlockCreateOptions *cryptoopts;
+ QCryptoBlock *crypto;
+
+ /* Extract "encrypt." options into a qdict */
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
+ qobject_unref(opts_qdict);
+
+ /* Build QCryptoBlockCreateOptions object from qdict */
+ qdict_put_str(cryptoopts_qdict, "format", "luks");
+ cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
+ qobject_unref(cryptoopts_qdict);
+ if (!cryptoopts) {
+ return false;
+ }
+
+ /* Fake LUKS creation in order to determine the payload size */
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
+ qcow2_measure_crypto_hdr_init_func,
+ qcow2_measure_crypto_hdr_write_func,
+ len, errp);
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
+ if (!crypto) {
+ return false;
+ }
+
+ qcrypto_block_free(crypto);
+ return true;
+}
+
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
Error **errp)
{
@@ -4241,11 +4299,13 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
uint64_t virtual_size; /* disk size as seen by guest */
uint64_t refcount_bits;
uint64_t l2_tables;
+ uint64_t luks_payload_size = 0;
size_t cluster_size;
int version;
char *optstr;
PreallocMode prealloc;
bool has_backing_file;
+ bool has_luks;
/* Parse image creation options */
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
@@ -4275,6 +4335,20 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
has_backing_file = !!optstr;
g_free(optstr);
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
+ g_free(optstr);
+
+ if (has_luks) {
+ size_t headerlen;
+
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
+ goto err;
+ }
+
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
+ }
+
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
virtual_size = ROUND_UP(virtual_size, cluster_size);
@@ -4345,7 +4419,7 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
info = g_new(BlockMeasureInfo, 1);
info->fully_allocated =
qcow2_calc_prealloc_size(virtual_size, cluster_size,
- ctz32(refcount_bits));
+ ctz32(refcount_bits)) + luks_payload_size;
/* Remove data clusters that are not required. This overestimates the
* required size because metadata needed for the fully allocated file is
@@ -4932,6 +5006,12 @@ static QemuOptsList qcow2_create_opts = {
}
};
+static const char *const qcow2_strong_runtime_opts[] = {
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
+
+ NULL
+};
+
BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcow2State),
@@ -4980,6 +5060,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_inactivate = qcow2_inactivate,
.create_opts = &qcow2_create_opts,
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
.bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options,