qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Max Reitz" <mreitz@redhat.com>,
	"Kevin Wolf" <kwolf@redhat.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH 1/2] qcow2: include LUKS payload overhead in qemu-img measure
Date: Tue, 15 Jan 2019 11:10:06 +0000	[thread overview]
Message-ID: <20190115111007.27159-2-stefanha@redhat.com> (raw)
In-Reply-To: <20190115111007.27159-1-stefanha@redhat.com>

LUKS encryption reserves clusters for its own payload data.  The size of
this area must be included in the qemu-img measure calculation so that
we arrive at the correct minimum required image size.

(Ab)use the qcrypto_block_create() API to determine the payload
overhead.  We discard the payload data that qcrypto thinks will be
written to the image.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/qcow2.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 4897abae5e..7ab93a5d2f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4231,6 +4231,24 @@ 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;
+}
+
 static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
                                        Error **errp)
 {
@@ -4240,11 +4258,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);
@@ -4274,6 +4294,35 @@ 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) {
+        QCryptoBlockCreateOptions cryptoopts = {
+            .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+        };
+        QCryptoBlock *crypto;
+        size_t headerlen;
+
+        optstr = qemu_opt_get_del(opts, "encrypt.key-secret");
+        cryptoopts.u.luks.has_key_secret = !!optstr;
+        cryptoopts.u.luks.key_secret = optstr;
+
+        crypto = qcrypto_block_create(&cryptoopts, "encrypt.",
+                                      qcow2_measure_crypto_hdr_init_func,
+                                      qcow2_measure_crypto_hdr_write_func,
+                                      &headerlen, &local_err);
+
+        g_free(optstr);
+        if (!crypto) {
+            goto err;
+        }
+        qcrypto_block_free(crypto);
+
+        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);
 
@@ -4344,7 +4393,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
-- 
2.20.1

  reply	other threads:[~2019-01-15 11:10 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-15 11:10 [Qemu-devel] [PATCH 0/2] qcow2: include LUKS payload overhead in qemu-img measure Stefan Hajnoczi
2019-01-15 11:10 ` Stefan Hajnoczi [this message]
2019-01-21 13:08   ` [Qemu-devel] [PATCH 1/2] " Max Reitz
2019-01-21 13:15     ` Max Reitz
2019-01-21 13:29       ` Max Reitz
2019-01-21 13:45       ` Daniel P. Berrangé
2019-01-21 14:46         ` Stefan Hajnoczi
2019-01-15 11:10 ` [Qemu-devel] [PATCH 2/2] iotests: add LUKS payload overhead to 178 qemu-img measure test Stefan Hajnoczi
2019-01-21 13:13   ` Max Reitz
2019-01-15 11:49 ` [Qemu-devel] [PATCH 0/2] qcow2: include LUKS payload overhead in qemu-img measure Philippe Mathieu-Daudé
2019-01-21  1:51 ` no-reply
2019-01-21 10:35   ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190115111007.27159-2-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=berrange@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).