aboutsummaryrefslogtreecommitdiff
path: root/block/crypto.c
diff options
context:
space:
mode:
authorMaxim Levitsky <mlevitsk@redhat.com>2019-07-16 19:19:01 +0300
committerMax Reitz <mreitz@redhat.com>2019-08-19 17:13:26 +0200
commit672de729a1f93d84e7597652b1125ab5d62421d8 (patch)
treeb14e47186208d27681bdda241dea1be4df680a1c /block/crypto.c
parent3fbd3405d2b0604ea530fc7a1828f19da1e95ff9 (diff)
LUKS: support preallocation
preallocation=off and preallocation=metadata both allocate luks header only, and preallocation=falloc/full is passed to underlying file. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1534951 Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Message-id: 20190716161901.1430-1-mlevitsk@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'block/crypto.c')
-rw-r--r--block/crypto.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/block/crypto.c b/block/crypto.c
index 8237424ae6..7eb698774e 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -74,6 +74,7 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
struct BlockCryptoCreateData {
BlockBackend *blk;
uint64_t size;
+ PreallocMode prealloc;
};
@@ -112,7 +113,7 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
* available to the guest, so we must take account of that
* which will be used by the crypto header
*/
- return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
+ return blk_truncate(data->blk, data->size + headerlen, data->prealloc,
errp);
}
@@ -251,6 +252,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
static int block_crypto_co_create_generic(BlockDriverState *bs,
int64_t size,
QCryptoBlockCreateOptions *opts,
+ PreallocMode prealloc,
Error **errp)
{
int ret;
@@ -266,9 +268,14 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
goto cleanup;
}
+ if (prealloc == PREALLOC_MODE_METADATA) {
+ prealloc = PREALLOC_MODE_OFF;
+ }
+
data = (struct BlockCryptoCreateData) {
.blk = blk,
.size = size,
+ .prealloc = prealloc,
};
crypto = qcrypto_block_create(opts, NULL,
@@ -500,6 +507,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
BlockdevCreateOptionsLUKS *luks_opts;
BlockDriverState *bs = NULL;
QCryptoBlockCreateOptions create_opts;
+ PreallocMode preallocation = PREALLOC_MODE_OFF;
int ret;
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
@@ -515,8 +523,12 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
.u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
};
+ if (luks_opts->has_preallocation) {
+ preallocation = luks_opts->preallocation;
+ }
+
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
- errp);
+ preallocation, errp);
if (ret < 0) {
goto fail;
}
@@ -534,12 +546,24 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
QCryptoBlockCreateOptions *create_opts = NULL;
BlockDriverState *bs = NULL;
QDict *cryptoopts;
+ PreallocMode prealloc;
+ char *buf = NULL;
int64_t size;
int ret;
+ Error *local_err = NULL;
/* Parse options */
size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+ buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
+ PREALLOC_MODE_OFF, &local_err);
+ g_free(buf);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return -EINVAL;
+ }
+
cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
&block_crypto_create_opts_luks,
true);
@@ -565,7 +589,7 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
}
/* Create format layer */
- ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
+ ret = block_crypto_co_create_generic(bs, size, create_opts, prealloc, errp);
if (ret < 0) {
goto fail;
}