The qcow2 .bdrv_measure() code calculates the crypto payload offset. This logic really belongs in block/crypto.c where it can be reused by other image formats.
The "luks" block driver will need this same logic in order to implement .bdrv_measure(), so extract the block_crypto_calculate_payload_offset() function now. Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com> --- block/crypto.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ block/crypto.h | 5 ++++ block/qcow2.c | 59 ++++------------------------------------------ 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/block/crypto.c b/block/crypto.c index 24823835c1..ed32202fa2 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -185,6 +185,70 @@ block_crypto_create_opts_init(QDict *opts, Error **errp) } +static ssize_t block_crypto_headerlen_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 block_crypto_headerlen_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 crypto header */ +bool block_crypto_calculate_payload_offset(QemuOpts *opts, + const char *optprefix, + size_t *len, + Error **errp) +{ + QDict *cryptoopts_qdict; + QCryptoBlockCreateOptions *cryptoopts; + QCryptoBlock *crypto; + + /* Extract options into a qdict */ + if (optprefix) { + QDict *opts_qdict = qemu_opts_to_qdict(opts, NULL); + + qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, optprefix); + qobject_unref(opts_qdict); + } else { + cryptoopts_qdict = qemu_opts_to_qdict(opts, NULL); + } + + /* 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, optprefix, + block_crypto_headerlen_hdr_init_func, + block_crypto_headerlen_hdr_write_func, + len, errp); + qapi_free_QCryptoBlockCreateOptions(cryptoopts); + if (!crypto) { + return false; + } + + qcrypto_block_free(crypto); + return true; +} + + static int block_crypto_open_generic(QCryptoBlockFormat format, QemuOptsList *opts_spec, BlockDriverState *bs, diff --git a/block/crypto.h b/block/crypto.h index b935695e79..5a39bee71b 100644 --- a/block/crypto.h +++ b/block/crypto.h @@ -94,4 +94,9 @@ block_crypto_create_opts_init(QDict *opts, Error **errp); QCryptoBlockOpenOptions * block_crypto_open_opts_init(QDict *opts, Error **errp); +bool block_crypto_calculate_payload_offset(QemuOpts *opts, + const char *optprefix, + size_t *len, + Error **errp); + #endif /* BLOCK_CRYPTO_H */ diff --git a/block/qcow2.c b/block/qcow2.c index cef9d72b3a..3aaf79bbf6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4609,60 +4609,6 @@ 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) { @@ -4715,7 +4661,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, if (has_luks) { size_t headerlen; - if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) { + if (!block_crypto_calculate_payload_offset(opts, + "encrypt.", + &headerlen, + &local_err)) { goto err; } -- 2.24.1