diff options
167 files changed, 8274 insertions, 1873 deletions
diff --git a/Makefile.objs b/Makefile.objs index 3e24c320c3..bfd5a6ceb1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -122,7 +122,6 @@ trace-events-subdirs += crypto trace-events-subdirs += io trace-events-subdirs += migration trace-events-subdirs += block -trace-events-subdirs += backends trace-events-subdirs += chardev trace-events-subdirs += hw/block trace-events-subdirs += hw/block/dataplane diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 2eef7daa01..46ce479dc3 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2274,6 +2274,11 @@ int kvm_has_intx_set_mask(void) return kvm_state->intx_set_mask; } +bool kvm_arm_supports_user_irq(void) +{ + return kvm_check_extension(kvm_state, KVM_CAP_ARM_USER_IRQ); +} + #ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc) diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index ef0c7346af..3965c528d3 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -155,4 +155,9 @@ void kvm_init_cpu_signals(CPUState *cpu) { abort(); } + +bool kvm_arm_supports_user_irq(void) +{ + return false; +} #endif diff --git a/backends/trace-events b/backends/trace-events deleted file mode 100644 index e69de29bb2..0000000000 --- a/backends/trace-events +++ /dev/null @@ -2185,6 +2185,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, ret = -EINVAL; goto free_exit; } + bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs)); /* Hook up the backing file link; drop our reference, bs owns the * backing_hd reference now */ @@ -2573,15 +2574,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, goto close_and_fail; } - if (!bdrv_key_required(bs)) { - bdrv_parent_cb_change_media(bs, true); - } else if (!runstate_check(RUN_STATE_PRELAUNCH) - && !runstate_check(RUN_STATE_INMIGRATE) - && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */ - error_setg(errp, - "Guest must be stopped for opening of encrypted image"); - goto close_and_fail; - } + bdrv_parent_cb_change_media(bs, true); QDECREF(options); @@ -2989,24 +2982,45 @@ error: void bdrv_reopen_commit(BDRVReopenState *reopen_state) { BlockDriver *drv; + BlockDriverState *bs; + bool old_can_write, new_can_write; assert(reopen_state != NULL); - drv = reopen_state->bs->drv; + bs = reopen_state->bs; + drv = bs->drv; assert(drv != NULL); + old_can_write = + !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE); + /* If there are any driver level actions to take */ if (drv->bdrv_reopen_commit) { drv->bdrv_reopen_commit(reopen_state); } /* set BDS specific flags now */ - QDECREF(reopen_state->bs->explicit_options); + QDECREF(bs->explicit_options); - reopen_state->bs->explicit_options = reopen_state->explicit_options; - reopen_state->bs->open_flags = reopen_state->flags; - reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); + bs->explicit_options = reopen_state->explicit_options; + bs->open_flags = reopen_state->flags; + bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); + + bdrv_refresh_limits(bs, NULL); - bdrv_refresh_limits(reopen_state->bs, NULL); + new_can_write = + !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE); + if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) { + Error *local_err = NULL; + if (drv->bdrv_reopen_bitmaps_rw(bs, &local_err) < 0) { + /* This is not fatal, bitmaps just left read-only, so all following + * writes will fail. User can remove read-only bitmaps to unblock + * writes. + */ + error_reportf_err(local_err, + "%s: Failed to make dirty bitmaps writable: ", + bdrv_get_node_name(bs)); + } + } } /* @@ -3040,9 +3054,6 @@ static void bdrv_close(BlockDriverState *bs) bdrv_flush(bs); bdrv_drain(bs); /* in case flush left pending I/O */ - bdrv_release_named_dirty_bitmaps(bs); - assert(QLIST_EMPTY(&bs->dirty_bitmaps)); - if (bs->drv) { BdrvChild *child, *next; @@ -3072,7 +3083,6 @@ static void bdrv_close(BlockDriverState *bs) bs->backing_format[0] = '\0'; bs->total_sectors = 0; bs->encrypted = false; - bs->valid_key = false; bs->sg = false; QDECREF(bs->options); QDECREF(bs->explicit_options); @@ -3081,6 +3091,9 @@ static void bdrv_close(BlockDriverState *bs) bs->full_open_options = NULL; } + bdrv_release_named_dirty_bitmaps(bs); + assert(QLIST_EMPTY(&bs->dirty_bitmaps)); + QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) { g_free(ban); } @@ -3398,7 +3411,8 @@ exit: /** * Truncate file to 'offset' bytes (needed only for file protocols) */ -int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp) +int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, + Error **errp) { BlockDriverState *bs = child->bs; BlockDriver *drv = bs->drv; @@ -3421,7 +3435,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp) assert(!(bs->open_flags & BDRV_O_INACTIVE)); - ret = drv->bdrv_truncate(bs, offset, errp); + ret = drv->bdrv_truncate(bs, offset, prealloc, errp); if (ret == 0) { ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); bdrv_dirty_bitmap_truncate(bs); @@ -3450,6 +3464,41 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs) return -ENOTSUP; } +/* + * bdrv_measure: + * @drv: Format driver + * @opts: Creation options for new image + * @in_bs: Existing image containing data for new image (may be NULL) + * @errp: Error object + * Returns: A #BlockMeasureInfo (free using qapi_free_BlockMeasureInfo()) + * or NULL on error + * + * Calculate file size required to create a new image. + * + * If @in_bs is given then space for allocated clusters and zero clusters + * from that image are included in the calculation. If @opts contains a + * backing file that is shared by @in_bs then backing clusters may be omitted + * from the calculation. + * + * If @in_bs is NULL then the calculation includes no allocated clusters + * unless a preallocation option is given in @opts. + * + * Note that @in_bs may use a different BlockDriver from @drv. + * + * If an error occurs the @errp pointer is set. + */ +BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, + BlockDriverState *in_bs, Error **errp) +{ + if (!drv->bdrv_measure) { + error_setg(errp, "Block driver '%s' does not support size measurement", + drv->format_name); + return NULL; + } + + return drv->bdrv_measure(opts, in_bs, errp); +} + /** * Return number of sectors on success, -errno on error. */ @@ -3502,72 +3551,6 @@ bool bdrv_is_encrypted(BlockDriverState *bs) return bs->encrypted; } -bool bdrv_key_required(BlockDriverState *bs) -{ - BdrvChild *backing = bs->backing; - - if (backing && backing->bs->encrypted && !backing->bs->valid_key) { - return true; - } - return (bs->encrypted && !bs->valid_key); -} - -int bdrv_set_key(BlockDriverState *bs, const char *key) -{ - int ret; - if (bs->backing && bs->backing->bs->encrypted) { - ret = bdrv_set_key(bs->backing->bs, key); - if (ret < 0) - return ret; - if (!bs->encrypted) - return 0; - } - if (!bs->encrypted) { - return -EINVAL; - } else if (!bs->drv || !bs->drv->bdrv_set_key) { - return -ENOMEDIUM; - } - ret = bs->drv->bdrv_set_key(bs, key); - if (ret < 0) { - bs->valid_key = false; - } else if (!bs->valid_key) { - /* call the change callback now, we skipped it on open */ - bs->valid_key = true; - bdrv_parent_cb_change_media(bs, true); - } - return ret; -} - -/* - * Provide an encryption key for @bs. - * If @key is non-null: - * If @bs is not encrypted, fail. - * Else if the key is invalid, fail. - * Else set @bs's key to @key, replacing the existing key, if any. - * If @key is null: - * If @bs is encrypted and still lacks a key, fail. - * Else do nothing. - * On failure, store an error object through @errp if non-null. - */ -void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp) -{ - if (key) { - if (!bdrv_is_encrypted(bs)) { - error_setg(errp, "Node '%s' is not encrypted", - bdrv_get_device_or_node_name(bs)); - } else if (bdrv_set_key(bs, key) < 0) { - error_setg(errp, QERR_INVALID_PASSWORD); - } - } else { - if (bdrv_key_required(bs)) { - error_set(errp, ERROR_CLASS_DEVICE_ENCRYPTED, - "'%s' (%s) is encrypted", - bdrv_get_device_or_node_name(bs), - bdrv_get_encrypted_filename(bs)); - } - } -} - const char *bdrv_get_format_name(BlockDriverState *bs) { return bs->drv ? bs->drv->format_name : NULL; @@ -4135,6 +4118,10 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs, } } + /* At this point persistent bitmaps should be already stored by the format + * driver */ + bdrv_release_persistent_dirty_bitmaps(bs); + return 0; } @@ -4933,3 +4920,25 @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp) parent_bs->drv->bdrv_del_child(parent_bs, child, errp); } + +bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp) +{ + BlockDriver *drv = bs->drv; + + if (!drv) { + error_setg_errno(errp, ENOMEDIUM, + "Can't store persistent bitmaps to %s", + bdrv_get_device_or_node_name(bs)); + return false; + } + + if (!drv->bdrv_can_store_new_dirty_bitmap) { + error_setg_errno(errp, ENOTSUP, + "Can't store persistent bitmaps to %s", + bdrv_get_device_or_node_name(bs)); + return false; + } + + return drv->bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp); +} diff --git a/block/Makefile.objs b/block/Makefile.objs index f9368b52b8..2aaede4ae1 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -1,5 +1,5 @@ block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o -block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o +block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o diff --git a/block/blkdebug.c b/block/blkdebug.c index b25856c49c..c19ab28f07 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -821,9 +821,10 @@ static int64_t blkdebug_getlength(BlockDriverState *bs) return bdrv_getlength(bs->file->bs); } -static int blkdebug_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int blkdebug_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { - return bdrv_truncate(bs->file, offset, errp); + return bdrv_truncate(bs->file, offset, prealloc, errp); } static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options) diff --git a/block/block-backend.c b/block/block-backend.c index 0df3457a09..fe3542b3f8 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1773,14 +1773,15 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, BDRV_REQ_WRITE_COMPRESSED); } -int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp) +int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc, + Error **errp) { if (!blk_is_available(blk)) { error_setg(errp, "No medium inserted"); return -ENOMEDIUM; } - return bdrv_truncate(blk->root, offset, errp); + return bdrv_truncate(blk->root, offset, prealloc, errp); } static void blk_pdiscard_entry(void *opaque) diff --git a/block/commit.c b/block/commit.c index 774a8a599c..13143608f8 100644 --- a/block/commit.c +++ b/block/commit.c @@ -163,7 +163,7 @@ static void coroutine_fn commit_run(void *opaque) } if (base_len < s->common.len) { - ret = blk_truncate(s->base, s->common.len, NULL); + ret = blk_truncate(s->base, s->common.len, PREALLOC_MODE_OFF, NULL); if (ret) { goto out; } @@ -521,7 +521,7 @@ int bdrv_commit(BlockDriverState *bs) * grow the backing file image if possible. If not possible, * we must return an error */ if (length > backing_length) { - ret = blk_truncate(backing, length, &local_err); + ret = blk_truncate(backing, length, PREALLOC_MODE_OFF, &local_err); if (ret < 0) { error_report_err(local_err); goto ro_cleanup; diff --git a/block/crypto.c b/block/crypto.c index 10e5ddccaa..58ef6f2f52 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -24,16 +24,10 @@ #include "sysemu/block-backend.h" #include "crypto/block.h" #include "qapi/opts-visitor.h" +#include "qapi/qobject-input-visitor.h" #include "qapi-visit.h" #include "qapi/error.h" - -#define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret" -#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg" -#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode" -#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg" -#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg" -#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg" -#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time" +#include "block/crypto.h" typedef struct BlockCrypto BlockCrypto; @@ -135,11 +129,7 @@ static QemuOptsList block_crypto_runtime_opts_luks = { .name = "crypto", .head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head), .desc = { - { - .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, - .type = QEMU_OPT_STRING, - .help = "ID of the secret that provides the encryption key", - }, + BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""), { /* end of list */ } }, }; @@ -154,49 +144,21 @@ static QemuOptsList block_crypto_create_opts_luks = { .type = QEMU_OPT_SIZE, .help = "Virtual disk size" }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, - .type = QEMU_OPT_STRING, - .help = "ID of the secret that provides the encryption key", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, - .type = QEMU_OPT_STRING, - .help = "Name of encryption cipher algorithm", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, - .type = QEMU_OPT_STRING, - .help = "Name of encryption cipher mode", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, - .type = QEMU_OPT_STRING, - .help = "Name of IV generator algorithm", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, - .type = QEMU_OPT_STRING, - .help = "Name of IV generator hash algorithm", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, - .type = QEMU_OPT_STRING, - .help = "Name of encryption hash algorithm", - }, - { - .name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, - .type = QEMU_OPT_NUMBER, - .help = "Time to spend in PBKDF in milliseconds", - }, + BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""), + BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""), { /* end of list */ } }, }; -static QCryptoBlockOpenOptions * +QCryptoBlockOpenOptions * block_crypto_open_opts_init(QCryptoBlockFormat format, - QemuOpts *opts, + QDict *opts, Error **errp) { Visitor *v; @@ -206,7 +168,7 @@ block_crypto_open_opts_init(QCryptoBlockFormat format, ret = g_new0(QCryptoBlockOpenOptions, 1); ret->format = format; - v = opts_visitor_new(opts); + v = qobject_input_visitor_new_keyval(QOBJECT(opts)); visit_start_struct(v, NULL, NULL, 0, &local_err); if (local_err) { @@ -219,6 +181,11 @@ block_crypto_open_opts_init(QCryptoBlockFormat format, v, &ret->u.luks, &local_err); break; + case Q_CRYPTO_BLOCK_FORMAT_QCOW: + visit_type_QCryptoBlockOptionsQCow_members( + v, &ret->u.qcow, &local_err); + break; + default: error_setg(&local_err, "Unsupported block format %d", format); break; @@ -240,9 +207,9 @@ block_crypto_open_opts_init(QCryptoBlockFormat format, } -static QCryptoBlockCreateOptions * +QCryptoBlockCreateOptions * block_crypto_create_opts_init(QCryptoBlockFormat format, - QemuOpts *opts, + QDict *opts, Error **errp) { Visitor *v; @@ -252,7 +219,7 @@ block_crypto_create_opts_init(QCryptoBlockFormat format, ret = g_new0(QCryptoBlockCreateOptions, 1); ret->format = format; - v = opts_visitor_new(opts); + v = qobject_input_visitor_new_keyval(QOBJECT(opts)); visit_start_struct(v, NULL, NULL, 0, &local_err); if (local_err) { @@ -265,6 +232,11 @@ block_crypto_create_opts_init(QCryptoBlockFormat format, v, &ret->u.luks, &local_err); break; + case Q_CRYPTO_BLOCK_FORMAT_QCOW: + visit_type_QCryptoBlockOptionsQCow_members( + v, &ret->u.qcow, &local_err); + break; + default: error_setg(&local_err, "Unsupported block format %d", format); break; @@ -299,6 +271,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, int ret = -EINVAL; QCryptoBlockOpenOptions *open_opts = NULL; unsigned int cflags = 0; + QDict *cryptoopts = NULL; bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false, errp); @@ -313,7 +286,9 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, goto cleanup; } - open_opts = block_crypto_open_opts_init(format, opts, errp); + cryptoopts = qemu_opts_to_qdict(opts, NULL); + + open_opts = block_crypto_open_opts_init(format, cryptoopts, errp); if (!open_opts) { goto cleanup; } @@ -321,7 +296,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, if (flags & BDRV_O_NO_IO) { cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; } - crypto->block = qcrypto_block_open(open_opts, + crypto->block = qcrypto_block_open(open_opts, NULL, block_crypto_read_func, bs, cflags, @@ -333,10 +308,10 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, } bs->encrypted = true; - bs->valid_key = true; ret = 0; cleanup: + QDECREF(cryptoopts); qapi_free_QCryptoBlockOpenOptions(open_opts); return ret; } @@ -356,13 +331,16 @@ static int block_crypto_create_generic(QCryptoBlockFormat format, .opts = opts, .filename = filename, }; + QDict *cryptoopts; + + cryptoopts = qemu_opts_to_qdict(opts, NULL); - create_opts = block_crypto_create_opts_init(format, opts, errp); + create_opts = block_crypto_create_opts_init(format, cryptoopts, errp); if (!create_opts) { return -1; } - crypto = qcrypto_block_create(create_opts, + crypto = qcrypto_block_create(create_opts, NULL, block_crypto_init_func, block_crypto_write_func, &data, @@ -375,6 +353,7 @@ static int block_crypto_create_generic(QCryptoBlockFormat format, ret = 0; cleanup: + QDECREF(cryptoopts); qcrypto_block_free(crypto); blk_unref(data.blk); qapi_free_QCryptoBlockCreateOptions(create_opts); @@ -382,7 +361,7 @@ static int block_crypto_create_generic(QCryptoBlockFormat format, } static int block_crypto_truncate(BlockDriverState *bs, int64_t offset, - Error **errp) + PreallocMode prealloc, Error **errp) { BlockCrypto *crypto = bs->opaque; size_t payload_offset = @@ -390,7 +369,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset, offset += payload_offset; - return bdrv_truncate(bs->file, offset, errp); + return bdrv_truncate(bs->file, offset, prealloc, errp); } static void block_crypto_close(BlockDriverState *bs) diff --git a/block/crypto.h b/block/crypto.h new file mode 100644 index 0000000000..0f985ea4e2 --- /dev/null +++ b/block/crypto.h @@ -0,0 +1,101 @@ +/* + * QEMU block full disk encryption + * + * Copyright (c) 2015-2017 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef BLOCK_CRYPTO_H__ +#define BLOCK_CRYPTO_H__ + +#define BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, helpstr) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET, \ + .type = QEMU_OPT_STRING, \ + .help = helpstr, \ + } + +#define BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET "key-secret" + +#define BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET(prefix) \ + BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \ + "ID of the secret that provides the AES encryption key") + +#define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret" +#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg" +#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode" +#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg" +#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg" +#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg" +#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time" + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \ + BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \ + "ID of the secret that provides the keyslot passphrase") + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \ + .type = QEMU_OPT_STRING, \ + .help = "Name of encryption cipher algorithm", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \ + .type = QEMU_OPT_STRING, \ + .help = "Name of encryption cipher mode", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \ + .type = QEMU_OPT_STRING, \ + .help = "Name of IV generator algorithm", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \ + .type = QEMU_OPT_STRING, \ + .help = "Name of IV generator hash algorithm", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \ + .type = QEMU_OPT_STRING, \ + .help = "Name of encryption hash algorithm", \ + } + +#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(prefix) \ + { \ + .name = prefix BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \ + .type = QEMU_OPT_NUMBER, \ + .help = "Time to spend in PBKDF in milliseconds", \ + } + +QCryptoBlockCreateOptions * +block_crypto_create_opts_init(QCryptoBlockFormat format, + QDict *opts, + Error **errp); + +QCryptoBlockOpenOptions * +block_crypto_open_opts_init(QCryptoBlockFormat format, + QDict *opts, + Error **errp); + +#endif /* BLOCK_CRYPTO_H__ */ diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index a04c6e4154..543bddb9b5 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -43,8 +43,18 @@ struct BdrvDirtyBitmap { BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */ char *name; /* Optional non-empty unique ID */ int64_t size; /* Size of the bitmap (Number of sectors) */ - bool disabled; /* Bitmap is read-only */ + bool disabled; /* Bitmap is disabled. It ignores all writes to + the device */ int active_iterators; /* How many iterators are active */ + bool readonly; /* Bitmap is read-only. This field also + prevents the respective image from being + modified (i.e. blocks writes and discards). + Such operations must fail and both the image + and this bitmap must remain unchanged while + this flag is set. */ + bool autoload; /* For persistent bitmaps: bitmap must be + autoloaded on image opening */ + bool persistent; /* bitmap must be saved to owner disk image */ QLIST_ENTRY(BdrvDirtyBitmap) list; }; @@ -93,6 +103,8 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) assert(!bdrv_dirty_bitmap_frozen(bitmap)); g_free(bitmap->name); bitmap->name = NULL; + bitmap->persistent = false; + bitmap->autoload = false; } /* Called with BQL taken. */ @@ -289,6 +301,10 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, bitmap->name = NULL; successor->name = name; bitmap->successor = NULL; + successor->persistent = bitmap->persistent; + bitmap->persistent = false; + successor->autoload = bitmap->autoload; + bitmap->autoload = false; bdrv_release_dirty_bitmap(bs, bitmap); return successor; @@ -340,15 +356,20 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs) bdrv_dirty_bitmaps_unlock(bs); } +static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap) +{ + return !!bdrv_dirty_bitmap_name(bitmap); +} + /* Called with BQL taken. */ -static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs, - BdrvDirtyBitmap *bitmap, - bool only_named) +static void bdrv_do_release_matching_dirty_bitmap( + BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + bool (*cond)(BdrvDirtyBitmap *bitmap)) { BdrvDirtyBitmap *bm, *next; bdrv_dirty_bitmaps_lock(bs); QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { - if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) { + if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { assert(!bm->active_iterators); assert(!bdrv_dirty_bitmap_frozen(bm)); assert(!bm->meta); @@ -373,17 +394,47 @@ out: /* Called with BQL taken. */ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) { - bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false); + bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL); } /** * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). * There must not be any frozen bitmaps attached. + * This function does not remove persistent bitmaps from the storage. * Called with BQL taken. */ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) { - bdrv_do_release_matching_dirty_bitmap(bs, NULL, true); + bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name); +} + +/** + * Release all persistent dirty bitmaps attached to a BDS (for use in + * bdrv_inactivate_recurse()). + * There must not be any frozen bitmaps attached. + * This function does not remove persistent bitmaps from the storage. + */ +void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) +{ + bdrv_do_release_matching_dirty_bitmap(bs, NULL, + bdrv_dirty_bitmap_get_persistance); +} + +/** + * Remove persistent dirty bitmap from the storage if it exists. + * Absence of bitmap is not an error, because we have the following scenario: + * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no + * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should + * not fail. + * This function doesn't release corresponding BdrvDirtyBitmap. + */ +void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp) +{ + if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) { + bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp); + } } /* Called with BQL taken. */ @@ -455,7 +506,7 @@ uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) return granularity; } -uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap) +uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) { return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap); } @@ -504,6 +555,7 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) { assert(bdrv_dirty_bitmap_enabled(bitmap)); + assert(!bdrv_dirty_bitmap_readonly(bitmap)); hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); } @@ -520,6 +572,7 @@ void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) { assert(bdrv_dirty_bitmap_enabled(bitmap)); + assert(!bdrv_dirty_bitmap_readonly(bitmap)); hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors); } @@ -534,6 +587,7 @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) { assert(bdrv_dirty_bitmap_enabled(bitmap)); + assert(!bdrv_dirty_bitmap_readonly(bitmap)); bdrv_dirty_bitmap_lock(bitmap); if (!out) { hbitmap_reset_all(bitmap->bitmap); @@ -550,6 +604,7 @@ void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) { HBitmap *tmp = bitmap->bitmap; assert(bdrv_dirty_bitmap_enabled(bitmap)); + assert(!bdrv_dirty_bitmap_readonly(bitmap)); bitmap->bitmap = in; hbitmap_free(tmp); } @@ -586,6 +641,13 @@ void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, hbitmap_deserialize_zeroes(bitmap->bitmap, start, count, finish); } +void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, + uint64_t start, uint64_t count, + bool finish) +{ + hbitmap_deserialize_ones(bitmap->bitmap, start, count, finish); +} + void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) { hbitmap_deserialize_finish(bitmap->bitmap); @@ -605,6 +667,7 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, if (!bdrv_dirty_bitmap_enabled(bitmap)) { continue; } + assert(!bdrv_dirty_bitmap_readonly(bitmap)); hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); } bdrv_dirty_bitmaps_unlock(bs); @@ -627,3 +690,78 @@ int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) { return hbitmap_count(bitmap->meta); } + +bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) +{ + return bitmap->readonly; +} + +/* Called with BQL taken. */ +void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) +{ + qemu_mutex_lock(bitmap->mutex); + bitmap->readonly = value; + qemu_mutex_unlock(bitmap->mutex); +} + +bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) +{ + BdrvDirtyBitmap *bm; + QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { + if (bm->readonly) { + return true; + } + } + + return false; +} + +/* Called with BQL taken. */ +void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload) +{ + qemu_mutex_lock(bitmap->mutex); + bitmap->autoload = autoload; + qemu_mutex_unlock(bitmap->mutex); +} + +bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap) +{ + return bitmap->autoload; +} + +/* Called with BQL taken. */ +void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) +{ + qemu_mutex_lock(bitmap->mutex); + bitmap->persistent = persistent; + qemu_mutex_unlock(bitmap->mutex); +} + +bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap) +{ + return bitmap->persistent; +} + +bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) +{ + BdrvDirtyBitmap *bm; + QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { + if (bm->persistent && !bm->readonly) { + return true; + } + } + + return false; +} + +BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap) +{ + return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : + QLIST_NEXT(bitmap, list); +} + +char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) +{ + return hbitmap_sha256(bitmap->bitmap, errp); +} diff --git a/block/file-posix.c b/block/file-posix.c index 3927fabf06..cfbb236f6f 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1624,7 +1624,122 @@ static void raw_close(BlockDriverState *bs) } } -static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +/** + * Truncates the given regular file @fd to @offset and, when growing, fills the + * new space according to @prealloc. + * + * Returns: 0 on success, -errno on failure. + */ +static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc, + Error **errp) +{ + int result = 0; + int64_t current_length = 0; + char *buf = NULL; + struct stat st; + + if (fstat(fd, &st) < 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not stat file"); + return result; + } + + current_length = st.st_size; + if (current_length > offset && prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Cannot use preallocation for shrinking files"); + return -ENOTSUP; + } + + switch (prealloc) { +#ifdef CONFIG_POSIX_FALLOCATE + case PREALLOC_MODE_FALLOC: + /* + * Truncating before posix_fallocate() makes it about twice slower on + * file systems that do not support fallocate(), trying to check if a + * block is allocated before allocating it, so don't do that here. + */ + result = -posix_fallocate(fd, current_length, offset - current_length); + if (result != 0) { + /* posix_fallocate() doesn't set errno. */ + error_setg_errno(errp, -result, + "Could not preallocate new data"); + } + goto out; +#endif + case PREALLOC_MODE_FULL: + { + int64_t num = 0, left = offset - current_length; + + /* + * Knowing the final size from the beginning could allow the file + * system driver to do less allocations and possibly avoid + * fragmentation of the file. + */ + if (ftruncate(fd, offset) != 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not resize file"); + goto out; + } + + buf = g_malloc0(65536); + + result = lseek(fd, current_length, SEEK_SET); + if (result < 0) { + result = -errno; + error_setg_errno(errp, -result, + "Failed to seek to the old end of file"); + goto out; + } + + while (left > 0) { + num = MIN(left, 65536); + result = write(fd, buf, num); + if (result < 0) { + result = -errno; + error_setg_errno(errp, -result, + "Could not write zeros for preallocation"); + goto out; + } + left -= result; + } + if (result >= 0) { + result = fsync(fd); + if (result < 0) { + result = -errno; + error_setg_errno(errp, -result, + "Could not flush file to disk"); + goto out; + } + } + goto out; + } + case PREALLOC_MODE_OFF: + if (ftruncate(fd, offset) != 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not resize file"); + } + return result; + default: + result = -ENOTSUP; + error_setg(errp, "Unsupported preallocation mode: %s", + PreallocMode_lookup[prealloc]); + return result; + } + +out: + if (result < 0) { + if (ftruncate(fd, current_length) < 0) { + error_report("Failed to restore old file length: %s", + strerror(errno)); + } + } + + g_free(buf); + return result; +} + +static int raw_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVRawState *s = bs->opaque; struct stat st; @@ -1637,12 +1752,16 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp) } if (S_ISREG(st.st_mode)) { - if (ftruncate(s->fd, offset) < 0) { - ret = -errno; - error_setg_errno(errp, -ret, "Failed to resize the file"); - return ret; - } - } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { + return raw_regular_truncate(s->fd, offset, prealloc, errp); + } + + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Preallocation mode '%s' unsupported for this " + "non-regular file", PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + + if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { if (offset > raw_getlength(bs)) { error_setg(errp, "Cannot grow device files"); return -EINVAL; @@ -1885,71 +2004,9 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp) #endif } - switch (prealloc) { -#ifdef CONFIG_POSIX_FALLOCATE - case PREALLOC_MODE_FALLOC: - /* - * Truncating before posix_fallocate() makes it about twice slower on - * file systems that do not support fallocate(), trying to check if a - * block is allocated before allocating it, so don't do that here. - */ - result = -posix_fallocate(fd, 0, total_size); - if (result != 0) { - /* posix_fallocate() doesn't set errno. */ - error_setg_errno(errp, -result, - "Could not preallocate data for the new file"); - } - break; -#endif - case PREALLOC_MODE_FULL: - { - /* - * Knowing the final size from the beginning could allow the file - * system driver to do less allocations and possibly avoid - * fragmentation of the file. - */ - if (ftruncate(fd, total_size) != 0) { - result = -errno; - error_setg_errno(errp, -result, "Could not resize file"); - goto out_close; - } - - int64_t num = 0, left = total_size; - buf = g_malloc0(65536); - - while (left > 0) { - num = MIN(left, 65536); - result = write(fd, buf, num); - if (result < 0) { - result = -errno; - error_setg_errno(errp, -result, - "Could not write to the new file"); - break; - } - left -= result; - } - if (result >= 0) { - result = fsync(fd); - if (result < 0) { - result = -errno; - error_setg_errno(errp, -result, - "Could not flush new file to disk"); - } - } - g_free(buf); - break; - } - case PREALLOC_MODE_OFF: - if (ftruncate(fd, total_size) != 0) { - result = -errno; - error_setg_errno(errp, -result, "Could not resize file"); - } - break; - default: - result = -EINVAL; - error_setg(errp, "Unsupported preallocation mode: %s", - PreallocMode_lookup[prealloc]); - break; + result = raw_regular_truncate(fd, total_size, prealloc, errp); + if (result < 0) { + goto out_close; } out_close: diff --git a/block/file-win32.c b/block/file-win32.c index ef2910b03f..4706335cff 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -461,12 +461,19 @@ static void raw_close(BlockDriverState *bs) } } -static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int raw_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVRawState *s = bs->opaque; LONG low, high; DWORD dwPtrLow; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + low = offset; high = offset >> 32; diff --git a/block/gluster.c b/block/gluster.c index addceed6eb..bfa4df1c81 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1096,11 +1096,17 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs, } static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset, - Error **errp) + PreallocMode prealloc, Error **errp) { int ret; BDRVGlusterState *s = bs->opaque; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + ret = glfs_ftruncate(s->fd, offset); if (ret < 0) { ret = -errno; diff --git a/block/io.c b/block/io.c index 23170a57ee..b413727524 100644 --- a/block/io.c +++ b/block/io.c @@ -1315,6 +1315,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, uint64_t bytes_remaining = bytes; int max_transfer; + if (bdrv_has_readonly_bitmaps(bs)) { + return -EPERM; + } + assert(is_power_of_2(align)); assert((offset & (align - 1)) == 0); assert((bytes & (align - 1)) == 0); @@ -2287,6 +2291,10 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, return -ENOMEDIUM; } + if (bdrv_has_readonly_bitmaps(bs)) { + return -EPERM; + } + ret = bdrv_check_byte_request(bs, offset, bytes); if (ret < 0) { return ret; diff --git a/block/iscsi.c b/block/iscsi.c index 54067e2620..904ef2076b 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2079,11 +2079,18 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state) } } -static int iscsi_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int iscsi_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { IscsiLun *iscsilun = bs->opaque; Error *local_err = NULL; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + if (iscsilun->type != TYPE_DISK) { error_setg(errp, "Cannot resize non-disk iSCSI devices"); return -ENOTSUP; diff --git a/block/mirror.c b/block/mirror.c index eaf0fe7858..8583b764a0 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -739,7 +739,8 @@ static void coroutine_fn mirror_run(void *opaque) } if (s->bdev_length > base_length) { - ret = blk_truncate(s->target, s->bdev_length, NULL); + ret = blk_truncate(s->target, s->bdev_length, PREALLOC_MODE_OFF, + NULL); if (ret < 0) { goto immediate_exit; } diff --git a/block/nfs.c b/block/nfs.c index c3c5de0113..c396ee1dbd 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -759,11 +759,18 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs) return (task.ret < 0 ? task.ret : st.st_blocks * 512); } -static int nfs_file_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int nfs_file_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { NFSClient *client = bs->opaque; int ret; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + ret = nfs_ftruncate(client->context, client->fh, offset); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to truncate file"); diff --git a/block/parallels.c b/block/parallels.c index 8be46a7d48..5bbdfabb7a 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -224,7 +224,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, } else { ret = bdrv_truncate(bs->file, (s->data_end + space) << BDRV_SECTOR_BITS, - NULL); + PREALLOC_MODE_OFF, NULL); } if (ret < 0) { return ret; @@ -458,7 +458,8 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res, res->leaks += count; if (fix & BDRV_FIX_LEAKS) { Error *local_err = NULL; - ret = bdrv_truncate(bs->file, res->image_end_offset, &local_err); + ret = bdrv_truncate(bs->file, res->image_end_offset, + PREALLOC_MODE_OFF, &local_err); if (ret < 0) { error_report_err(local_err); res->check_errors++; @@ -507,7 +508,7 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp) blk_set_allow_write_beyond_eof(file, true); - ret = blk_truncate(file, 0, errp); + ret = blk_truncate(file, 0, PREALLOC_MODE_OFF, errp); if (ret < 0) { goto exit; } @@ -699,7 +700,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, } if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) || - bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs), NULL) != 0) { + bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs), + PREALLOC_MODE_OFF, NULL) != 0) { s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE; } @@ -742,7 +744,8 @@ static void parallels_close(BlockDriverState *bs) } if (bs->open_flags & BDRV_O_RDWR) { - bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, NULL); + bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, + PREALLOC_MODE_OFF, NULL); } g_free(s->bat_dirty_bmap); diff --git a/block/qapi.c b/block/qapi.c index 0a41d59bf3..080eb8f115 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -45,7 +45,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, info->ro = bs->read_only; info->drv = g_strdup(bs->drv->format_name); info->encrypted = bs->encrypted; - info->encryption_key_missing = bdrv_key_required(bs); + info->encryption_key_missing = false; info->cache = g_new(BlockdevCacheInfo, 1); *info->cache = (BlockdevCacheInfo) { diff --git a/block/qcow.c b/block/qcow.c index 7bd94dcd46..66827d6f24 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -31,8 +31,10 @@ #include "qemu/bswap.h" #include <zlib.h> #include "qapi/qmp/qerror.h" -#include "crypto/cipher.h" +#include "qapi/qmp/qstring.h" +#include "crypto/block.h" #include "migration/blocker.h" +#include "block/crypto.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ @@ -77,7 +79,7 @@ typedef struct BDRVQcowState { uint8_t *cluster_cache; uint8_t *cluster_data; uint64_t cluster_cache_offset; - QCryptoCipher *cipher; /* NULL if no key yet */ + QCryptoBlock *crypto; /* Disk encryption format driver */ uint32_t crypt_method_header; CoMutex lock; Error *migration_blocker; @@ -97,6 +99,15 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) return 0; } +static QemuOptsList qcow_runtime_opts = { + .name = "qcow", + .head = QTAILQ_HEAD_INITIALIZER(qcow_runtime_opts.head), + .desc = { + BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."), + { /* end of list */ } + }, +}; + static int qcow_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -105,11 +116,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, int ret; QCowHeader header; Error *local_err = NULL; + QCryptoBlockOpenOptions *crypto_opts = NULL; + unsigned int cflags = 0; + QDict *encryptopts = NULL; + const char *encryptfmt; + + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + encryptfmt = qdict_get_try_str(encryptopts, "format"); bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false, errp); if (!bs->file) { - return -EINVAL; + ret = -EINVAL; + goto fail; } ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); @@ -155,17 +174,6 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - if (header.crypt_method > QCOW_CRYPT_AES) { - error_setg(errp, "invalid encryption method in qcow header"); - ret = -EINVAL; - goto fail; - } - if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128, - QCRYPTO_CIPHER_MODE_CBC)) { - error_setg(errp, "AES cipher not available"); - ret = -EINVAL; - goto fail; - } s->crypt_method_header = header.crypt_method; if (s->crypt_method_header) { if (bdrv_uses_whitelist() && @@ -181,8 +189,44 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, ret = -ENOSYS; goto fail; } + if (s->crypt_method_header == QCOW_CRYPT_AES) { + if (encryptfmt && !g_str_equal(encryptfmt, "aes")) { + error_setg(errp, + "Header reported 'aes' encryption format but " + "options specify '%s'", encryptfmt); + ret = -EINVAL; + goto fail; + } + qdict_del(encryptopts, "format"); + crypto_opts = block_crypto_open_opts_init( + Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp); + if (!crypto_opts) { + ret = -EINVAL; + goto fail; + } + if (flags & BDRV_O_NO_IO) { + cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; + } + s->crypto = qcrypto_block_open(crypto_opts, "encrypt.", + NULL, NULL, cflags, errp); + if (!s->crypto) { + ret = -EINVAL; + goto fail; + } + } else { + error_setg(errp, "invalid encryption method in qcow header"); + ret = -EINVAL; + goto fail; + } bs->encrypted = true; + } else { + if (encryptfmt) { + error_setg(errp, "No encryption in image header, but options " + "specified format '%s'", encryptfmt); + ret = -EINVAL; + goto fail; + } } s->cluster_bits = header.cluster_bits; s->cluster_size = 1 << s->cluster_bits; @@ -266,6 +310,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } + QDECREF(encryptopts); + qapi_free_QCryptoBlockOpenOptions(crypto_opts); qemu_co_mutex_init(&s->lock); return 0; @@ -274,6 +320,9 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, qemu_vfree(s->l2_cache); g_free(s->cluster_cache); g_free(s->cluster_data); + qcrypto_block_free(s->crypto); + QDECREF(encryptopts); + qapi_free_QCryptoBlockOpenOptions(crypto_opts); return ret; } @@ -286,85 +335,6 @@ static int qcow_reopen_prepare(BDRVReopenState *state, return 0; } -static int qcow_set_key(BlockDriverState *bs, const char *key) -{ - BDRVQcowState *s = bs->opaque; - uint8_t keybuf[16]; - int len, i; - Error *err; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for(i = 0;i < len;i++) { - keybuf[i] = key[i]; - } - assert(bs->encrypted); - - qcrypto_cipher_free(s->cipher); - s->cipher = qcrypto_cipher_new( - QCRYPTO_CIPHER_ALG_AES_128, - QCRYPTO_CIPHER_MODE_CBC, - keybuf, G_N_ELEMENTS(keybuf), - &err); - - if (!s->cipher) { - /* XXX would be nice if errors in this method could - * be properly propagate to the caller. Would need - * the bdrv_set_key() API signature to be fixed. */ - error_free(err); - return -1; - } - return 0; -} - -/* The crypt function is compatible with the linux cryptoloop - algorithm for < 4 GB images. NOTE: out_buf == in_buf is - supported */ -static int encrypt_sectors(BDRVQcowState *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, bool enc, Error **errp) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - int ret; - - for(i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - if (qcrypto_cipher_setiv(s->cipher, - ivec.b, G_N_ELEMENTS(ivec.b), - errp) < 0) { - return -1; - } - if (enc) { - ret = qcrypto_cipher_encrypt(s->cipher, - in_buf, - out_buf, - 512, - errp); - } else { - ret = qcrypto_cipher_decrypt(s->cipher, - in_buf, - out_buf, - 512, - errp); - } - if (ret < 0) { - return -1; - } - sector_num++; - in_buf += 512; - out_buf += 512; - } - return 0; -} /* 'allocate' is: * @@ -473,22 +443,23 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, /* round to cluster size */ cluster_offset = (cluster_offset + s->cluster_size - 1) & ~(s->cluster_size - 1); - bdrv_truncate(bs->file, cluster_offset + s->cluster_size, NULL); + bdrv_truncate(bs->file, cluster_offset + s->cluster_size, + PREALLOC_MODE_OFF, NULL); /* if encrypted, we must initialize the cluster content which won't be written */ if (bs->encrypted && (n_end - n_start) < s->cluster_sectors) { uint64_t start_sect; - assert(s->cipher); + assert(s->crypto); start_sect = (offset & ~(s->cluster_size - 1)) >> 9; - memset(s->cluster_data + 512, 0x00, 512); for(i = 0; i < s->cluster_sectors; i++) { if (i < n_start || i >= n_end) { Error *err = NULL; - if (encrypt_sectors(s, start_sect + i, - s->cluster_data, - s->cluster_data + 512, 1, - true, &err) < 0) { + memset(s->cluster_data, 0x00, 512); + if (qcrypto_block_encrypt(s->crypto, start_sect + i, + s->cluster_data, + BDRV_SECTOR_SIZE, + &err) < 0) { error_free(err); errno = EIO; return -1; @@ -533,7 +504,7 @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs, if (!cluster_offset) { return 0; } - if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->cipher) { + if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypto) { return BDRV_BLOCK_DATA; } cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS); @@ -664,9 +635,9 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num, break; } if (bs->encrypted) { - assert(s->cipher); - if (encrypt_sectors(s, sector_num, buf, buf, - n, false, &err) < 0) { + assert(s->crypto); + if (qcrypto_block_decrypt(s->crypto, sector_num, buf, + n * BDRV_SECTOR_SIZE, &err) < 0) { goto fail; } } @@ -700,9 +671,7 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, BDRVQcowState *s = bs->opaque; int index_in_cluster; uint64_t cluster_offset; - const uint8_t *src_buf; int ret = 0, n; - uint8_t *cluster_data = NULL; struct iovec hd_iov; QEMUIOVector hd_qiov; uint8_t *buf; @@ -710,7 +679,9 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, s->cluster_cache_offset = -1; /* disable compressed cache */ - if (qiov->niov > 1) { + /* We must always copy the iov when encrypting, so we + * don't modify the original data buffer during encryption */ + if (bs->encrypted || qiov->niov > 1) { buf = orig_buf = qemu_try_blockalign(bs, qiov->size); if (buf == NULL) { return -ENOMEM; @@ -739,22 +710,16 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, } if (bs->encrypted) { Error *err = NULL; - assert(s->cipher); - if (!cluster_data) { - cluster_data = g_malloc0(s->cluster_size); - } - if (encrypt_sectors(s, sector_num, cluster_data, buf, - n, true, &err) < 0) { + assert(s->crypto); + if (qcrypto_block_encrypt(s->crypto, sector_num, buf, + n * BDRV_SECTOR_SIZE, &err) < 0) { error_free(err); ret = -EIO; break; } - src_buf = cluster_data; - } else { - src_buf = buf; } - hd_iov.iov_base = (void *)src_buf; + hd_iov.iov_base = (void *)buf; hd_iov.iov_len = n * 512; qemu_iovec_init_external(&hd_qiov, &hd_iov, 1); qemu_co_mutex_unlock(&s->lock); @@ -773,10 +738,7 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, } qemu_co_mutex_unlock(&s->lock); - if (qiov->niov > 1) { - qemu_vfree(orig_buf); - } - g_free(cluster_data); + qemu_vfree(orig_buf); return ret; } @@ -785,8 +747,8 @@ static void qcow_close(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; - qcrypto_cipher_free(s->cipher); - s->cipher = NULL; + qcrypto_block_free(s->crypto); + s->crypto = NULL; g_free(s->l1_table); qemu_vfree(s->l2_cache); g_free(s->cluster_cache); @@ -803,17 +765,35 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) uint8_t *tmp; int64_t total_size = 0; char *backing_file = NULL; - int flags = 0; Error *local_err = NULL; int ret; BlockBackend *qcow_blk; + const char *encryptfmt = NULL; + QDict *options; + QDict *encryptopts = NULL; + QCryptoBlockCreateOptions *crypto_opts = NULL; + QCryptoBlock *crypto = NULL; /* Read out options */ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); + if (total_size == 0) { + error_setg(errp, "Image size is too small, cannot be zero length"); + ret = -EINVAL; + goto cleanup; + } + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); - if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) { - flags |= BLOCK_FLAG_ENCRYPT; + encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT); + if (encryptfmt) { + if (qemu_opt_get(opts, BLOCK_OPT_ENCRYPT)) { + error_setg(errp, "Options " BLOCK_OPT_ENCRYPT " and " + BLOCK_OPT_ENCRYPT_FORMAT " are mutually exclusive"); + ret = -EINVAL; + goto cleanup; + } + } else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) { + encryptfmt = "aes"; } ret = bdrv_create_file(filename, opts, &local_err); @@ -833,7 +813,7 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) blk_set_allow_write_beyond_eof(qcow_blk, true); - ret = blk_truncate(qcow_blk, 0, errp); + ret = blk_truncate(qcow_blk, 0, PREALLOC_MODE_OFF, errp); if (ret < 0) { goto exit; } @@ -867,8 +847,32 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) l1_size = (total_size + (1LL << shift) - 1) >> shift; header.l1_table_offset = cpu_to_be64(header_size); - if (flags & BLOCK_FLAG_ENCRYPT) { + + options = qemu_opts_to_qdict(opts, NULL); + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + QDECREF(options); + if (encryptfmt) { + if (!g_str_equal(encryptfmt, "aes")) { + error_setg(errp, "Unknown encryption format '%s', expected 'aes'", + encryptfmt); + ret = -EINVAL; + goto exit; + } header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); + + crypto_opts = block_crypto_create_opts_init( + Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp); + if (!crypto_opts) { + ret = -EINVAL; + goto exit; + } + + crypto = qcrypto_block_create(crypto_opts, "encrypt.", + NULL, NULL, NULL, errp); + if (!crypto) { + ret = -EINVAL; + goto exit; + } } else { header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); } @@ -903,6 +907,9 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp) exit: blk_unref(qcow_blk); cleanup: + QDECREF(encryptopts); + qcrypto_block_free(crypto); + qapi_free_QCryptoBlockCreateOptions(crypto_opts); g_free(backing_file); return ret; } @@ -917,7 +924,8 @@ static int qcow_make_empty(BlockDriverState *bs) if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0) return -1; - ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, NULL); + ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, + PREALLOC_MODE_OFF, NULL); if (ret < 0) return ret; @@ -1041,9 +1049,15 @@ static QemuOptsList qcow_create_opts = { { .name = BLOCK_OPT_ENCRYPT, .type = QEMU_OPT_BOOL, - .help = "Encrypt the image", - .def_value_str = "off" + .help = "Encrypt the image with format 'aes'. (Deprecated " + "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)", + }, + { + .name = BLOCK_OPT_ENCRYPT_FORMAT, + .type = QEMU_OPT_STRING, + .help = "Encrypt the image, format choices: 'aes'", }, + BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."), { /* end of list */ } } }; @@ -1064,7 +1078,6 @@ static BlockDriver bdrv_qcow = { .bdrv_co_writev = qcow_co_writev, .bdrv_co_get_block_status = qcow_co_get_block_status, - .bdrv_set_key = qcow_set_key, .bdrv_make_empty = qcow_make_empty, .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed, .bdrv_get_info = qcow_get_info, diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c new file mode 100644 index 0000000000..3e8735a20d --- /dev/null +++ b/block/qcow2-bitmap.c @@ -0,0 +1,1482 @@ +/* + * Bitmaps for the QCOW version 2 format + * + * Copyright (c) 2014-2017 Vladimir Sementsov-Ogievskiy + * + * This file is derived from qcow2-snapshot.c, original copyright: + * Copyright (c) 2004-2006 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/cutils.h" + +#include "block/block_int.h" +#include "block/qcow2.h" + +/* NOTICE: BME here means Bitmaps Extension and used as a namespace for + * _internal_ constants. Please do not use this _internal_ abbreviation for + * other needs and/or outside of this file. */ + +/* Bitmap directory entry constraints */ +#define BME_MAX_TABLE_SIZE 0x8000000 +#define BME_MAX_PHYS_SIZE 0x20000000 /* restrict BdrvDirtyBitmap size in RAM */ +#define BME_MAX_GRANULARITY_BITS 31 +#define BME_MIN_GRANULARITY_BITS 9 +#define BME_MAX_NAME_SIZE 1023 + +#if BME_MAX_TABLE_SIZE * 8ULL > INT_MAX +#error In the code bitmap table physical size assumed to fit into int +#endif + +/* Bitmap directory entry flags */ +#define BME_RESERVED_FLAGS 0xfffffffcU +#define BME_FLAG_IN_USE (1U << 0) +#define BME_FLAG_AUTO (1U << 1) + +/* bits [1, 8] U [56, 63] are reserved */ +#define BME_TABLE_ENTRY_RESERVED_MASK 0xff000000000001feULL +#define BME_TABLE_ENTRY_OFFSET_MASK 0x00fffffffffffe00ULL +#define BME_TABLE_ENTRY_FLAG_ALL_ONES (1ULL << 0) + +typedef struct QEMU_PACKED Qcow2BitmapDirEntry { + /* header is 8 byte aligned */ + uint64_t bitmap_table_offset; + + uint32_t bitmap_table_size; + uint32_t flags; + + uint8_t type; + uint8_t granularity_bits; + uint16_t name_size; + uint32_t extra_data_size; + /* extra data follows */ + /* name follows */ +} Qcow2BitmapDirEntry; + +typedef struct Qcow2BitmapTable { + uint64_t offset; + uint32_t size; /* number of 64bit entries */ + QSIMPLEQ_ENTRY(Qcow2BitmapTable) entry; +} Qcow2BitmapTable; +typedef QSIMPLEQ_HEAD(Qcow2BitmapTableList, Qcow2BitmapTable) + Qcow2BitmapTableList; + +typedef struct Qcow2Bitmap { + Qcow2BitmapTable table; + uint32_t flags; + uint8_t granularity_bits; + char *name; + + BdrvDirtyBitmap *dirty_bitmap; + + QSIMPLEQ_ENTRY(Qcow2Bitmap) entry; +} Qcow2Bitmap; +typedef QSIMPLEQ_HEAD(Qcow2BitmapList, Qcow2Bitmap) Qcow2BitmapList; + +typedef enum BitmapType { + BT_DIRTY_TRACKING_BITMAP = 1 +} BitmapType; + +static inline bool can_write(BlockDriverState *bs) +{ + return !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE); +} + +static int update_header_sync(BlockDriverState *bs) +{ + int ret; + + ret = qcow2_update_header(bs); + if (ret < 0) { + return ret; + } + + return bdrv_flush(bs); +} + +static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size) +{ + size_t i; + + for (i = 0; i < size; ++i) { + cpu_to_be64s(&bitmap_table[i]); + } +} + +static int check_table_entry(uint64_t entry, int cluster_size) +{ + uint64_t offset; + + if (entry & BME_TABLE_ENTRY_RESERVED_MASK) { + return -EINVAL; + } + + offset = entry & BME_TABLE_ENTRY_OFFSET_MASK; + if (offset != 0) { + /* if offset specified, bit 0 is reserved */ + if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) { + return -EINVAL; + } + + if (offset % cluster_size != 0) { + return -EINVAL; + } + } + + return 0; +} + +static int check_constraints_on_bitmap(BlockDriverState *bs, + const char *name, + uint32_t granularity, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + int granularity_bits = ctz32(granularity); + int64_t len = bdrv_getlength(bs); + + assert(granularity > 0); + assert((granularity & (granularity - 1)) == 0); + + if (len < 0) { + error_setg_errno(errp, -len, "Failed to get size of '%s'", + bdrv_get_device_or_node_name(bs)); + return len; + } + + if (granularity_bits > BME_MAX_GRANULARITY_BITS) { + error_setg(errp, "Granularity exceeds maximum (%llu bytes)", + 1ULL << BME_MAX_GRANULARITY_BITS); + return -EINVAL; + } + if (granularity_bits < BME_MIN_GRANULARITY_BITS) { + error_setg(errp, "Granularity is under minimum (%llu bytes)", + 1ULL << BME_MIN_GRANULARITY_BITS); + return -EINVAL; + } + + if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) || + (len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size << + granularity_bits)) + { + error_setg(errp, "Too much space will be occupied by the bitmap. " + "Use larger granularity"); + return -EINVAL; + } + + if (strlen(name) > BME_MAX_NAME_SIZE) { + error_setg(errp, "Name length exceeds maximum (%u characters)", + BME_MAX_NAME_SIZE); + return -EINVAL; + } + + return 0; +} + +static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table, + uint32_t bitmap_table_size) +{ + BDRVQcow2State *s = bs->opaque; + int i; + + for (i = 0; i < bitmap_table_size; ++i) { + uint64_t addr = bitmap_table[i] & BME_TABLE_ENTRY_OFFSET_MASK; + if (!addr) { + continue; + } + + qcow2_free_clusters(bs, addr, s->cluster_size, QCOW2_DISCARD_OTHER); + bitmap_table[i] = 0; + } +} + +static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb, + uint64_t **bitmap_table) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + uint32_t i; + uint64_t *table; + + assert(tb->size != 0); + table = g_try_new(uint64_t, tb->size); + if (table == NULL) { + return -ENOMEM; + } + + assert(tb->size <= BME_MAX_TABLE_SIZE); + ret = bdrv_pread(bs->file, tb->offset, + table, tb->size * sizeof(uint64_t)); + if (ret < 0) { + goto fail; + } + + for (i = 0; i < tb->size; ++i) { + be64_to_cpus(&table[i]); + ret = check_table_entry(table[i], s->cluster_size); + if (ret < 0) { + goto fail; + } + } + + *bitmap_table = table; + return 0; + +fail: + g_free(table); + + return ret; +} + +static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) +{ + int ret; + uint64_t *bitmap_table; + + ret = bitmap_table_load(bs, tb, &bitmap_table); + if (ret < 0) { + assert(bitmap_table == NULL); + return ret; + } + + clear_bitmap_table(bs, bitmap_table, tb->size); + qcow2_free_clusters(bs, tb->offset, tb->size * sizeof(uint64_t), + QCOW2_DISCARD_OTHER); + g_free(bitmap_table); + + tb->offset = 0; + tb->size = 0; + + return 0; +} + +/* This function returns the number of disk sectors covered by a single qcow2 + * cluster of bitmap data. */ +static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s, + const BdrvDirtyBitmap *bitmap) +{ + uint32_t sector_granularity = + bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS; + + return (uint64_t)sector_granularity * (s->cluster_size << 3); +} + +/* load_bitmap_data + * @bitmap_table entries must satisfy specification constraints. + * @bitmap must be cleared */ +static int load_bitmap_data(BlockDriverState *bs, + const uint64_t *bitmap_table, + uint32_t bitmap_table_size, + BdrvDirtyBitmap *bitmap) +{ + int ret = 0; + BDRVQcow2State *s = bs->opaque; + uint64_t sector, sbc; + uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap); + uint8_t *buf = NULL; + uint64_t i, tab_size = + size_to_clusters(s, + bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size)); + + if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) { + return -EINVAL; + } + + buf = g_malloc(s->cluster_size); + sbc = sectors_covered_by_bitmap_cluster(s, bitmap); + for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) { + uint64_t count = MIN(bm_size - sector, sbc); + uint64_t entry = bitmap_table[i]; + uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK; + + assert(check_table_entry(entry, s->cluster_size) == 0); + + if (offset == 0) { + if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) { + bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, count, + false); + } else { + /* No need to deserialize zeros because the dirty bitmap is + * already cleared */ + } + } else { + ret = bdrv_pread(bs->file, offset, buf, s->cluster_size); + if (ret < 0) { + goto finish; + } + bdrv_dirty_bitmap_deserialize_part(bitmap, buf, sector, count, + false); + } + } + ret = 0; + + bdrv_dirty_bitmap_deserialize_finish(bitmap); + +finish: + g_free(buf); + + return ret; +} + +static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs, + Qcow2Bitmap *bm, Error **errp) +{ + int ret; + uint64_t *bitmap_table = NULL; + uint32_t granularity; + BdrvDirtyBitmap *bitmap = NULL; + + if (bm->flags & BME_FLAG_IN_USE) { + error_setg(errp, "Bitmap '%s' is in use", bm->name); + goto fail; + } + + ret = bitmap_table_load(bs, &bm->table, &bitmap_table); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Could not read bitmap_table table from image for " + "bitmap '%s'", bm->name); + goto fail; + } + + granularity = 1U << bm->granularity_bits; + bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp); + if (bitmap == NULL) { + goto fail; + } + + ret = load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not read bitmap '%s' from image", + bm->name); + goto fail; + } + + g_free(bitmap_table); + return bitmap; + +fail: + g_free(bitmap_table); + if (bitmap != NULL) { + bdrv_release_dirty_bitmap(bs, bitmap); + } + + return NULL; +} + +/* + * Bitmap List + */ + +/* + * Bitmap List private functions + * Only Bitmap List knows about bitmap directory structure in Qcow2. + */ + +static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry) +{ + be64_to_cpus(&entry->bitmap_table_offset); + be32_to_cpus(&entry->bitmap_table_size); + be32_to_cpus(&entry->flags); + be16_to_cpus(&entry->name_size); + be32_to_cpus(&entry->extra_data_size); +} + +static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry) +{ + cpu_to_be64s(&entry->bitmap_table_offset); + cpu_to_be32s(&entry->bitmap_table_size); + cpu_to_be32s(&entry->flags); + cpu_to_be16s(&entry->name_size); + cpu_to_be32s(&entry->extra_data_size); +} + +static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size) +{ + return align_offset(sizeof(Qcow2BitmapDirEntry) + + name_size + extra_data_size, 8); +} + +static inline int dir_entry_size(Qcow2BitmapDirEntry *entry) +{ + return calc_dir_entry_size(entry->name_size, entry->extra_data_size); +} + +static inline const char *dir_entry_name_field(Qcow2BitmapDirEntry *entry) +{ + return (const char *)(entry + 1) + entry->extra_data_size; +} + +static inline char *dir_entry_copy_name(Qcow2BitmapDirEntry *entry) +{ + const char *name_field = dir_entry_name_field(entry); + return g_strndup(name_field, entry->name_size); +} + +static inline Qcow2BitmapDirEntry *next_dir_entry(Qcow2BitmapDirEntry *entry) +{ + return (Qcow2BitmapDirEntry *)((uint8_t *)entry + dir_entry_size(entry)); +} + +static int check_dir_entry(BlockDriverState *bs, Qcow2BitmapDirEntry *entry) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t phys_bitmap_bytes; + int64_t len; + + bool fail = (entry->bitmap_table_size == 0) || + (entry->bitmap_table_offset == 0) || + (entry->bitmap_table_offset % s->cluster_size) || + (entry->bitmap_table_size > BME_MAX_TABLE_SIZE) || + (entry->granularity_bits > BME_MAX_GRANULARITY_BITS) || + (entry->granularity_bits < BME_MIN_GRANULARITY_BITS) || + (entry->flags & BME_RESERVED_FLAGS) || + (entry->name_size > BME_MAX_NAME_SIZE) || + (entry->type != BT_DIRTY_TRACKING_BITMAP); + + if (fail) { + return -EINVAL; + } + + phys_bitmap_bytes = (uint64_t)entry->bitmap_table_size * s->cluster_size; + len = bdrv_getlength(bs); + + if (len < 0) { + return len; + } + + fail = (phys_bitmap_bytes > BME_MAX_PHYS_SIZE) || + (len > ((phys_bitmap_bytes * 8) << entry->granularity_bits)); + + return fail ? -EINVAL : 0; +} + +static inline void bitmap_directory_to_be(uint8_t *dir, size_t size) +{ + uint8_t *end = dir + size; + while (dir < end) { + Qcow2BitmapDirEntry *e = (Qcow2BitmapDirEntry *)dir; + dir += dir_entry_size(e); + + bitmap_dir_entry_to_be(e); + } +} + +/* + * Bitmap List public functions + */ + +static void bitmap_free(Qcow2Bitmap *bm) +{ + g_free(bm->name); + g_free(bm); +} + +static void bitmap_list_free(Qcow2BitmapList *bm_list) +{ + Qcow2Bitmap *bm; + + if (bm_list == NULL) { + return; + } + + while ((bm = QSIMPLEQ_FIRST(bm_list)) != NULL) { + QSIMPLEQ_REMOVE_HEAD(bm_list, entry); + bitmap_free(bm); + } + + g_free(bm_list); +} + +static Qcow2BitmapList *bitmap_list_new(void) +{ + Qcow2BitmapList *bm_list = g_new(Qcow2BitmapList, 1); + QSIMPLEQ_INIT(bm_list); + + return bm_list; +} + +static uint32_t bitmap_list_count(Qcow2BitmapList *bm_list) +{ + Qcow2Bitmap *bm; + uint32_t nb_bitmaps = 0; + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + nb_bitmaps++; + } + + return nb_bitmaps; +} + +/* bitmap_list_load + * Get bitmap list from qcow2 image. Actually reads bitmap directory, + * checks it and convert to bitmap list. + */ +static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset, + uint64_t size, Error **errp) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + uint8_t *dir, *dir_end; + Qcow2BitmapDirEntry *e; + uint32_t nb_dir_entries = 0; + Qcow2BitmapList *bm_list = NULL; + + if (size == 0) { + error_setg(errp, "Requested bitmap directory size is zero"); + return NULL; + } + + if (size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) { + error_setg(errp, "Requested bitmap directory size is too big"); + return NULL; + } + + dir = g_try_malloc(size); + if (dir == NULL) { + error_setg(errp, "Failed to allocate space for bitmap directory"); + return NULL; + } + dir_end = dir + size; + + ret = bdrv_pread(bs->file, offset, dir, size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to read bitmap directory"); + goto fail; + } + + bm_list = bitmap_list_new(); + for (e = (Qcow2BitmapDirEntry *)dir; + e < (Qcow2BitmapDirEntry *)dir_end; + e = next_dir_entry(e)) + { + Qcow2Bitmap *bm; + + if ((uint8_t *)(e + 1) > dir_end) { + goto broken_dir; + } + + if (++nb_dir_entries > s->nb_bitmaps) { + error_setg(errp, "More bitmaps found than specified in header" + " extension"); + goto fail; + } + bitmap_dir_entry_to_cpu(e); + + if ((uint8_t *)next_dir_entry(e) > dir_end) { + goto broken_dir; + } + + if (e->extra_data_size != 0) { + error_setg(errp, "Bitmap extra data is not supported"); + goto fail; + } + + ret = check_dir_entry(bs, e); + if (ret < 0) { + error_setg(errp, "Bitmap '%.*s' doesn't satisfy the constraints", + e->name_size, dir_entry_name_field(e)); + goto fail; + } + + bm = g_new(Qcow2Bitmap, 1); + bm->table.offset = e->bitmap_table_offset; + bm->table.size = e->bitmap_table_size; + bm->flags = e->flags; + bm->granularity_bits = e->granularity_bits; + bm->name = dir_entry_copy_name(e); + QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry); + } + + if (nb_dir_entries != s->nb_bitmaps) { + error_setg(errp, "Less bitmaps found than specified in header" + " extension"); + goto fail; + } + + if ((uint8_t *)e != dir_end) { + goto broken_dir; + } + + g_free(dir); + return bm_list; + +broken_dir: + ret = -EINVAL; + error_setg(errp, "Broken bitmap directory"); + +fail: + g_free(dir); + bitmap_list_free(bm_list); + + return NULL; +} + +int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + void **refcount_table, + int64_t *refcount_table_size) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + + if (s->nb_bitmaps == 0) { + return 0; + } + + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, + s->bitmap_directory_offset, + s->bitmap_directory_size); + if (ret < 0) { + return ret; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, NULL); + if (bm_list == NULL) { + res->corruptions++; + return -EINVAL; + } + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + uint64_t *bitmap_table = NULL; + int i; + + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + bm->table.offset, + bm->table.size * sizeof(uint64_t)); + if (ret < 0) { + goto out; + } + + ret = bitmap_table_load(bs, &bm->table, &bitmap_table); + if (ret < 0) { + res->corruptions++; + goto out; + } + + for (i = 0; i < bm->table.size; ++i) { + uint64_t entry = bitmap_table[i]; + uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK; + + if (check_table_entry(entry, s->cluster_size) < 0) { + res->corruptions++; + continue; + } + + if (offset == 0) { + continue; + } + + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + offset, s->cluster_size); + if (ret < 0) { + g_free(bitmap_table); + goto out; + } + } + + g_free(bitmap_table); + } + +out: + bitmap_list_free(bm_list); + + return ret; +} + +/* bitmap_list_store + * Store bitmap list to qcow2 image as a bitmap directory. + * Everything is checked. + */ +static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list, + uint64_t *offset, uint64_t *size, bool in_place) +{ + int ret; + uint8_t *dir; + int64_t dir_offset = 0; + uint64_t dir_size = 0; + Qcow2Bitmap *bm; + Qcow2BitmapDirEntry *e; + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + dir_size += calc_dir_entry_size(strlen(bm->name), 0); + } + + if (dir_size == 0 || dir_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) { + return -EINVAL; + } + + if (in_place) { + if (*size != dir_size || *offset == 0) { + return -EINVAL; + } + + dir_offset = *offset; + } + + dir = g_try_malloc(dir_size); + if (dir == NULL) { + return -ENOMEM; + } + + e = (Qcow2BitmapDirEntry *)dir; + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + e->bitmap_table_offset = bm->table.offset; + e->bitmap_table_size = bm->table.size; + e->flags = bm->flags; + e->type = BT_DIRTY_TRACKING_BITMAP; + e->granularity_bits = bm->granularity_bits; + e->name_size = strlen(bm->name); + e->extra_data_size = 0; + memcpy(e + 1, bm->name, e->name_size); + + if (check_dir_entry(bs, e) < 0) { + ret = -EINVAL; + goto fail; + } + + e = next_dir_entry(e); + } + + bitmap_directory_to_be(dir, dir_size); + + if (!in_place) { + dir_offset = qcow2_alloc_clusters(bs, dir_size); + if (dir_offset < 0) { + ret = dir_offset; + goto fail; + } + } + + ret = qcow2_pre_write_overlap_check(bs, 0, dir_offset, dir_size); + if (ret < 0) { + goto fail; + } + + ret = bdrv_pwrite(bs->file, dir_offset, dir, dir_size); + if (ret < 0) { + goto fail; + } + + g_free(dir); + + if (!in_place) { + *size = dir_size; + *offset = dir_offset; + } + + return 0; + +fail: + g_free(dir); + + if (!in_place && dir_offset > 0) { + qcow2_free_clusters(bs, dir_offset, dir_size, QCOW2_DISCARD_OTHER); + } + + return ret; +} + +/* + * Bitmap List end + */ + +static int update_ext_header_and_dir_in_place(BlockDriverState *bs, + Qcow2BitmapList *bm_list) +{ + BDRVQcow2State *s = bs->opaque; + int ret; + + if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS) || + bm_list == NULL || QSIMPLEQ_EMPTY(bm_list) || + bitmap_list_count(bm_list) != s->nb_bitmaps) + { + return -EINVAL; + } + + s->autoclear_features &= ~(uint64_t)QCOW2_AUTOCLEAR_BITMAPS; + ret = update_header_sync(bs); + if (ret < 0) { + /* Two variants are possible here: + * 1. Autoclear flag is dropped, all bitmaps will be lost. + * 2. Autoclear flag is not dropped, old state is left. + */ + return ret; + } + + /* autoclear bit is not set, so we can safely update bitmap directory */ + + ret = bitmap_list_store(bs, bm_list, &s->bitmap_directory_offset, + &s->bitmap_directory_size, true); + if (ret < 0) { + /* autoclear bit is cleared, so all leaked clusters would be removed on + * qemu-img check */ + return ret; + } + + ret = update_header_sync(bs); + if (ret < 0) { + /* autoclear bit is cleared, so all leaked clusters would be removed on + * qemu-img check */ + return ret; + } + + s->autoclear_features |= QCOW2_AUTOCLEAR_BITMAPS; + return update_header_sync(bs); + /* If final update_header_sync() fails, two variants are possible: + * 1. Autoclear flag is not set, all bitmaps will be lost. + * 2. Autoclear flag is set, header and directory are successfully updated. + */ +} + +static int update_ext_header_and_dir(BlockDriverState *bs, + Qcow2BitmapList *bm_list) +{ + BDRVQcow2State *s = bs->opaque; + int ret; + uint64_t new_offset = 0; + uint64_t new_size = 0; + uint32_t new_nb_bitmaps = 0; + uint64_t old_offset = s->bitmap_directory_offset; + uint64_t old_size = s->bitmap_directory_size; + uint32_t old_nb_bitmaps = s->nb_bitmaps; + uint64_t old_autocl = s->autoclear_features; + + if (bm_list != NULL && !QSIMPLEQ_EMPTY(bm_list)) { + new_nb_bitmaps = bitmap_list_count(bm_list); + + if (new_nb_bitmaps > QCOW2_MAX_BITMAPS) { + return -EINVAL; + } + + ret = bitmap_list_store(bs, bm_list, &new_offset, &new_size, false); + if (ret < 0) { + return ret; + } + + ret = bdrv_flush(bs->file->bs); + if (ret < 0) { + goto fail; + } + + s->autoclear_features |= QCOW2_AUTOCLEAR_BITMAPS; + } else { + s->autoclear_features &= ~(uint64_t)QCOW2_AUTOCLEAR_BITMAPS; + } + + s->bitmap_directory_offset = new_offset; + s->bitmap_directory_size = new_size; + s->nb_bitmaps = new_nb_bitmaps; + + ret = update_header_sync(bs); + if (ret < 0) { + goto fail; + } + + if (old_size > 0) { + qcow2_free_clusters(bs, old_offset, old_size, QCOW2_DISCARD_OTHER); + } + + return 0; + +fail: + if (new_offset > 0) { + qcow2_free_clusters(bs, new_offset, new_size, QCOW2_DISCARD_OTHER); + } + + s->bitmap_directory_offset = old_offset; + s->bitmap_directory_size = old_size; + s->nb_bitmaps = old_nb_bitmaps; + s->autoclear_features = old_autocl; + + return ret; +} + +/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */ +static void release_dirty_bitmap_helper(gpointer bitmap, + gpointer bs) +{ + bdrv_release_dirty_bitmap(bs, bitmap); +} + +/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */ +static void set_readonly_helper(gpointer bitmap, gpointer value) +{ + bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value); +} + +/* qcow2_load_autoloading_dirty_bitmaps() + * Return value is a hint for caller: true means that the Qcow2 header was + * updated. (false doesn't mean that the header should be updated by the + * caller, it just means that updating was not needed or the image cannot be + * written to). + * On failure the function returns false. + */ +bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + GSList *created_dirty_bitmaps = NULL; + bool header_updated = false; + + if (s->nb_bitmaps == 0) { + /* No bitmaps - nothing to do */ + return false; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + return false; + } + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + if ((bm->flags & BME_FLAG_AUTO) && !(bm->flags & BME_FLAG_IN_USE)) { + BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp); + if (bitmap == NULL) { + goto fail; + } + + bdrv_dirty_bitmap_set_persistance(bitmap, true); + bdrv_dirty_bitmap_set_autoload(bitmap, true); + bm->flags |= BME_FLAG_IN_USE; + created_dirty_bitmaps = + g_slist_append(created_dirty_bitmaps, bitmap); + } + } + + if (created_dirty_bitmaps != NULL) { + if (can_write(bs)) { + /* in_use flags must be updated */ + int ret = update_ext_header_and_dir_in_place(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Can't update bitmap directory"); + goto fail; + } + header_updated = true; + } else { + g_slist_foreach(created_dirty_bitmaps, set_readonly_helper, + (gpointer)true); + } + } + + g_slist_free(created_dirty_bitmaps); + bitmap_list_free(bm_list); + + return header_updated; + +fail: + g_slist_foreach(created_dirty_bitmaps, release_dirty_bitmap_helper, bs); + g_slist_free(created_dirty_bitmaps); + bitmap_list_free(bm_list); + + return false; +} + +int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + GSList *ro_dirty_bitmaps = NULL; + int ret = 0; + + if (s->nb_bitmaps == 0) { + /* No bitmaps - nothing to do */ + return 0; + } + + if (!can_write(bs)) { + error_setg(errp, "Can't write to the image on reopening bitmaps rw"); + return -EINVAL; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + return -EINVAL; + } + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + if (!(bm->flags & BME_FLAG_IN_USE)) { + BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(bs, bm->name); + if (bitmap == NULL) { + continue; + } + + if (!bdrv_dirty_bitmap_readonly(bitmap)) { + error_setg(errp, "Bitmap %s is not readonly but not marked" + "'IN_USE' in the image. Something went wrong," + "all the bitmaps may be corrupted", bm->name); + ret = -EINVAL; + goto out; + } + + bm->flags |= BME_FLAG_IN_USE; + ro_dirty_bitmaps = g_slist_append(ro_dirty_bitmaps, bitmap); + } + } + + if (ro_dirty_bitmaps != NULL) { + /* in_use flags must be updated */ + ret = update_ext_header_and_dir_in_place(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Can't update bitmap directory"); + goto out; + } + g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); + } + +out: + g_slist_free(ro_dirty_bitmaps); + bitmap_list_free(bm_list); + + return ret; +} + +/* store_bitmap_data() + * Store bitmap to image, filling bitmap table accordingly. + */ +static uint64_t *store_bitmap_data(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, + uint32_t *bitmap_table_size, Error **errp) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + int64_t sector; + uint64_t sbc; + uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap); + const char *bm_name = bdrv_dirty_bitmap_name(bitmap); + uint8_t *buf = NULL; + BdrvDirtyBitmapIter *dbi; + uint64_t *tb; + uint64_t tb_size = + size_to_clusters(s, + bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size)); + + if (tb_size > BME_MAX_TABLE_SIZE || + tb_size * s->cluster_size > BME_MAX_PHYS_SIZE) + { + error_setg(errp, "Bitmap '%s' is too big", bm_name); + return NULL; + } + + tb = g_try_new0(uint64_t, tb_size); + if (tb == NULL) { + error_setg(errp, "No memory"); + return NULL; + } + + dbi = bdrv_dirty_iter_new(bitmap, 0); + buf = g_malloc(s->cluster_size); + sbc = sectors_covered_by_bitmap_cluster(s, bitmap); + assert(DIV_ROUND_UP(bm_size, sbc) == tb_size); + + while ((sector = bdrv_dirty_iter_next(dbi)) != -1) { + uint64_t cluster = sector / sbc; + uint64_t end, write_size; + int64_t off; + + sector = cluster * sbc; + end = MIN(bm_size, sector + sbc); + write_size = + bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector); + assert(write_size <= s->cluster_size); + + off = qcow2_alloc_clusters(bs, s->cluster_size); + if (off < 0) { + error_setg_errno(errp, -off, + "Failed to allocate clusters for bitmap '%s'", + bm_name); + goto fail; + } + tb[cluster] = off; + + bdrv_dirty_bitmap_serialize_part(bitmap, buf, sector, end - sector); + if (write_size < s->cluster_size) { + memset(buf + write_size, 0, s->cluster_size - write_size); + } + + ret = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Qcow2 overlap check failed"); + goto fail; + } + + ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file", + bm_name); + goto fail; + } + + if (end >= bm_size) { + break; + } + + bdrv_set_dirty_iter(dbi, end); + } + + *bitmap_table_size = tb_size; + g_free(buf); + bdrv_dirty_iter_free(dbi); + + return tb; + +fail: + clear_bitmap_table(bs, tb, tb_size); + g_free(buf); + bdrv_dirty_iter_free(dbi); + g_free(tb); + + return NULL; +} + +/* store_bitmap() + * Store bm->dirty_bitmap to qcow2. + * Set bm->table_offset and bm->table_size accordingly. + */ +static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp) +{ + int ret; + uint64_t *tb; + int64_t tb_offset; + uint32_t tb_size; + BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; + const char *bm_name; + + assert(bitmap != NULL); + + bm_name = bdrv_dirty_bitmap_name(bitmap); + + tb = store_bitmap_data(bs, bitmap, &tb_size, errp); + if (tb == NULL) { + return -EINVAL; + } + + assert(tb_size <= BME_MAX_TABLE_SIZE); + tb_offset = qcow2_alloc_clusters(bs, tb_size * sizeof(tb[0])); + if (tb_offset < 0) { + error_setg_errno(errp, -tb_offset, + "Failed to allocate clusters for bitmap '%s'", + bm_name); + ret = tb_offset; + goto fail; + } + + ret = qcow2_pre_write_overlap_check(bs, 0, tb_offset, + tb_size * sizeof(tb[0])); + if (ret < 0) { + error_setg_errno(errp, -ret, "Qcow2 overlap check failed"); + goto fail; + } + + bitmap_table_to_be(tb, tb_size); + ret = bdrv_pwrite(bs->file, tb_offset, tb, tb_size * sizeof(tb[0])); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file", + bm_name); + goto fail; + } + + g_free(tb); + + bm->table.offset = tb_offset; + bm->table.size = tb_size; + + return 0; + +fail: + clear_bitmap_table(bs, tb, tb_size); + + if (tb_offset > 0) { + qcow2_free_clusters(bs, tb_offset, tb_size * sizeof(tb[0]), + QCOW2_DISCARD_OTHER); + } + + g_free(tb); + + return ret; +} + +static Qcow2Bitmap *find_bitmap_by_name(Qcow2BitmapList *bm_list, + const char *name) +{ + Qcow2Bitmap *bm; + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + if (strcmp(name, bm->name) == 0) { + return bm; + } + } + + return NULL; +} + +void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + Qcow2Bitmap *bm; + Qcow2BitmapList *bm_list; + + if (s->nb_bitmaps == 0) { + /* Absence of the bitmap is not an error: see explanation above + * bdrv_remove_persistent_dirty_bitmap() definition. */ + return; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + return; + } + + bm = find_bitmap_by_name(bm_list, name); + if (bm == NULL) { + goto fail; + } + + QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry); + + ret = update_ext_header_and_dir(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to update bitmap extension"); + goto fail; + } + + free_bitmap_clusters(bs, &bm->table); + +fail: + bitmap_free(bm); + bitmap_list_free(bm_list); +} + +void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp) +{ + BdrvDirtyBitmap *bitmap; + BDRVQcow2State *s = bs->opaque; + uint32_t new_nb_bitmaps = s->nb_bitmaps; + uint64_t new_dir_size = s->bitmap_directory_size; + int ret; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + Qcow2BitmapTableList drop_tables; + Qcow2BitmapTable *tb, *tb_next; + + if (!bdrv_has_changed_persistent_bitmaps(bs)) { + /* nothing to do */ + return; + } + + if (!can_write(bs)) { + error_setg(errp, "No write access"); + return; + } + + QSIMPLEQ_INIT(&drop_tables); + + if (s->nb_bitmaps == 0) { + bm_list = bitmap_list_new(); + } else { + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + return; + } + } + + /* check constraints and names */ + for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL; + bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) + { + const char *name = bdrv_dirty_bitmap_name(bitmap); + uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); + Qcow2Bitmap *bm; + + if (!bdrv_dirty_bitmap_get_persistance(bitmap) || + bdrv_dirty_bitmap_readonly(bitmap)) + { + continue; + } + + if (check_constraints_on_bitmap(bs, name, granularity, errp) < 0) { + error_prepend(errp, "Bitmap '%s' doesn't satisfy the constraints: ", + name); + goto fail; + } + + bm = find_bitmap_by_name(bm_list, name); + if (bm == NULL) { + if (++new_nb_bitmaps > QCOW2_MAX_BITMAPS) { + error_setg(errp, "Too many persistent bitmaps"); + goto fail; + } + + new_dir_size += calc_dir_entry_size(strlen(name), 0); + if (new_dir_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) { + error_setg(errp, "Bitmap directory is too large"); + goto fail; + } + + bm = g_new0(Qcow2Bitmap, 1); + bm->name = g_strdup(name); + QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry); + } else { + if (!(bm->flags & BME_FLAG_IN_USE)) { + error_setg(errp, "Bitmap '%s' already exists in the image", + name); + goto fail; + } + tb = g_memdup(&bm->table, sizeof(bm->table)); + bm->table.offset = 0; + bm->table.size = 0; + QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry); + } + bm->flags = bdrv_dirty_bitmap_get_autoload(bitmap) ? BME_FLAG_AUTO : 0; + bm->granularity_bits = ctz32(bdrv_dirty_bitmap_granularity(bitmap)); + bm->dirty_bitmap = bitmap; + } + + /* allocate clusters and store bitmaps */ + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + if (bm->dirty_bitmap == NULL) { + continue; + } + + ret = store_bitmap(bs, bm, errp); + if (ret < 0) { + goto fail; + } + } + + ret = update_ext_header_and_dir(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to update bitmap extension"); + goto fail; + } + + /* Bitmap directory was successfully updated, so, old data can be dropped. + * TODO it is better to reuse these clusters */ + QSIMPLEQ_FOREACH_SAFE(tb, &drop_tables, entry, tb_next) { + free_bitmap_clusters(bs, tb); + g_free(tb); + } + + bitmap_list_free(bm_list); + return; + +fail: + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + if (bm->dirty_bitmap == NULL || bm->table.offset == 0) { + continue; + } + + free_bitmap_clusters(bs, &bm->table); + } + + QSIMPLEQ_FOREACH_SAFE(tb, &drop_tables, entry, tb_next) { + g_free(tb); + } + + bitmap_list_free(bm_list); +} + +int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp) +{ + BdrvDirtyBitmap *bitmap; + Error *local_err = NULL; + + qcow2_store_persistent_dirty_bitmaps(bs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return -EINVAL; + } + + for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL; + bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) + { + if (bdrv_dirty_bitmap_get_persistance(bitmap)) { + bdrv_dirty_bitmap_set_readonly(bitmap, true); + } + } + + return 0; +} + +bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs, + const char *name, + uint32_t granularity, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + bool found; + Qcow2BitmapList *bm_list; + + if (check_constraints_on_bitmap(bs, name, granularity, errp) != 0) { + goto fail; + } + + if (s->nb_bitmaps == 0) { + return true; + } + + if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) { + error_setg(errp, + "Maximum number of persistent bitmaps is already reached"); + goto fail; + } + + if (s->bitmap_directory_size + calc_dir_entry_size(strlen(name), 0) > + QCOW2_MAX_BITMAP_DIRECTORY_SIZE) + { + error_setg(errp, "Not enough space in the bitmap directory"); + goto fail; + } + + bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, errp); + if (bm_list == NULL) { + goto fail; + } + + found = find_bitmap_by_name(bm_list, name); + bitmap_list_free(bm_list); + if (found) { + error_setg(errp, "Bitmap with the same name is already stored"); + goto fail; + } + + return true; + +fail: + error_prepend(errp, "Can't make bitmap '%s' persistent in '%s': ", + name, bdrv_get_device_or_node_name(bs)); + return false; +} diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 3d341fd9cb..f06c08f64c 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -357,52 +357,6 @@ static int count_contiguous_clusters_unallocated(int nb_clusters, return i; } -/* The crypt function is compatible with the linux cryptoloop - algorithm for < 4 GB images. NOTE: out_buf == in_buf is - supported */ -int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, bool enc, - Error **errp) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - int ret; - - for(i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - if (qcrypto_cipher_setiv(s->cipher, - ivec.b, G_N_ELEMENTS(ivec.b), - errp) < 0) { - return -1; - } - if (enc) { - ret = qcrypto_cipher_encrypt(s->cipher, - in_buf, - out_buf, - 512, - errp); - } else { - ret = qcrypto_cipher_decrypt(s->cipher, - in_buf, - out_buf, - 512, - errp); - } - if (ret < 0) { - return -1; - } - sector_num++; - in_buf += 512; - out_buf += 512; - } - return 0; -} - static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset, unsigned offset_in_cluster, @@ -435,19 +389,22 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, uint64_t src_cluster_offset, + uint64_t cluster_offset, unsigned offset_in_cluster, uint8_t *buffer, unsigned bytes) { if (bytes && bs->encrypted) { BDRVQcow2State *s = bs->opaque; - int64_t sector = (src_cluster_offset + offset_in_cluster) + int64_t sector = (s->crypt_physical_offset ? + (cluster_offset + offset_in_cluster) : + (src_cluster_offset + offset_in_cluster)) >> BDRV_SECTOR_BITS; - assert(s->cipher); assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); assert((bytes & ~BDRV_SECTOR_MASK) == 0); - if (qcow2_encrypt_sectors(s, sector, buffer, buffer, - bytes >> BDRV_SECTOR_BITS, true, NULL) < 0) { + assert(s->crypto); + if (qcrypto_block_encrypt(s->crypto, sector, buffer, + bytes, NULL) < 0) { return false; } } @@ -834,10 +791,11 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) /* Encrypt the data if necessary before writing it */ if (bs->encrypted) { - if (!do_perform_cow_encrypt(bs, m->offset, start->offset, - start_buffer, start->nb_bytes) || - !do_perform_cow_encrypt(bs, m->offset, end->offset, - end_buffer, end->nb_bytes)) { + if (!do_perform_cow_encrypt(bs, m->offset, m->alloc_offset, + start->offset, start_buffer, + start->nb_bytes) || + !do_perform_cow_encrypt(bs, m->offset, m->alloc_offset, + end->offset, end_buffer, end->nb_bytes)) { ret = -EIO; goto fail; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 7c06061aae..c9b0dcb4f3 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -281,25 +281,6 @@ int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index, return 0; } -/* - * Rounds the refcount table size up to avoid growing the table for each single - * refcount block that is allocated. - */ -static unsigned int next_refcount_table_size(BDRVQcow2State *s, - unsigned int min_size) -{ - unsigned int min_clusters = (min_size >> (s->cluster_bits - 3)) + 1; - unsigned int refcount_table_clusters = - MAX(1, s->refcount_table_size >> (s->cluster_bits - 3)); - - while (min_clusters > refcount_table_clusters) { - refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2; - } - - return refcount_table_clusters << (s->cluster_bits - 3); -} - - /* Checks if two offsets are described by the same refcount block */ static int in_same_refcount_block(BDRVQcow2State *s, uint64_t offset_a, uint64_t offset_b) @@ -321,7 +302,7 @@ static int alloc_refcount_block(BlockDriverState *bs, { BDRVQcow2State *s = bs->opaque; unsigned int refcount_table_index; - int ret; + int64_t ret; BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC); @@ -396,7 +377,7 @@ static int alloc_refcount_block(BlockDriverState *bs, ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, refcount_block); if (ret < 0) { - goto fail_block; + goto fail; } memset(*refcount_block, 0, s->cluster_size); @@ -411,12 +392,12 @@ static int alloc_refcount_block(BlockDriverState *bs, ret = update_refcount(bs, new_block, s->cluster_size, 1, false, QCOW2_DISCARD_NEVER); if (ret < 0) { - goto fail_block; + goto fail; } ret = qcow2_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { - goto fail_block; + goto fail; } /* Initialize the new refcount block only after updating its refcount, @@ -424,7 +405,7 @@ static int alloc_refcount_block(BlockDriverState *bs, ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, refcount_block); if (ret < 0) { - goto fail_block; + goto fail; } memset(*refcount_block, 0, s->cluster_size); @@ -435,7 +416,7 @@ static int alloc_refcount_block(BlockDriverState *bs, qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, *refcount_block); ret = qcow2_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { - goto fail_block; + goto fail; } /* If the refcount table is big enough, just hook the block up there */ @@ -446,7 +427,7 @@ static int alloc_refcount_block(BlockDriverState *bs, s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), &data64, sizeof(data64)); if (ret < 0) { - goto fail_block; + goto fail; } s->refcount_table[refcount_table_index] = new_block; @@ -490,74 +471,201 @@ static int alloc_refcount_block(BlockDriverState *bs, (new_block >> s->cluster_bits) + 1), s->refcount_block_size); - if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { - return -EFBIG; + /* Create the new refcount table and blocks */ + uint64_t meta_offset = (blocks_used * s->refcount_block_size) * + s->cluster_size; + + ret = qcow2_refcount_area(bs, meta_offset, 0, false, + refcount_table_index, new_block); + if (ret < 0) { + return ret; } - /* And now we need at least one block more for the new metadata */ - uint64_t table_size = next_refcount_table_size(s, blocks_used + 1); - uint64_t last_table_size; - uint64_t blocks_clusters; - do { - uint64_t table_clusters = - size_to_clusters(s, table_size * sizeof(uint64_t)); - blocks_clusters = 1 + - DIV_ROUND_UP(table_clusters, s->refcount_block_size); - uint64_t meta_clusters = table_clusters + blocks_clusters; + ret = load_refcount_block(bs, new_block, refcount_block); + if (ret < 0) { + return ret; + } - last_table_size = table_size; - table_size = next_refcount_table_size(s, blocks_used + - DIV_ROUND_UP(meta_clusters, s->refcount_block_size)); + /* If we were trying to do the initial refcount update for some cluster + * allocation, we might have used the same clusters to store newly + * allocated metadata. Make the caller search some new space. */ + return -EAGAIN; - } while (last_table_size != table_size); +fail: + if (*refcount_block != NULL) { + qcow2_cache_put(bs, s->refcount_block_cache, refcount_block); + } + return ret; +} -#ifdef DEBUG_ALLOC2 - fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n", - s->refcount_table_size, table_size); -#endif +/* + * Starting at @start_offset, this function creates new self-covering refcount + * structures: A new refcount table and refcount blocks which cover all of + * themselves, and a number of @additional_clusters beyond their end. + * @start_offset must be at the end of the image file, that is, there must be + * only empty space beyond it. + * If @exact_size is false, the refcount table will have 50 % more entries than + * necessary so it will not need to grow again soon. + * If @new_refblock_offset is not zero, it contains the offset of a refcount + * block that should be entered into the new refcount table at index + * @new_refblock_index. + * + * Returns: The offset after the new refcount structures (i.e. where the + * @additional_clusters may be placed) on success, -errno on error. + */ +int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, + uint64_t additional_clusters, bool exact_size, + int new_refblock_index, + uint64_t new_refblock_offset) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t total_refblock_count_u64, additional_refblock_count; + int total_refblock_count, table_size, area_reftable_index, table_clusters; + int i; + uint64_t table_offset, block_offset, end_offset; + int ret; + uint64_t *new_table; - /* Create the new refcount table and blocks */ - uint64_t meta_offset = (blocks_used * s->refcount_block_size) * - s->cluster_size; - uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size; - uint64_t *new_table = g_try_new0(uint64_t, table_size); - void *new_blocks = g_try_malloc0(blocks_clusters * s->cluster_size); + assert(!(start_offset % s->cluster_size)); + + qcow2_refcount_metadata_size(start_offset / s->cluster_size + + additional_clusters, + s->cluster_size, s->refcount_order, + !exact_size, &total_refblock_count_u64); + if (total_refblock_count_u64 > QCOW_MAX_REFTABLE_SIZE) { + return -EFBIG; + } + total_refblock_count = total_refblock_count_u64; + + /* Index in the refcount table of the first refcount block to cover the area + * of refcount structures we are about to create; we know that + * @total_refblock_count can cover @start_offset, so this will definitely + * fit into an int. */ + area_reftable_index = (start_offset / s->cluster_size) / + s->refcount_block_size; - assert(table_size > 0 && blocks_clusters > 0); - if (new_table == NULL || new_blocks == NULL) { + if (exact_size) { + table_size = total_refblock_count; + } else { + table_size = total_refblock_count + + DIV_ROUND_UP(total_refblock_count, 2); + } + /* The qcow2 file can only store the reftable size in number of clusters */ + table_size = ROUND_UP(table_size, s->cluster_size / sizeof(uint64_t)); + table_clusters = (table_size * sizeof(uint64_t)) / s->cluster_size; + + if (table_size > QCOW_MAX_REFTABLE_SIZE) { + return -EFBIG; + } + + new_table = g_try_new0(uint64_t, table_size); + + assert(table_size > 0); + if (new_table == NULL) { ret = -ENOMEM; - goto fail_table; + goto fail; } /* Fill the new refcount table */ - memcpy(new_table, s->refcount_table, - s->refcount_table_size * sizeof(uint64_t)); - new_table[refcount_table_index] = new_block; + if (table_size > s->max_refcount_table_index) { + /* We're actually growing the reftable */ + memcpy(new_table, s->refcount_table, + (s->max_refcount_table_index + 1) * sizeof(uint64_t)); + } else { + /* Improbable case: We're shrinking the reftable. However, the caller + * has assured us that there is only empty space beyond @start_offset, + * so we can simply drop all of the refblocks that won't fit into the + * new reftable. */ + memcpy(new_table, s->refcount_table, table_size * sizeof(uint64_t)); + } - int i; - for (i = 0; i < blocks_clusters; i++) { - new_table[blocks_used + i] = meta_offset + (i * s->cluster_size); + if (new_refblock_offset) { + assert(new_refblock_index < total_refblock_count); + new_table[new_refblock_index] = new_refblock_offset; } - /* Fill the refcount blocks */ - uint64_t table_clusters = size_to_clusters(s, table_size * sizeof(uint64_t)); - int block = 0; - for (i = 0; i < table_clusters + blocks_clusters; i++) { - s->set_refcount(new_blocks, block++, 1); + /* Count how many new refblocks we have to create */ + additional_refblock_count = 0; + for (i = area_reftable_index; i < total_refblock_count; i++) { + if (!new_table[i]) { + additional_refblock_count++; + } + } + + table_offset = start_offset + additional_refblock_count * s->cluster_size; + end_offset = table_offset + table_clusters * s->cluster_size; + + /* Fill the refcount blocks, and create new ones, if necessary */ + block_offset = start_offset; + for (i = area_reftable_index; i < total_refblock_count; i++) { + void *refblock_data; + uint64_t first_offset_covered; + + /* Reuse an existing refblock if possible, create a new one otherwise */ + if (new_table[i]) { + ret = qcow2_cache_get(bs, s->refcount_block_cache, new_table[i], + &refblock_data); + if (ret < 0) { + goto fail; + } + } else { + ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, + block_offset, &refblock_data); + if (ret < 0) { + goto fail; + } + memset(refblock_data, 0, s->cluster_size); + qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, + refblock_data); + + new_table[i] = block_offset; + block_offset += s->cluster_size; + } + + /* First host offset covered by this refblock */ + first_offset_covered = (uint64_t)i * s->refcount_block_size * + s->cluster_size; + if (first_offset_covered < end_offset) { + int j, end_index; + + /* Set the refcount of all of the new refcount structures to 1 */ + + if (first_offset_covered < start_offset) { + assert(i == area_reftable_index); + j = (start_offset - first_offset_covered) / s->cluster_size; + assert(j < s->refcount_block_size); + } else { + j = 0; + } + + end_index = MIN((end_offset - first_offset_covered) / + s->cluster_size, + s->refcount_block_size); + + for (; j < end_index; j++) { + /* The caller guaranteed us this space would be empty */ + assert(s->get_refcount(refblock_data, j) == 0); + s->set_refcount(refblock_data, j, 1); + } + + qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, + refblock_data); + } + + qcow2_cache_put(bs, s->refcount_block_cache, &refblock_data); } + assert(block_offset == table_offset); + /* Write refcount blocks to disk */ BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS); - ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks, - blocks_clusters * s->cluster_size); - g_free(new_blocks); - new_blocks = NULL; + ret = qcow2_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { - goto fail_table; + goto fail; } /* Write refcount table to disk */ - for(i = 0; i < table_size; i++) { + for (i = 0; i < total_refblock_count; i++) { cpu_to_be64s(&new_table[i]); } @@ -565,10 +673,10 @@ static int alloc_refcount_block(BlockDriverState *bs, ret = bdrv_pwrite_sync(bs->file, table_offset, new_table, table_size * sizeof(uint64_t)); if (ret < 0) { - goto fail_table; + goto fail; } - for(i = 0; i < table_size; i++) { + for (i = 0; i < total_refblock_count; i++) { be64_to_cpus(&new_table[i]); } @@ -584,7 +692,7 @@ static int alloc_refcount_block(BlockDriverState *bs, offsetof(QCowHeader, refcount_table_offset), &data, sizeof(data)); if (ret < 0) { - goto fail_table; + goto fail; } /* And switch it in memory */ @@ -601,23 +709,10 @@ static int alloc_refcount_block(BlockDriverState *bs, qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), QCOW2_DISCARD_OTHER); - ret = load_refcount_block(bs, new_block, refcount_block); - if (ret < 0) { - return ret; - } + return end_offset; - /* If we were trying to do the initial refcount update for some cluster - * allocation, we might have used the same clusters to store newly - * allocated metadata. Make the caller search some new space. */ - return -EAGAIN; - -fail_table: - g_free(new_blocks); +fail: g_free(new_table); -fail_block: - if (*refcount_block != NULL) { - qcow2_cache_put(bs, s->refcount_block_cache, refcount_block); - } return ret; } @@ -1323,11 +1418,10 @@ static int realloc_refcount_array(BDRVQcow2State *s, void **array, * * Modifies the number of errors in res. */ -static int inc_refcounts(BlockDriverState *bs, - BdrvCheckResult *res, - void **refcount_table, - int64_t *refcount_table_size, - int64_t offset, int64_t size) +int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, + void **refcount_table, + int64_t *refcount_table_size, + int64_t offset, int64_t size) { BDRVQcow2State *s = bs->opaque; uint64_t start, last, cluster_offset, k, refcount; @@ -1420,8 +1514,9 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, nb_csectors = ((l2_entry >> s->csize_shift) & s->csize_mask) + 1; l2_entry &= s->cluster_offset_mask; - ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, - l2_entry & ~511, nb_csectors * 512); + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + l2_entry & ~511, nb_csectors * 512); if (ret < 0) { goto fail; } @@ -1454,8 +1549,9 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, } /* Mark cluster as used */ - ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, - offset, s->cluster_size); + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + offset, s->cluster_size); if (ret < 0) { goto fail; } @@ -1508,8 +1604,8 @@ static int check_refcounts_l1(BlockDriverState *bs, l1_size2 = l1_size * sizeof(uint64_t); /* Mark L1 table as used */ - ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, - l1_table_offset, l1_size2); + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, + l1_table_offset, l1_size2); if (ret < 0) { goto fail; } @@ -1538,8 +1634,9 @@ static int check_refcounts_l1(BlockDriverState *bs, if (l2_offset) { /* Mark L2 table as used */ l2_offset &= L1E_OFFSET_MASK; - ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, - l2_offset, s->cluster_size); + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + l2_offset, s->cluster_size); if (ret < 0) { goto fail; } @@ -1730,7 +1827,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, } ret = bdrv_truncate(bs->file, offset + s->cluster_size, - &local_err); + PREALLOC_MODE_OFF, &local_err); if (ret < 0) { error_report_err(local_err); goto resize_fail; @@ -1757,14 +1854,15 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, } res->corruptions_fixed++; - ret = inc_refcounts(bs, res, refcount_table, nb_clusters, - offset, s->cluster_size); + ret = qcow2_inc_refcounts_imrt(bs, res, + refcount_table, nb_clusters, + offset, s->cluster_size); if (ret < 0) { return ret; } /* No need to check whether the refcount is now greater than 1: * This area was just allocated and zeroed, so it can only be - * exactly 1 after inc_refcounts() */ + * exactly 1 after qcow2_inc_refcounts_imrt() */ continue; resize_fail: @@ -1779,8 +1877,8 @@ resize_fail: } if (offset != 0) { - ret = inc_refcounts(bs, res, refcount_table, nb_clusters, - offset, s->cluster_size); + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, + offset, s->cluster_size); if (ret < 0) { return ret; } @@ -1820,8 +1918,8 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, } /* header */ - ret = inc_refcounts(bs, res, refcount_table, nb_clusters, - 0, s->cluster_size); + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, + 0, s->cluster_size); if (ret < 0) { return ret; } @@ -1842,16 +1940,32 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, return ret; } } - ret = inc_refcounts(bs, res, refcount_table, nb_clusters, - s->snapshots_offset, s->snapshots_size); + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, + s->snapshots_offset, s->snapshots_size); if (ret < 0) { return ret; } /* refcount data */ - ret = inc_refcounts(bs, res, refcount_table, nb_clusters, - s->refcount_table_offset, - s->refcount_table_size * sizeof(uint64_t)); + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, + s->refcount_table_offset, + s->refcount_table_size * sizeof(uint64_t)); + if (ret < 0) { + return ret; + } + + /* encryption */ + if (s->crypto_header.length) { + ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, + s->crypto_header.offset, + s->crypto_header.length); + if (ret < 0) { + return ret; + } + } + + /* bitmaps */ + ret = qcow2_check_bitmaps_refcounts(bs, res, refcount_table, nb_clusters); if (ret < 0) { return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 2f94f0326e..c144ea5620 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -37,6 +37,9 @@ #include "qemu/option_int.h" #include "qemu/cutils.h" #include "qemu/bswap.h" +#include "qapi/opts-visitor.h" +#include "qapi-visit.h" +#include "block/crypto.h" /* Differences with QCOW: @@ -63,6 +66,8 @@ typedef struct { #define QCOW2_EXT_MAGIC_END 0 #define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 +#define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 +#define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) { @@ -77,6 +82,86 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) } +static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset, + uint8_t *buf, size_t buflen, + void *opaque, Error **errp) +{ + BlockDriverState *bs = opaque; + BDRVQcow2State *s = bs->opaque; + ssize_t ret; + + if ((offset + buflen) > s->crypto_header.length) { + error_setg(errp, "Request for data outside of extension header"); + return -1; + } + + ret = bdrv_pread(bs->file, + s->crypto_header.offset + offset, buf, buflen); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not read encryption header"); + return -1; + } + return ret; +} + + +static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, + void *opaque, Error **errp) +{ + BlockDriverState *bs = opaque; + BDRVQcow2State *s = bs->opaque; + int64_t ret; + int64_t clusterlen; + + ret = qcow2_alloc_clusters(bs, headerlen); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Cannot allocate cluster for LUKS header size %zu", + headerlen); + return -1; + } + + s->crypto_header.length = headerlen; + s->crypto_header.offset = ret; + + /* Zero fill remaining space in cluster so it has predictable + * content in case of future spec changes */ + clusterlen = size_to_clusters(s, headerlen) * s->cluster_size; + ret = bdrv_pwrite_zeroes(bs->file, + ret + headerlen, + clusterlen - headerlen, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not zero fill encryption header"); + return -1; + } + + return ret; +} + + +static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset, + const uint8_t *buf, size_t buflen, + void *opaque, Error **errp) +{ + BlockDriverState *bs = opaque; + BDRVQcow2State *s = bs->opaque; + ssize_t ret; + + if ((offset + buflen) > s->crypto_header.length) { + error_setg(errp, "Request for data outside of extension header"); + return -1; + } + + ret = bdrv_pwrite(bs->file, + s->crypto_header.offset + offset, buf, buflen); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not read encryption header"); + return -1; + } + return ret; +} + + /* * read qcow2 extension and fill bs * start reading from start_offset @@ -86,12 +171,18 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) */ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, uint64_t end_offset, void **p_feature_table, + int flags, bool *need_update_header, Error **errp) { BDRVQcow2State *s = bs->opaque; QCowExtension ext; uint64_t offset; int ret; + Qcow2BitmapHeaderExt bitmaps_ext; + + if (need_update_header != NULL) { + *need_update_header = false; + } #ifdef DEBUG_EXT printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset); @@ -162,6 +253,126 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, } break; + case QCOW2_EXT_MAGIC_CRYPTO_HEADER: { + unsigned int cflags = 0; + if (s->crypt_method_header != QCOW_CRYPT_LUKS) { + error_setg(errp, "CRYPTO header extension only " + "expected with LUKS encryption method"); + return -EINVAL; + } + if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) { + error_setg(errp, "CRYPTO header extension size %u, " + "but expected size %zu", ext.len, + sizeof(Qcow2CryptoHeaderExtension)); + return -EINVAL; + } + + ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Unable to read CRYPTO header extension"); + return ret; + } + be64_to_cpus(&s->crypto_header.offset); + be64_to_cpus(&s->crypto_header.length); + + if ((s->crypto_header.offset % s->cluster_size) != 0) { + error_setg(errp, "Encryption header offset '%" PRIu64 "' is " + "not a multiple of cluster size '%u'", + s->crypto_header.offset, s->cluster_size); + return -EINVAL; + } + + if (flags & BDRV_O_NO_IO) { + cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; + } + s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", + qcow2_crypto_hdr_read_func, + bs, cflags, errp); + if (!s->crypto) { + return -EINVAL; + } + } break; + + case QCOW2_EXT_MAGIC_BITMAPS: + if (ext.len != sizeof(bitmaps_ext)) { + error_setg_errno(errp, -ret, "bitmaps_ext: " + "Invalid extension length"); + return -EINVAL; + } + + if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) { + error_report("WARNING: a program lacking bitmap support " + "modified this file, so all bitmaps are now " + "considered inconsistent. Some clusters may be " + "leaked, run 'qemu-img check -r' on the image " + "file to fix."); + if (need_update_header != NULL) { + /* Updating is needed to drop invalid bitmap extension. */ + *need_update_header = true; + } + break; + } + + ret = bdrv_pread(bs->file, offset, &bitmaps_ext, ext.len); + if (ret < 0) { + error_setg_errno(errp, -ret, "bitmaps_ext: " + "Could not read ext header"); + return ret; + } + + if (bitmaps_ext.reserved32 != 0) { + error_setg_errno(errp, -ret, "bitmaps_ext: " + "Reserved field is not zero"); + return -EINVAL; + } + + be32_to_cpus(&bitmaps_ext.nb_bitmaps); + be64_to_cpus(&bitmaps_ext.bitmap_directory_size); + be64_to_cpus(&bitmaps_ext.bitmap_directory_offset); + + if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) { + error_setg(errp, + "bitmaps_ext: Image has %" PRIu32 " bitmaps, " + "exceeding the QEMU supported maximum of %d", + bitmaps_ext.nb_bitmaps, QCOW2_MAX_BITMAPS); + return -EINVAL; + } + + if (bitmaps_ext.nb_bitmaps == 0) { + error_setg(errp, "found bitmaps extension with zero bitmaps"); + return -EINVAL; + } + + if (bitmaps_ext.bitmap_directory_offset & (s->cluster_size - 1)) { + error_setg(errp, "bitmaps_ext: " + "invalid bitmap directory offset"); + return -EINVAL; + } + + if (bitmaps_ext.bitmap_directory_size > + QCOW2_MAX_BITMAP_DIRECTORY_SIZE) { + error_setg(errp, "bitmaps_ext: " + "bitmap directory size (%" PRIu64 ") exceeds " + "the maximum supported size (%d)", + bitmaps_ext.bitmap_directory_size, + QCOW2_MAX_BITMAP_DIRECTORY_SIZE); + return -EINVAL; + } + + s->nb_bitmaps = bitmaps_ext.nb_bitmaps; + s->bitmap_directory_offset = + bitmaps_ext.bitmap_directory_offset; + s->bitmap_directory_size = + bitmaps_ext.bitmap_directory_size; + +#ifdef DEBUG_EXT + printf("Qcow2: Got bitmaps extension: " + "offset=%" PRIu64 " nb_bitmaps=%" PRIu32 "\n", + s->bitmap_directory_offset, s->nb_bitmaps); +#endif + break; + default: /* unknown magic - save it in case we need to rewrite the header */ { @@ -461,6 +672,8 @@ static QemuOptsList qcow2_runtime_opts = { .type = QEMU_OPT_NUMBER, .help = "Clean unused cache entries after this time (in seconds)", }, + BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.", + "ID of secret providing qcow2 AES key or LUKS passphrase"), { /* end of list */ } }, }; @@ -585,6 +798,7 @@ typedef struct Qcow2ReopenState { int overlap_check; bool discard_passthrough[QCOW2_DISCARD_MAX]; uint64_t cache_clean_interval; + QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */ } Qcow2ReopenState; static int qcow2_update_options_prepare(BlockDriverState *bs, @@ -598,9 +812,14 @@ static int qcow2_update_options_prepare(BlockDriverState *bs, int overlap_check_template = 0; uint64_t l2_cache_size, refcount_cache_size; int i; + const char *encryptfmt; + QDict *encryptopts = NULL; Error *local_err = NULL; int ret; + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + encryptfmt = qdict_get_try_str(encryptopts, "format"); + opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { @@ -751,8 +970,55 @@ static int qcow2_update_options_prepare(BlockDriverState *bs, r->discard_passthrough[QCOW2_DISCARD_OTHER] = qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); + switch (s->crypt_method_header) { + case QCOW_CRYPT_NONE: + if (encryptfmt) { + error_setg(errp, "No encryption in image header, but options " + "specified format '%s'", encryptfmt); + ret = -EINVAL; + goto fail; + } + break; + + case QCOW_CRYPT_AES: + if (encryptfmt && !g_str_equal(encryptfmt, "aes")) { + error_setg(errp, + "Header reported 'aes' encryption format but " + "options specify '%s'", encryptfmt); + ret = -EINVAL; + goto fail; + } + qdict_del(encryptopts, "format"); + r->crypto_opts = block_crypto_open_opts_init( + Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp); + break; + + case QCOW_CRYPT_LUKS: + if (encryptfmt && !g_str_equal(encryptfmt, "luks")) { + error_setg(errp, + "Header reported 'luks' encryption format but " + "options specify '%s'", encryptfmt); + ret = -EINVAL; + goto fail; + } + qdict_del(encryptopts, "format"); + r->crypto_opts = block_crypto_open_opts_init( + Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp); + break; + + default: + error_setg(errp, "Unsupported encryption method %d", + s->crypt_method_header); + break; + } + if (s->crypt_method_header != QCOW_CRYPT_NONE && !r->crypto_opts) { + ret = -EINVAL; + goto fail; + } + ret = 0; fail: + QDECREF(encryptopts); qemu_opts_del(opts); opts = NULL; return ret; @@ -785,6 +1051,9 @@ static void qcow2_update_options_commit(BlockDriverState *bs, s->cache_clean_interval = r->cache_clean_interval; cache_clean_timer_init(bs, bdrv_get_aio_context(bs)); } + + qapi_free_QCryptoBlockOpenOptions(s->crypto_opts); + s->crypto_opts = r->crypto_opts; } static void qcow2_update_options_abort(BlockDriverState *bs, @@ -796,6 +1065,7 @@ static void qcow2_update_options_abort(BlockDriverState *bs, if (r->refcount_block_cache) { qcow2_cache_destroy(bs, r->refcount_block_cache); } + qapi_free_QCryptoBlockOpenOptions(r->crypto_opts); } static int qcow2_update_options(BlockDriverState *bs, QDict *options, @@ -824,6 +1094,7 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, Error *local_err = NULL; uint64_t ext_end; uint64_t l1_vm_state_index; + bool update_header = false; ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); if (ret < 0) { @@ -929,7 +1200,7 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { void *feature_table = NULL; qcow2_read_extensions(bs, header.header_length, ext_end, - &feature_table, NULL); + &feature_table, flags, NULL, NULL); report_unsupported_feature(errp, feature_table, s->incompatible_features & ~QCOW2_INCOMPAT_MASK); @@ -961,18 +1232,6 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1); s->refcount_max += s->refcount_max - 1; - if (header.crypt_method > QCOW_CRYPT_AES) { - error_setg(errp, "Unsupported encryption method: %" PRIu32, - header.crypt_method); - ret = -EINVAL; - goto fail; - } - if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128, - QCRYPTO_CIPHER_MODE_CBC)) { - error_setg(errp, "AES cipher not available"); - ret = -EINVAL; - goto fail; - } s->crypt_method_header = header.crypt_method; if (s->crypt_method_header) { if (bdrv_uses_whitelist() && @@ -989,6 +1248,15 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } + if (s->crypt_method_header == QCOW_CRYPT_AES) { + s->crypt_physical_offset = false; + } else { + /* Assuming LUKS and any future crypt methods we + * add will all use physical offsets, due to the + * fact that the alternative is insecure... */ + s->crypt_physical_offset = true; + } + bs->encrypted = true; } @@ -1116,12 +1384,36 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, /* read qcow2 extensions */ if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL, - &local_err)) { + flags, &update_header, &local_err)) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; } + /* qcow2_read_extension may have set up the crypto context + * if the crypt method needs a header region, some methods + * don't need header extensions, so must check here + */ + if (s->crypt_method_header && !s->crypto) { + if (s->crypt_method_header == QCOW_CRYPT_AES) { + unsigned int cflags = 0; + if (flags & BDRV_O_NO_IO) { + cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; + } + s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", + NULL, NULL, cflags, errp); + if (!s->crypto) { + ret = -EINVAL; + goto fail; + } + } else if (!(flags & BDRV_O_NO_IO)) { + error_setg(errp, "Missing CRYPTO header for crypt method %d", + s->crypt_method_header); + ret = -EINVAL; + goto fail; + } + } + /* read the backing file name */ if (header.backing_file_offset != 0) { len = header.backing_file_size; @@ -1152,8 +1444,23 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, } /* Clear unknown autoclear feature bits */ - if (!bs->read_only && !(flags & BDRV_O_INACTIVE) && s->autoclear_features) { - s->autoclear_features = 0; + update_header |= s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK; + update_header = + update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE); + if (update_header) { + s->autoclear_features &= QCOW2_AUTOCLEAR_MASK; + } + + if (qcow2_load_autoloading_dirty_bitmaps(bs, &local_err)) { + update_header = false; + } + if (local_err != NULL) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } + + if (update_header) { ret = qcow2_update_header(bs); if (ret < 0) { error_setg_errno(errp, -ret, "Could not update qcow2 header"); @@ -1202,6 +1509,8 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, } g_free(s->cluster_cache); qemu_vfree(s->cluster_data); + qcrypto_block_free(s->crypto); + qapi_free_QCryptoBlockOpenOptions(s->crypto_opts); return ret; } @@ -1229,41 +1538,6 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.pdiscard_alignment = s->cluster_size; } -static int qcow2_set_key(BlockDriverState *bs, const char *key) -{ - BDRVQcow2State *s = bs->opaque; - uint8_t keybuf[16]; - int len, i; - Error *err = NULL; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for(i = 0;i < len;i++) { - keybuf[i] = key[i]; - } - assert(bs->encrypted); - - qcrypto_cipher_free(s->cipher); - s->cipher = qcrypto_cipher_new( - QCRYPTO_CIPHER_ALG_AES_128, - QCRYPTO_CIPHER_MODE_CBC, - keybuf, G_N_ELEMENTS(keybuf), - &err); - - if (!s->cipher) { - /* XXX would be nice if errors in this method could - * be properly propagate to the caller. Would need - * the bdrv_set_key() API signature to be fixed. */ - error_free(err); - return -1; - } - return 0; -} - static int qcow2_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { @@ -1281,6 +1555,11 @@ static int qcow2_reopen_prepare(BDRVReopenState *state, /* We need to write out any unwritten data if we reopen read-only. */ if ((state->flags & BDRV_O_RDWR) == 0) { + ret = qcow2_reopen_bitmaps_ro(state->bs, errp); + if (ret < 0) { + goto fail; + } + ret = bdrv_flush(state->bs); if (ret < 0) { goto fail; @@ -1379,7 +1658,7 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, *pnum = bytes >> BDRV_SECTOR_BITS; if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED && - !s->cipher) { + !s->crypto) { index_in_cluster = sector_num & (s->cluster_sectors - 1); cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS); *file = bs->file->bs; @@ -1436,7 +1715,7 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, /* prepare next request */ cur_bytes = MIN(bytes, INT_MAX); - if (s->cipher) { + if (s->crypto) { cur_bytes = MIN(cur_bytes, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } @@ -1506,7 +1785,7 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, } if (bs->encrypted) { - assert(s->cipher); + assert(s->crypto); /* * For encrypted images, read everything into a temporary @@ -1538,14 +1817,17 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, goto fail; } if (bs->encrypted) { - assert(s->cipher); + assert(s->crypto); assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0); Error *err = NULL; - if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS, - cluster_data, cluster_data, - cur_bytes >> BDRV_SECTOR_BITS, - false, &err) < 0) { + if (qcrypto_block_decrypt(s->crypto, + (s->crypt_physical_offset ? + cluster_offset + offset_in_cluster : + offset) >> BDRV_SECTOR_BITS, + cluster_data, + cur_bytes, + &err) < 0) { error_free(err); ret = -EIO; goto fail; @@ -1661,7 +1943,7 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, if (bs->encrypted) { Error *err = NULL; - assert(s->cipher); + assert(s->crypto); if (!cluster_data) { cluster_data = qemu_try_blockalign(bs->file->bs, QCOW_MAX_CRYPT_CLUSTERS @@ -1676,10 +1958,12 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size); - if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS, - cluster_data, cluster_data, - cur_bytes >>BDRV_SECTOR_BITS, - true, &err) < 0) { + if (qcrypto_block_encrypt(s->crypto, + (s->crypt_physical_offset ? + cluster_offset + offset_in_cluster : + offset) >> BDRV_SECTOR_BITS, + cluster_data, + cur_bytes, &err) < 0) { error_free(err); ret = -EIO; goto fail; @@ -1767,6 +2051,7 @@ static int qcow2_inactivate(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; int ret, result = 0; + Error *local_err = NULL; ret = qcow2_cache_flush(bs, s->l2_table_cache); if (ret) { @@ -1782,6 +2067,14 @@ static int qcow2_inactivate(BlockDriverState *bs) strerror(-ret)); } + qcow2_store_persistent_dirty_bitmaps(bs, &local_err); + if (local_err != NULL) { + result = -EINVAL; + error_report_err(local_err); + error_report("Persistent bitmaps are lost for node '%s'", + bdrv_get_device_or_node_name(bs)); + } + if (result == 0) { qcow2_mark_clean(bs); } @@ -1804,8 +2097,8 @@ static void qcow2_close(BlockDriverState *bs) qcow2_cache_destroy(bs, s->l2_table_cache); qcow2_cache_destroy(bs, s->refcount_block_cache); - qcrypto_cipher_free(s->cipher); - s->cipher = NULL; + qcrypto_block_free(s->crypto); + s->crypto = NULL; g_free(s->unknown_header_fields); cleanup_unknown_header_ext(bs); @@ -1823,7 +2116,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp) { BDRVQcow2State *s = bs->opaque; int flags = s->flags; - QCryptoCipher *cipher = NULL; + QCryptoBlock *crypto = NULL; QDict *options; Error *local_err = NULL; int ret; @@ -1833,8 +2126,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp) * that means we don't have to worry about reopening them here. */ - cipher = s->cipher; - s->cipher = NULL; + crypto = s->crypto; + s->crypto = NULL; qcow2_close(bs); @@ -1855,7 +2148,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp) return; } - s->cipher = cipher; + s->crypto = crypto; } static size_t header_ext_add(char *buf, uint32_t magic, const void *s, @@ -1981,6 +2274,22 @@ int qcow2_update_header(BlockDriverState *bs) buflen -= ret; } + /* Full disk encryption header pointer extension */ + if (s->crypto_header.offset != 0) { + cpu_to_be64s(&s->crypto_header.offset); + cpu_to_be64s(&s->crypto_header.length); + ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER, + &s->crypto_header, sizeof(s->crypto_header), + buflen); + be64_to_cpus(&s->crypto_header.offset); + be64_to_cpus(&s->crypto_header.length); + if (ret < 0) { + goto fail; + } + buf += ret; + buflen -= ret; + } + /* Feature table */ if (s->qcow_version >= 3) { Qcow2Feature features[] = { @@ -2010,6 +2319,25 @@ int qcow2_update_header(BlockDriverState *bs) buflen -= ret; } + /* Bitmap extension */ + if (s->nb_bitmaps > 0) { + Qcow2BitmapHeaderExt bitmaps_header = { + .nb_bitmaps = cpu_to_be32(s->nb_bitmaps), + .bitmap_directory_size = + cpu_to_be64(s->bitmap_directory_size), + .bitmap_directory_offset = + cpu_to_be64(s->bitmap_directory_offset) + }; + ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BITMAPS, + &bitmaps_header, sizeof(bitmaps_header), + buflen); + if (ret < 0) { + goto fail; + } + buf += ret; + buflen -= ret; + } + /* Keep unknown header extensions */ QLIST_FOREACH(uext, &s->unknown_header_ext, next) { ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen); @@ -2079,24 +2407,105 @@ static int qcow2_change_backing_file(BlockDriverState *bs, return qcow2_update_header(bs); } -static int preallocate(BlockDriverState *bs) +static int qcow2_crypt_method_from_format(const char *encryptfmt) +{ + if (g_str_equal(encryptfmt, "luks")) { + return QCOW_CRYPT_LUKS; + } else if (g_str_equal(encryptfmt, "aes")) { + return QCOW_CRYPT_AES; + } else { + return -EINVAL; + } +} + +static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt, + QemuOpts *opts, Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + QCryptoBlockCreateOptions *cryptoopts = NULL; + QCryptoBlock *crypto = NULL; + int ret = -EINVAL; + QDict *options, *encryptopts; + int fmt; + + options = qemu_opts_to_qdict(opts, NULL); + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + QDECREF(options); + + fmt = qcow2_crypt_method_from_format(encryptfmt); + + switch (fmt) { + case QCOW_CRYPT_LUKS: + cryptoopts = block_crypto_create_opts_init( + Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp); + break; + case QCOW_CRYPT_AES: + cryptoopts = block_crypto_create_opts_init( + Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp); + break; + default: + error_setg(errp, "Unknown encryption format '%s'", encryptfmt); + break; + } + if (!cryptoopts) { + ret = -EINVAL; + goto out; + } + s->crypt_method_header = fmt; + + crypto = qcrypto_block_create(cryptoopts, "encrypt.", + qcow2_crypto_hdr_init_func, + qcow2_crypto_hdr_write_func, + bs, errp); + if (!crypto) { + ret = -EINVAL; + goto out; + } + + ret = qcow2_update_header(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not write encryption header"); + goto out; + } + + out: + QDECREF(encryptopts); + qcrypto_block_free(crypto); + qapi_free_QCryptoBlockCreateOptions(cryptoopts); + return ret; +} + + +/** + * Preallocates metadata structures for data clusters between @offset (in the + * guest disk) and @new_length (which is thus generally the new guest disk + * size). + * + * Returns: 0 on success, -errno on failure. + */ +static int preallocate(BlockDriverState *bs, + uint64_t offset, uint64_t new_length) { + BDRVQcow2State *s = bs->opaque; uint64_t bytes; - uint64_t offset; uint64_t host_offset = 0; unsigned int cur_bytes; int ret; QCowL2Meta *meta; - bytes = bdrv_getlength(bs); - offset = 0; + if (qemu_in_coroutine()) { + qemu_co_mutex_lock(&s->lock); + } + + assert(offset <= new_length); + bytes = new_length - offset; while (bytes) { cur_bytes = MIN(bytes, INT_MAX); ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, &host_offset, &meta); if (ret < 0) { - return ret; + goto done; } while (meta) { @@ -2106,7 +2515,7 @@ static int preallocate(BlockDriverState *bs) if (ret < 0) { qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, QCOW2_DISCARD_NEVER); - return ret; + goto done; } /* There are no dependent requests, but we need to remove our @@ -2133,32 +2542,174 @@ static int preallocate(BlockDriverState *bs) ret = bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1, &data, 1); if (ret < 0) { - return ret; + goto done; } } - return 0; + ret = 0; + +done: + if (qemu_in_coroutine()) { + qemu_co_mutex_unlock(&s->lock); + } + return ret; } -static int qcow2_create2(const char *filename, int64_t total_size, - const char *backing_file, const char *backing_format, - int flags, size_t cluster_size, PreallocMode prealloc, - QemuOpts *opts, int version, int refcount_order, - Error **errp) +/* qcow2_refcount_metadata_size: + * @clusters: number of clusters to refcount (including data and L1/L2 tables) + * @cluster_size: size of a cluster, in bytes + * @refcount_order: refcount bits power-of-2 exponent + * @generous_increase: allow for the refcount table to be 1.5x as large as it + * needs to be + * + * Returns: Number of bytes required for refcount blocks and table metadata. + */ +int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, + int refcount_order, bool generous_increase, + uint64_t *refblock_count) { + /* + * Every host cluster is reference-counted, including metadata (even + * refcount metadata is recursively included). + * + * An accurate formula for the size of refcount metadata size is difficult + * to derive. An easier method of calculation is finding the fixed point + * where no further refcount blocks or table clusters are required to + * reference count every cluster. + */ + int64_t blocks_per_table_cluster = cluster_size / sizeof(uint64_t); + int64_t refcounts_per_block = cluster_size * 8 / (1 << refcount_order); + int64_t table = 0; /* number of refcount table clusters */ + int64_t blocks = 0; /* number of refcount block clusters */ + int64_t last; + int64_t n = 0; + + do { + last = n; + blocks = DIV_ROUND_UP(clusters + table + blocks, refcounts_per_block); + table = DIV_ROUND_UP(blocks, blocks_per_table_cluster); + n = clusters + blocks + table; + + if (n == last && generous_increase) { + clusters += DIV_ROUND_UP(table, 2); + n = 0; /* force another loop */ + generous_increase = false; + } + } while (n != last); + + if (refblock_count) { + *refblock_count = blocks; + } + + return (blocks + table) * cluster_size; +} + +/** + * qcow2_calc_prealloc_size: + * @total_size: virtual disk size in bytes + * @cluster_size: cluster size in bytes + * @refcount_order: refcount bits power-of-2 exponent + * + * Returns: Total number of bytes required for the fully allocated image + * (including metadata). + */ +static int64_t qcow2_calc_prealloc_size(int64_t total_size, + size_t cluster_size, + int refcount_order) +{ + int64_t meta_size = 0; + uint64_t nl1e, nl2e; + int64_t aligned_total_size = align_offset(total_size, cluster_size); + + /* header: 1 cluster */ + meta_size += cluster_size; + + /* total size of L2 tables */ + nl2e = aligned_total_size / cluster_size; + nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t)); + meta_size += nl2e * sizeof(uint64_t); + + /* total size of L1 tables */ + nl1e = nl2e * sizeof(uint64_t) / cluster_size; + nl1e = align_offset(nl1e, cluster_size / sizeof(uint64_t)); + meta_size += nl1e * sizeof(uint64_t); + + /* total size of refcount table and blocks */ + meta_size += qcow2_refcount_metadata_size( + (meta_size + aligned_total_size) / cluster_size, + cluster_size, refcount_order, false, NULL); + + return meta_size + aligned_total_size; +} + +static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp) +{ + size_t cluster_size; int cluster_bits; - QDict *options; - /* Calculate cluster_bits */ + cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, + DEFAULT_CLUSTER_SIZE); cluster_bits = ctz32(cluster_size); if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS || (1 << cluster_bits) != cluster_size) { error_setg(errp, "Cluster size must be a power of two between %d and " "%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); - return -EINVAL; + return 0; + } + return cluster_size; +} + +static int qcow2_opt_get_version_del(QemuOpts *opts, Error **errp) +{ + char *buf; + int ret; + + buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL); + if (!buf) { + ret = 3; /* default */ + } else if (!strcmp(buf, "0.10")) { + ret = 2; + } else if (!strcmp(buf, "1.1")) { + ret = 3; + } else { + error_setg(errp, "Invalid compatibility level: '%s'", buf); + ret = -EINVAL; + } + g_free(buf); + return ret; +} + +static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version, + Error **errp) +{ + uint64_t refcount_bits; + + refcount_bits = qemu_opt_get_number_del(opts, BLOCK_OPT_REFCOUNT_BITS, 16); + if (refcount_bits > 64 || !is_power_of_2(refcount_bits)) { + error_setg(errp, "Refcount width must be a power of two and may not " + "exceed 64 bits"); + return 0; } + if (version < 3 && refcount_bits != 16) { + error_setg(errp, "Different refcount widths than 16 bits require " + "compatibility level 1.1 or above (use compat=1.1 or " + "greater)"); + return 0; + } + + return refcount_bits; +} + +static int qcow2_create2(const char *filename, int64_t total_size, + const char *backing_file, const char *backing_format, + int flags, size_t cluster_size, PreallocMode prealloc, + QemuOpts *opts, int version, int refcount_order, + const char *encryptfmt, Error **errp) +{ + QDict *options; + /* * Open the image file and write a minimal qcow2 header. * @@ -2178,65 +2729,9 @@ static int qcow2_create2(const char *filename, int64_t total_size, int ret; if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) { - /* Note: The following calculation does not need to be exact; if it is a - * bit off, either some bytes will be "leaked" (which is fine) or we - * will need to increase the file size by some bytes (which is fine, - * too, as long as the bulk is allocated here). Therefore, using - * floating point arithmetic is fine. */ - int64_t meta_size = 0; - uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count; - int64_t aligned_total_size = align_offset(total_size, cluster_size); - int refblock_bits, refblock_size; - /* refcount entry size in bytes */ - double rces = (1 << refcount_order) / 8.; - - /* see qcow2_open() */ - refblock_bits = cluster_bits - (refcount_order - 3); - refblock_size = 1 << refblock_bits; - - /* header: 1 cluster */ - meta_size += cluster_size; - - /* total size of L2 tables */ - nl2e = aligned_total_size / cluster_size; - nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t)); - meta_size += nl2e * sizeof(uint64_t); - - /* total size of L1 tables */ - nl1e = nl2e * sizeof(uint64_t) / cluster_size; - nl1e = align_offset(nl1e, cluster_size / sizeof(uint64_t)); - meta_size += nl1e * sizeof(uint64_t); - - /* total size of refcount blocks - * - * note: every host cluster is reference-counted, including metadata - * (even refcount blocks are recursively included). - * Let: - * a = total_size (this is the guest disk size) - * m = meta size not including refcount blocks and refcount tables - * c = cluster size - * y1 = number of refcount blocks entries - * y2 = meta size including everything - * rces = refcount entry size in bytes - * then, - * y1 = (y2 + a)/c - * y2 = y1 * rces + y1 * rces * sizeof(u64) / c + m - * we can get y1: - * y1 = (a + m) / (c - rces - rces * sizeof(u64) / c) - */ - nrefblocke = (aligned_total_size + meta_size + cluster_size) - / (cluster_size - rces - rces * sizeof(uint64_t) - / cluster_size); - refblock_count = DIV_ROUND_UP(nrefblocke, refblock_size); - meta_size += refblock_count * cluster_size; - - /* total size of refcount tables */ - nreftablee = align_offset(refblock_count, - cluster_size / sizeof(uint64_t)); - meta_size += nreftablee * sizeof(uint64_t); - - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, - aligned_total_size + meta_size, &error_abort); + int64_t prealloc_size = + qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort); qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[prealloc], &error_abort); } @@ -2263,7 +2758,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, *header = (QCowHeader) { .magic = cpu_to_be32(QCOW_MAGIC), .version = cpu_to_be32(version), - .cluster_bits = cpu_to_be32(cluster_bits), + .cluster_bits = cpu_to_be32(ctz32(cluster_size)), .size = cpu_to_be64(0), .l1_table_offset = cpu_to_be64(0), .l1_size = cpu_to_be32(0), @@ -2273,11 +2768,8 @@ static int qcow2_create2(const char *filename, int64_t total_size, .header_length = cpu_to_be32(sizeof(*header)), }; - if (flags & BLOCK_FLAG_ENCRYPT) { - header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES); - } else { - header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); - } + /* We'll update this to correct value later */ + header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) { header->compatible_features |= @@ -2340,7 +2832,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, } /* Okay, now that we have a valid image, let's give it the right size */ - ret = blk_truncate(blk, total_size, errp); + ret = blk_truncate(blk, total_size, PREALLOC_MODE_OFF, errp); if (ret < 0) { error_prepend(errp, "Could not resize image: "); goto out; @@ -2356,12 +2848,17 @@ static int qcow2_create2(const char *filename, int64_t total_size, } } + /* Want encryption? There you go. */ + if (encryptfmt) { + ret = qcow2_set_up_encryption(blk_bs(blk), encryptfmt, opts, errp); + if (ret < 0) { + goto out; + } + } + /* And if we're supposed to preallocate metadata, do that now */ if (prealloc != PREALLOC_MODE_OFF) { - BDRVQcow2State *s = blk_bs(blk)->opaque; - qemu_co_mutex_lock(&s->lock); - ret = preallocate(blk_bs(blk)); - qemu_co_mutex_unlock(&s->lock); + ret = preallocate(blk_bs(blk), 0, total_size); if (ret < 0) { error_setg_errno(errp, -ret, "Could not preallocate metadata"); goto out; @@ -2371,11 +2868,17 @@ static int qcow2_create2(const char *filename, int64_t total_size, blk_unref(blk); blk = NULL; - /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */ + /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning. + * Using BDRV_O_NO_IO, since encryption is now setup we don't want to + * have to setup decryption context. We're not doing any I/O on the top + * level BlockDriverState, only lower layers, where BDRV_O_NO_IO does + * not have effect. + */ options = qdict_new(); qdict_put_str(options, "driver", "qcow2"); blk = blk_new_open(filename, NULL, options, - BDRV_O_RDWR | BDRV_O_NO_BACKING, &local_err); + BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO, + &local_err); if (blk == NULL) { error_propagate(errp, local_err); ret = -EIO; @@ -2399,9 +2902,10 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp) int flags = 0; size_t cluster_size = DEFAULT_CLUSTER_SIZE; PreallocMode prealloc; - int version = 3; - uint64_t refcount_bits = 16; + int version; + uint64_t refcount_bits; int refcount_order; + const char *encryptfmt = NULL; Error *local_err = NULL; int ret; @@ -2410,11 +2914,23 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp) BDRV_SECTOR_SIZE); backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); - if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) { - flags |= BLOCK_FLAG_ENCRYPT; + encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT); + if (encryptfmt) { + if (qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT)) { + error_setg(errp, "Options " BLOCK_OPT_ENCRYPT " and " + BLOCK_OPT_ENCRYPT_FORMAT " are mutually exclusive"); + ret = -EINVAL; + goto finish; + } + } else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) { + encryptfmt = "aes"; + } + cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto finish; } - cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, - DEFAULT_CLUSTER_SIZE); buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); prealloc = qapi_enum_parse(PreallocMode_lookup, buf, PREALLOC_MODE__MAX, PREALLOC_MODE_OFF, @@ -2424,16 +2940,10 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp) ret = -EINVAL; goto finish; } - g_free(buf); - buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL); - if (!buf) { - /* keep the default */ - } else if (!strcmp(buf, "0.10")) { - version = 2; - } else if (!strcmp(buf, "1.1")) { - version = 3; - } else { - error_setg(errp, "Invalid compatibility level: '%s'", buf); + + version = qcow2_opt_get_version_del(opts, &local_err); + if (local_err) { + error_propagate(errp, local_err); ret = -EINVAL; goto finish; } @@ -2456,19 +2966,9 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp) goto finish; } - refcount_bits = qemu_opt_get_number_del(opts, BLOCK_OPT_REFCOUNT_BITS, - refcount_bits); - if (refcount_bits > 64 || !is_power_of_2(refcount_bits)) { - error_setg(errp, "Refcount width must be a power of two and may not " - "exceed 64 bits"); - ret = -EINVAL; - goto finish; - } - - if (version < 3 && refcount_bits != 16) { - error_setg(errp, "Different refcount widths than 16 bits require " - "compatibility level 1.1 or above (use compat=1.1 or " - "greater)"); + refcount_bits = qcow2_opt_get_refcount_bits_del(opts, version, &local_err); + if (local_err) { + error_propagate(errp, local_err); ret = -EINVAL; goto finish; } @@ -2477,7 +2977,7 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp) ret = qcow2_create2(filename, size, backing_file, backing_fmt, flags, cluster_size, prealloc, opts, version, refcount_order, - &local_err); + encryptfmt, &local_err); error_propagate(errp, local_err); finish: @@ -2585,12 +3085,22 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs, return ret; } -static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int qcow2_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVQcow2State *s = bs->opaque; + uint64_t old_length; int64_t new_l1_size; int ret; + if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA && + prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL) + { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + if (offset & 511) { error_setg(errp, "The new size must be a multiple of 512"); return -EINVAL; @@ -2602,8 +3112,17 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp) return -ENOTSUP; } + /* cannot proceed if image has bitmaps */ + if (s->nb_bitmaps) { + /* TODO: resize bitmaps in the image */ + error_setg(errp, "Can't resize an image which has bitmaps"); + return -ENOTSUP; + } + + old_length = bs->total_sectors * 512; + /* shrinking is currently not supported */ - if (offset < bs->total_sectors * 512) { + if (offset < old_length) { error_setg(errp, "qcow2 doesn't support shrinking images yet"); return -ENOTSUP; } @@ -2615,6 +3134,128 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp) return ret; } + switch (prealloc) { + case PREALLOC_MODE_OFF: + break; + + case PREALLOC_MODE_METADATA: + ret = preallocate(bs, old_length, offset); + if (ret < 0) { + error_setg_errno(errp, -ret, "Preallocation failed"); + return ret; + } + break; + + case PREALLOC_MODE_FALLOC: + case PREALLOC_MODE_FULL: + { + int64_t allocation_start, host_offset, guest_offset; + int64_t clusters_allocated; + int64_t old_file_size, new_file_size; + uint64_t nb_new_data_clusters, nb_new_l2_tables; + + old_file_size = bdrv_getlength(bs->file->bs); + if (old_file_size < 0) { + error_setg_errno(errp, -old_file_size, + "Failed to inquire current file length"); + return ret; + } + + nb_new_data_clusters = DIV_ROUND_UP(offset - old_length, + s->cluster_size); + + /* This is an overestimation; we will not actually allocate space for + * these in the file but just make sure the new refcount structures are + * able to cover them so we will not have to allocate new refblocks + * while entering the data blocks in the potentially new L2 tables. + * (We do not actually care where the L2 tables are placed. Maybe they + * are already allocated or they can be placed somewhere before + * @old_file_size. It does not matter because they will be fully + * allocated automatically, so they do not need to be covered by the + * preallocation. All that matters is that we will not have to allocate + * new refcount structures for them.) */ + nb_new_l2_tables = DIV_ROUND_UP(nb_new_data_clusters, + s->cluster_size / sizeof(uint64_t)); + /* The cluster range may not be aligned to L2 boundaries, so add one L2 + * table for a potential head/tail */ + nb_new_l2_tables++; + + allocation_start = qcow2_refcount_area(bs, old_file_size, + nb_new_data_clusters + + nb_new_l2_tables, + true, 0, 0); + if (allocation_start < 0) { + error_setg_errno(errp, -allocation_start, + "Failed to resize refcount structures"); + return -allocation_start; + } + + clusters_allocated = qcow2_alloc_clusters_at(bs, allocation_start, + nb_new_data_clusters); + if (clusters_allocated < 0) { + error_setg_errno(errp, -clusters_allocated, + "Failed to allocate data clusters"); + return -clusters_allocated; + } + + assert(clusters_allocated == nb_new_data_clusters); + + /* Allocate the data area */ + new_file_size = allocation_start + + nb_new_data_clusters * s->cluster_size; + ret = bdrv_truncate(bs->file, new_file_size, prealloc, errp); + if (ret < 0) { + error_prepend(errp, "Failed to resize underlying file: "); + qcow2_free_clusters(bs, allocation_start, + nb_new_data_clusters * s->cluster_size, + QCOW2_DISCARD_OTHER); + return ret; + } + + /* Create the necessary L2 entries */ + host_offset = allocation_start; + guest_offset = old_length; + while (nb_new_data_clusters) { + int64_t guest_cluster = guest_offset >> s->cluster_bits; + int64_t nb_clusters = MIN(nb_new_data_clusters, + s->l2_size - guest_cluster % s->l2_size); + QCowL2Meta allocation = { + .offset = guest_offset, + .alloc_offset = host_offset, + .nb_clusters = nb_clusters, + }; + qemu_co_queue_init(&allocation.dependent_requests); + + ret = qcow2_alloc_cluster_link_l2(bs, &allocation); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to update L2 tables"); + qcow2_free_clusters(bs, host_offset, + nb_new_data_clusters * s->cluster_size, + QCOW2_DISCARD_OTHER); + return ret; + } + + guest_offset += nb_clusters * s->cluster_size; + host_offset += nb_clusters * s->cluster_size; + nb_new_data_clusters -= nb_clusters; + } + break; + } + + default: + g_assert_not_reached(); + } + + if (prealloc != PREALLOC_MODE_OFF) { + /* Flush metadata before actually changing the image size */ + ret = bdrv_flush(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Failed to flush the preallocated area to disk"); + return ret; + } + } + /* write updated header.size */ offset = cpu_to_be64(offset); ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), @@ -2646,7 +3287,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset, /* align end of file to a sector boundary to ease reading with sector based I/Os */ cluster_offset = bdrv_getlength(bs->file->bs); - return bdrv_truncate(bs->file, cluster_offset, NULL); + return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL); } buf = qemu_blockalign(bs, s->cluster_size); @@ -2862,7 +3503,7 @@ static int make_completely_empty(BlockDriverState *bs) } ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, - &local_err); + PREALLOC_MODE_OFF, &local_err); if (ret < 0) { error_report_err(local_err); goto fail; @@ -2946,6 +3587,142 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) return 0; } +static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, + Error **errp) +{ + Error *local_err = NULL; + BlockMeasureInfo *info; + uint64_t required = 0; /* bytes that contribute to required size */ + uint64_t virtual_size; /* disk size as seen by guest */ + uint64_t refcount_bits; + uint64_t l2_tables; + size_t cluster_size; + int version; + char *optstr; + PreallocMode prealloc; + bool has_backing_file; + + /* Parse image creation options */ + cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err); + if (local_err) { + goto err; + } + + version = qcow2_opt_get_version_del(opts, &local_err); + if (local_err) { + goto err; + } + + refcount_bits = qcow2_opt_get_refcount_bits_del(opts, version, &local_err); + if (local_err) { + goto err; + } + + optstr = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); + prealloc = qapi_enum_parse(PreallocMode_lookup, optstr, + PREALLOC_MODE__MAX, PREALLOC_MODE_OFF, + &local_err); + g_free(optstr); + if (local_err) { + goto err; + } + + optstr = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + has_backing_file = !!optstr; + g_free(optstr); + + virtual_size = align_offset(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + cluster_size); + + /* Check that virtual disk size is valid */ + l2_tables = DIV_ROUND_UP(virtual_size / cluster_size, + cluster_size / sizeof(uint64_t)); + if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) { + error_setg(&local_err, "The image size is too large " + "(try using a larger cluster size)"); + goto err; + } + + /* Account for input image */ + if (in_bs) { + int64_t ssize = bdrv_getlength(in_bs); + if (ssize < 0) { + error_setg_errno(&local_err, -ssize, + "Unable to get image virtual_size"); + goto err; + } + + virtual_size = align_offset(ssize, cluster_size); + + if (has_backing_file) { + /* We don't how much of the backing chain is shared by the input + * image and the new image file. In the worst case the new image's + * backing file has nothing in common with the input image. Be + * conservative and assume all clusters need to be written. + */ + required = virtual_size; + } else { + int cluster_sectors = cluster_size / BDRV_SECTOR_SIZE; + int64_t sector_num; + int pnum = 0; + + for (sector_num = 0; + sector_num < ssize / BDRV_SECTOR_SIZE; + sector_num += pnum) { + int nb_sectors = MAX(ssize / BDRV_SECTOR_SIZE - sector_num, + INT_MAX); + BlockDriverState *file; + int64_t ret; + + ret = bdrv_get_block_status_above(in_bs, NULL, + sector_num, nb_sectors, + &pnum, &file); + if (ret < 0) { + error_setg_errno(&local_err, -ret, + "Unable to get block status"); + goto err; + } + + if (ret & BDRV_BLOCK_ZERO) { + /* Skip zero regions (safe with no backing file) */ + } else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) == + (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) { + /* Extend pnum to end of cluster for next iteration */ + pnum = ROUND_UP(sector_num + pnum, cluster_sectors) - + sector_num; + + /* Count clusters we've seen */ + required += (sector_num % cluster_sectors + pnum) * + BDRV_SECTOR_SIZE; + } + } + } + } + + /* Take into account preallocation. Nothing special is needed for + * PREALLOC_MODE_METADATA since metadata is always counted. + */ + if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) { + required = virtual_size; + } + + info = g_new(BlockMeasureInfo, 1); + info->fully_allocated = + qcow2_calc_prealloc_size(virtual_size, cluster_size, + ctz32(refcount_bits)); + + /* Remove data clusters that are not required. This overestimates the + * required size because metadata needed for the fully allocated file is + * still counted. + */ + info->required = info->fully_allocated - virtual_size + required; + return info; + +err: + error_propagate(errp, local_err); + return NULL; +} + static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcow2State *s = bs->opaque; @@ -2959,8 +3736,14 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; - ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1); + ImageInfoSpecific *spec_info; + QCryptoBlockInfo *encrypt_info = NULL; + if (s->crypto != NULL) { + encrypt_info = qcrypto_block_get_info(s->crypto, &error_abort); + } + + spec_info = g_new(ImageInfoSpecific, 1); *spec_info = (ImageInfoSpecific){ .type = IMAGE_INFO_SPECIFIC_KIND_QCOW2, .u.qcow2.data = g_new(ImageInfoSpecificQCow2, 1), @@ -2987,6 +3770,30 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) assert(false); } + if (encrypt_info) { + ImageInfoSpecificQCow2Encryption *qencrypt = + g_new(ImageInfoSpecificQCow2Encryption, 1); + switch (encrypt_info->format) { + case Q_CRYPTO_BLOCK_FORMAT_QCOW: + qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_AES; + qencrypt->u.aes = encrypt_info->u.qcow; + break; + case Q_CRYPTO_BLOCK_FORMAT_LUKS: + qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_LUKS; + qencrypt->u.luks = encrypt_info->u.luks; + break; + default: + abort(); + } + /* Since we did shallow copy above, erase any pointers + * in the original info */ + memset(&encrypt_info->u, 0, sizeof(encrypt_info->u)); + qapi_free_QCryptoBlockInfo(encrypt_info); + + spec_info->u.qcow2.data->has_encrypt = true; + spec_info->u.qcow2.data->encrypt = qencrypt; + } + return spec_info; } @@ -3175,6 +3982,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, const char *compat = NULL; uint64_t cluster_size = s->cluster_size; bool encrypt; + int encformat; int refcount_bits = s->refcount_bits; Error *local_err = NULL; int ret; @@ -3211,12 +4019,20 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT); } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) { encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, - !!s->cipher); + !!s->crypto); - if (encrypt != !!s->cipher) { + if (encrypt != !!s->crypto) { error_report("Changing the encryption flag is not supported"); return -ENOTSUP; } + } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) { + encformat = qcow2_crypt_method_from_format( + qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT)); + + if (encformat != s->crypt_method_header) { + error_report("Changing the encryption format is not supported"); + return -ENOTSUP; + } } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) { cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, cluster_size); @@ -3333,7 +4149,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, return ret; } - ret = blk_truncate(blk, new_size, &local_err); + ret = blk_truncate(blk, new_size, PREALLOC_MODE_OFF, &local_err); blk_unref(blk); if (ret < 0) { error_report_err(local_err); @@ -3431,10 +4247,23 @@ static QemuOptsList qcow2_create_opts = { { .name = BLOCK_OPT_ENCRYPT, .type = QEMU_OPT_BOOL, - .help = "Encrypt the image", - .def_value_str = "off" + .help = "Encrypt the image with format 'aes'. (Deprecated " + "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)", }, { + .name = BLOCK_OPT_ENCRYPT_FORMAT, + .type = QEMU_OPT_STRING, + .help = "Encrypt the image, format choices: 'aes', 'luks'", + }, + BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.", + "ID of secret providing qcow AES key or LUKS passphrase"), + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."), + BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."), + { .name = BLOCK_OPT_CLUSTER_SIZE, .type = QEMU_OPT_SIZE, .help = "qcow2 cluster size", @@ -3476,7 +4305,6 @@ BlockDriver bdrv_qcow2 = { .bdrv_create = qcow2_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_get_block_status = qcow2_co_get_block_status, - .bdrv_set_key = qcow2_set_key, .bdrv_co_preadv = qcow2_co_preadv, .bdrv_co_pwritev = qcow2_co_pwritev, @@ -3493,6 +4321,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_snapshot_delete = qcow2_snapshot_delete, .bdrv_snapshot_list = qcow2_snapshot_list, .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, + .bdrv_measure = qcow2_measure, .bdrv_get_info = qcow2_get_info, .bdrv_get_specific_info = qcow2_get_specific_info, @@ -3512,6 +4341,10 @@ BlockDriver bdrv_qcow2 = { .bdrv_detach_aio_context = qcow2_detach_aio_context, .bdrv_attach_aio_context = qcow2_attach_aio_context, + + .bdrv_reopen_bitmaps_rw = qcow2_reopen_bitmaps_rw, + .bdrv_can_store_new_dirty_bitmap = qcow2_can_store_new_dirty_bitmap, + .bdrv_remove_persistent_dirty_bitmap = qcow2_remove_persistent_dirty_bitmap, }; static void bdrv_qcow2_init(void) diff --git a/block/qcow2.h b/block/qcow2.h index 87b15eb4aa..96a8d43c17 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -25,7 +25,7 @@ #ifndef BLOCK_QCOW2_H #define BLOCK_QCOW2_H -#include "crypto/cipher.h" +#include "crypto/block.h" #include "qemu/coroutine.h" //#define DEBUG_ALLOC @@ -36,6 +36,7 @@ #define QCOW_CRYPT_NONE 0 #define QCOW_CRYPT_AES 1 +#define QCOW_CRYPT_LUKS 2 #define QCOW_MAX_CRYPT_CLUSTERS 32 #define QCOW_MAX_SNAPSHOTS 65536 @@ -52,6 +53,10 @@ * space for snapshot names and IDs */ #define QCOW_MAX_SNAPSHOTS_SIZE (1024 * QCOW_MAX_SNAPSHOTS) +/* Bitmap header extension constraints */ +#define QCOW2_MAX_BITMAPS 65535 +#define QCOW2_MAX_BITMAP_DIRECTORY_SIZE (1024 * QCOW2_MAX_BITMAPS) + /* indicate that the refcount of the referenced cluster is exactly one. */ #define QCOW_OFLAG_COPIED (1ULL << 63) /* indicate that the cluster is compressed (they never have the copied flag) */ @@ -163,6 +168,11 @@ typedef struct QCowSnapshot { struct Qcow2Cache; typedef struct Qcow2Cache Qcow2Cache; +typedef struct Qcow2CryptoHeaderExtension { + uint64_t offset; + uint64_t length; +} QEMU_PACKED Qcow2CryptoHeaderExtension; + typedef struct Qcow2UnknownHeaderExtension { uint32_t magic; uint32_t len; @@ -195,6 +205,14 @@ enum { QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS, }; +/* Autoclear feature bits */ +enum { + QCOW2_AUTOCLEAR_BITMAPS_BITNR = 0, + QCOW2_AUTOCLEAR_BITMAPS = 1 << QCOW2_AUTOCLEAR_BITMAPS_BITNR, + + QCOW2_AUTOCLEAR_MASK = QCOW2_AUTOCLEAR_BITMAPS, +}; + enum qcow2_discard_type { QCOW2_DISCARD_NEVER = 0, QCOW2_DISCARD_ALWAYS, @@ -222,6 +240,13 @@ typedef uint64_t Qcow2GetRefcountFunc(const void *refcount_array, typedef void Qcow2SetRefcountFunc(void *refcount_array, uint64_t index, uint64_t value); +typedef struct Qcow2BitmapHeaderExt { + uint32_t nb_bitmaps; + uint32_t reserved32; + uint64_t bitmap_directory_size; + uint64_t bitmap_directory_offset; +} QEMU_PACKED Qcow2BitmapHeaderExt; + typedef struct BDRVQcow2State { int cluster_bits; int cluster_size; @@ -257,13 +282,21 @@ typedef struct BDRVQcow2State { CoMutex lock; - QCryptoCipher *cipher; /* current cipher, NULL if no key yet */ + Qcow2CryptoHeaderExtension crypto_header; /* QCow2 header extension */ + QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */ + QCryptoBlock *crypto; /* Disk encryption format driver */ + bool crypt_physical_offset; /* Whether to use virtual or physical offset + for encryption initialization vector tweak */ uint32_t crypt_method_header; uint64_t snapshots_offset; int snapshots_size; unsigned int nb_snapshots; QCowSnapshot *snapshots; + uint32_t nb_bitmaps; + uint64_t bitmap_directory_size; + uint64_t bitmap_directory_offset; + int flags; int qcow_version; bool use_lazy_refcounts; @@ -492,6 +525,10 @@ static inline uint64_t refcount_diff(uint64_t r1, uint64_t r2) int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, int64_t sector_num, int nb_sectors); +int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, + int refcount_order, bool generous_increase, + uint64_t *refblock_count); + int qcow2_mark_dirty(BlockDriverState *bs); int qcow2_mark_corrupt(BlockDriverState *bs); int qcow2_mark_consistent(BlockDriverState *bs); @@ -512,6 +549,11 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index, uint64_t addend, bool decrease, enum qcow2_discard_type type); +int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset, + uint64_t additional_clusters, bool exact_size, + int new_refblock_index, + uint64_t new_refblock_offset); + int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size); int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, int64_t nb_clusters); @@ -534,6 +576,10 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, int64_t size); int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, int64_t size); +int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, + void **refcount_table, + int64_t *refcount_table_size, + int64_t offset, int64_t size); int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, BlockDriverAmendStatusCB *status_cb, @@ -545,8 +591,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, bool enc, Error **errp); + uint8_t *buf, int nb_sectors, bool enc, Error **errp); int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, unsigned int *bytes, uint64_t *cluster_offset); @@ -605,4 +650,20 @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, void **table); void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); +/* qcow2-bitmap.c functions */ +int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + void **refcount_table, + int64_t *refcount_table_size); +bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp); +int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp); +void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp); +int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp); +bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs, + const char *name, + uint32_t granularity, + Error **errp); +void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp); + #endif diff --git a/block/qed.c b/block/qed.c index 385381a78a..86cad2188c 100644 --- a/block/qed.c +++ b/block/qed.c @@ -583,7 +583,7 @@ static int qed_create(const char *filename, uint32_t cluster_size, blk_set_allow_write_beyond_eof(blk, true); /* File must start empty and grow, check truncate is supported */ - ret = blk_truncate(blk, 0, errp); + ret = blk_truncate(blk, 0, PREALLOC_MODE_OFF, errp); if (ret < 0) { goto out; } @@ -1342,12 +1342,19 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, QED_AIOCB_WRITE | QED_AIOCB_ZERO); } -static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVQEDState *s = bs->opaque; uint64_t old_image_size; int ret; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + if (!qed_is_image_size_valid(offset, s->header.cluster_size, s->header.table_size)) { error_setg(errp, "Invalid image size specified"); diff --git a/block/raw-format.c b/block/raw-format.c index 1ea8c2d7ff..142649ed56 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -312,6 +312,31 @@ static int64_t raw_getlength(BlockDriverState *bs) return s->size; } +static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs, + Error **errp) +{ + BlockMeasureInfo *info; + int64_t required; + + if (in_bs) { + required = bdrv_getlength(in_bs); + if (required < 0) { + error_setg_errno(errp, -required, "Unable to get image size"); + return NULL; + } + } else { + required = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); + } + + info = g_new(BlockMeasureInfo, 1); + info->required = required; + + /* Unallocated sectors count towards the file size in raw images */ + info->fully_allocated = info->required; + return info; +} + static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { return bdrv_get_info(bs->file->bs, bdi); @@ -327,7 +352,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) } } -static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int raw_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVRawState *s = bs->opaque; @@ -343,7 +369,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp) s->size = offset; offset += s->offset; - return bdrv_truncate(bs->file, offset, errp); + return bdrv_truncate(bs->file, offset, prealloc, errp); } static int raw_media_changed(BlockDriverState *bs) @@ -479,6 +505,7 @@ BlockDriver bdrv_raw = { .bdrv_truncate = &raw_truncate, .bdrv_getlength = &raw_getlength, .has_variable_length = true, + .bdrv_measure = &raw_measure, .bdrv_get_info = &raw_get_info, .bdrv_refresh_limits = &raw_refresh_limits, .bdrv_probe_blocksizes = &raw_probe_blocksizes, diff --git a/block/rbd.c b/block/rbd.c index 9da02cdceb..9151d5caa6 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -936,11 +936,18 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs) return info.size; } -static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVRBDState *s = bs->opaque; int r; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + r = rbd_resize(s->image, offset); if (r < 0) { error_setg_errno(errp, -r, "Failed to resize file"); diff --git a/block/sheepdog.c b/block/sheepdog.c index 08d7b11e9d..b7b7e6bbe5 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -2153,13 +2153,20 @@ static int64_t sd_getlength(BlockDriverState *bs) return s->inode.vdi_size; } -static int sd_truncate(BlockDriverState *bs, int64_t offset, Error **errp) +static int sd_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BDRVSheepdogState *s = bs->opaque; int ret, fd; unsigned int datalen; uint64_t max_vdi_size; + if (prealloc != PREALLOC_MODE_OFF) { + error_setg(errp, "Unsupported preallocation mode '%s'", + PreallocMode_lookup[prealloc]); + return -ENOTSUP; + } + max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS; if (offset < s->inode.vdi_size) { error_setg(errp, "shrinking is not supported"); @@ -2448,7 +2455,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, BDRVSheepdogState *s = bs->opaque; if (offset > s->inode.vdi_size) { - ret = sd_truncate(bs, offset, NULL); + ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL); if (ret < 0) { return ret; } diff --git a/block/vdi.c b/block/vdi.c index 79af47763b..2b6e8fa1ed 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -832,7 +832,8 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) } if (image_type == VDI_TYPE_STATIC) { - ret = blk_truncate(blk, offset + blocks * block_size, errp); + ret = blk_truncate(blk, offset + blocks * block_size, + PREALLOC_MODE_OFF, errp); if (ret < 0) { error_prepend(errp, "Failed to statically allocate %s", filename); goto exit; diff --git a/block/vhdx-log.c b/block/vhdx-log.c index 3f4c2aa095..01278f3fc9 100644 --- a/block/vhdx-log.c +++ b/block/vhdx-log.c @@ -548,7 +548,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s, if (new_file_size % (1024*1024)) { /* round up to nearest 1MB boundary */ new_file_size = ((new_file_size >> 20) + 1) << 20; - bdrv_truncate(bs->file, new_file_size, NULL); + bdrv_truncate(bs->file, new_file_size, PREALLOC_MODE_OFF, NULL); } } qemu_vfree(desc_entries); diff --git a/block/vhdx.c b/block/vhdx.c index 8b270b57c9..a9cecd2773 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1171,7 +1171,8 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, /* per the spec, the address for a block is in units of 1MB */ *new_offset = ROUND_UP(*new_offset, 1024 * 1024); - return bdrv_truncate(bs->file, *new_offset + s->block_size, NULL); + return bdrv_truncate(bs->file, *new_offset + s->block_size, + PREALLOC_MODE_OFF, NULL); } /* @@ -1607,12 +1608,13 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, if (type == VHDX_TYPE_DYNAMIC) { /* All zeroes, so we can just extend the file - the end of the BAT * is the furthest thing we have written yet */ - ret = blk_truncate(blk, data_file_offset, errp); + ret = blk_truncate(blk, data_file_offset, PREALLOC_MODE_OFF, errp); if (ret < 0) { goto exit; } } else if (type == VHDX_TYPE_FIXED) { - ret = blk_truncate(blk, data_file_offset + image_size, errp); + ret = blk_truncate(blk, data_file_offset + image_size, + PREALLOC_MODE_OFF, errp); if (ret < 0) { goto exit; } diff --git a/block/vmdk.c b/block/vmdk.c index 55581b03fe..24d71b5982 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1714,7 +1714,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, blk_set_allow_write_beyond_eof(blk, true); if (flat) { - ret = blk_truncate(blk, filesize, errp); + ret = blk_truncate(blk, filesize, PREALLOC_MODE_OFF, errp); goto exit; } magic = cpu_to_be32(VMDK4_MAGIC); @@ -1777,7 +1777,8 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, goto exit; } - ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, errp); + ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, + PREALLOC_MODE_OFF, errp); if (ret < 0) { goto exit; } @@ -2086,7 +2087,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) /* bdrv_pwrite write padding zeros to align to sector, we don't need that * for description file */ if (desc_offset == 0) { - ret = blk_truncate(new_blk, desc_len, errp); + ret = blk_truncate(new_blk, desc_len, PREALLOC_MODE_OFF, errp); } exit: if (new_blk) { diff --git a/block/vpc.c b/block/vpc.c index b313c68148..9a6f8173a5 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -858,7 +858,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, /* Add footer to total size */ total_size += HEADER_SIZE; - ret = blk_truncate(blk, total_size, errp); + ret = blk_truncate(blk, total_size, PREALLOC_MODE_OFF, errp); if (ret < 0) { return ret; } diff --git a/blockdev.c b/blockdev.c index e2016b6f37..9c6dd270b7 100644 --- a/blockdev.c +++ b/blockdev.c @@ -593,10 +593,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, bs->detect_zeroes = detect_zeroes; - if (bdrv_key_required(bs)) { - autostart = 0; - } - block_acct_setup(blk_get_stats(blk), account_invalid, account_failed); if (!parse_stats_intervals(blk_get_stats(blk), interval_list, errp)) { @@ -1987,6 +1983,8 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common, /* AIO context taken and released within qmp_block_dirty_bitmap_add */ qmp_block_dirty_bitmap_add(action->node, action->name, action->has_granularity, action->granularity, + action->has_persistent, action->persistent, + action->has_autoload, action->autoload, &local_err); if (!local_err) { @@ -2037,6 +2035,9 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common, } else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) { error_setg(errp, "Cannot clear a disabled bitmap"); return; + } else if (bdrv_dirty_bitmap_readonly(state->bitmap)) { + error_setg(errp, "Cannot clear a readonly bitmap"); + return; } bdrv_clear_dirty_bitmap(state->bitmap, &state->backup); @@ -2265,24 +2266,8 @@ void qmp_block_passwd(bool has_device, const char *device, bool has_node_name, const char *node_name, const char *password, Error **errp) { - Error *local_err = NULL; - BlockDriverState *bs; - AioContext *aio_context; - - bs = bdrv_lookup_bs(has_device ? device : NULL, - has_node_name ? node_name : NULL, - &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - - bdrv_add_key(bs, password, errp); - - aio_context_release(aio_context); + error_setg(errp, + "Setting block passwords directly is no longer supported"); } /* @@ -2591,12 +2576,6 @@ void qmp_blockdev_change_medium(bool has_device, const char *device, goto fail; } - bdrv_add_key(medium_bs, NULL, &err); - if (err) { - error_propagate(errp, err); - goto fail; - } - rc = do_open_tray(has_device ? device : NULL, has_id ? id : NULL, false, &err); @@ -2731,9 +2710,12 @@ out: void qmp_block_dirty_bitmap_add(const char *node, const char *name, bool has_granularity, uint32_t granularity, + bool has_persistent, bool persistent, + bool has_autoload, bool autoload, Error **errp) { BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; if (!name || name[0] == '\0') { error_setg(errp, "Bitmap name cannot be empty"); @@ -2756,7 +2738,32 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, granularity = bdrv_get_default_bitmap_granularity(bs); } - bdrv_create_dirty_bitmap(bs, granularity, name, errp); + if (!has_persistent) { + persistent = false; + } + if (!has_autoload) { + autoload = false; + } + + if (has_autoload && !persistent) { + error_setg(errp, "Autoload flag must be used only for persistent " + "bitmaps"); + return; + } + + if (persistent && + !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) + { + return; + } + + bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); + if (bitmap == NULL) { + return; + } + + bdrv_dirty_bitmap_set_persistance(bitmap, persistent); + bdrv_dirty_bitmap_set_autoload(bitmap, autoload); } void qmp_block_dirty_bitmap_remove(const char *node, const char *name, @@ -2764,6 +2771,7 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name, { BlockDriverState *bs; BdrvDirtyBitmap *bitmap; + Error *local_err = NULL; bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); if (!bitmap || !bs) { @@ -2776,6 +2784,15 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name, name); return; } + + if (bdrv_dirty_bitmap_get_persistance(bitmap)) { + bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + } + bdrv_dirty_bitmap_make_anon(bitmap); bdrv_release_dirty_bitmap(bs, bitmap); } @@ -2805,11 +2822,39 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name, "Bitmap '%s' is currently disabled and cannot be cleared", name); return; + } else if (bdrv_dirty_bitmap_readonly(bitmap)) { + error_setg(errp, "Bitmap '%s' is readonly and cannot be cleared", name); + return; } bdrv_clear_dirty_bitmap(bitmap, NULL); } +BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, + const char *name, + Error **errp) +{ + BdrvDirtyBitmap *bitmap; + BlockDriverState *bs; + BlockDirtyBitmapSha256 *ret = NULL; + char *sha256; + + bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); + if (!bitmap || !bs) { + return NULL; + } + + sha256 = bdrv_dirty_bitmap_sha256(bitmap, errp); + if (sha256 == NULL) { + return NULL; + } + + ret = g_new(BlockDirtyBitmapSha256, 1); + ret->sha256 = sha256; + + return ret; +} + void hmp_drive_del(Monitor *mon, const QDict *qdict) { const char *id = qdict_get_str(qdict, "id"); @@ -2913,7 +2958,7 @@ void qmp_block_resize(bool has_device, const char *device, } bdrv_drained_begin(bs); - ret = blk_truncate(blk, size, errp); + ret = blk_truncate(blk, size, PREALLOC_MODE_OFF, errp); bdrv_drained_end(bs); out: @@ -3866,13 +3911,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list); - if (bs && bdrv_key_required(bs)) { - QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list); - bdrv_unref(bs); - error_setg(errp, "blockdev-add doesn't support encrypted devices"); - goto fail; - } - fail: visit_free(v); } @@ -202,9 +202,9 @@ supported_kvm_target() { supported_xen_target() { test "$xen" = "yes" || return 1 glob "$1" "*-softmmu" || return 1 - case "${1%-softmmu}:$cpu" in - arm:arm | aarch64:aarch64 | \ - i386:i386 | i386:x86_64 | x86_64:i386 | x86_64:x86_64) + # Only i386 and x86_64 provide the xenpv machine. + case "${1%-softmmu}" in + i386|x86_64) return 0 ;; esac diff --git a/crypto/block-luks.c b/crypto/block-luks.c index 2b97d89a69..afb8543108 100644 --- a/crypto/block-luks.c +++ b/crypto/block-luks.c @@ -638,6 +638,7 @@ qcrypto_block_luks_find_key(QCryptoBlock *block, static int qcrypto_block_luks_open(QCryptoBlock *block, QCryptoBlockOpenOptions *options, + const char *optprefix, QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, @@ -661,7 +662,8 @@ qcrypto_block_luks_open(QCryptoBlock *block, if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { if (!options->u.luks.key_secret) { - error_setg(errp, "Parameter 'key-secret' is required for cipher"); + error_setg(errp, "Parameter '%skey-secret' is required for cipher", + optprefix ? optprefix : ""); return -1; } password = qcrypto_secret_lookup_as_utf8( @@ -885,6 +887,7 @@ qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) static int qcrypto_block_luks_create(QCryptoBlock *block, QCryptoBlockCreateOptions *options, + const char *optprefix, QCryptoBlockInitFunc initfunc, QCryptoBlockWriteFunc writefunc, void *opaque, @@ -937,7 +940,8 @@ qcrypto_block_luks_create(QCryptoBlock *block, * be silently ignored, for compatibility with dm-crypt */ if (!options->u.luks.key_secret) { - error_setg(errp, "Parameter 'key-secret' is required for cipher"); + error_setg(errp, "Parameter '%skey-secret' is required for cipher", + optprefix ? optprefix : ""); return -1; } password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c index be88c6f0ef..a456fe338b 100644 --- a/crypto/block-qcow.c +++ b/crypto/block-qcow.c @@ -94,6 +94,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block, static int qcrypto_block_qcow_open(QCryptoBlock *block, QCryptoBlockOpenOptions *options, + const char *optprefix, QCryptoBlockReadFunc readfunc G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED, unsigned int flags, @@ -104,7 +105,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block, } else { if (!options->u.qcow.key_secret) { error_setg(errp, - "Parameter 'key-secret' is required for cipher"); + "Parameter '%skey-secret' is required for cipher", + optprefix ? optprefix : ""); return -1; } return qcrypto_block_qcow_init(block, @@ -116,13 +118,15 @@ qcrypto_block_qcow_open(QCryptoBlock *block, static int qcrypto_block_qcow_create(QCryptoBlock *block, QCryptoBlockCreateOptions *options, + const char *optprefix, QCryptoBlockInitFunc initfunc G_GNUC_UNUSED, QCryptoBlockWriteFunc writefunc G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED, Error **errp) { if (!options->u.qcow.key_secret) { - error_setg(errp, "Parameter 'key-secret' is required for cipher"); + error_setg(errp, "Parameter '%skey-secret' is required for cipher", + optprefix ? optprefix : ""); return -1; } /* QCow2 has no special header, since everything is hardwired */ diff --git a/crypto/block.c b/crypto/block.c index 64c8420425..b097d451af 100644 --- a/crypto/block.c +++ b/crypto/block.c @@ -48,6 +48,7 @@ bool qcrypto_block_has_format(QCryptoBlockFormat format, QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, + const char *optprefix, QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, @@ -67,7 +68,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, block->driver = qcrypto_block_drivers[options->format]; - if (block->driver->open(block, options, + if (block->driver->open(block, options, optprefix, readfunc, opaque, flags, errp) < 0) { g_free(block); return NULL; @@ -78,6 +79,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, + const char *optprefix, QCryptoBlockInitFunc initfunc, QCryptoBlockWriteFunc writefunc, void *opaque, @@ -97,7 +99,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, block->driver = qcrypto_block_drivers[options->format]; - if (block->driver->create(block, options, initfunc, + if (block->driver->create(block, options, optprefix, initfunc, writefunc, opaque, errp) < 0) { g_free(block); return NULL; diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h index 68f0f06704..0edb810e22 100644 --- a/crypto/blockpriv.h +++ b/crypto/blockpriv.h @@ -41,6 +41,7 @@ struct QCryptoBlock { struct QCryptoBlockDriver { int (*open)(QCryptoBlock *block, QCryptoBlockOpenOptions *options, + const char *optprefix, QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, @@ -48,6 +49,7 @@ struct QCryptoBlockDriver { int (*create)(QCryptoBlock *block, QCryptoBlockCreateOptions *options, + const char *optprefix, QCryptoBlockInitFunc initfunc, QCryptoBlockWriteFunc writefunc, void *opaque, diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index 80cdfd0e91..d7fdb1fee3 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -45,6 +45,7 @@ The first cluster of a qcow2 image contains the file header: 32 - 35: crypt_method 0 for no encryption 1 for AES encryption + 2 for LUKS encryption 36 - 39: l1_size Number of entries in the active L1 table @@ -135,6 +136,7 @@ be stored. Each extension has a structure like the following: 0xE2792ACA - Backing file format name 0x6803f857 - Feature name table 0x23852875 - Bitmaps extension + 0x0537be77 - Full disk encryption header pointer other - Unknown header extension, can be safely ignored @@ -201,12 +203,113 @@ The fields of the bitmaps extension are: 8 - 15: bitmap_directory_size Size of the bitmap directory in bytes. It is the cumulative - size of all (nb_bitmaps) bitmap headers. + size of all (nb_bitmaps) bitmap directory entries. 16 - 23: bitmap_directory_offset Offset into the image file at which the bitmap directory starts. Must be aligned to a cluster boundary. +== Full disk encryption header pointer == + +The full disk encryption header must be present if, and only if, the +'crypt_method' header requires metadata. Currently this is only true +of the 'LUKS' crypt method. The header extension must be absent for +other methods. + +This header provides the offset at which the crypt method can store +its additional data, as well as the length of such data. + + Byte 0 - 7: Offset into the image file at which the encryption + header starts in bytes. Must be aligned to a cluster + boundary. + Byte 8 - 15: Length of the written encryption header in bytes. + Note actual space allocated in the qcow2 file may + be larger than this value, since it will be rounded + to the nearest multiple of the cluster size. Any + unused bytes in the allocated space will be initialized + to 0. + +For the LUKS crypt method, the encryption header works as follows. + +The first 592 bytes of the header clusters will contain the LUKS +partition header. This is then followed by the key material data areas. +The size of the key material data areas is determined by the number of +stripes in the key slot and key size. Refer to the LUKS format +specification ('docs/on-disk-format.pdf' in the cryptsetup source +package) for details of the LUKS partition header format. + +In the LUKS partition header, the "payload-offset" field will be +calculated as normal for the LUKS spec. ie the size of the LUKS +header, plus key material regions, plus padding, relative to the +start of the LUKS header. This offset value is not required to be +qcow2 cluster aligned. Its value is currently never used in the +context of qcow2, since the qcow2 file format itself defines where +the real payload offset is, but none the less a valid payload offset +should always be present. + +In the LUKS key slots header, the "key-material-offset" is relative +to the start of the LUKS header clusters in the qcow2 container, +not the start of the qcow2 file. + +Logically the layout looks like + + +-----------------------------+ + | QCow2 header | + | QCow2 header extension X | + | QCow2 header extension FDE | + | QCow2 header extension ... | + | QCow2 header extension Z | + +-----------------------------+ + | ....other QCow2 tables.... | + . . + . . + +-----------------------------+ + | +-------------------------+ | + | | LUKS partition header | | + | +-------------------------+ | + | | LUKS key material 1 | | + | +-------------------------+ | + | | LUKS key material 2 | | + | +-------------------------+ | + | | LUKS key material ... | | + | +-------------------------+ | + | | LUKS key material 8 | | + | +-------------------------+ | + +-----------------------------+ + | QCow2 cluster payload | + . . + . . + . . + | | + +-----------------------------+ + +== Data encryption == + +When an encryption method is requested in the header, the image payload +data must be encrypted/decrypted on every write/read. The image headers +and metadata are never encrypted. + +The algorithms used for encryption vary depending on the method + + - AES: + + The AES cipher, in CBC mode, with 256 bit keys. + + Initialization vectors generated using plain64 method, with + the virtual disk sector as the input tweak. + + This format is no longer supported in QEMU system emulators, due + to a number of design flaws affecting its security. It is only + supported in the command line tools for the sake of back compatibility + and data liberation. + + - LUKS: + + The algorithms are specified in the LUKS header. + + Initialization vectors generated using the method specified + in the LUKS header, with the physical disk sector as the + input tweak. == Host cluster management == @@ -426,8 +529,7 @@ Each bitmap saved in the image is described in a bitmap directory entry. The bitmap directory is a contiguous area in the image file, whose starting offset and length are given by the header extension fields bitmap_directory_offset and bitmap_directory_size. The entries of the bitmap directory have variable -length, depending on the lengths of the bitmap name and extra data. These -entries are also called bitmap headers. +length, depending on the lengths of the bitmap name and extra data. Structure of a bitmap directory entry: @@ -472,8 +574,7 @@ Structure of a bitmap directory entry: 17: granularity_bits Granularity bits. Valid values: 0 - 63. - Note: Qemu currently doesn't support granularity_bits - greater than 31. + Note: Qemu currently supports only values 9 - 31. Granularity is calculated as granularity = 1 << granularity_bits diff --git a/hmp-commands.hx b/hmp-commands.hx index 275ccdfbc7..75f8bac01b 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1646,6 +1646,8 @@ STEXI @item block_passwd @var{device} @var{password} @findex block_passwd Set the encrypted device @var{device} password to @var{password} + +This command is now obsolete and will always return an error since 2.10 ETEXI { @@ -1088,37 +1088,12 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict) g_free(data); } -static void hmp_cont_cb(void *opaque, int err) -{ - if (!err) { - qmp_cont(NULL); - } -} - -static bool key_is_missing(const BlockInfo *bdev) -{ - return (bdev->inserted && bdev->inserted->encryption_key_missing); -} - void hmp_cont(Monitor *mon, const QDict *qdict) { - BlockInfoList *bdev_list, *bdev; Error *err = NULL; - bdev_list = qmp_query_block(NULL); - for (bdev = bdev_list; bdev; bdev = bdev->next) { - if (key_is_missing(bdev->value)) { - monitor_read_block_device_key(mon, bdev->value->device, - hmp_cont_cb, NULL); - goto out; - } - } - qmp_cont(&err); hmp_handle_error(mon, &err); - -out: - qapi_free_BlockInfoList(bdev_list); } void hmp_system_wakeup(Monitor *mon, const QDict *qdict) @@ -1741,12 +1716,6 @@ void hmp_change(Monitor *mon, const QDict *qdict) qmp_blockdev_change_medium(true, device, false, NULL, target, !!arg, arg, !!read_only, read_only_mode, &err); - if (err && - error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { - error_free(err); - monitor_read_block_device_key(mon, device, NULL, NULL); - return; - } } hmp_handle_error(mon, &err); diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 4937e2bc83..3034849c80 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -62,6 +62,7 @@ static const AspeedSoCInfo aspeed_socs[] = { .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, + .wdts_num = 2, }, { .name = "ast2400-a1", .cpu_model = "arm926", @@ -72,6 +73,7 @@ static const AspeedSoCInfo aspeed_socs[] = { .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, + .wdts_num = 2, }, { .name = "ast2400", .cpu_model = "arm926", @@ -82,6 +84,7 @@ static const AspeedSoCInfo aspeed_socs[] = { .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, + .wdts_num = 2, }, { .name = "ast2500-a1", .cpu_model = "arm1176", @@ -92,6 +95,7 @@ static const AspeedSoCInfo aspeed_socs[] = { .spi_bases = aspeed_soc_ast2500_spi_bases, .fmc_typename = "aspeed.smc.ast2500-fmc", .spi_typename = aspeed_soc_ast2500_typenames, + .wdts_num = 3, }, }; @@ -175,9 +179,11 @@ static void aspeed_soc_init(Object *obj) object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), "ram-size", &error_abort); - object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT); - object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL); - qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default()); + for (i = 0; i < sc->info->wdts_num; i++) { + object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT); + object_property_add_child(obj, "wdt[*]", OBJECT(&s->wdt[i]), NULL); + qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus_get_default()); + } object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100); object_property_add_child(obj, "ftgmac100", OBJECT(&s->ftgmac100), NULL); @@ -300,12 +306,15 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE); /* Watch dog */ - object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; + for (i = 0; i < sc->info->wdts_num; i++) { + object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, + ASPEED_SOC_WDT_BASE + i * 0x20); } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE); /* Net */ qdev_set_nic_properties(DEVICE(&s->ftgmac100), &nd_table[0]); diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 0050626a69..ee851e3ae5 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -87,6 +87,9 @@ /* Clock controller SFR base address */ #define EXYNOS4210_CLK_BASE_ADDR 0x10030000 +/* PRNG/HASH SFR base address */ +#define EXYNOS4210_RNG_BASE_ADDR 0x10830400 + /* Display controllers (FIMD) */ #define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000 @@ -305,6 +308,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem) sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL); sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL); + sysbus_create_simple("exynos4210.rng", EXYNOS4210_RNG_BASE_ADDR, NULL); /* PWM */ sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR, diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index b305d9032a..5a0e2a3c1a 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -25,6 +25,7 @@ #include "qom/cpu.h" #include "qemu/log.h" #include "trace.h" +#include "sysemu/kvm.h" /* #define DEBUG_GIC */ @@ -1412,6 +1413,12 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) return; } + if (kvm_enabled() && !kvm_arm_supports_user_irq()) { + error_setg(errp, "KVM with user space irqchip only works when the " + "host kernel supports KVM_CAP_ARM_USER_IRQ"); + return; + } + /* This creates distributor and main CPU interface (s->cpuiomem[0]) */ gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops); diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 95cdabb2dd..dad2f37fb1 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -841,8 +841,9 @@ static int64_t load_kernel (void) if (loaderparams.initrd_filename) { initrd_size = get_image_size (loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; - if (initrd_offset + initrd_size > ram_size) { + initrd_offset = (loaderparams.ram_low_size - initrd_size + - ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; + if (kernel_high >= initrd_offset) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", loaderparams.initrd_filename); diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 44e0e79ba7..7e373dbbff 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -28,7 +28,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o obj-$(CONFIG_REALVIEW) += arm_sysctl.o obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o -obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o +obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o exynos4210_rng.o obj-$(CONFIG_IMX) += imx_ccm.o obj-$(CONFIG_IMX) += imx31_ccm.o obj-$(CONFIG_IMX) += imx25_ccm.o diff --git a/hw/misc/exynos4210_rng.c b/hw/misc/exynos4210_rng.c new file mode 100644 index 0000000000..31ebe38e26 --- /dev/null +++ b/hw/misc/exynos4210_rng.c @@ -0,0 +1,277 @@ +/* + * Exynos4210 Pseudo Random Nubmer Generator Emulation + * + * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "crypto/random.h" +#include "hw/sysbus.h" +#include "qemu/log.h" + +#define DEBUG_EXYNOS_RNG 0 + +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_EXYNOS_RNG) { \ + printf("exynos4210_rng: " fmt, ## __VA_ARGS__); \ + } \ + } while (0) + +#define TYPE_EXYNOS4210_RNG "exynos4210.rng" +#define EXYNOS4210_RNG(obj) \ + OBJECT_CHECK(Exynos4210RngState, (obj), TYPE_EXYNOS4210_RNG) + +/* + * Exynos4220, PRNG, only polling mode is supported. + */ + +/* RNG_CONTROL_1 register bitfields, reset value: 0x0 */ +#define EXYNOS4210_RNG_CONTROL_1_PRNG 0x8 +#define EXYNOS4210_RNG_CONTROL_1_START_INIT BIT(4) +/* RNG_STATUS register bitfields, reset value: 0x1 */ +#define EXYNOS4210_RNG_STATUS_PRNG_ERROR BIT(7) +#define EXYNOS4210_RNG_STATUS_PRNG_DONE BIT(5) +#define EXYNOS4210_RNG_STATUS_MSG_DONE BIT(4) +#define EXYNOS4210_RNG_STATUS_PARTIAL_DONE BIT(3) +#define EXYNOS4210_RNG_STATUS_PRNG_BUSY BIT(2) +#define EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE BIT(1) +#define EXYNOS4210_RNG_STATUS_BUFFER_READY BIT(0) +#define EXYNOS4210_RNG_STATUS_WRITE_MASK (EXYNOS4210_RNG_STATUS_PRNG_DONE \ + | EXYNOS4210_RNG_STATUS_MSG_DONE \ + | EXYNOS4210_RNG_STATUS_PARTIAL_DONE) + +#define EXYNOS4210_RNG_CONTROL_1 0x0 +#define EXYNOS4210_RNG_STATUS 0x10 +#define EXYNOS4210_RNG_SEED_IN 0x140 +#define EXYNOS4210_RNG_SEED_IN_OFFSET(n) (EXYNOS4210_RNG_SEED_IN + (n * 0x4)) +#define EXYNOS4210_RNG_PRNG 0x160 +#define EXYNOS4210_RNG_PRNG_OFFSET(n) (EXYNOS4210_RNG_PRNG + (n * 0x4)) + +#define EXYNOS4210_RNG_PRNG_NUM 5 + +#define EXYNOS4210_RNG_REGS_MEM_SIZE 0x200 + +typedef struct Exynos4210RngState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + int32_t randr_value[EXYNOS4210_RNG_PRNG_NUM]; + /* bits from 0 to EXYNOS4210_RNG_PRNG_NUM if given seed register was set */ + uint32_t seed_set; + + /* Register values */ + uint32_t reg_control; + uint32_t reg_status; +} Exynos4210RngState; + +static bool exynos4210_rng_seed_ready(const Exynos4210RngState *s) +{ + uint32_t mask = MAKE_64BIT_MASK(0, EXYNOS4210_RNG_PRNG_NUM); + + /* Return true if all the seed-set bits are set. */ + return (s->seed_set & mask) == mask; +} + +static void exynos4210_rng_set_seed(Exynos4210RngState *s, unsigned int i, + uint64_t val) +{ + /* + * We actually ignore the seed and always generate true random numbers. + * Theoretically this should not match the device as Exynos has + * a Pseudo Random Number Generator but testing shown that it always + * generates random numbers regardless of the seed value. + */ + s->seed_set |= BIT(i); + + /* If all seeds were written, update the status to reflect it */ + if (exynos4210_rng_seed_ready(s)) { + s->reg_status |= EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE; + } else { + s->reg_status &= ~EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE; + } +} + +static void exynos4210_rng_run_engine(Exynos4210RngState *s) +{ + Error *err = NULL; + int ret; + + /* Seed set? */ + if ((s->reg_status & EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE) == 0) { + goto out; + } + + /* PRNG engine chosen? */ + if ((s->reg_control & EXYNOS4210_RNG_CONTROL_1_PRNG) == 0) { + goto out; + } + + /* PRNG engine started? */ + if ((s->reg_control & EXYNOS4210_RNG_CONTROL_1_START_INIT) == 0) { + goto out; + } + + /* Get randoms */ + ret = qcrypto_random_bytes((uint8_t *)s->randr_value, + sizeof(s->randr_value), &err); + if (!ret) { + /* Notify that PRNG is ready */ + s->reg_status |= EXYNOS4210_RNG_STATUS_PRNG_DONE; + } else { + error_report_err(err); + } + +out: + /* Always clear start engine bit */ + s->reg_control &= ~EXYNOS4210_RNG_CONTROL_1_START_INIT; +} + +static uint64_t exynos4210_rng_read(void *opaque, hwaddr offset, + unsigned size) +{ + Exynos4210RngState *s = (Exynos4210RngState *)opaque; + uint32_t val = 0; + + assert(size == 4); + + switch (offset) { + case EXYNOS4210_RNG_CONTROL_1: + val = s->reg_control; + break; + + case EXYNOS4210_RNG_STATUS: + val = s->reg_status; + break; + + case EXYNOS4210_RNG_PRNG_OFFSET(0): + case EXYNOS4210_RNG_PRNG_OFFSET(1): + case EXYNOS4210_RNG_PRNG_OFFSET(2): + case EXYNOS4210_RNG_PRNG_OFFSET(3): + case EXYNOS4210_RNG_PRNG_OFFSET(4): + val = s->randr_value[(offset - EXYNOS4210_RNG_PRNG_OFFSET(0)) / 4]; + DPRINTF("returning random @0x%" HWADDR_PRIx ": 0x%" PRIx32 "\n", + offset, val); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } + + return val; +} + +static void exynos4210_rng_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + Exynos4210RngState *s = (Exynos4210RngState *)opaque; + + assert(size == 4); + + switch (offset) { + case EXYNOS4210_RNG_CONTROL_1: + DPRINTF("RNG_CONTROL_1 = 0x%" PRIx64 "\n", val); + s->reg_control = val; + exynos4210_rng_run_engine(s); + break; + + case EXYNOS4210_RNG_STATUS: + /* For clearing status fields */ + s->reg_status &= ~EXYNOS4210_RNG_STATUS_WRITE_MASK; + s->reg_status |= val & EXYNOS4210_RNG_STATUS_WRITE_MASK; + break; + + case EXYNOS4210_RNG_SEED_IN_OFFSET(0): + case EXYNOS4210_RNG_SEED_IN_OFFSET(1): + case EXYNOS4210_RNG_SEED_IN_OFFSET(2): + case EXYNOS4210_RNG_SEED_IN_OFFSET(3): + case EXYNOS4210_RNG_SEED_IN_OFFSET(4): + exynos4210_rng_set_seed(s, + (offset - EXYNOS4210_RNG_SEED_IN_OFFSET(0)) / 4, + val); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad write offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } +} + +static const MemoryRegionOps exynos4210_rng_ops = { + .read = exynos4210_rng_read, + .write = exynos4210_rng_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void exynos4210_rng_reset(DeviceState *dev) +{ + Exynos4210RngState *s = EXYNOS4210_RNG(dev); + + s->reg_control = 0; + s->reg_status = EXYNOS4210_RNG_STATUS_BUFFER_READY; + memset(s->randr_value, 0, sizeof(s->randr_value)); + s->seed_set = 0; +} + +static void exynos4210_rng_init(Object *obj) +{ + Exynos4210RngState *s = EXYNOS4210_RNG(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &exynos4210_rng_ops, s, + TYPE_EXYNOS4210_RNG, EXYNOS4210_RNG_REGS_MEM_SIZE); + sysbus_init_mmio(dev, &s->iomem); +} + +static const VMStateDescription exynos4210_rng_vmstate = { + .name = TYPE_EXYNOS4210_RNG, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32_ARRAY(randr_value, Exynos4210RngState, + EXYNOS4210_RNG_PRNG_NUM), + VMSTATE_UINT32(seed_set, Exynos4210RngState), + VMSTATE_UINT32(reg_status, Exynos4210RngState), + VMSTATE_UINT32(reg_control, Exynos4210RngState), + VMSTATE_END_OF_LIST() + } +}; + +static void exynos4210_rng_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = exynos4210_rng_reset; + dc->vmsd = &exynos4210_rng_vmstate; +} + +static const TypeInfo exynos4210_rng_info = { + .name = TYPE_EXYNOS4210_RNG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Exynos4210RngState), + .instance_init = exynos4210_rng_init, + .class_init = exynos4210_rng_class_init, +}; + +static void exynos4210_rng_register(void) +{ + type_register_static(&exynos4210_rng_info); +} + +type_init(exynos4210_rng_register) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0ee9fac50b..d38563d9a4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -778,6 +778,11 @@ static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt, } } + /* /interrupt controller */ + if (!spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)) { + spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP); + } + offset = fdt_path_offset(fdt, "/chosen"); if (offset < 0) { offset = fdt_add_subnode(fdt, 0, "chosen"); @@ -801,7 +806,7 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr, size -= sizeof(hdr); - /* Create sceleton */ + /* Create skeleton */ fdt_skel = g_malloc0(size); _FDT((fdt_create(fdt_skel, size))); _FDT((fdt_begin_node(fdt_skel, ""))); @@ -910,7 +915,8 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) { PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); - char val[2 * 3] = { + char val[2 * 4] = { + 23, 0x00, /* Xive mode: 0 = legacy (as in ISA 2.7), 1 = Exploitation */ 24, 0x00, /* Hash/Radix, filled in below. */ 25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */ 26, 0x40, /* Radix options: GTSE == yes. */ @@ -918,19 +924,19 @@ static void spapr_dt_ov5_platform_support(void *fdt, int chosen) if (kvm_enabled()) { if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) { - val[1] = 0x80; /* OV5_MMU_BOTH */ + val[3] = 0x80; /* OV5_MMU_BOTH */ } else if (kvmppc_has_cap_mmu_radix()) { - val[1] = 0x40; /* OV5_MMU_RADIX_300 */ + val[3] = 0x40; /* OV5_MMU_RADIX_300 */ } else { - val[1] = 0x00; /* Hash */ + val[3] = 0x00; /* Hash */ } } else { if (first_ppc_cpu->env.mmu_model & POWERPC_MMU_V3) { /* V3 MMU supports both hash and radix (with dynamic switching) */ - val[1] = 0xC0; + val[3] = 0xC0; } else { /* Otherwise we can only do hash */ - val[1] = 0x00; + val[3] = 0x00; } } _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", @@ -1068,9 +1074,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr, _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); - /* /interrupt controller */ - spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP); - ret = spapr_populate_memory(spapr, fdt); if (ret < 0) { error_report("couldn't setup memory nodes in fdt"); @@ -1945,7 +1948,7 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void htab_cleanup(void *opaque) +static void htab_save_cleanup(void *opaque) { sPAPRMachineState *spapr = opaque; @@ -1953,10 +1956,10 @@ static void htab_cleanup(void *opaque) } static SaveVMHandlers savevm_htab_handlers = { - .save_live_setup = htab_save_setup, + .save_setup = htab_save_setup, .save_live_iterate = htab_save_iterate, .save_live_complete_precopy = htab_save_complete, - .cleanup = htab_cleanup, + .save_cleanup = htab_save_cleanup, .load_state = htab_load, }; @@ -1967,24 +1970,6 @@ static void spapr_boot_set(void *opaque, const char *boot_device, machine->boot_order = g_strdup(boot_device); } -/* - * Reset routine for LMB DR devices. - * - * Unlike PCI DR devices, LMB DR devices explicitly register this reset - * routine. Reset for PCI DR devices will be handled by PHB reset routine - * when it walks all its children devices. LMB devices reset occurs - * as part of spapr_ppc_reset(). - */ -static void spapr_drc_reset(void *opaque) -{ - sPAPRDRConnector *drc = opaque; - DeviceState *d = DEVICE(drc); - - if (d) { - device_reset(d); - } -} - static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) { MachineState *machine = MACHINE(spapr); @@ -1993,13 +1978,11 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) int i; for (i = 0; i < nr_lmbs; i++) { - sPAPRDRConnector *drc; uint64_t addr; addr = i * lmb_size + spapr->hotplug_memory.base; - drc = spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, - addr/lmb_size); - qemu_register_reset(spapr_drc_reset, drc); + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, + addr / lmb_size); } } @@ -2093,11 +2076,8 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) int core_id = i * smp_threads; if (mc->has_hotpluggable_cpus) { - sPAPRDRConnector *drc = - spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, - (core_id / smp_threads) * smt); - - qemu_register_reset(spapr_drc_reset, drc); + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, + (core_id / smp_threads) * smt); } if (i < boot_cores_nr) { @@ -2624,6 +2604,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, int i, fdt_offset, fdt_size; void *fdt; uint64_t addr = addr_start; + Error *local_err = NULL; for (i = 0; i < nr_lmbs; i++) { drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, @@ -2634,7 +2615,18 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, fdt_offset = spapr_populate_memory_node(fdt, node, addr, SPAPR_MEMORY_BLOCK_SIZE); - spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); + spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); + if (local_err) { + while (addr > addr_start) { + addr -= SPAPR_MEMORY_BLOCK_SIZE; + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr / SPAPR_MEMORY_BLOCK_SIZE); + spapr_drc_detach(drc, dev, NULL); + } + g_free(fdt); + error_propagate(errp, local_err); + return; + } addr += SPAPR_MEMORY_BLOCK_SIZE; } /* send hotplug notification to the @@ -2674,14 +2666,20 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); if (local_err) { - pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); - goto out; + goto out_unplug; } spapr_add_lmbs(dev, addr, size, node, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), - &error_abort); + &local_err); + if (local_err) { + goto out_unplug; + } + + return; +out_unplug: + pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); out: error_propagate(errp, local_err); } @@ -2863,8 +2861,8 @@ out: error_propagate(errp, local_err); } -void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, - sPAPRMachineState *spapr) +static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, + sPAPRMachineState *spapr) { PowerPCCPU *cpu = POWERPC_CPU(cs); DeviceClass *dc = DEVICE_GET_CLASS(cs); @@ -2979,17 +2977,10 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, g_assert(drc || !mc->has_hotpluggable_cpus); - /* - * Setup CPU DT entries only for hotplugged CPUs. For boot time or - * coldplugged CPUs DT entries are setup in spapr_build_fdt(). - */ - if (dev->hotplugged) { - fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); - } + fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); if (drc) { - spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, - &local_err); + spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err); if (local_err) { g_free(fdt); error_propagate(errp, local_err); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index bd40b84cfc..f34355dad1 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -340,7 +340,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, - int fdt_start_offset, bool coldplug, Error **errp) + int fdt_start_offset, Error **errp) { trace_spapr_drc_attach(spapr_drc_index(drc)); @@ -351,14 +351,11 @@ void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { g_assert(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE); } - g_assert(fdt || coldplug); - - drc->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE; + g_assert(fdt); drc->dev = d; drc->fdt = fdt; drc->fdt_start_offset = fdt_start_offset; - drc->configured = coldplug; if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->awaiting_allocation = true; @@ -372,24 +369,9 @@ void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, static void spapr_drc_release(sPAPRDRConnector *drc) { - drc->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE; + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - /* Calling release callbacks based on spapr_drc_type(drc). */ - switch (spapr_drc_type(drc)) { - case SPAPR_DR_CONNECTOR_TYPE_CPU: - spapr_core_release(drc->dev); - break; - case SPAPR_DR_CONNECTOR_TYPE_PCI: - spapr_phb_remove_pci_device_cb(drc->dev); - break; - case SPAPR_DR_CONNECTOR_TYPE_LMB: - spapr_lmb_release(drc->dev); - break; - case SPAPR_DR_CONNECTOR_TYPE_PHB: - case SPAPR_DR_CONNECTOR_TYPE_VIO: - default: - g_assert(false); - } + drck->release(drc->dev); drc->awaiting_release = false; g_free(drc->fdt); @@ -430,9 +412,9 @@ static bool release_pending(sPAPRDRConnector *drc) return drc->awaiting_release; } -static void reset(DeviceState *d) +static void drc_reset(void *opaque) { - sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); + sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(opaque); trace_spapr_drc_reset(spapr_drc_index(drc)); @@ -454,12 +436,14 @@ static void reset(DeviceState *d) if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE; } + drc->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE; } else { /* Otherwise device is absent, but might be hotplugged */ drc->isolation_state = SPAPR_DR_ISOLATION_STATE_ISOLATED; if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_UNUSABLE; } + drc->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE; } } @@ -540,6 +524,7 @@ static void realize(DeviceState *d, Error **errp) g_free(child_name); vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc, drc); + qemu_register_reset(drc_reset, drc); trace_spapr_drc_realize_complete(spapr_drc_index(drc)); } @@ -598,7 +583,6 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) DeviceClass *dk = DEVICE_CLASS(k); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); - dk->reset = reset; dk->realize = realize; dk->unrealize = unrealize; drck->release_pending = release_pending; @@ -633,6 +617,7 @@ static void spapr_drc_cpu_class_init(ObjectClass *k, void *data) drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU; drck->typename = "CPU"; drck->drc_name_prefix = "CPU "; + drck->release = spapr_core_release; } static void spapr_drc_pci_class_init(ObjectClass *k, void *data) @@ -642,6 +627,7 @@ static void spapr_drc_pci_class_init(ObjectClass *k, void *data) drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI; drck->typename = "28"; drck->drc_name_prefix = "C"; + drck->release = spapr_phb_remove_pci_device_cb; } static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) @@ -651,6 +637,7 @@ static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB; drck->typename = "MEM"; drck->drc_name_prefix = "LMB "; + drck->release = spapr_lmb_release; } static const TypeInfo spapr_dr_connector_info = { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 3b37dcdc09..a52dcf8ec0 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1388,8 +1388,8 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb, return spapr_drc_index(drc); } -static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, - DeviceState *plugged_dev, Error **errp) +static void spapr_pci_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) { sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); @@ -1435,8 +1435,7 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, goto out; } - spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, - !plugged_dev->hotplugged, &local_err); + spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, &local_err); if (local_err) { goto out; } @@ -1470,8 +1469,8 @@ out: } } -static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, - DeviceState *plugged_dev, Error **errp) +static void spapr_pci_unplug_request(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) { sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); @@ -1486,6 +1485,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, } g_assert(drc); + g_assert(drc->dev == plugged_dev); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); if (!drck->release_pending(drc)) { @@ -1745,7 +1745,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) } /* DMA setup */ - if ((sphb->page_size_mask & qemu_getrampagesize()) == 0) { + if (((sphb->page_size_mask & qemu_getrampagesize()) == 0) + && kvm_enabled()) { error_report("System page size 0x%lx is not enabled in page_size_mask " "(0x%"PRIx64"). Performance may be slow", qemu_getrampagesize(), sphb->page_size_mask); @@ -1873,20 +1874,6 @@ static void spapr_pci_pre_save(void *opaque) gpointer key, value; int i; - g_free(sphb->msi_devs); - sphb->msi_devs = NULL; - sphb->msi_devs_num = g_hash_table_size(sphb->msi); - if (!sphb->msi_devs_num) { - return; - } - sphb->msi_devs = g_malloc(sphb->msi_devs_num * sizeof(spapr_pci_msi_mig)); - - g_hash_table_iter_init(&iter, sphb->msi); - for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) { - sphb->msi_devs[i].key = *(uint32_t *) key; - sphb->msi_devs[i].value = *(spapr_pci_msi *) value; - } - if (sphb->pre_2_8_migration) { sphb->mig_liobn = sphb->dma_liobn[0]; sphb->mig_mem_win_addr = sphb->mem_win_addr; @@ -1900,6 +1887,20 @@ static void spapr_pci_pre_save(void *opaque) sphb->mig_mem_win_size += sphb->mem64_win_size; } } + + g_free(sphb->msi_devs); + sphb->msi_devs = NULL; + sphb->msi_devs_num = g_hash_table_size(sphb->msi); + if (!sphb->msi_devs_num) { + return; + } + sphb->msi_devs = g_malloc(sphb->msi_devs_num * sizeof(spapr_pci_msi_mig)); + + g_hash_table_iter_init(&iter, sphb->msi); + for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) { + sphb->msi_devs[i].key = *(uint32_t *) key; + sphb->msi_devs[i].value = *(spapr_pci_msi *) value; + } } static int spapr_pci_post_load(void *opaque, int version_id) @@ -1973,8 +1974,8 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) /* Supported by TYPE_SPAPR_MACHINE */ dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - hp->plug = spapr_phb_hot_plug_child; - hp->unplug = spapr_phb_hot_unplug_child; + hp->plug = spapr_pci_plug; + hp->unplug_request = spapr_pci_unplug_request; } static const TypeInfo spapr_phb_info = { diff --git a/hw/vfio/common.c b/hw/vfio/common.c index b9abe77f5a..29923e4990 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -858,13 +858,15 @@ void vfio_reset_handler(void *opaque) QLIST_FOREACH(group, &vfio_group_list, next) { QLIST_FOREACH(vbasedev, &group->device_list, next) { - vbasedev->ops->vfio_compute_needs_reset(vbasedev); + if (vbasedev->dev->realized) { + vbasedev->ops->vfio_compute_needs_reset(vbasedev); + } } } QLIST_FOREACH(group, &vfio_group_list, next) { QLIST_FOREACH(vbasedev, &group->device_list, next) { - if (vbasedev->needs_reset) { + if (vbasedev->dev->realized && vbasedev->needs_reset) { vbasedev->ops->vfio_hot_reset_multi(vbasedev); } } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 8de8272e96..d4051cb951 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1743,6 +1743,18 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size, PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS); } + /* + * Intel 82599 SR-IOV VFs report an invalid PCIe capability version 0 + * (Niantic errate #35) causing Windows to error with a Code 10 for the + * device on Q35. Fixup any such devices to report version 1. If we + * were to remove the capability entirely the guest would lose extended + * config space. + */ + if ((flags & PCI_EXP_FLAGS_VERS) == 0) { + vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS, + 1, PCI_EXP_FLAGS_VERS); + } + pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size, errp); if (pos < 0) { @@ -2116,7 +2128,8 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single) /* Prep dependent devices for reset and clear our marker. */ QLIST_FOREACH(vbasedev_iter, &group->device_list, next) { - if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) { + if (!vbasedev_iter->dev->realized || + vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) { continue; } tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev); @@ -2197,7 +2210,8 @@ out: } QLIST_FOREACH(vbasedev_iter, &group->device_list, next) { - if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) { + if (!vbasedev_iter->dev->realized || + vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) { continue; } tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev); @@ -2647,6 +2661,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vdev->vbasedev.name = g_strdup(basename(vdev->vbasedev.sysfsdev)); vdev->vbasedev.ops = &vfio_pci_ops; vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI; + vdev->vbasedev.dev = &vdev->pdev.qdev; tmp = g_strdup_printf("%s/iommu_group", vdev->vbasedev.sysfsdev); len = readlink(tmp, group_path, sizeof(group_path)); diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index a4663c918e..7c09deda61 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -640,6 +640,7 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp) int i, ret; vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM; + vbasedev->dev = dev; vbasedev->ops = &vfio_platform_ops; trace_vfio_platform_realize(vbasedev->sysfsdev ? diff --git a/include/block/block.h b/include/block/block.h index 4a2725267d..b3e2674845 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -302,10 +302,13 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, const char *backing_file); int bdrv_get_backing_file_depth(BlockDriverState *bs); void bdrv_refresh_filename(BlockDriverState *bs); -int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp); +int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, + Error **errp); int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); +BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, + BlockDriverState *in_bs, Error **errp); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); int bdrv_commit(BlockDriverState *bs); @@ -464,9 +467,6 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it); BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs); bool bdrv_is_encrypted(BlockDriverState *bs); -bool bdrv_key_required(BlockDriverState *bs); -int bdrv_set_key(BlockDriverState *bs, const char *key); -void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp); void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque); const char *bdrv_get_node_name(const BlockDriverState *bs); @@ -620,4 +620,7 @@ void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child, Error **errp); void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp); +bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, + uint32_t granularity, Error **errp); + #endif diff --git a/include/block/block_int.h b/include/block/block_int.h index 15fa602150..669a2797fd 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -37,11 +37,11 @@ #include "qemu/main-loop.h" #include "qemu/throttle.h" -#define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_LAZY_REFCOUNTS 8 #define BLOCK_OPT_SIZE "size" #define BLOCK_OPT_ENCRYPT "encryption" +#define BLOCK_OPT_ENCRYPT_FORMAT "encrypt.format" #define BLOCK_OPT_COMPAT6 "compat6" #define BLOCK_OPT_HWVERSION "hwversion" #define BLOCK_OPT_BACKING_FILE "backing_file" @@ -204,11 +204,14 @@ struct BlockDriver { int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs); const char *protocol_name; - int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset, Error **errp); + int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp); int64_t (*bdrv_getlength)(BlockDriverState *bs); bool has_variable_length; int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); + BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs, + Error **errp); int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov); @@ -381,6 +384,20 @@ struct BlockDriver { uint64_t parent_perm, uint64_t parent_shared, uint64_t *nperm, uint64_t *nshared); + /** + * Bitmaps should be marked as 'IN_USE' in the image on reopening image + * as rw. This handler should realize it. It also should unset readonly + * field of BlockDirtyBitmap's in case of success. + */ + int (*bdrv_reopen_bitmaps_rw)(BlockDriverState *bs, Error **errp); + bool (*bdrv_can_store_new_dirty_bitmap)(BlockDriverState *bs, + const char *name, + uint32_t granularity, + Error **errp); + void (*bdrv_remove_persistent_dirty_bitmap)(BlockDriverState *bs, + const char *name, + Error **errp); + QLIST_ENTRY(BlockDriver) list; }; @@ -529,7 +546,6 @@ struct BlockDriverState { int open_flags; /* flags used to open the file, re-used for re-open */ bool read_only; /* if true, the media is read only */ bool encrypted; /* if true, the media is encrypted */ - bool valid_key; /* if true, a valid encryption key has been set */ bool sg; /* if true, the device is a /dev/sg* */ bool probed; /* if true, format was probed rather than specified */ bool force_share; /* if true, always allow all shared permissions */ diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index ad6558af56..a79a58d2c3 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -25,11 +25,15 @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap); void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs); +void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs); +void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, + const char *name, + Error **errp); void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs); uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs); -uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap); +uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap); uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap); @@ -66,8 +70,16 @@ void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, uint64_t start, uint64_t count, bool finish); +void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, + uint64_t start, uint64_t count, + bool finish); void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap); +void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value); +void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload); +void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, + bool persistent); + /* Functions that require manual locking. */ void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap); void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap); @@ -82,5 +94,13 @@ void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t sector_num); int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap); void bdrv_dirty_bitmap_truncate(BlockDriverState *bs); +bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap); +bool bdrv_has_readonly_bitmaps(BlockDriverState *bs); +bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap); +bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap); +bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs); +BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap); +char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp); #endif diff --git a/include/crypto/block.h b/include/crypto/block.h index 013a435f1b..f0e543bee1 100644 --- a/include/crypto/block.h +++ b/include/crypto/block.h @@ -71,6 +71,7 @@ typedef enum { /** * qcrypto_block_open: * @options: the encryption options + * @optprefix: name prefix for options * @readfunc: callback for reading data from the volume * @opaque: data to pass to @readfunc * @flags: bitmask of QCryptoBlockOpenFlags values @@ -102,6 +103,7 @@ typedef enum { * Returns: a block encryption format, or NULL on error */ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, + const char *optprefix, QCryptoBlockReadFunc readfunc, void *opaque, unsigned int flags, @@ -109,7 +111,8 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, /** * qcrypto_block_create: - * @format: the encryption format + * @options: the encryption options + * @optprefix: name prefix for options * @initfunc: callback for initializing volume header * @writefunc: callback for writing data to the volume header * @opaque: data to pass to @initfunc and @writefunc @@ -133,6 +136,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options, * Returns: a block encryption format, or NULL on error */ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options, + const char *optprefix, QCryptoBlockInitFunc initfunc, QCryptoBlockWriteFunc writefunc, void *opaque, diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 4c5fc66a1e..0b88baaad0 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -23,6 +23,7 @@ #include "hw/net/ftgmac100.h" #define ASPEED_SPIS_NUM 2 +#define ASPEED_WDTS_NUM 3 typedef struct AspeedSoCState { /*< private >*/ @@ -39,7 +40,7 @@ typedef struct AspeedSoCState { AspeedSMCState fmc; AspeedSMCState spi[ASPEED_SPIS_NUM]; AspeedSDMCState sdmc; - AspeedWDTState wdt; + AspeedWDTState wdt[ASPEED_WDTS_NUM]; FTGMAC100State ftgmac100; } AspeedSoCState; @@ -56,6 +57,7 @@ typedef struct AspeedSoCInfo { const hwaddr *spi_bases; const char *fmc_typename; const char **spi_typename; + int wdts_num; } AspeedSoCInfo; typedef struct AspeedSoCClass { diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index a66bbac352..a184ffab0e 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -377,9 +377,8 @@ struct sPAPRMachineState { * as well. * * We also need some hcalls which are specific to qemu / KVM-on-POWER. - * So far we just need one for H_RTAS, but in future we'll need more - * for extensions like virtio. We put those into the 0xf000-0xfffc - * range which is reserved by PAPR for "platform-specific" hcalls. + * We put those into the 0xf000-0xfffc range which is reserved by PAPR + * for "platform-specific" hcalls. */ #define KVMPPC_HCALL_BASE 0xf000 #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) @@ -640,8 +639,6 @@ void spapr_hotplug_req_add_by_count_indexed(sPAPRDRConnectorType drc_type, void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type, uint32_t count, uint32_t index); void spapr_cpu_parse_features(sPAPRMachineState *spapr); -void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, - sPAPRMachineState *spapr); /* CPU and LMB DRC release callbacks. */ void spapr_core_release(DeviceState *dev); diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index d9cacb368f..d15e9eb3b4 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -217,6 +217,7 @@ typedef struct sPAPRDRConnectorClass { sPAPRDREntitySense (*dr_entity_sense)(sPAPRDRConnector *drc); uint32_t (*isolate)(sPAPRDRConnector *drc); uint32_t (*unisolate)(sPAPRDRConnector *drc); + void (*release)(DeviceState *dev); /* QEMU interfaces for managing hotplug operations */ bool (*release_pending)(sPAPRDRConnector *drc); @@ -233,7 +234,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, uint32_t drc_type_mask); void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, - int fdt_start_offset, bool coldplug, Error **errp); + int fdt_start_offset, Error **errp); void spapr_drc_detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp); #endif /* HW_SPAPR_DRC_H */ diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h index f088833204..0b464e22e7 100644 --- a/include/hw/ppc/spapr_ovec.h +++ b/include/hw/ppc/spapr_ovec.h @@ -50,6 +50,7 @@ typedef struct sPAPROptionVector sPAPROptionVector; #define OV5_DRCONF_MEMORY OV_BIT(2, 2) #define OV5_FORM1_AFFINITY OV_BIT(5, 0) #define OV5_HP_EVT OV_BIT(6, 5) +#define OV5_XIVE_EXPLOIT OV_BIT(23, 7) /* ISA 3.00 MMU features: */ #define OV5_MMU_BOTH OV_BIT(24, 0) /* Radix and hash */ diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 9521013d52..0b475a3596 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -115,6 +115,7 @@ typedef struct VFIODevice { struct VFIOGroup *group; char *sysfsdev; char *name; + DeviceState *dev; int fd; int type; bool reset_works; diff --git a/include/migration/misc.h b/include/migration/misc.h index 22551216bb..c079b7771b 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -53,7 +53,6 @@ bool migration_has_finished(MigrationState *); bool migration_has_failed(MigrationState *); /* ...and after the device transmission */ bool migration_in_postcopy_after_devices(MigrationState *); -void migration_only_migratable_set(void); void migration_global_dump(Monitor *mon); #endif diff --git a/include/migration/register.h b/include/migration/register.h index d9498d95eb..a0f1edd8c7 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -18,7 +18,7 @@ typedef struct SaveVMHandlers { /* This runs inside the iothread lock. */ SaveStateHandler *save_state; - void (*cleanup)(void *opaque); + void (*save_cleanup)(void *opaque); int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); @@ -33,12 +33,14 @@ typedef struct SaveVMHandlers { int (*save_live_iterate)(QEMUFile *f, void *opaque); /* This runs outside the iothread lock! */ - int (*save_live_setup)(QEMUFile *f, void *opaque); + int (*save_setup)(QEMUFile *f, void *opaque); void (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t threshold_size, uint64_t *non_postcopiable_pending, uint64_t *postcopiable_pending); LoadStateHandler *load_state; + int (*load_setup)(QEMUFile *f, void *opaque); + int (*load_cleanup)(void *opaque); } SaveVMHandlers; int register_savevm_live(DeviceState *dev, diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index d2b3aafdb4..83ea4a1aaf 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -23,13 +23,6 @@ void monitor_cleanup(void); int monitor_suspend(Monitor *mon); void monitor_resume(Monitor *mon); -int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, - BlockCompletionFunc *completion_cb, - void *opaque); -int monitor_read_block_device_key(Monitor *mon, const char *device, - BlockCompletionFunc *completion_cb, - void *opaque); - int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp); int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp); diff --git a/include/qapi/error.h b/include/qapi/error.h index 7e532d00e9..5d5e737f75 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -125,7 +125,6 @@ typedef enum ErrorClass { ERROR_CLASS_GENERIC_ERROR = QAPI_ERROR_CLASS_GENERICERROR, ERROR_CLASS_COMMAND_NOT_FOUND = QAPI_ERROR_CLASS_COMMANDNOTFOUND, - ERROR_CLASS_DEVICE_ENCRYPTED = QAPI_ERROR_CLASS_DEVICEENCRYPTED, ERROR_CLASS_DEVICE_NOT_ACTIVE = QAPI_ERROR_CLASS_DEVICENOTACTIVE, ERROR_CLASS_DEVICE_NOT_FOUND = QAPI_ERROR_CLASS_DEVICENOTFOUND, ERROR_CLASS_KVM_MISSING_CAP = QAPI_ERROR_CLASS_KVMMISSINGCAP, diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index 9239fe515e..d3a74a21fc 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -229,6 +229,21 @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count, bool finish); /** + * hbitmap_deserialize_ones + * @hb: HBitmap to operate on. + * @start: First bit to restore. + * @count: Number of bits to restore. + * @finish: Whether to call hbitmap_deserialize_finish automatically. + * + * Fills the bitmap with ones. + * + * If @finish is false, caller must call hbitmap_serialize_finish before using + * the bitmap. + */ +void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count, + bool finish); + +/** * hbitmap_deserialize_finish * @hb: HBitmap to operate on. * @@ -238,6 +253,14 @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count, void hbitmap_deserialize_finish(HBitmap *hb); /** + * hbitmap_sha256: + * @bitmap: HBitmap to operate on. + * + * Returns SHA256 hash of the last level. + */ +char *hbitmap_sha256(const HBitmap *bitmap, Error **errp); + +/** * hbitmap_free: * @hb: HBitmap to operate on. * @@ -256,10 +279,9 @@ void hbitmap_free(HBitmap *hb); * the lowest-numbered bit that is set in @hb, starting at @first. * * Concurrent setting of bits is acceptable, and will at worst cause the - * iteration to miss some of those bits. Resetting bits before the current - * position of the iterator is also okay. However, concurrent resetting of - * bits can lead to unexpected behavior if the iterator has not yet reached - * those bits. + * iteration to miss some of those bits. + * + * The concurrent resetting of bits is OK. */ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first); @@ -298,24 +320,7 @@ void hbitmap_free_meta(HBitmap *hb); * Return the next bit that is set in @hbi's associated HBitmap, * or -1 if all remaining bits are zero. */ -static inline int64_t hbitmap_iter_next(HBitmapIter *hbi) -{ - unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1]; - int64_t item; - - if (cur == 0) { - cur = hbitmap_iter_skip_words(hbi); - if (cur == 0) { - return -1; - } - } - - /* The next call will resume work from the next bit. */ - hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); - item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); - - return item << hbi->granularity; -} +int64_t hbitmap_iter_next(HBitmapIter *hbi); /** * hbitmap_iter_next_word: diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 85596341fa..3b74f6fcb2 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -457,8 +457,6 @@ void qemu_set_tty_echo(int fd, bool echo); void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus, Error **errp); -int qemu_read_password(char *buf, int buf_size); - /** * qemu_get_pid_name: * @pid: pid of a process diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 1e05281fff..d9ea0cdb0f 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -223,7 +223,8 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset, int bytes, BdrvRequestFlags flags); int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf, int bytes); -int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp); +int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc, + Error **errp); int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes); int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, int64_t pos, int size); diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 052e11f621..91fc07ee9a 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -220,6 +220,17 @@ int kvm_init_vcpu(CPUState *cpu); int kvm_cpu_exec(CPUState *cpu); int kvm_destroy_vcpu(CPUState *cpu); +/** + * kvm_arm_supports_user_irq + * + * Not all KVM implementations support notifications for kernel generated + * interrupt events to user space. This function indicates whether the current + * KVM implementation does support them. + * + * Returns: true if KVM supports using kernel generated IRQs from user space + */ +bool kvm_arm_supports_user_irq(void); + #ifdef NEED_CPU_H #include "cpu.h" diff --git a/migration/block.c b/migration/block.c index 86c0b96cd1..9171f60028 100644 --- a/migration/block.c +++ b/migration/block.c @@ -1008,12 +1008,12 @@ static bool block_is_active(void *opaque) } static SaveVMHandlers savevm_block_handlers = { - .save_live_setup = block_save_setup, + .save_setup = block_save_setup, .save_live_iterate = block_save_iterate, .save_live_complete_precopy = block_save_complete, .save_live_pending = block_save_pending, .load_state = block_load, - .cleanup = block_migration_cleanup, + .save_cleanup = block_migration_cleanup, .is_active = block_is_active, }; diff --git a/migration/colo.c b/migration/colo.c index c4ba4c328b..ef35f00c9a 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -350,7 +350,7 @@ static int colo_do_checkpoint_transaction(MigrationState *s, /* Disable block migration */ migrate_set_block_enabled(false, &local_err); qemu_savevm_state_header(fb); - qemu_savevm_state_begin(fb); + qemu_savevm_state_setup(fb); qemu_mutex_lock_iothread(); qemu_savevm_state_complete_precopy(fb, false, false); qemu_mutex_unlock_iothread(); diff --git a/migration/migration.c b/migration/migration.c index 51ccd1a4c5..a0db40d364 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -128,11 +128,6 @@ MigrationState *migrate_get_current(void) return current_migration; } -void migration_only_migratable_set(void) -{ - migrate_get_current()->only_migratable = true; -} - MigrationIncomingState *migration_incoming_get_current(void) { static bool once; @@ -291,7 +286,6 @@ static void process_incoming_migration_bh(void *opaque) } else { runstate_set(global_state_get_runstate()); } - migrate_decompress_threads_join(); /* * This must happen after any state changes since as soon as an external * observer sees this event they might start to prod at the VM assuming @@ -354,12 +348,8 @@ static void process_incoming_migration_co(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_FAILED); error_report("load of migration failed: %s", strerror(-ret)); - migrate_decompress_threads_join(); exit(EXIT_FAILURE); } - - free_xbzrle_decoded_buf(); - mis->bh = qemu_bh_new(process_incoming_migration_bh, mis); qemu_bh_schedule(mis->bh); } @@ -368,7 +358,6 @@ void migration_fd_process_incoming(QEMUFile *f) { Coroutine *co = qemu_coroutine_create(process_incoming_migration_co, f); - migrate_decompress_threads_create(); qemu_file_set_blocking(f, false); qemu_coroutine_enter(co); } @@ -835,7 +824,6 @@ static void migrate_fd_cleanup(void *opaque) } qemu_mutex_lock_iothread(); - migrate_compress_threads_join(); qemu_fclose(s->to_dst_file); s->to_dst_file = NULL; } @@ -1840,7 +1828,7 @@ static void *migration_thread(void *opaque) qemu_savevm_send_postcopy_advise(s->to_dst_file); } - qemu_savevm_state_begin(s->to_dst_file); + qemu_savevm_state_setup(s->to_dst_file); s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, @@ -1998,7 +1986,6 @@ void migrate_fd_connect(MigrationState *s) } } - migrate_compress_threads_create(); qemu_thread_create(&s->thread, "live_migration", migration_thread, s, QEMU_THREAD_JOINABLE); s->migration_thread_running = true; @@ -2057,12 +2044,12 @@ static void migration_instance_init(Object *obj) static const TypeInfo migration_type = { .name = TYPE_MIGRATION, /* - * NOTE: "migration" itself is not really a device. We used - * TYPE_DEVICE here only to leverage some existing QDev features - * like "-global" properties, and HW_COMPAT_* fields (which are - * finally applied as global properties as well). If one day the - * global property feature can be migrated from QDev to QObject in - * general, then we can switch to QObject as well. + * NOTE: TYPE_MIGRATION is not really a device, as the object is + * not created using qdev_create(), it is not attached to the qdev + * device tree, and it is never realized. + * + * TODO: Make this TYPE_OBJECT once QOM provides something like + * TYPE_DEVICE's "-global" properties. */ .parent = TYPE_DEVICE, .class_init = migration_class_init, diff --git a/migration/ram.c b/migration/ram.c index 0baa1e0d56..1b08296d1b 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -85,11 +85,10 @@ static struct { QemuMutex lock; /* it will store a page full of zeros */ uint8_t *zero_target_page; + /* buffer used for XBZRLE decoding */ + uint8_t *decoded_buf; } XBZRLE; -/* buffer used for XBZRLE decoding */ -static uint8_t *xbzrle_decoded_buf; - static void XBZRLE_cache_lock(void) { if (migrate_use_xbzrle()) @@ -307,7 +306,7 @@ static inline void terminate_compression_threads(void) } } -void migrate_compress_threads_join(void) +static void compress_threads_save_cleanup(void) { int i, thread_count; @@ -330,7 +329,7 @@ void migrate_compress_threads_join(void) comp_param = NULL; } -void migrate_compress_threads_create(void) +static void compress_threads_save_setup(void) { int i, thread_count; @@ -1350,13 +1349,18 @@ uint64_t ram_bytes_total(void) return total; } -void free_xbzrle_decoded_buf(void) +static void xbzrle_load_setup(void) { - g_free(xbzrle_decoded_buf); - xbzrle_decoded_buf = NULL; + XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE); } -static void ram_migration_cleanup(void *opaque) +static void xbzrle_load_cleanup(void) +{ + g_free(XBZRLE.decoded_buf); + XBZRLE.decoded_buf = NULL; +} + +static void ram_save_cleanup(void *opaque) { RAMState **rsp = opaque; RAMBlock *block; @@ -1386,6 +1390,7 @@ static void ram_migration_cleanup(void *opaque) } XBZRLE_cache_unlock(); migration_page_queue_free(*rsp); + compress_threads_save_cleanup(); g_free(*rsp); *rsp = NULL; } @@ -1919,6 +1924,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) } rcu_read_unlock(); + compress_threads_save_setup(); ram_control_before_iterate(f, RAM_CONTROL_SETUP); ram_control_after_iterate(f, RAM_CONTROL_SETUP); @@ -2078,11 +2084,6 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) int xh_flags; uint8_t *loaded_data; - if (!xbzrle_decoded_buf) { - xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE); - } - loaded_data = xbzrle_decoded_buf; - /* extract RLE header */ xh_flags = qemu_get_byte(f); xh_len = qemu_get_be16(f); @@ -2096,7 +2097,9 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) error_report("Failed to load XBZRLE page - len overflow!"); return -1; } + loaded_data = XBZRLE.decoded_buf; /* load data and decode */ + /* it can change loaded_data to point to an internal buffer */ qemu_get_buffer_in_place(f, &loaded_data, xh_len); /* decode RLE */ @@ -2230,7 +2233,7 @@ static void wait_for_decompress_done(void) qemu_mutex_unlock(&decomp_done_lock); } -void migrate_decompress_threads_create(void) +static void compress_threads_load_setup(void) { int i, thread_count; @@ -2254,7 +2257,7 @@ void migrate_decompress_threads_create(void) } } -void migrate_decompress_threads_join(void) +static void compress_threads_load_cleanup(void) { int i, thread_count; @@ -2310,6 +2313,28 @@ static void decompress_data_with_multi_threads(QEMUFile *f, } /** + * ram_load_setup: Setup RAM for migration incoming side + * + * Returns zero to indicate success and negative for error + * + * @f: QEMUFile where to receive the data + * @opaque: RAMState pointer + */ +static int ram_load_setup(QEMUFile *f, void *opaque) +{ + xbzrle_load_setup(); + compress_threads_load_setup(); + return 0; +} + +static int ram_load_cleanup(void *opaque) +{ + xbzrle_load_cleanup(); + compress_threads_load_cleanup(); + return 0; +} + +/** * ram_postcopy_incoming_init: allocate postcopy data structures * * Returns 0 for success and negative if there was one error @@ -2623,13 +2648,15 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } static SaveVMHandlers savevm_ram_handlers = { - .save_live_setup = ram_save_setup, + .save_setup = ram_save_setup, .save_live_iterate = ram_save_iterate, .save_live_complete_postcopy = ram_save_complete, .save_live_complete_precopy = ram_save_complete, .save_live_pending = ram_save_pending, .load_state = ram_load, - .cleanup = ram_migration_cleanup, + .save_cleanup = ram_save_cleanup, + .load_setup = ram_load_setup, + .load_cleanup = ram_load_cleanup, }; void ram_mig_init(void) diff --git a/migration/ram.h b/migration/ram.h index 6272eb0007..c081fde86c 100644 --- a/migration/ram.h +++ b/migration/ram.h @@ -39,15 +39,9 @@ int64_t xbzrle_cache_resize(int64_t new_size); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_total(void); -void migrate_compress_threads_create(void); -void migrate_compress_threads_join(void); -void migrate_decompress_threads_create(void); -void migrate_decompress_threads_join(void); - uint64_t ram_pagesize_summary(void); int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); void acct_update_position(QEMUFile *f, size_t size, bool zero); -void free_xbzrle_decoded_buf(void); void ram_debug_dump_bitmap(unsigned long *todump, bool expected, unsigned long pages); void ram_postcopy_migrated_memory_release(MigrationState *ms); diff --git a/migration/savevm.c b/migration/savevm.c index be3f885119..fdd15fa0a7 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -596,7 +596,7 @@ int register_savevm_live(DeviceState *dev, se->opaque = opaque; se->vmsd = NULL; /* if this is a live_savem then set is_ram */ - if (ops->save_live_setup != NULL) { + if (ops->save_setup != NULL) { se->is_ram = 1; } @@ -955,14 +955,14 @@ void qemu_savevm_state_header(QEMUFile *f) } } -void qemu_savevm_state_begin(QEMUFile *f) +void qemu_savevm_state_setup(QEMUFile *f) { SaveStateEntry *se; int ret; - trace_savevm_state_begin(); + trace_savevm_state_setup(); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { - if (!se->ops || !se->ops->save_live_setup) { + if (!se->ops || !se->ops->save_setup) { continue; } if (se->ops && se->ops->is_active) { @@ -972,7 +972,7 @@ void qemu_savevm_state_begin(QEMUFile *f) } save_section_header(f, se, QEMU_VM_SECTION_START); - ret = se->ops->save_live_setup(f, se->opaque); + ret = se->ops->save_setup(f, se->opaque); save_section_footer(f, se); if (ret < 0) { qemu_file_set_error(f, ret); @@ -1215,8 +1215,8 @@ void qemu_savevm_state_cleanup(void) trace_savevm_state_cleanup(); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { - if (se->ops && se->ops->cleanup) { - se->ops->cleanup(se->opaque); + if (se->ops && se->ops->save_cleanup) { + se->ops->save_cleanup(se->opaque); } } } @@ -1241,7 +1241,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) qemu_mutex_unlock_iothread(); qemu_savevm_state_header(f); - qemu_savevm_state_begin(f); + qemu_savevm_state_setup(f); qemu_mutex_lock_iothread(); while (qemu_file_get_error(f) == 0) { @@ -1541,7 +1541,7 @@ static void *postcopy_ram_listen_thread(void *opaque) * got a bad migration state). */ migration_incoming_state_destroy(); - + qemu_loadvm_state_cleanup(); return NULL; } @@ -1901,6 +1901,44 @@ qemu_loadvm_section_part_end(QEMUFile *f, MigrationIncomingState *mis) return 0; } +static int qemu_loadvm_state_setup(QEMUFile *f) +{ + SaveStateEntry *se; + int ret; + + trace_loadvm_state_setup(); + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { + if (!se->ops || !se->ops->load_setup) { + continue; + } + if (se->ops && se->ops->is_active) { + if (!se->ops->is_active(se->opaque)) { + continue; + } + } + + ret = se->ops->load_setup(f, se->opaque); + if (ret < 0) { + qemu_file_set_error(f, ret); + error_report("Load state of device %s failed", se->idstr); + return ret; + } + } + return 0; +} + +void qemu_loadvm_state_cleanup(void) +{ + SaveStateEntry *se; + + trace_loadvm_state_cleanup(); + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { + if (se->ops && se->ops->load_cleanup) { + se->ops->load_cleanup(se->opaque); + } + } +} + static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis) { uint8_t section_type; @@ -1973,6 +2011,10 @@ int qemu_loadvm_state(QEMUFile *f) return -ENOTSUP; } + if (qemu_loadvm_state_setup(f) != 0) { + return -EINVAL; + } + if (migrate_get_current()->send_configuration) { if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) { error_report("Configuration section missing"); @@ -2036,6 +2078,7 @@ int qemu_loadvm_state(QEMUFile *f) } } + qemu_loadvm_state_cleanup(); cpu_synchronize_all_post_init(); return ret; diff --git a/migration/savevm.h b/migration/savevm.h index 5a2ed1161d..295c4a1f2c 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -30,7 +30,7 @@ #define QEMU_VM_SECTION_FOOTER 0x7e bool qemu_savevm_state_blocked(Error **errp); -void qemu_savevm_state_begin(QEMUFile *f); +void qemu_savevm_state_setup(QEMUFile *f); void qemu_savevm_state_header(QEMUFile *f); int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy); void qemu_savevm_state_cleanup(void); @@ -53,5 +53,6 @@ void qemu_savevm_send_postcopy_ram_discard(QEMUFile *f, const char *name, uint64_t *length_list); int qemu_loadvm_state(QEMUFile *f); +void qemu_loadvm_state_cleanup(void); #endif diff --git a/migration/trace-events b/migration/trace-events index 38345be9c3..cb2c4b5b40 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -7,6 +7,8 @@ qemu_loadvm_state_section_partend(uint32_t section_id) "%u" qemu_loadvm_state_post_main(int ret) "%d" qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u" qemu_savevm_send_packaged(void) "" +loadvm_state_setup(void) "" +loadvm_state_cleanup(void) "" loadvm_handle_cmd_packaged(unsigned int length) "%u" loadvm_handle_cmd_packaged_main(int ret) "%d" loadvm_handle_cmd_packaged_received(int ret) "%d" @@ -32,7 +34,7 @@ savevm_send_open_return_path(void) "" savevm_send_ping(uint32_t val) "%x" savevm_send_postcopy_listen(void) "" savevm_send_postcopy_run(void) "" -savevm_state_begin(void) "" +savevm_state_setup(void) "" savevm_state_header(void) "" savevm_state_iterate(void) "" savevm_state_cleanup(void) "" @@ -4136,74 +4136,6 @@ void monitor_cleanup(void) qemu_mutex_unlock(&monitor_lock); } -static void bdrv_password_cb(void *opaque, const char *password, - void *readline_opaque) -{ - Monitor *mon = opaque; - BlockDriverState *bs = readline_opaque; - int ret = 0; - Error *local_err = NULL; - - bdrv_add_key(bs, password, &local_err); - if (local_err) { - error_report_err(local_err); - ret = -EPERM; - } - if (mon->password_completion_cb) - mon->password_completion_cb(mon->password_opaque, ret); - - monitor_read_command(mon, 1); -} - -int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, - BlockCompletionFunc *completion_cb, - void *opaque) -{ - int err; - - monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs), - bdrv_get_encrypted_filename(bs)); - - mon->password_completion_cb = completion_cb; - mon->password_opaque = opaque; - - err = monitor_read_password(mon, bdrv_password_cb, bs); - - if (err && completion_cb) - completion_cb(opaque, err); - - return err; -} - -int monitor_read_block_device_key(Monitor *mon, const char *device, - BlockCompletionFunc *completion_cb, - void *opaque) -{ - Error *err = NULL; - BlockBackend *blk; - - blk = blk_by_name(device); - if (!blk) { - monitor_printf(mon, "Device not found %s\n", device); - return -1; - } - if (!blk_bs(blk)) { - monitor_printf(mon, "Device '%s' has no medium\n", device); - return -1; - } - - bdrv_add_key(blk_bs(blk), NULL, &err); - if (err) { - error_free(err); - return monitor_read_bdrv_key_start(mon, blk_bs(blk), completion_cb, opaque); - } - - if (completion_cb) { - completion_cb(opaque, 0); - } - return 0; -} - QemuOptsList qemu_mon_opts = { .name = "mon", .implied_opt_name = "chardev", diff --git a/qapi-schema.json b/qapi-schema.json index 37c4b95aad..485767f1ab 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2431,8 +2431,6 @@ # Since: 0.14.0 # # Returns: If successful, nothing -# If QEMU was started with an encrypted block device and a key has -# not yet been set, DeviceEncrypted. # # Notes: This command will succeed if the guest is currently running. It # will also succeed if the guest is in the "inmigrate" state; in @@ -2713,8 +2711,7 @@ # * This command is stateless, this means that commands that depend # on state information (such as getfd) might not work # -# * Commands that prompt the user for data (eg. 'cont' when the block -# device is encrypted) don't currently work +# * Commands that prompt the user for data don't currently work # # Example: # @@ -3019,11 +3016,6 @@ # # Returns: Nothing on success. # If @device is not a valid block device, DeviceNotFound -# If the new block device is encrypted, DeviceEncrypted. Note that -# if this error is returned, the device has been opened successfully -# and an additional call to @block_passwd is required to set the -# device's password. The behavior of reads and writes to the block -# device between when these calls are executed is undefined. # # Notes: This interface is deprecated, and it is strongly recommended that you # avoid using it. For changing block devices, use diff --git a/qapi/block-core.json b/qapi/block-core.json index f85c2235c7..c437aa50ef 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -33,6 +33,27 @@ 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } ## +# @ImageInfoSpecificQCow2EncryptionBase: +# +# @format: The encryption format +# +# Since: 2.10 +## +{ 'struct': 'ImageInfoSpecificQCow2EncryptionBase', + 'data': { 'format': 'BlockdevQcow2EncryptionFormat'}} + +## +# @ImageInfoSpecificQCow2Encryption: +# +# Since: 2.10 +## +{ 'union': 'ImageInfoSpecificQCow2Encryption', + 'base': 'ImageInfoSpecificQCow2EncryptionBase', + 'discriminator': 'format', + 'data': { 'aes': 'QCryptoBlockInfoQCow', + 'luks': 'QCryptoBlockInfoLUKS' } } + +## # @ImageInfoSpecificQCow2: # # @compat: compatibility level @@ -44,6 +65,9 @@ # # @refcount-bits: width of a refcount entry in bits (since 2.3) # +# @encrypt: details about encryption parameters; only set if image +# is encrypted (since 2.10) +# # Since: 1.7 ## { 'struct': 'ImageInfoSpecificQCow2', @@ -51,7 +75,8 @@ 'compat': 'str', '*lazy-refcounts': 'bool', '*corrupt': 'bool', - 'refcount-bits': 'int' + 'refcount-bits': 'int', + '*encrypt': 'ImageInfoSpecificQCow2Encryption' } } ## @@ -259,8 +284,7 @@ # # @encrypted: true if the backing device is encrypted # -# @encryption_key_missing: true if the backing device is encrypted but an -# valid encryption key is missing +# @encryption_key_missing: Deprecated; always false # # @detect_zeroes: detect and optimize zero writes (Since 2.1) # @@ -464,6 +488,31 @@ '*dirty-bitmaps': ['BlockDirtyInfo'] } } ## +# @BlockMeasureInfo: +# +# Image file size calculation information. This structure describes the size +# requirements for creating a new image file. +# +# The size requirements depend on the new image file format. File size always +# equals virtual disk size for the 'raw' format, even for sparse POSIX files. +# Compact formats such as 'qcow2' represent unallocated and zero regions +# efficiently so file size may be smaller than virtual disk size. +# +# The values are upper bounds that are guaranteed to fit the new image file. +# Subsequent modification, such as internal snapshot or bitmap creation, may +# require additional space and is not covered here. +# +# @required: Size required for a new image file, in bytes. +# +# @fully-allocated: Image file size, in bytes, once data has been written +# to all sectors. +# +# Since: 2.10 +## +{ 'struct': 'BlockMeasureInfo', + 'data': {'required': 'int', 'fully-allocated': 'int'} } + +## # @query-block: # # Get a list of BlockInfo for all virtual block devices. @@ -946,39 +995,7 @@ # This command sets the password of a block device that has not been open # with a password and requires one. # -# The two cases where this can happen are a block device is created through -# QEMU's initial command line or a block device is changed through the legacy -# @change interface. -# -# In the event that the block device is created through the initial command -# line, the VM will start in the stopped state regardless of whether '-S' is -# used. The intention is for a management tool to query the block devices to -# determine which ones are encrypted, set the passwords with this command, and -# then start the guest with the @cont command. -# -# Either @device or @node-name must be set but not both. -# -# @device: the name of the block backend device to set the password on -# -# @node-name: graph node name to set the password on (Since 2.0) -# -# @password: the password to use for the device -# -# Returns: nothing on success -# If @device is not a valid block device, DeviceNotFound -# If @device is not encrypted, DeviceNotEncrypted -# -# Notes: Not all block formats support encryption and some that do are not -# able to validate that a password is correct. Disk corruption may -# occur if an invalid password is specified. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "block_passwd", "arguments": { "device": "ide0-hd0", -# "password": "12345" } } -# <- { "return": {} } +# This command is now obsolete and will always return an error since 2.10 # ## { 'command': 'block_passwd', 'data': {'*device': 'str', @@ -1561,10 +1578,20 @@ # @granularity: the bitmap granularity, default is 64k for # block-dirty-bitmap-add # +# @persistent: the bitmap is persistent, i.e. it will be saved to the +# corresponding block device image file on its close. For now only +# Qcow2 disks support persistent bitmaps. Default is false for +# block-dirty-bitmap-add. (Since: 2.10) +# +# @autoload: the bitmap will be automatically loaded when the image it is stored +# in is opened. This flag may only be specified for persistent +# bitmaps. Default is false for block-dirty-bitmap-add. (Since: 2.10) +# # Since: 2.4 ## { 'struct': 'BlockDirtyBitmapAdd', - 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32' } } + 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32', + '*persistent': 'bool', '*autoload': 'bool' } } ## # @block-dirty-bitmap-add: @@ -1591,7 +1618,8 @@ # @block-dirty-bitmap-remove: # # Stop write tracking and remove the dirty bitmap that was created -# with block-dirty-bitmap-add. +# with block-dirty-bitmap-add. If the bitmap is persistent, remove it from its +# storage too. # # Returns: nothing on success # If @node is not a valid block device or node, DeviceNotFound @@ -1634,6 +1662,33 @@ 'data': 'BlockDirtyBitmap' } ## +# @BlockDirtyBitmapSha256: +# +# SHA256 hash of dirty bitmap data +# +# @sha256: ASCII representation of SHA256 bitmap hash +# +# Since: 2.10 +## + { 'struct': 'BlockDirtyBitmapSha256', + 'data': {'sha256': 'str'} } + +## +# @x-debug-block-dirty-bitmap-sha256: +# +# Get bitmap SHA256 +# +# Returns: BlockDirtyBitmapSha256 on success +# If @node is not a valid block device, DeviceNotFound +# If @name is not found or if hashing has failed, GenericError with an +# explanation +# +# Since: 2.10 +## + { 'command': 'x-debug-block-dirty-bitmap-sha256', + 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' } + +## # @blockdev-mirror: # # Start mirroring a block device's writes to a new destination. @@ -2282,6 +2337,63 @@ 'mode': 'Qcow2OverlapCheckMode' } } ## +# @BlockdevQcowEncryptionFormat: +# +# @aes: AES-CBC with plain64 initialization vectors +# +# Since: 2.10 +## +{ 'enum': 'BlockdevQcowEncryptionFormat', + 'data': [ 'aes' ] } + +## +# @BlockdevQcowEncryption: +# +# Since: 2.10 +## +{ 'union': 'BlockdevQcowEncryption', + 'base': { 'format': 'BlockdevQcowEncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'aes': 'QCryptoBlockOptionsQCow' } } + +## +# @BlockdevOptionsQcow: +# +# Driver specific block device options for qcow. +# +# @encrypt: Image decryption options. Mandatory for +# encrypted images, except when doing a metadata-only +# probe of the image. +# +# Since: 2.10 +## +{ 'struct': 'BlockdevOptionsQcow', + 'base': 'BlockdevOptionsGenericCOWFormat', + 'data': { '*encrypt': 'BlockdevQcowEncryption' } } + + + +## +# @BlockdevQcow2EncryptionFormat: +# @aes: AES-CBC with plain64 initialization venctors +# +# Since: 2.10 +## +{ 'enum': 'BlockdevQcow2EncryptionFormat', + 'data': [ 'aes', 'luks' ] } + +## +# @BlockdevQcow2Encryption: +# +# Since: 2.10 +## +{ 'union': 'BlockdevQcow2Encryption', + 'base': { 'format': 'BlockdevQcow2EncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'aes': 'QCryptoBlockOptionsQCow', + 'luks': 'QCryptoBlockOptionsLUKS'} } + +## # @BlockdevOptionsQcow2: # # Driver specific block device options for qcow2. @@ -2315,6 +2427,9 @@ # @cache-clean-interval: clean unused entries in the L2 and refcount # caches. The interval is in seconds. The default value # is 0 and it disables this feature (since 2.5) +# @encrypt: Image decryption options. Mandatory for +# encrypted images, except when doing a metadata-only +# probe of the image. (since 2.10) # # Since: 2.9 ## @@ -2328,8 +2443,8 @@ '*cache-size': 'int', '*l2-cache-size': 'int', '*refcount-cache-size': 'int', - '*cache-clean-interval': 'int' } } - + '*cache-clean-interval': 'int', + '*encrypt': 'BlockdevQcow2Encryption' } } ## # @BlockdevOptionsSsh: @@ -2976,7 +3091,7 @@ 'null-co': 'BlockdevOptionsNull', 'parallels': 'BlockdevOptionsGenericFormat', 'qcow2': 'BlockdevOptionsQcow2', - 'qcow': 'BlockdevOptionsGenericCOWFormat', + 'qcow': 'BlockdevOptionsQcow', 'qed': 'BlockdevOptionsGenericCOWFormat', 'quorum': 'BlockdevOptionsQuorum', 'raw': 'BlockdevOptionsRaw', diff --git a/qapi/common.json b/qapi/common.json index b626647b2f..8355d5a2f3 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -14,9 +14,6 @@ # # @CommandNotFound: the requested command has not been found # -# @DeviceEncrypted: the requested operation can't be fulfilled because the -# selected device is encrypted -# # @DeviceNotActive: a device has failed to be become active # # @DeviceNotFound: the requested device has not been found @@ -28,7 +25,7 @@ ## { 'enum': 'QapiErrorClass', # Keep this in sync with ErrorClass in error.h - 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted', + 'data': [ 'GenericError', 'CommandNotFound', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] } ## diff --git a/qemu-doc.texi b/qemu-doc.texi index d2986cba50..48af5155c7 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -540,10 +540,20 @@ File name of a base image (see @option{create} subcommand) @item backing_fmt Image format of the base image @item encryption -If this option is set to @code{on}, the image is encrypted with 128-bit AES-CBC. +This option is deprecated and equivalent to @code{encrypt.format=aes} -The use of encryption in qcow and qcow2 images is considered to be flawed by -modern cryptography standards, suffering from a number of design problems: +@item encrypt.format + +If this is set to @code{luks}, it requests that the qcow2 payload (not +qcow2 header) be encrypted using the LUKS format. The passphrase to +use to unlock the LUKS key slot is given by the @code{encrypt.key-secret} +parameter. LUKS encryption parameters can be tuned with the other +@code{encrypt.*} parameters. + +If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. +The encryption key is given by the @code{encrypt.key-secret} parameter. +This encryption format is considered to be flawed by modern cryptography +standards, suffering from a number of design problems: @itemize @minus @item The AES-CBC cipher is used with predictable initialization vectors based @@ -558,10 +568,45 @@ original file must then be securely erased using a program like shred, though even this is ineffective with many modern storage technologies. @end itemize -Use of qcow / qcow2 encryption with QEMU is deprecated, and support for -it will go away in a future release. Users are recommended to use an -alternative encryption technology such as the Linux dm-crypt / LUKS -system. +The use of this is no longer supported in system emulators. Support only +remains in the command line utilities, for the purposes of data liberation +and interoperability with old versions of QEMU. The @code{luks} format +should be used instead. + +@item encrypt.key-secret + +Provides the ID of a @code{secret} object that contains the passphrase +(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}). + +@item encrypt.cipher-alg + +Name of the cipher algorithm and key length. Currently defaults +to @code{aes-256}. Only used when @code{encrypt.format=luks}. + +@item encrypt.cipher-mode + +Name of the encryption mode to use. Currently defaults to @code{xts}. +Only used when @code{encrypt.format=luks}. + +@item encrypt.ivgen-alg + +Name of the initialization vector generator algorithm. Currently defaults +to @code{plain64}. Only used when @code{encrypt.format=luks}. + +@item encrypt.ivgen-hash-alg + +Name of the hash algorithm to use with the initialization vector generator +(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. + +@item encrypt.hash-alg + +Name of the hash algorithm to use for PBKDF algorithm +Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}. + +@item encrypt.iter-time + +Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. +Defaults to @code{2000}. Only used when @code{encrypt.format=luks}. @item cluster_size Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster @@ -636,7 +681,69 @@ Supported options: @item backing_file File name of a base image (see @option{create} subcommand) @item encryption -If this option is set to @code{on}, the image is encrypted. +This option is deprecated and equivalent to @code{encrypt.format=aes} + +@item encrypt.format +If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC. +The encryption key is given by the @code{encrypt.key-secret} parameter. +This encryption format is considered to be flawed by modern cryptography +standards, suffering from a number of design problems enumerated previously +against the @code{qcow2} image format. + +The use of this is no longer supported in system emulators. Support only +remains in the command line utilities, for the purposes of data liberation +and interoperability with old versions of QEMU. + +Users requiring native encryption should use the @code{qcow2} format +instead with @code{encrypt.format=luks}. + +@item encrypt.key-secret + +Provides the ID of a @code{secret} object that contains the encryption +key (@code{encrypt.format=aes}). + +@end table + +@item luks + +LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup + +Supported options: +@table @code + +@item key-secret + +Provides the ID of a @code{secret} object that contains the passphrase. + +@item cipher-alg + +Name of the cipher algorithm and key length. Currently defaults +to @code{aes-256}. + +@item cipher-mode + +Name of the encryption mode to use. Currently defaults to @code{xts}. + +@item ivgen-alg + +Name of the initialization vector generator algorithm. Currently defaults +to @code{plain64}. + +@item ivgen-hash-alg + +Name of the hash algorithm to use with the initialization vector generator +(if required). Defaults to @code{sha256}. + +@item hash-alg + +Name of the hash algorithm to use for PBKDF algorithm +Defaults to @code{sha256}. + +@item iter-time + +Amount of time, in milliseconds, to use for PBKDF algorithm per key slot. +Defaults to @code{2000}. + @end table @item vdi diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index a39fcdba71..ac5946bc4f 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -63,6 +63,12 @@ STEXI @item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [-U] @var{filename} ETEXI +DEF("measure", img_measure, +"measure [--output=ofmt] [-O output_fmt] [-o options] [--size N | [--object objectdef] [--image-opts] [-f fmt] [-l snapshot_param] filename]") +STEXI +@item measure [--output=@var{ofmt}] [-O @var{output_fmt}] [-o @var{options}] [--size @var{N} | [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-l @var{snapshot_param}] @var{filename}] +ETEXI + DEF("snapshot", img_snapshot, "snapshot [--object objectdef] [--image-opts] [-U] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") STEXI diff --git a/qemu-img.c b/qemu-img.c index f7ffb79db6..28022145d5 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-version.h" #include "qapi/error.h" +#include "qapi/util.h" #include "qapi-visit.h" #include "qapi/qobject-output-visitor.h" #include "qapi/qmp/qerror.h" @@ -61,6 +62,8 @@ enum { OPTION_FLUSH_INTERVAL = 261, OPTION_NO_DRAIN = 262, OPTION_TARGET_IMAGE_OPTS = 263, + OPTION_SIZE = 264, + OPTION_PREALLOCATION = 265, }; typedef enum OutputFormat { @@ -260,29 +263,6 @@ static int print_block_option_help(const char *filename, const char *fmt) } -static int img_open_password(BlockBackend *blk, const char *filename, - int flags, bool quiet) -{ - BlockDriverState *bs; - char password[256]; - - bs = blk_bs(blk); - if (bdrv_is_encrypted(bs) && bdrv_key_required(bs) && - !(flags & BDRV_O_NO_IO)) { - qprintf(quiet, "Disk image '%s' is encrypted.\n", filename); - if (qemu_read_password(password, sizeof(password)) < 0) { - error_report("No password given"); - return -1; - } - if (bdrv_set_key(bs, password) < 0) { - error_report("invalid password"); - return -1; - } - } - return 0; -} - - static BlockBackend *img_open_opts(const char *optstr, QemuOpts *opts, int flags, bool writethrough, bool quiet, bool force_share) @@ -307,10 +287,6 @@ static BlockBackend *img_open_opts(const char *optstr, } blk_set_enable_write_cache(blk, !writethrough); - if (img_open_password(blk, optstr, flags, quiet) < 0) { - blk_unref(blk); - return NULL; - } return blk; } @@ -340,10 +316,6 @@ static BlockBackend *img_open_file(const char *filename, } blk_set_enable_write_cache(blk, !writethrough); - if (img_open_password(blk, filename, flags, quiet) < 0) { - blk_unref(blk); - return NULL; - } return blk; } @@ -2264,6 +2236,8 @@ static int img_convert(int argc, char **argv) if (s.compressed) { bool encryption = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false); + const char *encryptfmt = + qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT); const char *preallocation = qemu_opt_get(opts, BLOCK_OPT_PREALLOC); @@ -2273,7 +2247,7 @@ static int img_convert(int argc, char **argv) goto out; } - if (encryption) { + if (encryption || encryptfmt) { error_report("Compression and encryption not supported at " "the same time"); ret = -1; @@ -3436,9 +3410,10 @@ static int img_resize(int argc, char **argv) Error *err = NULL; int c, ret, relative; const char *filename, *fmt, *size; - int64_t n, total_size; + int64_t n, total_size, current_size; bool quiet = false; BlockBackend *blk = NULL; + PreallocMode prealloc = PREALLOC_MODE_OFF; QemuOpts *param; static QemuOptsList resize_options = { @@ -3472,6 +3447,7 @@ static int img_resize(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"object", required_argument, 0, OPTION_OBJECT}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"preallocation", required_argument, 0, OPTION_PREALLOCATION}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, ":f:hq", @@ -3506,6 +3482,15 @@ static int img_resize(int argc, char **argv) case OPTION_IMAGE_OPTS: image_opts = true; break; + case OPTION_PREALLOCATION: + prealloc = qapi_enum_parse(PreallocMode_lookup, optarg, + PREALLOC_MODE__MAX, PREALLOC_MODE__MAX, + NULL); + if (prealloc == PREALLOC_MODE__MAX) { + error_report("Invalid preallocation mode '%s'", optarg); + return 1; + } + break; } } if (optind != argc - 1) { @@ -3554,8 +3539,16 @@ static int img_resize(int argc, char **argv) goto out; } + current_size = blk_getlength(blk); + if (current_size < 0) { + error_report("Failed to inquire current image length: %s", + strerror(-current_size)); + ret = -1; + goto out; + } + if (relative) { - total_size = blk_getlength(blk) + n * relative; + total_size = current_size + n * relative; } else { total_size = n; } @@ -3565,7 +3558,13 @@ static int img_resize(int argc, char **argv) goto out; } - ret = blk_truncate(blk, total_size, &err); + if (total_size <= current_size && prealloc != PREALLOC_MODE_OFF) { + error_report("Preallocation can only be used for growing images"); + ret = -1; + goto out; + } + + ret = blk_truncate(blk, total_size, prealloc, &err); if (!ret) { qprintf(quiet, "Image resized.\n"); } else { @@ -4448,6 +4447,239 @@ out: return 0; } +static void dump_json_block_measure_info(BlockMeasureInfo *info) +{ + QString *str; + QObject *obj; + Visitor *v = qobject_output_visitor_new(&obj); + + visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort); + visit_complete(v, &obj); + str = qobject_to_json_pretty(obj); + assert(str != NULL); + printf("%s\n", qstring_get_str(str)); + qobject_decref(obj); + visit_free(v); + QDECREF(str); +} + +static int img_measure(int argc, char **argv) +{ + static const struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"object", required_argument, 0, OPTION_OBJECT}, + {"output", required_argument, 0, OPTION_OUTPUT}, + {"size", required_argument, 0, OPTION_SIZE}, + {"force-share", no_argument, 0, 'U'}, + {0, 0, 0, 0} + }; + OutputFormat output_format = OFORMAT_HUMAN; + BlockBackend *in_blk = NULL; + BlockDriver *drv; + const char *filename = NULL; + const char *fmt = NULL; + const char *out_fmt = "raw"; + char *options = NULL; + char *snapshot_name = NULL; + bool force_share = false; + QemuOpts *opts = NULL; + QemuOpts *object_opts = NULL; + QemuOpts *sn_opts = NULL; + QemuOptsList *create_opts = NULL; + bool image_opts = false; + uint64_t img_size = UINT64_MAX; + BlockMeasureInfo *info = NULL; + Error *local_err = NULL; + int ret = 1; + int c; + + while ((c = getopt_long(argc, argv, "hf:O:o:l:U", + long_options, NULL)) != -1) { + switch (c) { + case '?': + case 'h': + help(); + break; + case 'f': + fmt = optarg; + break; + case 'O': + out_fmt = optarg; + break; + case 'o': + if (!is_valid_option_list(optarg)) { + error_report("Invalid option list: %s", optarg); + goto out; + } + if (!options) { + options = g_strdup(optarg); + } else { + char *old_options = options; + options = g_strdup_printf("%s,%s", options, optarg); + g_free(old_options); + } + break; + case 'l': + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { + sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts, + optarg, false); + if (!sn_opts) { + error_report("Failed in parsing snapshot param '%s'", + optarg); + goto out; + } + } else { + snapshot_name = optarg; + } + break; + case 'U': + force_share = true; + break; + case OPTION_OBJECT: + object_opts = qemu_opts_parse_noisily(&qemu_object_opts, + optarg, true); + if (!object_opts) { + goto out; + } + break; + case OPTION_IMAGE_OPTS: + image_opts = true; + break; + case OPTION_OUTPUT: + if (!strcmp(optarg, "json")) { + output_format = OFORMAT_JSON; + } else if (!strcmp(optarg, "human")) { + output_format = OFORMAT_HUMAN; + } else { + error_report("--output must be used with human or json " + "as argument."); + goto out; + } + break; + case OPTION_SIZE: + { + int64_t sval; + + sval = cvtnum(optarg); + if (sval < 0) { + if (sval == -ERANGE) { + error_report("Image size must be less than 8 EiB!"); + } else { + error_report("Invalid image size specified! You may use " + "k, M, G, T, P or E suffixes for "); + error_report("kilobytes, megabytes, gigabytes, terabytes, " + "petabytes and exabytes."); + } + goto out; + } + img_size = (uint64_t)sval; + } + break; + } + } + + if (qemu_opts_foreach(&qemu_object_opts, + user_creatable_add_opts_foreach, + NULL, NULL)) { + goto out; + } + + if (argc - optind > 1) { + error_report("At most one filename argument is allowed."); + goto out; + } else if (argc - optind == 1) { + filename = argv[optind]; + } + + if (!filename && + (object_opts || image_opts || fmt || snapshot_name || sn_opts)) { + error_report("--object, --image-opts, -f, and -l " + "require a filename argument."); + goto out; + } + if (filename && img_size != UINT64_MAX) { + error_report("--size N cannot be used together with a filename."); + goto out; + } + if (!filename && img_size == UINT64_MAX) { + error_report("Either --size N or one filename must be specified."); + goto out; + } + + if (filename) { + in_blk = img_open(image_opts, filename, fmt, 0, + false, false, force_share); + if (!in_blk) { + goto out; + } + + if (sn_opts) { + bdrv_snapshot_load_tmp(blk_bs(in_blk), + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), + &local_err); + } else if (snapshot_name != NULL) { + bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(in_blk), + snapshot_name, &local_err); + } + if (local_err) { + error_reportf_err(local_err, "Failed to load snapshot: "); + goto out; + } + } + + drv = bdrv_find_format(out_fmt); + if (!drv) { + error_report("Unknown file format '%s'", out_fmt); + goto out; + } + if (!drv->create_opts) { + error_report("Format driver '%s' does not support image creation", + drv->format_name); + goto out; + } + + create_opts = qemu_opts_append(create_opts, drv->create_opts); + create_opts = qemu_opts_append(create_opts, bdrv_file.create_opts); + opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); + if (options) { + qemu_opts_do_parse(opts, options, NULL, &local_err); + if (local_err) { + error_report_err(local_err); + error_report("Invalid options for file format '%s'", out_fmt); + goto out; + } + } + if (img_size != UINT64_MAX) { + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort); + } + + info = bdrv_measure(drv, opts, in_blk ? blk_bs(in_blk) : NULL, &local_err); + if (local_err) { + error_report_err(local_err); + goto out; + } + + if (output_format == OFORMAT_HUMAN) { + printf("required size: %" PRIu64 "\n", info->required); + printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated); + } else { + dump_json_block_measure_info(info); + } + + ret = 0; + +out: + qapi_free_BlockMeasureInfo(info); + qemu_opts_del(object_opts); + qemu_opts_del(opts); + qemu_opts_del(sn_opts); + qemu_opts_free(create_opts); + g_free(options); + blk_unref(in_blk); + return ret; +} static const img_cmd_t img_cmds[] = { #define DEF(option, callback, arg_string) \ diff --git a/qemu-img.texi b/qemu-img.texi index 5b925ecf41..f11f6036ad 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -438,6 +438,36 @@ preallocated. For more information, consult @file{include/block/block.h} in QEMU's source code. +@item measure [--output=@var{ofmt}] [-O @var{output_fmt}] [-o @var{options}] [--size @var{N} | [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-l @var{snapshot_param}] @var{filename}] + +Calculate the file size required for a new image. This information can be used +to size logical volumes or SAN LUNs appropriately for the image that will be +placed in them. The values reported are guaranteed to be large enough to fit +the image. The command can output in the format @var{ofmt} which is either +@code{human} or @code{json}. + +If the size @var{N} is given then act as if creating a new empty image file +using @command{qemu-img create}. If @var{filename} is given then act as if +converting an existing image file using @command{qemu-img convert}. The format +of the new file is given by @var{output_fmt} while the format of an existing +file is given by @var{fmt}. + +A snapshot in an existing image can be specified using @var{snapshot_param}. + +The following fields are reported: +@example +required size: 524288 +fully allocated size: 1074069504 +@end example + +The @code{required size} is the file size of the new image. It may be smaller +than the virtual disk size if the image format supports compact representation. + +The @code{fully allocated size} is the file size of the new image once data has +been written to all sectors. This is the maximum size that the image file can +occupy with the exception of internal snapshots, dirty bitmaps, vmstate data, +and other advanced image format features. + @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename} List, apply, create or delete snapshots in image @var{filename}. @@ -499,7 +529,7 @@ qemu-img rebase -b base.img diff.qcow2 At this point, @code{modified.img} can be discarded, since @code{base.img + diff.qcow2} contains the same information. -@item resize @var{filename} [+ | -]@var{size} +@item resize [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size} Change the disk image as if it had been created with @var{size}. @@ -511,6 +541,11 @@ After using this command to grow a disk image, you must use file system and partitioning tools inside the VM to actually begin using the new space on the device. +When growing an image, the @code{--preallocation} option may be used to specify +how the additional image area should be allocated on the host. See the format +description in the @code{NOTES} section which values are allowed. Using this +option may result in slightly more data being allocated than necessary. + @item amend [-p] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} Amends the image format specific @var{options} for the image file @@ -567,16 +602,29 @@ The use of encryption in qcow and qcow2 images is considered to be flawed by modern cryptography standards, suffering from a number of design problems: @itemize @minus -@item The AES-CBC cipher is used with predictable initialization vectors based +@item +The AES-CBC cipher is used with predictable initialization vectors based on the sector number. This makes it vulnerable to chosen plaintext attacks which can reveal the existence of encrypted data. -@item The user passphrase is directly used as the encryption key. A poorly +@item +The user passphrase is directly used as the encryption key. A poorly chosen or short passphrase will compromise the security of the encryption. -@item In the event of the passphrase being compromised there is no way to +@item +In the event of the passphrase being compromised there is no way to change the passphrase to protect data in any qcow images. The files must be cloned, using a different encryption passphrase in the new file. The original file must then be securely erased using a program like shred, though even this is ineffective with many modern storage technologies. +@item +Initialization vectors used to encrypt sectors are based on the +guest virtual sector number, instead of the host physical sector. When +a disk image has multiple internal snapshots this means that data in +multiple physical sectors is encrypted with the same initialization +vector. With the CBC mode, this opens the possibility of watermarking +attacks if the attack can collect multiple sectors encrypted with the +same IV and some predictable data. Having multiple qcow2 images with +the same passphrase also exposes this weakness since the passphrase +is directly used as the key. @end itemize Use of qcow / qcow2 encryption is thus strongly discouraged. Users are diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index f4fdf2dcce..3eb42c6728 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1577,7 +1577,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv) return 0; } - ret = blk_truncate(blk, offset, &local_err); + ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err); if (ret < 0) { error_report_err(local_err); return 0; @@ -58,7 +58,6 @@ static int openfile(char *name, int flags, bool writethrough, bool force_share, QDict *opts) { Error *local_err = NULL; - BlockDriverState *bs; if (qemuio_blk) { error_report("file open already, try 'help close'"); @@ -85,28 +84,9 @@ static int openfile(char *name, int flags, bool writethrough, bool force_share, return 1; } - bs = blk_bs(qemuio_blk); - if (bdrv_is_encrypted(bs) && bdrv_key_required(bs)) { - char password[256]; - printf("Disk image '%s' is encrypted.\n", name); - if (qemu_read_password(password, sizeof(password)) < 0) { - error_report("No password given"); - goto error; - } - if (bdrv_set_key(bs, password) < 0) { - error_report("invalid password"); - goto error; - } - } - blk_set_enable_write_cache(qemuio_blk, !writethrough); return 0; - - error: - blk_unref(qemuio_blk); - qemuio_blk = NULL; - return 1; } static void open_help(void) diff --git a/qemu-options.hx b/qemu-options.hx index ddab656eb3..2cc70b9cfc 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -85,6 +85,12 @@ Enables or disables NVDIMM support. The default is off. @item s390-squash-mcss=on|off Enables or disables squashing subchannels into the default css. The default is off. +@item enforce-config-section=on|off +If @option{enforce-config-section} is set to @var{on}, force migration +code to send configuration section even if the machine-type sets the +@option{migration.send-configuration} property to @var{off}. +NOTE: this parameter is deprecated. Please use @option{-global} +@option{migration.send-configuration}=@var{on|off} instead. @end table ETEXI @@ -4368,7 +4374,7 @@ The simplest (insecure) usage is to provide the secret inline The simplest secure usage is to provide the secret via a file - # echo -n "letmein" > mypasswd.txt + # printf "letmein" > mypasswd.txt # $QEMU -object secret,id=sec0,file=mypasswd.txt,format=raw For greater security, AES-256-CBC should be used. To illustrate usage, @@ -4396,7 +4402,7 @@ telling openssl to base64 encode the result, but it could be left as raw bytes if desired. @example - # SECRET=$(echo -n "letmein" | + # SECRET=$(printf "letmein" | openssl enc -aes-256-cbc -a -K $KEY -iv $IV) @end example @@ -164,10 +164,8 @@ SpiceInfo *qmp_query_spice(Error **errp) void qmp_cont(Error **errp) { - Error *local_err = NULL; BlockBackend *blk; - BlockDriverState *bs; - BdrvNextIterator it; + Error *local_err = NULL; /* if there is a dump in background, we should wait until the dump * finished */ @@ -187,14 +185,6 @@ void qmp_cont(Error **errp) blk_iostatus_reset(blk); } - for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { - bdrv_add_key(bs, NULL, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } - /* Continuing after completed migration. Images have been inactivated to * allow the destination to take control. Need to get control back now. * diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 16a1e59615..102c58afac 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -706,6 +706,9 @@ struct ARMCPU { void *el_change_hook_opaque; int32_t node_id; /* NUMA node this CPU belongs to */ + + /* Used to synchronize KVM and QEMU in-kernel device levels */ + uint8_t device_irq_level; }; static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) diff --git a/target/arm/helper.c b/target/arm/helper.c index 2594faa9b8..4ed32c56b8 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -8768,9 +8768,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) } break; case 20: /* CONTROL */ - switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0); - env->v7m.control = val & (R_V7M_CONTROL_SPSEL_MASK | - R_V7M_CONTROL_NPRIV_MASK); + /* Writing to the SPSEL bit only has an effect if we are in + * thread mode; other bits can be updated by any privileged code. + * switch_v7m_sp() deals with updating the SPSEL bit in + * env->v7m.control, so we only need update the others. + */ + if (env->v7m.exception == 0) { + switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0); + } + env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK; + env->v7m.control |= val & R_V7M_CONTROL_NPRIV_MASK; break; default: qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special" diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 45554682f2..7c17f0d629 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -174,6 +174,12 @@ int kvm_arch_init(MachineState *ms, KVMState *s) */ kvm_async_interrupts_allowed = true; + /* + * PSCI wakes up secondary cores, so we always need to + * have vCPUs waiting in kernel space + */ + kvm_halt_in_kernel_allowed = true; + cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); type_register_static(&host_arm_cpu_type_info); @@ -528,6 +534,51 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { + ARMCPU *cpu; + uint32_t switched_level; + + if (kvm_irqchip_in_kernel()) { + /* + * We only need to sync timer states with user-space interrupt + * controllers, so return early and save cycles if we don't. + */ + return MEMTXATTRS_UNSPECIFIED; + } + + cpu = ARM_CPU(cs); + + /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */ + if (run->s.regs.device_irq_level != cpu->device_irq_level) { + switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; + + qemu_mutex_lock_iothread(); + + if (switched_level & KVM_ARM_DEV_EL1_VTIMER) { + qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT], + !!(run->s.regs.device_irq_level & + KVM_ARM_DEV_EL1_VTIMER)); + switched_level &= ~KVM_ARM_DEV_EL1_VTIMER; + } + + if (switched_level & KVM_ARM_DEV_EL1_PTIMER) { + qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS], + !!(run->s.regs.device_irq_level & + KVM_ARM_DEV_EL1_PTIMER)); + switched_level &= ~KVM_ARM_DEV_EL1_PTIMER; + } + + /* XXX PMU IRQ is missing */ + + if (switched_level) { + qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n", + __func__, switched_level); + } + + /* We also mark unknown levels as processed to not waste cycles */ + cpu->device_irq_level = run->s.regs.device_irq_level; + qemu_mutex_unlock_iothread(); + } + return MEMTXATTRS_UNSPECIFIED; } diff --git a/target/mips/translate.c b/target/mips/translate.c index 559f8fed89..befb87f814 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -18712,10 +18712,14 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, #endif switch (MASK_MSA_ELM(ctx->opcode)) { case OPC_COPY_S_df: - gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn); + if (likely(wd != 0)) { + gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn); + } break; case OPC_COPY_U_df: - gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn); + if (likely(wd != 0)) { + gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn); + } break; case OPC_INSERT_df: gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn); diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3a9f0861e7..e6009e70e5 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -283,6 +283,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) * precise in the MSR. */ msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index f2f7c531bc..f7a7ea5858 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2445,6 +2445,7 @@ static int kvm_ppc_register_host_cpu_type(void) .class_init = kvmppc_host_cpu_class_init, }; PowerPCCPUClass *pvr_pcc; + ObjectClass *oc; DeviceClass *dc; int i; @@ -2455,6 +2456,9 @@ static int kvm_ppc_register_host_cpu_type(void) type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); + oc = object_class_by_name(type_info.name); + g_assert(oc); + #if defined(TARGET_PPC64) type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host"); type_info.parent = TYPE_SPAPR_CPU_CORE, @@ -2474,7 +2478,6 @@ static int kvm_ppc_register_host_cpu_type(void) dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { if (strcmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { - ObjectClass *oc = OBJECT_CLASS(pvr_pcc); char *suffix; ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 69fde65276..bbd37e3c7d 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -147,11 +147,10 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, int rwx, uint64_t pte, } } -static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, +static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, vaddr eaddr, uint64_t base_addr, uint64_t nls, hwaddr *raddr, int *psize, - int *fault_cause, int *prot, - hwaddr *pte_addr) + int *fault_cause, hwaddr *pte_addr) { CPUState *cs = CPU(cpu); uint64_t index, pde; @@ -177,10 +176,6 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, uint64_t rpn = pde & R_PTE_RPN; uint64_t mask = (1UL << *psize) - 1; - if (ppc_radix64_check_prot(cpu, rwx, pde, fault_cause, prot)) { - return 0; /* Protection Denied Access */ - } - /* Or high bits of rpn and low bits to ea to form whole real addr */ *raddr = (rpn & ~mask) | (eaddr & mask); *pte_addr = base_addr + (index * sizeof(pde)); @@ -188,9 +183,8 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, int rwx, vaddr eaddr, } /* Next Level of Radix Tree */ - return ppc_radix64_walk_tree(cpu, rwx, eaddr, pde & R_PDE_NLB, - pde & R_PDE_NLS, raddr, psize, - fault_cause, prot, pte_addr); + return ppc_radix64_walk_tree(cpu, eaddr, pde & R_PDE_NLB, pde & R_PDE_NLS, + raddr, psize, fault_cause, pte_addr); } int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, @@ -241,11 +235,11 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ page_size = PRTBE_R_GET_RTS(prtbe0); - pte = ppc_radix64_walk_tree(cpu, rwx, eaddr & R_EADDR_MASK, + pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, - &raddr, &page_size, &fault_cause, &prot, - &pte_addr); - if (!pte) { + &raddr, &page_size, &fault_cause, &pte_addr); + if (!pte || ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, &prot)) { + /* Couldn't get pte or access denied due to protection */ ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause); return 1; } @@ -257,3 +251,48 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, prot, mmu_idx, 1UL << page_size); return 0; } + +hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + hwaddr raddr, pte_addr; + uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte; + int page_size, fault_cause = 0; + + /* Handle Real Mode */ + if (msr_dr == 0) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + return eaddr & 0x0FFFFFFFFFFFFFFFULL; + } + + /* Virtual Mode Access - get the fully qualified address */ + if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) { + return -1; + } + + /* Get Process Table */ + patbe = vhc->get_patbe(cpu->vhyp); + + /* Index Process Table by PID to Find Corresponding Process Table Entry */ + offset = pid * sizeof(struct prtb_entry); + size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12); + if (offset >= size) { + /* offset exceeds size of the process table */ + return -1; + } + prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset); + + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */ + page_size = PRTBE_R_GET_RTS(prtbe0); + pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK, + prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS, + &raddr, &page_size, &fault_cause, &pte_addr); + if (!pte) { + return -1; + } + + return raddr & TARGET_PAGE_MASK; +} diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 1d5c7cfea5..0ecf063a17 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -46,6 +46,7 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); +hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) { diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 65d1c8692d..b7b9088842 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -30,6 +30,7 @@ #include "helper_regs.h" #include "qemu/error-report.h" #include "mmu-book3s-v3.h" +#include "mmu-radix64.h" //#define DEBUG_MMU //#define DEBUG_BATS @@ -1432,7 +1433,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return ppc_hash64_get_phys_page_debug(cpu, addr); case POWERPC_MMU_VER_3_00: if (ppc64_radix_guest(ppc_env_get_cpu(env))) { - /* TODO - Unsupported */ + return ppc_radix64_get_phys_page_debug(cpu, addr); } else { return ppc_hash64_get_phys_page_debug(cpu, addr); } diff --git a/tests/Makefile.include b/tests/Makefile.include index 18cd06a6b3..42e17e21ab 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -554,7 +554,7 @@ tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-u tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) -tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) +tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y) tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o diff --git a/tests/multiboot/run_test.sh b/tests/multiboot/run_test.sh index 78d7edfc3b..c8f3da8f37 100755 --- a/tests/multiboot/run_test.sh +++ b/tests/multiboot/run_test.sh @@ -26,7 +26,7 @@ run_qemu() { local kernel=$1 shift - echo -e "\n\n=== Running test case: $kernel $@ ===\n" >> test.log + printf %b "\n\n=== Running test case: $kernel $@ ===\n\n" >> test.log $QEMU \ -kernel $kernel \ @@ -68,21 +68,21 @@ for t in mmap modules; do pass=1 if [ $debugexit != 1 ]; then - echo -e "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)" + printf %b "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)\n" pass=0 elif [ $ret != 0 ]; then - echo -e "\e[31mFAIL\e[0m $t (exit code $ret)" + printf %b "\e[31mFAIL\e[0m $t (exit code $ret)\n" pass=0 fi if ! diff $t.out test.log > /dev/null 2>&1; then - echo -e "\e[31mFAIL\e[0m $t (output difference)" + printf %b "\e[31mFAIL\e[0m $t (output difference)\n" diff -u $t.out test.log pass=0 fi if [ $pass == 1 ]; then - echo -e "\e[32mPASS\e[0m $t" + printf %b "\e[32mPASS\e[0m $t\n" fi done diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033 index 16edcf2f00..2cdfd1397a 100755 --- a/tests/qemu-iotests/033 +++ b/tests/qemu-iotests/033 @@ -50,10 +50,18 @@ do_test() local align=$1 local iocmd=$2 local img=$3 + if [ "$IMGOPTSSYNTAX" = "true" ] + then + IO_OPEN_ARG="$img" + IO_EXTRA_ARGS="--image-opts" + else + IO_OPEN_ARG="-o driver=$IMGFMT,file.align=$align blkdebug::$img" + IO_EXTRA_ARGS="" + fi { - echo "open -o driver=$IMGFMT,file.align=$align blkdebug::$img" + echo "open $IO_OPEN_ARG" echo $iocmd - } | $QEMU_IO + } | $QEMU_IO $IO_EXTRA_ARGS } for write_zero_cmd in "write -z" "aio_write -z"; do diff --git a/tests/qemu-iotests/042 b/tests/qemu-iotests/042 index 351b2830a2..a53e7cb757 100755 --- a/tests/qemu-iotests/042 +++ b/tests/qemu-iotests/042 @@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt qcow2 qcow qed +_supported_fmt qcow2 qed _supported_proto file _supported_os Linux diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out index 4789a5310e..703cf3dee1 100644 --- a/tests/qemu-iotests/044.out +++ b/tests/qemu-iotests/044.out @@ -1,6 +1,6 @@ No errors were found on the image. 7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters -Image end offset: 4296152064 +Image end offset: 4296217088 . ---------------------------------------------------------------------- Ran 1 tests diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048 index 203c04fc7f..9ed04a068d 100755 --- a/tests/qemu-iotests/048 +++ b/tests/qemu-iotests/048 @@ -46,7 +46,7 @@ _compare() . ./common.filter . ./common.pattern -_supported_fmt raw qcow qcow2 qed luks +_supported_fmt raw qcow2 qed luks _supported_proto file _supported_os Linux diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049 index fff07604fc..df35b6d21e 100755 --- a/tests/qemu-iotests/049 +++ b/tests/qemu-iotests/049 @@ -106,7 +106,7 @@ test_qemu_img create -f $IMGFMT -o preallocation=1234 "$TEST_IMG" 64M echo "== Check encryption option ==" echo test_qemu_img create -f $IMGFMT -o encryption=off "$TEST_IMG" 64M -test_qemu_img create -f $IMGFMT -o encryption=on "$TEST_IMG" 64M +test_qemu_img create -f $IMGFMT --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 "$TEST_IMG" 64M echo "== Check lazy_refcounts option (only with v3) ==" echo diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index 34e66db691..003247023e 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -4,90 +4,90 @@ QA output created by 049 == 1. Traditional size parameter == qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 == 2. Specifying size via -o == qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 == 3. Invalid sizes == @@ -128,84 +128,84 @@ qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2' == Check correct interpretation of suffixes for cluster size == qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 == Check compat level option == qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar' -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 == Check preallocation option == qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234 -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 == Check encryption option == qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16 +qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16 == Check lazy_refcounts option (only with v3) == qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 *** done diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 26c29deb51..c8cfc764bc 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -217,7 +217,7 @@ run_qemu -drive driver=null-co,cache=invalid_value # Test 142 checks the direct=on cases for cache in writeback writethrough unsafe invalid_value; do - echo -e "info block\ninfo block file\ninfo block backing\ninfo block backing-file" | \ + printf "info block %s\n" '' file backing backing-file | \ run_qemu -drive file="$TEST_IMG",cache=$cache,backing.file.filename="$TEST_IMG.base",backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=$device_id -nodefaults done @@ -325,8 +325,9 @@ echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_I $QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io -echo -e "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id\ - | _filter_qemu_io +printf %b "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id\n" | + run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id | + _filter_qemu_io $QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068 index 3801b65b9d..cfa0f2aed5 100755 --- a/tests/qemu-iotests/068 +++ b/tests/qemu-iotests/068 @@ -76,7 +76,7 @@ for extra_args in \ _make_test_img $IMG_SIZE # Give qemu some time to boot before saving the VM state - bash -c 'sleep 1; echo -e "savevm 0\nquit"' | _qemu $extra_args + { sleep 1; printf "savevm 0\nquit\n"; } | _qemu $extra_args # Now try to continue from that VM state (this should just work) echo quit | _qemu $extra_args -loadvm 0 done diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out index a952330ba5..dbed67f2ba 100644 --- a/tests/qemu-iotests/082.out +++ b/tests/qemu-iotests/082.out @@ -3,14 +3,14 @@ QA output created by 082 === create: Options specified more than once === Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) cluster_size: 65536 Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -22,7 +22,7 @@ Format specific information: corrupt: false Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -34,7 +34,7 @@ Format specific information: corrupt: false Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16 image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128M (134217728 bytes) @@ -48,7 +48,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -61,7 +69,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -74,7 +90,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -87,7 +111,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -100,7 +132,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -113,7 +153,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -126,7 +174,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -139,7 +195,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -147,10 +211,10 @@ refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, @@ -167,7 +231,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -180,7 +252,7 @@ size Virtual disk size === convert: Options specified more than once === Testing: create -f qcow2 TEST_DIR/t.qcow2 128M -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base image: TEST_DIR/t.IMGFMT.base @@ -229,7 +301,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -242,7 +322,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -255,7 +343,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -268,7 +364,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -281,7 +385,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -294,7 +406,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -307,7 +427,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -320,7 +448,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -348,7 +484,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -407,7 +551,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -420,7 +572,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -433,7 +593,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -446,7 +614,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -459,7 +635,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -472,7 +656,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -485,7 +677,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -498,7 +698,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates @@ -528,7 +736,15 @@ size Virtual disk size compat Compatibility level (0.10 or 1.1) backing_file File name of a base image backing_fmt Image format of the base image -encryption Encrypt the image +encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) +encrypt.format Encrypt the image, format choices: 'aes', 'luks' +encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase +encrypt.cipher-alg Name of encryption cipher algorithm +encrypt.cipher-mode Name of encryption cipher mode +encrypt.ivgen-alg Name of IV generator algorithm +encrypt.ivgen-hash-alg Name of IV generator hash algorithm +encrypt.hash-alg Name of encryption hash algorithm +encrypt.iter-time Time to spend in PBKDF in milliseconds cluster_size qcow2 cluster size preallocation Preallocation mode (allowed values: off, metadata, falloc, full) lazy_refcounts Postpone refcount updates diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out index a5d4cc3494..6edf107f55 100644 --- a/tests/qemu-iotests/085.out +++ b/tests/qemu-iotests/085.out @@ -11,7 +11,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === Create a single snapshot on virtio0 === -Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} === Invalid command - missing device and nodename === @@ -25,32 +25,32 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file === Create several transactional group snapshots === -Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} -Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} === Create a couple of snapshots using blockdev-snapshot === diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087 index 6d52f7d1b7..f8e4903f4f 100755 --- a/tests/qemu-iotests/087 +++ b/tests/qemu-iotests/087 @@ -119,12 +119,21 @@ run_qemu <<EOF EOF echo -echo === Encrypted image === +echo === Encrypted image QCow === echo -_make_test_img -o encryption=on $size -run_qemu -S <<EOF +_make_test_img --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 $size +run_qemu <<EOF { "execute": "qmp_capabilities" } +{ "execute": "object-add", + "arguments": { + "qom-type": "secret", + "id": "sec0", + "props": { + "data": "123456" + } + } +} { "execute": "blockdev-add", "arguments": { "driver": "$IMGFMT", @@ -132,14 +141,32 @@ run_qemu -S <<EOF "file": { "driver": "file", "filename": "$TEST_IMG" + }, + "encrypt": { + "format": "aes", + "key-secret": "sec0" } } } { "execute": "quit" } EOF +echo +echo === Encrypted image LUKS === +echo + +_make_test_img --object secret,id=sec0,data=123456 -o encrypt.format=luks,encrypt.key-secret=sec0 $size run_qemu <<EOF { "execute": "qmp_capabilities" } +{ "execute": "object-add", + "arguments": { + "qom-type": "secret", + "id": "sec0", + "props": { + "data": "123456" + } + } +} { "execute": "blockdev-add", "arguments": { "driver": "$IMGFMT", @@ -147,6 +174,10 @@ run_qemu <<EOF "file": { "driver": "file", "filename": "$TEST_IMG" + }, + "encrypt": { + "format": "luks", + "key-secret": "sec0" } } } @@ -157,7 +188,7 @@ echo echo === Missing driver === echo -_make_test_img -o encryption=on $size +_make_test_img --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 $size run_qemu -S <<EOF { "execute": "qmp_capabilities" } { "execute": "blockdev-add", diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index 59c5208272..b1318c6ed6 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -32,27 +32,33 @@ QMP_VERSION {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} -=== Encrypted image === +=== Encrypted image QCow === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on -Testing: -S +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 +Testing: QMP_VERSION {"return": {}} +{"return": {}} {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} + +=== Encrypted image LUKS === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encrypt.format=luks encrypt.key-secret=sec0 Testing: QMP_VERSION {"return": {}} -{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}} +{"return": {}} +{"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} === Missing driver === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 Testing: -S QMP_VERSION {"return": {}} diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 new file mode 100755 index 0000000000..32649578fb --- /dev/null +++ b/tests/qemu-iotests/106 @@ -0,0 +1,92 @@ +#!/bin/bash +# +# Test preallocated resize of raw images +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq=$(basename $0) +echo "QA output created by $seq" + +here=$PWD +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment and filters +. ./common.rc +. ./common.filter + +_supported_fmt raw +_supported_proto file +_supported_os Linux + +# in kB +CREATION_SIZE=128 +GROWTH_SIZE=256 + +echo '=== Testing image growth ===' + +for create_mode in off falloc full; do + for growth_mode in off falloc full; do + echo + echo "--- create_mode=$create_mode growth_mode=$growth_mode ---" + + IMGOPTS="preallocation=$create_mode" _make_test_img ${CREATION_SIZE}K + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K + + expected_size=0 + if [ $create_mode != off ]; then + expected_size=$CREATION_SIZE + fi + if [ $growth_mode != off ]; then + expected_size=$((expected_size + $GROWTH_SIZE)) + fi + + actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') + actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') + + # The actual size may exceed the expected size, depending on the file + # system. Therefore we just test that the actual size is at least what + # we expect. + if [ $actual_size -lt $expected_size ]; then + echo "ERROR: Image should have at least ${expected_size}K, but has ${actual_size}K" + fi + done +done + +echo +echo '=== Testing image shrinking ===' + +# None of this should work except for "off", because other modes cannot be used +# for shrinking +for growth_mode in falloc full off; do + echo + echo "--- growth_mode=$growth_mode ---" + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K +done + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/106.out b/tests/qemu-iotests/106.out new file mode 100644 index 0000000000..0a42312301 --- /dev/null +++ b/tests/qemu-iotests/106.out @@ -0,0 +1,50 @@ +QA output created by 106 +=== Testing image growth === + +--- create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=off +Image resized. + +--- create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=off +Image resized. + +--- create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=off +Image resized. + +--- create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=falloc +Image resized. + +--- create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=falloc +Image resized. + +--- create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=falloc +Image resized. + +--- create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=full +Image resized. + +--- create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=full +Image resized. + +--- create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 preallocation=full +Image resized. + +=== Testing image shrinking === + +--- growth_mode=falloc --- +qemu-img: Preallocation can only be used for growing images + +--- growth_mode=full --- +qemu-img: Preallocation can only be used for growing images + +--- growth_mode=off --- +Image resized. +*** done diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120 index 4f88a67fe1..f40b97d099 100755 --- a/tests/qemu-iotests/120 +++ b/tests/qemu-iotests/120 @@ -41,6 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt generic _supported_proto file _supported_os Linux +_unsupported_fmt luks _make_test_img 64M diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 new file mode 100755 index 0000000000..9424313e82 --- /dev/null +++ b/tests/qemu-iotests/125 @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Test preallocated growth of qcow2 images +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq=$(basename $0) +echo "QA output created by $seq" + +here=$PWD +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +get_image_size_on_host() +{ + $QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep "disk size" \ + | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/' +} + +# get standard environment and filters +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +if [ -z "$TEST_IMG_FILE" ]; then + TEST_IMG_FILE=$TEST_IMG +fi + +# Generally, we create some image with or without existing preallocation and +# then resize it. Then we write some data into the image and verify that its +# size does not change if we have used preallocation. + +# With a cluster size of 512 B, one L2 table covers 64 * 512 B = 32 kB. +# One cluster of the L1 table covers 64 * 32 kB = 2 MB. +# There are multiple cases we want to test: +# (1) Grow an image without having to allocate a new L2 table. +# (2) Grow an image, having to allocate a new L2 table. +# (3) Grow an image, having to grow the L1 table. +# Therefore, we create an image that is 48 kB below 2 MB. Then: +# (1) We resize it to 2 MB - 32 kB. (+ 16 kB) +# (2) We resize it to 2 MB. (+ 48 kB) +# (3) We resize it to 2 MB + 32 kB. (+ 80 kB) + +# in B +CREATION_SIZE=$((2 * 1024 * 1024 - 48 * 1024)) + +# in kB +for GROWTH_SIZE in 16 48 80; do + for create_mode in off metadata falloc full; do + for growth_mode in off metadata falloc full; do + echo "--- growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---" + + IMGOPTS="preallocation=$create_mode,cluster_size=512" _make_test_img ${CREATION_SIZE} + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K + + host_size_0=$(get_image_size_on_host) + file_length_0=$(stat -c '%s' "$TEST_IMG_FILE") + + $QEMU_IO -c "write 0 $CREATION_SIZE" "$TEST_IMG" | _filter_qemu_io + + host_size_1=$(get_image_size_on_host) + file_length_1=$(stat -c '%s' "$TEST_IMG_FILE") + + $QEMU_IO -c "write $CREATION_SIZE ${GROWTH_SIZE}K" "$TEST_IMG" | _filter_qemu_io + + host_size_2=$(get_image_size_on_host) + file_length_2=$(stat -c '%s' "$TEST_IMG_FILE") + + # Test creation preallocation: Compare #0 against #1 + if [ $create_mode != off ]; then + # The image length should not have grown + if [ $file_length_1 -gt $file_length_0 ]; then + echo "ERROR (create): Image length has grown from $file_length_0 to $file_length_1" + fi + if [ $create_mode != metadata ]; then + # The host size should not have grown either + if [ $host_size_1 -gt $host_size_0 ]; then + echo "ERROR (create): Host size has grown from $host_size_0 to $host_size_1" + fi + fi + fi + + # Test resize preallocation: Compare #2 against #1 + if [ $growth_mode != off ]; then + # The image length should not have grown + if [ $file_length_2 -gt $file_length_1 ]; then + echo "ERROR (grow): Image length has grown from $file_length_1 to $file_length_2" + fi + if [ $create_mode != metadata ]; then + # The host size should not have grown either + if [ $host_size_2 -gt $host_size_1 ]; then + echo "ERROR (grow): Host size has grown from $host_size_1 to $host_size_2" + fi + fi + fi + + echo + done + done +done + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out new file mode 100644 index 0000000000..3f4d6e31a6 --- /dev/null +++ b/tests/qemu-iotests/125.out @@ -0,0 +1,386 @@ +QA output created by 125 +--- growth_size=16 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=16 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 16384/16384 bytes at offset 2048000 +16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=48 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 49152/49152 bytes at offset 2048000 +48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=off growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=off growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=off growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=off growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=metadata growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=metadata growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=metadata growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=metadata growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=falloc growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=falloc growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=falloc growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=falloc growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=full growth_mode=off --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=full growth_mode=metadata --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=full growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +--- growth_size=80 create_mode=full growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full +Image resized. +wrote 2048000/2048000 bytes at offset 0 +1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 81920/81920 bytes at offset 2048000 +80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +*** done diff --git a/tests/qemu-iotests/126 b/tests/qemu-iotests/126 new file mode 100755 index 0000000000..a2d4d6c73d --- /dev/null +++ b/tests/qemu-iotests/126 @@ -0,0 +1,105 @@ +#!/bin/bash +# +# Tests handling of colons in filenames (which may be confused with protocol +# prefixes) +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +status=1 # failure is the default! + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# Needs backing file support +_supported_fmt qcow qcow2 qed vmdk +# This is the default protocol (and we want to test the difference between +# colons which separate a protocol prefix from the rest and colons which are +# just part of the filename, so we cannot test protocols which require a prefix) +_supported_proto file +_supported_os Linux + +echo +echo '=== Testing plain files ===' +echo + +# A colon after a slash is not a protocol prefix separator +TEST_IMG="$TEST_DIR/a:b.$IMGFMT" _make_test_img 64M +_rm_test_img "$TEST_DIR/a:b.$IMGFMT" + +# But if you want to be really sure, you can do this +TEST_IMG="file:$TEST_DIR/a:b.$IMGFMT" _make_test_img 64M +_rm_test_img "$TEST_DIR/a:b.$IMGFMT" + + +echo +echo '=== Testing relative backing filename resolution ===' +echo + +BASE_IMG="$TEST_DIR/image:base.$IMGFMT" +TOP_IMG="$TEST_DIR/image:top.$IMGFMT" + +TEST_IMG=$BASE_IMG _make_test_img 64M +TEST_IMG=$TOP_IMG _make_test_img -b ./image:base.$IMGFMT + +# The default cluster size depends on the image format +TEST_IMG=$TOP_IMG _img_info | grep -v 'cluster_size' + +_rm_test_img "$BASE_IMG" +_rm_test_img "$TOP_IMG" + + +# Do another test where we access both top and base without any slash in them +echo +pushd "$TEST_DIR" >/dev/null + +BASE_IMG="base.$IMGFMT" +TOP_IMG="file:image:top.$IMGFMT" + +TEST_IMG=$BASE_IMG _make_test_img 64M +TEST_IMG=$TOP_IMG _make_test_img -b "$BASE_IMG" + +TEST_IMG=$TOP_IMG _img_info | grep -v 'cluster_size' + +_rm_test_img "$BASE_IMG" +_rm_test_img "image:top.$IMGFMT" + +popd >/dev/null + +# Note that we could also do the same test with BASE_IMG=file:image:base.$IMGFMT +# -- but behavior for that case is a bit strange. Protocol-prefixed paths are +# in a sense always absolute paths, so such paths will never be combined with +# the path of the overlay. But since "image:base.$IMGFMT" is actually a +# relative path, it will always be evaluated relative to qemu's CWD (but not +# relative to the overlay!). While this is more or less intended, it is still +# pretty strange and thus not something that is tested here. +# (The root of the issue is the use of a relative path with a protocol prefix. +# This may always give you weird results because in one sense, qemu considers +# such paths absolute, whereas in another, they are still relative.) + + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out new file mode 100644 index 0000000000..50d73080fa --- /dev/null +++ b/tests/qemu-iotests/126.out @@ -0,0 +1,23 @@ +QA output created by 126 + +=== Testing plain files === + +Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 + +=== Testing relative backing filename resolution === + +Formatting 'TEST_DIR/image:base.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=./image:base.IMGFMT +image: TEST_DIR/image:top.IMGFMT +file format: IMGFMT +virtual size: 64M (67108864 bytes) +backing file: ./image:base.IMGFMT (actual path: TEST_DIR/./image:base.IMGFMT) + +Formatting 'base.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'file:image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=base.IMGFMT +image: ./image:top.IMGFMT +file format: IMGFMT +virtual size: 64M (67108864 bytes) +backing file: base.IMGFMT (actual path: ./base.IMGFMT) +*** done diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134 index acce946e75..99144151b8 100755 --- a/tests/qemu-iotests/134 +++ b/tests/qemu-iotests/134 @@ -37,30 +37,38 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt qcow2 +_supported_fmt qcow qcow2 _supported_proto generic _unsupported_proto vxhs _supported_os Linux size=128M -IMGOPTS="encryption=on" _make_test_img $size + +SECRET="secret,id=sec0,data=astrochicken" +SECRETALT="secret,id=sec0,data=platypus" + +_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" $size + +IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" + +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT echo echo "== reading whole image ==" -echo "astrochicken" | $QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir echo echo "== rewriting whole image ==" -echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir echo echo "== verify pattern ==" -echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir echo echo "== verify pattern failure with wrong password ==" -echo "platypus" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir # success, all done diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out index 6493704ecf..972be49d91 100644 --- a/tests/qemu-iotests/134.out +++ b/tests/qemu-iotests/134.out @@ -1,27 +1,19 @@ QA output created by 134 -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 == reading whole image == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == rewriting whole image == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == verify pattern == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == verify pattern failure with wrong password == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: Pattern verification failed at offset 0, 134217728 bytes read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140 index 8c80a5a866..f89d0d6789 100755 --- a/tests/qemu-iotests/140 +++ b/tests/qemu-iotests/140 @@ -52,8 +52,15 @@ _make_test_img 64k $QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io +if test "$IMGOPTSSYNTAX" = "true" +then + SYSEMU_DRIVE_ARG=if=none,media=cdrom,id=drv,"$TEST_IMG" +else + SYSEMU_DRIVE_ARG=if=none,media=cdrom,id=drv,file="$TEST_IMG",driver=$IMGFMT +fi + keep_stderr=y \ -_launch_qemu -drive if=none,media=cdrom,id=drv,file="$TEST_IMG",format=$IMGFMT \ +_launch_qemu -drive $SYSEMU_DRIVE_ARG \ 2> >(_filter_nbd) _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142 index 9a5b713256..1639c83985 100755 --- a/tests/qemu-iotests/142 +++ b/tests/qemu-iotests/142 @@ -94,36 +94,36 @@ function check_cache_all() # cache.direct is supposed to be inherited by both bs->file and # bs->backing - echo -e "cache.direct=on on none0" + printf "cache.direct=on on none0\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" - echo -e "\ncache.direct=on on file" + printf "\ncache.direct=on on file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" - echo -e "\ncache.direct=on on backing" + printf "\ncache.direct=on on backing\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" - echo -e "\ncache.direct=on on backing-file" + printf "\ncache.direct=on on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" # cache.writeback is supposed to be inherited by bs->backing; bs->file # always gets cache.writeback=on - echo -e "\n\ncache.writeback=off on none0" + printf "\n\ncache.writeback=off on none0\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.writeback=off on file" + printf "\ncache.writeback=off on file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep -e "doesn't" -e "does not" - echo -e "\ncache.writeback=off on backing" + printf "\ncache.writeback=off on backing\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep -e "doesn't" -e "does not" - echo -e "\ncache.writeback=off on backing-file" + printf "\ncache.writeback=off on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep -e "doesn't" -e "does not" # cache.no-flush is supposed to be inherited by both bs->file and bs->backing - echo -e "\n\ncache.no-flush=on on none0" + printf "\n\ncache.no-flush=on on none0\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on file" + printf "\ncache.no-flush=on on file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on backing" + printf "\ncache.no-flush=on on backing\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on backing-file" + printf "\ncache.no-flush=on on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" } @@ -236,35 +236,35 @@ function check_cache_all_separate() { # Check cache.direct - echo -e "cache.direct=on on blk" + printf "cache.direct=on on blk\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.direct=on on file" + printf "\ncache.direct=on on file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.direct=on on backing" + printf "\ncache.direct=on on backing\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.direct=on on backing-file" + printf "\ncache.direct=on on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" # Check cache.writeback - echo -e "\n\ncache.writeback=off on blk" + printf "\n\ncache.writeback=off on blk\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.writeback=off on file" + printf "\ncache.writeback=off on file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.writeback=off on backing" + printf "\ncache.writeback=off on backing\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.writeback=off on backing-file" + printf "\ncache.writeback=off on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" # Check cache.no-flush - echo -e "\n\ncache.no-flush=on on blk" + printf "\n\ncache.no-flush=on on blk\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on file" + printf "\ncache.no-flush=on on file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on backing" + printf "\ncache.no-flush=on on backing\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" - echo -e "\ncache.no-flush=on on backing-file" + printf "\ncache.no-flush=on on backing-file\n" echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" } diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out index 387855c378..014b2817ee 100644 --- a/tests/qemu-iotests/144.out +++ b/tests/qemu-iotests/144.out @@ -7,7 +7,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912 === Performing Live Snapshot 1 === {"return": {}} -Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} === Performing block-commit on active layer === @@ -19,6 +19,6 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ === Performing Live Snapshot 2 === -Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} *** done diff --git a/tests/qemu-iotests/145 b/tests/qemu-iotests/145 index e6c6bc4a4f..c371b3c46a 100755 --- a/tests/qemu-iotests/145 +++ b/tests/qemu-iotests/145 @@ -43,8 +43,23 @@ _supported_proto generic _supported_os Linux _make_test_img 1M -echo quit | $QEMU -nographic -hda "$TEST_IMG" -incoming 'exec:true' -snapshot -serial none -monitor stdio | - _filter_qemu | _filter_hmp + +if test "$IMGOPTSSYNTAX" = "true" +then + SYSEMU_DRIVE_ARG=if=none,$TEST_IMG + SYSEMU_EXTRA_ARGS="" + if [ -n "$IMGKEYSECRET" ]; then + SECRET_ARG="secret,id=keysec0,data=$IMGKEYSECRET" + SYSEMU_EXTRA_ARGS="-object $SECRET_ARG" + fi +else + SYSEMU_DRIVE_ARG=if=none,file="$TEST_IMG",driver=$IMGFMT + SYSEMU_EXTRA_ARGS="" +fi + +echo quit | $QEMU -nographic $SYSEMU_EXTRA_ARGS -drive $SYSEMU_DRIVE_ARG \ + -incoming 'exec:true' -snapshot -serial none -monitor stdio \ + | _filter_qemu | _filter_hmp # success, all done echo "*** done" diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 index 84072513db..223cd68ad5 100755 --- a/tests/qemu-iotests/149 +++ b/tests/qemu-iotests/149 @@ -136,6 +136,7 @@ def cryptsetup_add_password(config, slot): args = ["luksAddKey", config.image_path(), "--key-slot", slot, "--key-file", "-", + "--iter-time", "10", pwfile] cryptsetup(args, password) @@ -164,6 +165,7 @@ def cryptsetup_format(config): args.extend(["--hash", config.hash]) args.extend(["--key-slot", slot]) args.extend(["--key-file", "-"]) + args.extend(["--iter-time", "10"]) args.append(config.image_path()) cryptsetup(args, password) @@ -184,7 +186,7 @@ def chown(config): msg = proc.communicate()[0] if proc.returncode != 0: - raise Exception("Cannot change owner on %s" % path) + raise Exception(msg) def cryptsetup_open(config): @@ -230,6 +232,7 @@ def qemu_img_create(config, size_mb): opts = [ "key-secret=sec0", + "iter-time=10", "cipher-alg=%s-%d" % (config.cipher, config.keylen), "cipher-mode=%s" % config.mode, "ivgen-alg=%s" % config.ivgen, @@ -268,6 +271,8 @@ def qemu_io_image_args(config, dev=False): def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False): """Write a pattern of data to a LUKS image or device""" + if dev: + chown(config) args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)] args.extend(qemu_io_image_args(config, dev)) iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir]) @@ -278,6 +283,8 @@ def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False): def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False): """Read a pattern of data to a LUKS image or device""" + if dev: + chown(config) args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)] args.extend(qemu_io_image_args(config, dev)) iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir]) @@ -328,9 +335,6 @@ def test_once(config, qemu_img=False): cryptsetup_open(config) try: - iotests.log("# Set dev owner") - chown(config) - iotests.log("# Write test pattern 0xa7") qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True) iotests.log("# Write test pattern 0x13") @@ -362,9 +366,6 @@ def test_once(config, qemu_img=False): cryptsetup_open(config) try: - iotests.log("# Set dev owner") - chown(config) - iotests.log("# Read test pattern 0x91") qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True) iotests.log("# Read test pattern 0x5e") @@ -454,8 +455,12 @@ configs = [ # LUKS default but diff hash + LUKSConfig("aes-256-xts-plain64-sha224", + "aes", 256, "xts", "plain64", None, "sha224"), LUKSConfig("aes-256-xts-plain64-sha256", "aes", 256, "xts", "plain64", None, "sha256"), + LUKSConfig("aes-256-xts-plain64-sha384", + "aes", 256, "xts", "plain64", None, "sha384"), LUKSConfig("aes-256-xts-plain64-sha512", "aes", 256, "xts", "plain64", None, "sha512"), LUKSConfig("aes-256-xts-plain64-ripemd160", @@ -501,12 +506,6 @@ blacklist = [ # GCrypt doesn't support Twofish with 192 bit key "twofish-192-xts-plain64-sha1", - - # We don't have sha512 hash wired up yet - "aes-256-xts-plain64-sha512", - - # We don't have ripemd160 hash wired up yet - "aes-256-xts-plain64-ripemd160", ] whitelist = [] diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out index 90b5b55efb..5dea00bfa8 100644 --- a/tests/qemu-iotests/149.out +++ b/tests/qemu-iotests/149.out @@ -2,17 +2,17 @@ # Create image truncate TEST_DIR/luks-aes-256-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -41,14 +41,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -60,19 +60,19 @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img # ================= qemu-img aes-256-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -101,14 +101,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -122,17 +122,17 @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img # Create image truncate TEST_DIR/luks-twofish-256-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-256-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -161,14 +161,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -180,19 +180,19 @@ unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img # ================= qemu-img twofish-256-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=twofish-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -221,14 +221,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -242,17 +242,17 @@ unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img # Create image truncate TEST_DIR/luks-serpent-256-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-256-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -281,14 +281,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -300,19 +300,19 @@ unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img # ================= qemu-img serpent-256-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -341,14 +341,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -362,17 +362,17 @@ unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img # Create image truncate TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -401,14 +401,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -420,19 +420,19 @@ unlink TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img # ================= qemu-img cast5-128-cbc-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=cast5-128,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=cast5-128 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=cast5-128,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=cast5-128 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -461,14 +461,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -483,17 +483,17 @@ Skipping cast6-256-xts-plain64-sha1 in blacklist # Create image truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -522,14 +522,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -541,19 +541,19 @@ unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img # ================= qemu-img aes-256-cbc-plain-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -582,14 +582,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -603,17 +603,17 @@ unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img # Create image truncate TEST_DIR/luks-aes-256-cbc-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -642,14 +642,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -661,19 +661,19 @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img # ================= qemu-img aes-256-cbc-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -702,14 +702,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -723,17 +723,17 @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img # Create image truncate TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -762,14 +762,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -781,19 +781,19 @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img # ================= qemu-img aes-256-cbc-essiv-sha256-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -822,14 +822,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -843,17 +843,17 @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img # Create image truncate TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -882,14 +882,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -901,19 +901,19 @@ unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img # ================= qemu-img aes-256-xts-essiv-sha256-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -942,14 +942,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -963,17 +963,17 @@ unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img # Create image truncate TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1002,14 +1002,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1021,19 +1021,19 @@ unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img # ================= qemu-img aes-128-xts-plain64-sha256-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1062,14 +1062,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1083,17 +1083,17 @@ unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img # Create image truncate TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1122,14 +1122,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1141,19 +1141,19 @@ unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img # ================= qemu-img aes-192-xts-plain64-sha256-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1182,14 +1182,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1203,17 +1203,17 @@ unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img # Create image truncate TEST_DIR/luks-twofish-128-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-128-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1242,14 +1242,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1261,19 +1261,19 @@ unlink TEST_DIR/luks-twofish-128-xts-plain64-sha1.img # ================= qemu-img twofish-128-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=twofish-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1302,14 +1302,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1324,17 +1324,17 @@ Skipping twofish-192-xts-plain64-sha1 in blacklist # Create image truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-128-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1363,14 +1363,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1382,19 +1382,19 @@ unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img # ================= qemu-img serpent-128-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1423,14 +1423,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1444,17 +1444,17 @@ unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img # Create image truncate TEST_DIR/luks-serpent-192-xts-plain64-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-192-xts-plain64-sha1.img +sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1483,14 +1483,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1502,19 +1502,19 @@ unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img # ================= qemu-img serpent-192-xts-plain64-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img 4194304M -Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img 4194304M +Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1543,14 +1543,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1562,21 +1562,141 @@ unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img Skipping cast6-128-xts-plain64-sha1 in blacklist Skipping cast6-192-xts-plain64-sha1 in blacklist +# ================= dm-crypt aes-256-xts-plain64-sha224 ================= +# Create image +truncate TEST_DIR/luks-aes-256-xts-plain64-sha224.img --size 4194304MB +# Format image +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha224 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha224.img +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha224.img + +# ================= qemu-img aes-256-xts-plain64-sha224 ================= +# Create image +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha224 TEST_DIR/luks-aes-256-xts-plain64-sha224.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha224.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha224 iter-time=10 + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha224.img + # ================= dm-crypt aes-256-xts-plain64-sha256 ================= # Create image truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha256.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha256.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1605,14 +1725,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1624,19 +1744,19 @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img # ================= qemu-img aes-256-xts-plain64-sha256 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha256 TEST_DIR/luks-aes-256-xts-plain64-sha256.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha256 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha256 TEST_DIR/luks-aes-256-xts-plain64-sha256.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha256 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1665,14 +1785,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1682,23 +1802,381 @@ sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256 # Delete image unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img -Skipping aes-256-xts-plain64-sha512 in blacklist -Skipping aes-256-xts-plain64-ripemd160 in blacklist +# ================= dm-crypt aes-256-xts-plain64-sha384 ================= +# Create image +truncate TEST_DIR/luks-aes-256-xts-plain64-sha384.img --size 4194304MB +# Format image +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha384 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha384.img +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha384.img + +# ================= qemu-img aes-256-xts-plain64-sha384 ================= +# Create image +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha384 TEST_DIR/luks-aes-256-xts-plain64-sha384.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha384.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha384 iter-time=10 + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha384.img + +# ================= dm-crypt aes-256-xts-plain64-sha512 ================= +# Create image +truncate TEST_DIR/luks-aes-256-xts-plain64-sha512.img --size 4194304MB +# Format image +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha512 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha512.img +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha512.img + +# ================= qemu-img aes-256-xts-plain64-sha512 ================= +# Create image +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha512 TEST_DIR/luks-aes-256-xts-plain64-sha512.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha512.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha512 iter-time=10 + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-sha512.img + +# ================= dm-crypt aes-256-xts-plain64-ripemd160 ================= +# Create image +truncate TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img --size 4194304MB +# Format image +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash ripemd160 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img + +# ================= qemu-img aes-256-xts-plain64-ripemd160 ================= +# Create image +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=ripemd160 TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=ripemd160 iter-time=10 + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160 +# Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160 +# Read test pattern 0xa7 +qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x13 +qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x91 +qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +wrote 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Write test pattern 0x5e +qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img +wrote 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Open dev +sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160 +# Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +read 10485760/10485760 bytes at offset 104857600 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160 +read 10485760/10485760 bytes at offset 3298534883328 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +# Close dev +sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160 +# Delete image +unlink TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img + # ================= dm-crypt aes-256-xts-plain-sha1-pwslot3 ================= # Create image truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1727,14 +2205,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1748,31 +2226,31 @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img # Create image truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img +sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img # Add password slot 1 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 1 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 1 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 2 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 2 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 2 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 3 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 3 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 3 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 4 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 4 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 4 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 5 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 5 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 5 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 6 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 6 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 6 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Add password slot 7 -sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - TEST_DIR/passwd.txt +sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - --iter-time 10 TEST_DIR/passwd.txt # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1801,14 +2279,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1820,19 +2298,19 @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img # ================= qemu-img aes-256-xts-plain-sha1-pwallslots ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=c2xvdDE=,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=c2xvdDE=,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1861,14 +2339,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1882,17 +2360,17 @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img # Create image truncate TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1921,14 +2399,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1940,19 +2418,19 @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img # ================= qemu-img aes-256-cbc-essiv-auto-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -1981,14 +2459,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2002,17 +2480,17 @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img # Create image truncate TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img --size 4194304MB # Format image -sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img +sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2041,14 +2519,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2060,19 +2538,19 @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img # ================= qemu-img aes-256-cbc-plain64-sha256-sha1 ================= # Create image -qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img 4194304M -Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 ivgen-hash-alg=sha256 hash-alg=sha1 +qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img 4194304M +Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 # Write test pattern 0xa7 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Write test pattern 0x13 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 wrote 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -2101,14 +2579,14 @@ wrote 10485760/10485760 bytes at offset 3298534883328 # Open dev sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1 -# Set dev owner -sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 # Read test pattern 0x91 +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 104857600 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Read test pattern 0x5e +sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1 read 10485760/10485760 bytes at offset 3298534883328 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/157 b/tests/qemu-iotests/157 index 8d939cb747..2bf02be465 100755 --- a/tests/qemu-iotests/157 +++ b/tests/qemu-iotests/157 @@ -43,7 +43,6 @@ _supported_os Linux function do_run_qemu() { - echo Testing: "$@" ( if ! test -t 0; then while read cmd; do @@ -63,7 +62,18 @@ function run_qemu() size=128M -drive="if=none,file=$TEST_IMG,driver=$IMGFMT" +if test "$IMGOPTSSYNTAX" = "true" +then + SYSEMU_DRIVE_ARG=if=none,$TEST_IMG + SYSEMU_EXTRA_ARGS="" + if [ -n "$IMGKEYSECRET" ]; then + SECRET_ARG="secret,id=keysec0,data=$IMGKEYSECRET" + SYSEMU_EXTRA_ARGS="-object $SECRET_ARG" + fi +else + SYSEMU_DRIVE_ARG=if=none,file="$TEST_IMG",driver=$IMGFMT + SYSEMU_EXTRA_ARGS="" +fi _make_test_img $size @@ -76,8 +86,9 @@ echo for cache in "writeback" "writethrough"; do for wce in "" ",write-cache=auto" ",write-cache=on" ",write-cache=off"; do + echo "Testing: cache='$cache' wce='$wce'" echo "info block" \ - | run_qemu -drive "$drive,cache=$cache" \ + | run_qemu $SYSEMU_EXTRA_ARGS -drive "$SYSEMU_DRIVE_ARG,cache=$cache" \ -device "virtio-blk,drive=none0$wce" \ | grep -e "Testing" -e "Cache mode" done diff --git a/tests/qemu-iotests/157.out b/tests/qemu-iotests/157.out index 77a9c03d2c..fdc807f541 100644 --- a/tests/qemu-iotests/157.out +++ b/tests/qemu-iotests/157.out @@ -3,20 +3,20 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === Setting WCE with qdev and with manually created BB === -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0 +Testing: cache='writeback' wce='' Cache mode: writeback -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=auto +Testing: cache='writeback' wce=',write-cache=auto' Cache mode: writeback -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=on +Testing: cache='writeback' wce=',write-cache=on' Cache mode: writeback -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=off +Testing: cache='writeback' wce=',write-cache=off' Cache mode: writethrough -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0 +Testing: cache='writethrough' wce='' Cache mode: writethrough -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=auto +Testing: cache='writethrough' wce=',write-cache=auto' Cache mode: writethrough -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=on +Testing: cache='writethrough' wce=',write-cache=on' Cache mode: writeback -Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=off +Testing: cache='writethrough' wce=',write-cache=off' Cache mode: writethrough *** done diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158 index ef8d70f109..823c12002e 100755 --- a/tests/qemu-iotests/158 +++ b/tests/qemu-iotests/158 @@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt qcow2 +_supported_fmt qcow qcow2 _supported_proto generic _unsupported_proto vxhs _supported_os Linux @@ -45,34 +45,39 @@ _supported_os Linux size=128M TEST_IMG_BASE=$TEST_IMG.base +SECRET="secret,id=sec0,data=astrochicken" TEST_IMG_SAVE=$TEST_IMG TEST_IMG=$TEST_IMG_BASE echo "== create base ==" -IMGOPTS="encryption=on" _make_test_img $size +_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" $size TEST_IMG=$TEST_IMG_SAVE +IMGSPECBASE="driver=$IMGFMT,file.filename=$TEST_IMG_BASE,encrypt.key-secret=sec0" +IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,backing.driver=$IMGFMT,backing.file.filename=$TEST_IMG_BASE,backing.encrypt.key-secret=sec0,encrypt.key-secret=sec0" +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + echo echo "== writing whole image ==" -echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo echo "== verify pattern ==" -echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo "== create overlay ==" -IMGOPTS="encryption=on" _make_test_img -b "$TEST_IMG_BASE" $size +_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size echo echo "== writing part of a cluster ==" -echo "astrochicken" | $QEMU_IO -c "write -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "write -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir echo echo "== verify pattern ==" -echo "astrochicken" | $QEMU_IO -c "read -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "read -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir echo echo "== verify pattern ==" -echo "astrochicken" | $QEMU_IO -c "read -P 0xa 1024 64512" "$TEST_IMG" | _filter_qemu_io | _filter_testdir +$QEMU_IO --object $SECRET -c "read -P 0xa 1024 64512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir # success, all done diff --git a/tests/qemu-iotests/158.out b/tests/qemu-iotests/158.out index b3f37e28ef..6def216e55 100644 --- a/tests/qemu-iotests/158.out +++ b/tests/qemu-iotests/158.out @@ -1,36 +1,26 @@ QA output created by 158 == create base == -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0 == writing whole image == -Disk image 'TEST_DIR/t.qcow2.base' is encrypted. -password: wrote 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == verify pattern == -Disk image 'TEST_DIR/t.qcow2.base' is encrypted. -password: read 134217728/134217728 bytes at offset 0 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == create overlay == -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on encrypt.key-secret=sec0 == writing part of a cluster == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: wrote 1024/1024 bytes at offset 0 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == verify pattern == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: read 1024/1024 bytes at offset 0 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == verify pattern == -Disk image 'TEST_DIR/t.qcow2' is encrypted. -password: read 64512/64512 bytes at offset 1024 63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159 index 825f05fab8..9b0e1ecc90 100755 --- a/tests/qemu-iotests/159 +++ b/tests/qemu-iotests/159 @@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt generic _supported_proto file _supported_os Linux +_unsupported_fmt luks TEST_SIZES="5 512 1024 1999 1K 64K 1M" diff --git a/tests/qemu-iotests/165 b/tests/qemu-iotests/165 new file mode 100755 index 0000000000..74d7b79a0b --- /dev/null +++ b/tests/qemu-iotests/165 @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# +# Tests for persistent dirty bitmaps. +# +# Copyright: Vladimir Sementsov-Ogievskiy 2015-2017 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import os +import re +import iotests +from iotests import qemu_img + +disk = os.path.join(iotests.test_dir, 'disk') +disk_size = 0x40000000 # 1G + +# regions for qemu_io: (start, count) in bytes +regions1 = ((0, 0x100000), + (0x200000, 0x100000)) + +regions2 = ((0x10000000, 0x20000), + (0x3fff0000, 0x10000)) + +class TestPersistentDirtyBitmap(iotests.QMPTestCase): + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, disk, str(disk_size)) + + def tearDown(self): + os.remove(disk) + + def mkVm(self): + return iotests.VM().add_drive(disk) + + def mkVmRo(self): + return iotests.VM().add_drive(disk, opts='readonly=on') + + def getSha256(self): + result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap0') + return result['return']['sha256'] + + def checkBitmap(self, sha256): + result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap0') + self.assert_qmp(result, 'return/sha256', sha256); + + def writeRegions(self, regions): + for r in regions: + self.vm.hmp_qemu_io('drive0', + 'write %d %d' % r) + + def qmpAddBitmap(self): + self.vm.qmp('block-dirty-bitmap-add', node='drive0', + name='bitmap0', persistent=True, autoload=True) + + def test_persistent(self): + self.vm = self.mkVm() + self.vm.launch() + self.qmpAddBitmap() + + self.writeRegions(regions1) + sha256 = self.getSha256() + + self.vm.shutdown() + + self.vm = self.mkVmRo() + self.vm.launch() + self.vm.shutdown() + + #catch 'Persistent bitmaps are lost' possible error + log = self.vm.get_log() + log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log) + log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log) + if log: + print log + + self.vm = self.mkVm() + self.vm.launch() + + self.checkBitmap(sha256) + self.writeRegions(regions2) + sha256 = self.getSha256() + + self.vm.shutdown() + self.vm.launch() + + self.checkBitmap(sha256) + + self.vm.shutdown() + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2']) diff --git a/tests/qemu-iotests/165.out b/tests/qemu-iotests/165.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/165.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170 index 5b335dbc3e..b79359fc4e 100755 --- a/tests/qemu-iotests/170 +++ b/tests/qemu-iotests/170 @@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt generic _supported_proto file _supported_os Linux +_unsupported_fmt luks echo echo "== Creating image ==" diff --git a/tests/qemu-iotests/171 b/tests/qemu-iotests/171 index 257be10a0e..bcfaaf1be2 100755 --- a/tests/qemu-iotests/171 +++ b/tests/qemu-iotests/171 @@ -45,15 +45,15 @@ _supported_os Linux # Create JSON with options img_json() { - echo -n 'json:{"driver":"raw", ' - echo -n "\"offset\":\"$img_offset\", " + printf %s 'json:{"driver":"raw", ' + printf %s "\"offset\":\"$img_offset\", " if [ "$img_size" -ne -1 ] ; then - echo -n "\"size\":\"$img_size\", " + printf %s "\"size\":\"$img_size\", " fi - echo -n '"file": {' - echo -n '"driver":"file", ' - echo -n "\"filename\":\"$TEST_IMG\" " - echo -n "} }" + printf %s '"file": {' + printf %s '"driver":"file", ' + printf %s "\"filename\":\"$TEST_IMG\" " + printf %s "} }" } do_general_test() { diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174 index c1c20a1a57..552879db32 100755 --- a/tests/qemu-iotests/174 +++ b/tests/qemu-iotests/174 @@ -41,7 +41,7 @@ _unsupported_fmt raw size=256K -IMGFMT=raw IMGOPTS= _make_test_img $size | _filter_imgfmt +IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img $size | _filter_imgfmt echo echo "== reading wrong format should fail ==" diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178 new file mode 100755 index 0000000000..6af52c653a --- /dev/null +++ b/tests/qemu-iotests/178 @@ -0,0 +1,170 @@ +#!/bin/bash +# +# qemu-img measure sub-command tests +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=stefanha@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f "$TEST_IMG.converted" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.pattern + +_supported_fmt raw qcow2 +_supported_proto file +_supported_os Linux + +echo "== Input validation ==" +echo + +_make_test_img 1G + +$QEMU_IMG measure # missing arguments +$QEMU_IMG measure --size 2G "$TEST_IMG" # only one allowed +$QEMU_IMG measure "$TEST_IMG" a # only one filename allowed +$QEMU_IMG measure --object secret,id=sec0,data=MTIzNDU2,format=base64 # missing filename +$QEMU_IMG measure --image-opts # missing filename +$QEMU_IMG measure -f qcow2 # missing filename +$QEMU_IMG measure -l snap1 # missing filename +$QEMU_IMG measure -o , # invalid option list +$QEMU_IMG measure -l snapshot.foo # invalid snapshot option +$QEMU_IMG measure --output foo # invalid output format +$QEMU_IMG measure --size -1 # invalid image size +$QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format + +make_test_img_with_fmt() { + # Shadow global variables within this function + local IMGFMT="$1" IMGOPTS="" + _make_test_img "$2" +} + +qemu_io_with_fmt() { + # Shadow global variables within this function + local QEMU_IO_OPTIONS=$(echo "$QEMU_IO_OPTIONS" | sed "s/-f $IMGFMT/-f $1/") + shift + $QEMU_IO "$@" +} + +# The proof is in the pudding: converted image size cannot be larger than the +# required size. +# +# Note: if a change to the image format code causes the file size to change, +# then this test fails! This is good because it's a reminder to check that the +# required size is still at least as big as the actual converted file size. +convert_and_show_size() { + local fmt="$1" + shift + $QEMU_IMG convert -f "$fmt" -O "$IMGFMT" "$TEST_IMG" "$@" "$TEST_IMG.converted" + stat -c "converted image file size in bytes: %s" "$TEST_IMG.converted" +} + +for ofmt in human json; do + echo + echo "== Size calculation for a new file ($ofmt) ==" + echo + + # Try a few interesting sizes + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 0 + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 2G + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 64G + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 256G + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 1T + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 2P + $QEMU_IMG measure --output=$ofmt -O "$IMGFMT" --size 7E + + # Always test the raw input files but also IMGFMT + for fmt in $(echo -e "raw\n$IMGFMT\n" | sort -u); do + echo + echo "== Empty $fmt input image ($ofmt) ==" + echo + make_test_img_with_fmt "$fmt" 0 + $QEMU_IMG measure --output=$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" + + echo + echo "== $fmt input image with data ($ofmt) ==" + echo + make_test_img_with_fmt "$fmt" 1G + $QEMU_IMG measure --output=$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + qemu_io_with_fmt "$fmt" -c "write 512 512" "$TEST_IMG" | _filter_qemu_io + qemu_io_with_fmt "$fmt" -c "write 64K 64K" "$TEST_IMG" | _filter_qemu_io + if [ "$fmt" = "qcow2" ]; then + $QEMU_IMG snapshot -c snapshot1 "$TEST_IMG" + fi + qemu_io_with_fmt "$fmt" -c "write 128M 63K" "$TEST_IMG" | _filter_qemu_io + $QEMU_IMG measure --output=$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" + + if [ "$fmt" = "qcow2" ]; then + echo + echo "== $fmt input image with internal snapshot ($ofmt) ==" + echo + $QEMU_IMG measure --output=$ofmt -f "$fmt" -l snapshot1 \ + -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" -l snapshot1 + fi + + if [ "$IMGFMT" = "qcow2" ]; then + echo + echo "== $fmt input image and a backing file ($ofmt) ==" + echo + # The backing file doesn't need to exist :) + $QEMU_IMG measure --output=$ofmt -o backing_file=x \ + -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + fi + + echo + echo "== $fmt input image and preallocation ($ofmt) ==" + echo + $QEMU_IMG measure --output=$ofmt -o preallocation=full \ + -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" -o preallocation=full + + echo + echo "== Fully-allocated $fmt input image ($ofmt) ==" + echo + make_test_img_with_fmt "$fmt" 8M + qemu_io_with_fmt "$fmt" -c "write 0 8M" "$TEST_IMG" | _filter_qemu_io + $QEMU_IMG measure --output=$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" + done +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 new file mode 100644 index 0000000000..d42d4a4597 --- /dev/null +++ b/tests/qemu-iotests/178.out.qcow2 @@ -0,0 +1,286 @@ +QA output created by 178 +== Input validation == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +qemu-img: Either --size N or one filename must be specified. +qemu-img: --size N cannot be used together with a filename. +qemu-img: At most one filename argument is allowed. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: Invalid option list: , +qemu-img: Invalid parameter 'snapshot.foo' +qemu-img: Failed in parsing snapshot param 'snapshot.foo' +qemu-img: --output must be used with human or json as argument. +qemu-img: Image size must be less than 8 EiB! +qemu-img: Unknown file format 'foo' + +== Size calculation for a new file (human) == + +required size: 196608 +fully allocated size: 196608 +required size: 589824 +fully allocated size: 2148073472 +required size: 10747904 +fully allocated size: 68730224640 +required size: 42205184 +fully allocated size: 274920112128 +required size: 168034304 +fully allocated size: 1099679662080 +required size: 343650009088 +fully allocated size: 2252143463694336 +qemu-img: The image size is too large (try using a larger cluster size) + +== Empty qcow2 input image (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +required size: 196608 +fully allocated size: 196608 + +converted image file size in bytes: 196608 + +== qcow2 input image with data (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +required size: 393216 +fully allocated size: 1074135040 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 589824 +fully allocated size: 1074135040 + +converted image file size in bytes: 524288 + +== qcow2 input image with internal snapshot (human) == + +required size: 524288 +fully allocated size: 1074135040 + +converted image file size in bytes: 458752 + +== qcow2 input image and a backing file (human) == + +required size: 1074135040 +fully allocated size: 1074135040 + +== qcow2 input image and preallocation (human) == + +required size: 1074135040 +fully allocated size: 1074135040 + +converted image file size in bytes: 1074135040 + +== Fully-allocated qcow2 input image (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8716288 +fully allocated size: 8716288 + +converted image file size in bytes: 8716288 + +== Empty raw input image (human) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=0 +required size: 196608 +fully allocated size: 196608 + +converted image file size in bytes: 196608 + +== raw input image with data (human) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 +required size: 393216 +fully allocated size: 1074135040 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 589824 +fully allocated size: 1074135040 + +converted image file size in bytes: 524288 + +== raw input image and a backing file (human) == + +required size: 1074135040 +fully allocated size: 1074135040 + +== raw input image and preallocation (human) == + +required size: 1074135040 +fully allocated size: 1074135040 + +converted image file size in bytes: 1074135040 + +== Fully-allocated raw input image (human) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8716288 +fully allocated size: 8716288 + +converted image file size in bytes: 8716288 + +== Size calculation for a new file (json) == + +{ + "required": 196608, + "fully-allocated": 196608 +} +{ + "required": 589824, + "fully-allocated": 2148073472 +} +{ + "required": 10747904, + "fully-allocated": 68730224640 +} +{ + "required": 42205184, + "fully-allocated": 274920112128 +} +{ + "required": 168034304, + "fully-allocated": 1099679662080 +} +{ + "required": 343650009088, + "fully-allocated": 2252143463694336 +} +qemu-img: The image size is too large (try using a larger cluster size) + +== Empty qcow2 input image (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +{ + "required": 196608, + "fully-allocated": 196608 +} + +converted image file size in bytes: 196608 + +== qcow2 input image with data (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +{ + "required": 393216, + "fully-allocated": 1074135040 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 589824, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 524288 + +== qcow2 input image with internal snapshot (json) == + +{ + "required": 524288, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 458752 + +== qcow2 input image and a backing file (json) == + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +== qcow2 input image and preallocation (json) == + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 1074135040 + +== Fully-allocated qcow2 input image (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8716288, + "fully-allocated": 8716288 +} + +converted image file size in bytes: 8716288 + +== Empty raw input image (json) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=0 +{ + "required": 196608, + "fully-allocated": 196608 +} + +converted image file size in bytes: 196608 + +== raw input image with data (json) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 +{ + "required": 393216, + "fully-allocated": 1074135040 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 589824, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 524288 + +== raw input image and a backing file (json) == + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +== raw input image and preallocation (json) == + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 1074135040 + +== Fully-allocated raw input image (json) == + +Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8716288, + "fully-allocated": 8716288 +} + +converted image file size in bytes: 8716288 +*** done diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw new file mode 100644 index 0000000000..6478365905 --- /dev/null +++ b/tests/qemu-iotests/178.out.raw @@ -0,0 +1,158 @@ +QA output created by 178 +== Input validation == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +qemu-img: Either --size N or one filename must be specified. +qemu-img: --size N cannot be used together with a filename. +qemu-img: At most one filename argument is allowed. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: Invalid option list: , +qemu-img: Invalid parameter 'snapshot.foo' +qemu-img: Failed in parsing snapshot param 'snapshot.foo' +qemu-img: --output must be used with human or json as argument. +qemu-img: Image size must be less than 8 EiB! +qemu-img: Unknown file format 'foo' + +== Size calculation for a new file (human) == + +required size: 0 +fully allocated size: 0 +required size: 2147483648 +fully allocated size: 2147483648 +required size: 68719476736 +fully allocated size: 68719476736 +required size: 274877906944 +fully allocated size: 274877906944 +required size: 1099511627776 +fully allocated size: 1099511627776 +required size: 2251799813685248 +fully allocated size: 2251799813685248 +required size: 8070450532247928832 +fully allocated size: 8070450532247928832 + +== Empty raw input image (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +required size: 0 +fully allocated size: 0 + +converted image file size in bytes: 0 + +== raw input image with data (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +required size: 1073741824 +fully allocated size: 1073741824 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 1073741824 +fully allocated size: 1073741824 + +converted image file size in bytes: 1073741824 + +== raw input image and preallocation (human) == + +required size: 1073741824 +fully allocated size: 1073741824 + +converted image file size in bytes: 1073741824 + +== Fully-allocated raw input image (human) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8388608 +fully allocated size: 8388608 + +converted image file size in bytes: 8388608 + +== Size calculation for a new file (json) == + +{ + "required": 0, + "fully-allocated": 0 +} +{ + "required": 2147483648, + "fully-allocated": 2147483648 +} +{ + "required": 68719476736, + "fully-allocated": 68719476736 +} +{ + "required": 274877906944, + "fully-allocated": 274877906944 +} +{ + "required": 1099511627776, + "fully-allocated": 1099511627776 +} +{ + "required": 2251799813685248, + "fully-allocated": 2251799813685248 +} +{ + "required": 8070450532247928832, + "fully-allocated": 8070450532247928832 +} + +== Empty raw input image (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 +{ + "required": 0, + "fully-allocated": 0 +} + +converted image file size in bytes: 0 + +== raw input image with data (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} + +converted image file size in bytes: 1073741824 + +== raw input image and preallocation (json) == + +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} + +converted image file size in bytes: 1073741824 + +== Fully-allocated raw input image (json) == + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8388608, + "fully-allocated": 8388608 +} + +converted image file size in bytes: 8388608 +*** done diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181 index e969a2a94f..0333dda0e3 100755 --- a/tests/qemu-iotests/181 +++ b/tests/qemu-iotests/181 @@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.qemu _supported_fmt generic +# Formats that do not support live migration +_unsupported_fmt qcow vdi vhdx vmdk vpc vvfat _supported_proto generic _supported_os Linux @@ -55,13 +57,24 @@ echo qemu_comm_method="monitor" -_launch_qemu \ - -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk +if [ "$IMGOPTSSYNTAX" = "true" ]; then + _launch_qemu \ + -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk +else + _launch_qemu \ + -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk +fi src=$QEMU_HANDLE -_launch_qemu \ - -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \ - -incoming "unix:${MIG_SOCKET}" +if [ "$IMGOPTSSYNTAX" = "true" ]; then + _launch_qemu \ + -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk \ + -incoming "unix:${MIG_SOCKET}" +else + _launch_qemu \ + -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \ + -incoming "unix:${MIG_SOCKET}" +fi dest=$QEMU_HANDLE echo diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out index 45bc7cb1a5..57eaf8d699 100644 --- a/tests/qemu-iotests/185.out +++ b/tests/qemu-iotests/185.out @@ -7,12 +7,12 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 === Creating backing chain === -Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} wrote 4194304/4194304 bytes at offset 0 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} -Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} === Start commit job and exit qemu === @@ -33,7 +33,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q === Start mirror job and exit qemu === {"return": {}} -Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} @@ -42,7 +42,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off clust === Start backup job and exit qemu === {"return": {}} -Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 +Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188 new file mode 100755 index 0000000000..83ed03e33e --- /dev/null +++ b/tests/qemu-iotests/188 @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Test encrypted read/write using plain bdrv_read/bdrv_write +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=berrange@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + + +size=16M + +SECRET="secret,id=sec0,data=astrochicken" +SECRETALT="secret,id=sec0,data=platypus" + +_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size + +IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" + +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + +echo +echo "== reading whole image ==" +$QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + +echo +echo "== rewriting whole image ==" +$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + +echo +echo "== verify pattern ==" +$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + +echo +echo "== verify open failure with wrong password ==" +$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out new file mode 100644 index 0000000000..8af24e5d8b --- /dev/null +++ b/tests/qemu-iotests/188.out @@ -0,0 +1,18 @@ +QA output created by 188 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 + +== reading whole image == +read 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== rewriting whole image == +wrote 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify pattern == +read 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify open failure with wrong password == +can't open: Invalid password, cannot unlock any keyslot +*** done diff --git a/tests/qemu-iotests/189 b/tests/qemu-iotests/189 new file mode 100755 index 0000000000..54ad980a4e --- /dev/null +++ b/tests/qemu-iotests/189 @@ -0,0 +1,86 @@ +#!/bin/bash +# +# Test encrypted read/write using backing files +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=berrange@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + + +size=16M +TEST_IMG_BASE=$TEST_IMG.base +SECRET0="secret,id=sec0,data=astrochicken" +SECRET1="secret,id=sec1,data=furby" + +TEST_IMG_SAVE=$TEST_IMG +TEST_IMG=$TEST_IMG_BASE +echo "== create base ==" +_make_test_img --object $SECRET0 -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size +TEST_IMG=$TEST_IMG_SAVE + +IMGSPECBASE="driver=$IMGFMT,file.filename=$TEST_IMG_BASE,encrypt.key-secret=sec0" +IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,backing.driver=$IMGFMT,backing.file.filename=$TEST_IMG_BASE,backing.encrypt.key-secret=sec0,encrypt.key-secret=sec1" +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + +echo +echo "== writing whole image ==" +$QEMU_IO --object $SECRET0 -c "write -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir + +echo +echo "== verify pattern ==" +$QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir + +echo "== create overlay ==" +_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -b "$TEST_IMG_BASE" $size + +echo +echo "== writing part of a cluster ==" +$QEMU_IO --object $SECRET0 --object $SECRET1 -c "write -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + +echo +echo "== verify pattern ==" +$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir +echo +echo "== verify pattern ==" +$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0xa 1024 64512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir + + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/189.out b/tests/qemu-iotests/189.out new file mode 100644 index 0000000000..a0b7c9c24c --- /dev/null +++ b/tests/qemu-iotests/189.out @@ -0,0 +1,26 @@ +QA output created by 189 +== create base == +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 + +== writing whole image == +wrote 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify pattern == +read 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== create overlay == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base encrypt.format=luks encrypt.key-secret=sec1 encrypt.iter-time=10 + +== writing part of a cluster == +wrote 1024/1024 bytes at offset 0 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify pattern == +read 1024/1024 bytes at offset 0 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify pattern == +read 64512/64512 bytes at offset 1024 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 4b1c6749b7..2a55ec9ada 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -141,7 +141,7 @@ _wallclock() _timestamp() { now=`date "+%T"` - echo -n " [$now]" + printf %s " [$now]" } _wrapup() @@ -255,7 +255,7 @@ seq="check" for seq in $list do err=false - echo -n "$seq" + printf %s "$seq" if [ -n "$TESTS_REMAINING_LOG" ] ; then sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG @@ -281,9 +281,9 @@ do rm -f $seq.out.bad lasttime=`sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE` if [ "X$lasttime" != X ]; then - echo -n " ${lasttime}s ..." + printf %s " ${lasttime}s ..." else - echo -n " " # prettier output with timestamps. + printf " " # prettier output with timestamps. fi rm -f core $seq.notrun @@ -291,7 +291,7 @@ do echo "$seq" > "${TEST_DIR}"/check.sts start=`_wallclock` - $timestamp && echo -n " ["`date "+%T"`"]" + $timestamp && printf %s " [$(date "+%T")]" if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then run_command="$PYTHON $seq" @@ -314,21 +314,21 @@ do if [ -f core ] then - echo -n " [dumped core]" + printf " [dumped core]" mv core $seq.core err=true fi if [ -f $seq.notrun ] then - $timestamp || echo -n " [not run] " - $timestamp && echo " [not run]" && echo -n " $seq -- " + $timestamp || printf " [not run] " + $timestamp && echo " [not run]" && printf %s " $seq -- " cat $seq.notrun notrun="$notrun $seq" else if [ $sts -ne 0 ] then - echo -n " [failed, exit status $sts]" + printf %s " [failed, exit status $sts]" err=true fi @@ -338,6 +338,11 @@ do reference="$reference_machine" fi + reference_format="$source_iotests/$seq.out.$IMGFMT" + if [ -f "$reference_format" ]; then + reference="$reference_format" + fi + if [ "$CACHEMODE" = "none" ]; then [ -f "$source_iotests/$seq.out.nocache" ] && reference="$source_iotests/$seq.out.nocache" fi diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index f2a7199c4b..d34c11c056 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -50,6 +50,7 @@ export IMGPROTO=file export IMGOPTS="" export CACHEMODE="writeback" export QEMU_IO_OPTIONS="" +export QEMU_IO_OPTIONS_NO_FMT="" export CACHEMODE_IS_DEFAULT=true export QEMU_OPTIONS="-nodefaults -machine accel=qtest" export VALGRIND_QEMU= @@ -413,10 +414,11 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \ done # Set qemu-io cache mode with $CACHEMODE we have -if [ "$IMGOPTSSYNTAX" = "true" ]; then - QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE" -else - QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE" +QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE" + +QEMU_IO_OPTIONS_NO_FMT="$QEMU_IO_OPTIONS" +if [ "$IMGOPTSSYNTAX" != "true" ]; then + QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT" fi # Set default options for qemu-img create -o if they were not specified diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index d1b45f5447..e0883a0c65 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -103,6 +103,17 @@ if [ -z "$QEMU_VXHS_PROG" ]; then export QEMU_VXHS_PROG="`set_prog_path qnio_server`" fi +export QEMU_PROG=$(realpath -- "$(type -p "$QEMU_PROG")") +export QEMU_IMG_PROG=$(realpath -- "$(type -p "$QEMU_IMG_PROG")") +export QEMU_IO_PROG=$(realpath -- "$(type -p "$QEMU_IO_PROG")") +export QEMU_NBD_PROG=$(realpath -- "$(type -p "$QEMU_NBD_PROG")") + +# This program is not built as part of qemu but (possibly) provided by the +# system, so it may not be present at all +if [ -n "$QEMU_VXHS_PROG" ]; then + export QEMU_VXHS_PROG=$(realpath -- "$(type -p "$QEMU_VXHS_PROG")") +fi + _qemu_wrapper() { ( diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 2f595b2ce2..7a58e57317 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -126,7 +126,8 @@ _filter_img_create() -e "s# block_state_zero=\\(on\\|off\\)##g" \ -e "s# log_size=[0-9]\\+##g" \ -e "s# refcount_bits=[0-9]\\+##g" \ - -e "s# key-secret=[a-zA-Z0-9]\\+##g" + -e "s# key-secret=[a-zA-Z0-9]\\+##g" \ + -e "s# iter-time=[0-9]\\+##g" } _filter_img_info() diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu index 76ef298d3f..7645f1dc72 100644 --- a/tests/qemu-iotests/common.qemu +++ b/tests/qemu-iotests/common.qemu @@ -153,14 +153,19 @@ function _launch_qemu() mkfifo "${fifo_out}" mkfifo "${fifo_in}" + object_options= + if [ -n "$IMGKEYSECRET" ]; then + object_options="--object secret,id=keysec0,data=$IMGKEYSECRET" + fi + if [ -z "$keep_stderr" ]; then QEMU_NEED_PID='y'\ - ${QEMU} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \ + ${QEMU} ${object_options} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \ 2>&1 \ <"${fifo_in}" & elif [ "$keep_stderr" = "y" ]; then QEMU_NEED_PID='y'\ - ${QEMU} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \ + ${QEMU} ${object_options} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \ <"${fifo_in}" & else exit 1 diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 9fd3130bde..2548e58b99 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -107,6 +107,9 @@ _set_default_imgopts() if [ "$IMGFMT" == "qcow2" ] && ! (echo "$IMGOPTS" | grep "compat=" > /dev/null); then IMGOPTS=$(_optstr_add "$IMGOPTS" "compat=1.1") fi + if [ "$IMGFMT" == "luks" ] && ! (echo "$IMGOPTS" | grep "iter-time=" > /dev/null); then + IMGOPTS=$(_optstr_add "$IMGOPTS" "iter-time=10") + fi } _use_sample_img() diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 318ae74b10..2aba585287 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -112,6 +112,7 @@ 103 rw auto quick 104 rw auto 105 rw auto quick +106 rw auto quick 107 rw auto quick 108 rw auto quick 109 rw auto @@ -130,6 +131,8 @@ 122 rw auto 123 rw auto quick 124 rw auto backing +125 rw auto +126 rw auto backing 128 rw auto quick 129 rw auto quick 130 rw auto quick @@ -163,6 +166,7 @@ 159 rw auto quick 160 rw auto quick 162 auto quick +165 rw auto quick 170 rw auto quick 171 rw auto quick 172 auto @@ -171,8 +175,11 @@ 175 auto quick 176 rw auto backing 177 rw auto quick +178 auto quick 179 rw auto quick 181 rw auto migration 182 rw auto quick 183 rw auto migration 185 rw auto +188 rw auto quick +189 rw auto quick diff --git a/tests/rocker/all b/tests/rocker/all index d5ae9632a2..3f9b786daf 100755 --- a/tests/rocker/all +++ b/tests/rocker/all @@ -1,19 +1,19 @@ -echo -n "Running port test... " +printf "Running port test... " ./port if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi -echo -n "Running bridge test... " +printf "Running bridge test... " ./bridge if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi -echo -n "Running bridge STP test... " +printf "Running bridge STP test... " ./bridge-stp if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi -echo -n "Running bridge VLAN test... " +printf "Running bridge VLAN test... " ./bridge-vlan if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi -echo -n "Running bridge VLAN STP test... " +printf "Running bridge VLAN STP test... " ./bridge-vlan-stp if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile index 6b3dba446c..664b30ce81 100644 --- a/tests/tcg/cris/Makefile +++ b/tests/tcg/cris/Makefile @@ -150,17 +150,17 @@ check_addcv17.tst: crtv10.o sysv10.o build: $(CRT) $(SYS) $(TESTCASES) check: $(CRT) $(SYS) $(TESTCASES) - @echo -e "\nQEMU simulator." + @printf "\nQEMU simulator.\n" for case in $(TESTCASES); do \ - echo -n "$$case "; \ + printf %s "$$case "; \ SIMARGS=; \ case $$case in *v17*) SIMARGS="-cpu crisv17";; esac; \ $(SIM) $$SIMARGS ./$$case; \ done check-g: $(CRT) $(SYS) $(TESTCASES) - @echo -e "\nGDB simulator." + @printf "\nGDB simulator.\n" @for case in $(TESTCASES); do \ - echo -n "$$case "; \ + printf %s "$$case "; \ $(SIMG) $$case; \ done diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c index 95c4bd5da3..bd7fe593e3 100644 --- a/tests/test-crypto-block.c +++ b/tests/test-crypto-block.c @@ -281,7 +281,7 @@ static void test_block(gconstpointer opaque) memset(&header, 0, sizeof(header)); buffer_init(&header, "header"); - blk = qcrypto_block_create(data->create_opts, + blk = qcrypto_block_create(data->create_opts, NULL, test_block_init_func, test_block_write_func, &header, @@ -300,7 +300,7 @@ static void test_block(gconstpointer opaque) object_unparent(sec); /* Ensure we can't open without the secret */ - blk = qcrypto_block_open(data->open_opts, + blk = qcrypto_block_open(data->open_opts, NULL, test_block_read_func, &header, 0, @@ -308,7 +308,7 @@ static void test_block(gconstpointer opaque) g_assert(blk == NULL); /* Ensure we can't open without the secret, unless NO_IO */ - blk = qcrypto_block_open(data->open_opts, + blk = qcrypto_block_open(data->open_opts, NULL, test_block_read_func, &header, QCRYPTO_BLOCK_OPEN_NO_IO, @@ -322,7 +322,7 @@ static void test_block(gconstpointer opaque) /* Now open for real with secret */ sec = test_block_secret(); - blk = qcrypto_block_open(data->open_opts, + blk = qcrypto_block_open(data->open_opts, NULL, test_block_read_func, &header, 0, diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c index 23773d2051..1acb353889 100644 --- a/tests/test-hbitmap.c +++ b/tests/test-hbitmap.c @@ -909,6 +909,22 @@ static void hbitmap_test_add(const char *testpath, hbitmap_test_teardown); } +static void test_hbitmap_iter_and_reset(TestHBitmapData *data, + const void *unused) +{ + HBitmapIter hbi; + + hbitmap_test_init(data, L1 * 2, 0); + hbitmap_set(data->hb, 0, data->size); + + hbitmap_iter_init(&hbi, data->hb, BITS_PER_LONG - 1); + + hbitmap_iter_next(&hbi); + + hbitmap_reset_all(data->hb); + hbitmap_iter_next(&hbi); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -966,6 +982,9 @@ int main(int argc, char **argv) test_hbitmap_serialize_part); hbitmap_test_add("/hbitmap/serialize/zeroes", test_hbitmap_serialize_zeroes); + + hbitmap_test_add("/hbitmap/iter/iter_and_reset", + test_hbitmap_iter_and_reset); g_test_run(); return 0; diff --git a/trace/control-target.c b/trace/control-target.c index 6266e6380d..99a8ed5157 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -1,7 +1,7 @@ /* * Interface for configuring and controlling the state of tracing events. * - * Copyright (C) 2014-2016 Lluís Vilanova <vilanova@ac.upc.edu> + * Copyright (C) 2014-2017 Lluís Vilanova <vilanova@ac.upc.edu> * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -38,12 +38,16 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state) { CPUState *vcpu; assert(trace_event_get_state_static(ev)); - if (trace_event_is_vcpu(ev)) { + if (trace_event_is_vcpu(ev) && likely(first_cpu != NULL)) { CPU_FOREACH(vcpu) { trace_event_set_vcpu_state_dynamic(vcpu, ev, state); } } else { - /* Without the "vcpu" property, dstate can only be 1 or 0 */ + /* + * Without the "vcpu" property, dstate can only be 1 or 0. With it, we + * haven't instantiated any vCPU yet, so we will set a global state + * instead, and trace_init_vcpu will reconcile it afterwards. + */ bool state_pre = *ev->dstate; if (state_pre != state) { if (state) { diff --git a/util/hbitmap.c b/util/hbitmap.c index 35088e19c4..21535cc90b 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -13,6 +13,7 @@ #include "qemu/hbitmap.h" #include "qemu/host-utils.h" #include "trace.h" +#include "crypto/hash.h" /* HBitmaps provides an array of bits. The bits are stored as usual in an * array of unsigned longs, but HBitmap is also optimized to provide fast @@ -106,8 +107,9 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) unsigned long cur; do { - cur = hbi->cur[--i]; + i--; pos >>= BITS_PER_LEVEL; + cur = hbi->cur[i] & hb->levels[i][pos]; } while (cur == 0); /* Check for end of iteration. We always use fewer than BITS_PER_LONG @@ -139,6 +141,26 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) return cur; } +int64_t hbitmap_iter_next(HBitmapIter *hbi) +{ + unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1] & + hbi->hb->levels[HBITMAP_LEVELS - 1][hbi->pos]; + int64_t item; + + if (cur == 0) { + cur = hbitmap_iter_skip_words(hbi); + if (cur == 0) { + return -1; + } + } + + /* The next call will resume work from the next bit. */ + hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); + item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); + + return item << hbi->granularity; +} + void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first) { unsigned i, bit; @@ -530,6 +552,23 @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count, } } +void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count, + bool finish) +{ + uint64_t el_count; + unsigned long *first; + + if (!count) { + return; + } + serialization_chunk(hb, start, count, &first, &el_count); + + memset(first, 0xff, el_count * sizeof(unsigned long)); + if (finish) { + hbitmap_deserialize_finish(hb); + } +} + void hbitmap_deserialize_finish(HBitmap *bitmap) { int64_t i, size, prev_size; @@ -689,3 +728,13 @@ void hbitmap_free_meta(HBitmap *hb) hbitmap_free(hb->meta); hb->meta = NULL; } + +char *hbitmap_sha256(const HBitmap *bitmap, Error **errp) +{ + size_t size = bitmap->sizes[HBITMAP_LEVELS - 1] * sizeof(unsigned long); + char *data = (char *)bitmap->levels[HBITMAP_LEVELS - 1]; + char *hash = NULL; + qcrypto_hash_digest(QCRYPTO_HASH_ALG_SHA256, data, size, &hash, errp); + + return hash; +} diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 5e8b4b39ed..b2dea48f40 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -414,72 +414,6 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } -static struct termios oldtty; - -static void term_exit(void) -{ - tcsetattr(0, TCSANOW, &oldtty); -} - -static void term_init(void) -{ - struct termios tty; - - tcgetattr(0, &tty); - oldtty = tty; - - tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP - |INLCR|IGNCR|ICRNL|IXON); - tty.c_oflag |= OPOST; - tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); - tty.c_cflag &= ~(CSIZE|PARENB); - tty.c_cflag |= CS8; - tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 0; - - tcsetattr(0, TCSANOW, &tty); - - atexit(term_exit); -} - -int qemu_read_password(char *buf, int buf_size) -{ - uint8_t ch; - int i, ret; - - printf("password: "); - fflush(stdout); - term_init(); - i = 0; - for (;;) { - ret = read(0, &ch, 1); - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) { - continue; - } else { - break; - } - } else if (ret == 0) { - ret = -1; - break; - } else { - if (ch == '\r' || - ch == '\n') { - ret = 0; - break; - } - if (i < (buf_size - 1)) { - buf[i++] = ch; - } - } - } - term_exit(); - buf[i] = '\0'; - printf("\n"); - return ret; -} - - char *qemu_get_pid_name(pid_t pid) { char *name = NULL; diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 3de9e7777e..69a6286d50 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -552,30 +552,6 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } -/* XXX: put correct support for win32 */ -int qemu_read_password(char *buf, int buf_size) -{ - int c, i; - - printf("Password: "); - fflush(stdout); - i = 0; - for (;;) { - c = getchar(); - if (c < 0) { - buf[i] = '\0'; - return -1; - } else if (c == '\n') { - break; - } else if (i < (buf_size - 1)) { - buf[i++] = c; - } - } - buf[i] = '\0'; - return 0; -} - - char *qemu_get_pid_name(pid_t pid) { /* XXX Implement me */ @@ -3962,7 +3962,7 @@ int main(int argc, char **argv, char **envp) * * "-global migration.only-migratable=true" */ - migration_only_migratable_set(); + qemu_global_option("migration.only-migratable=true"); break; case QEMU_OPTION_nodefaults: has_defaults = 0; @@ -4418,6 +4418,18 @@ int main(int argc, char **argv, char **envp) configure_accelerator(current_machine); + /* + * Register all the global properties, including accel properties, + * machine properties, and user-specified ones. + */ + register_global_properties(current_machine); + + /* + * Migration object can only be created after global properties + * are applied correctly. + */ + migration_object_init(); + if (qtest_chrdev) { qtest_init(qtest_chrdev, qtest_log, &error_fatal); } @@ -4601,18 +4613,6 @@ int main(int argc, char **argv, char **envp) exit (i == 1 ? 1 : 0); } - /* - * Register all the global properties, including accel properties, - * machine properties, and user-specified ones. - */ - register_global_properties(current_machine); - - /* - * Migration object can only be created after global properties - * are applied correctly. - */ - migration_object_init(); - /* This checkpoint is required by replay to separate prior clock reading from the other reads, because timer polling functions query clock values from the log. */ |