mirror of
https://github.com/qemu/qemu.git
synced 2025-08-09 10:25:06 +00:00
Block patches for 5.1:
- LUKS keyslot amendment (+ patches to make the iotests pass on non-Linux systems, and to keep the tests passing for qcow v1, and to skip LUKS tests (including qcow2 LUKS) when the built qemu does not support it) - Refactoring in the block layer: Drop the basically unnecessary unallocated_blocks_are_zero field from BlockDriverInfo - Fix qcow2 preallocation when the image size is not a multiple of the cluster size - Fix in block-copy code -----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl8C9s0SHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9AgMsH/A3fe7F6w1eaVQWoU/ABNwJahWzv5oNG 7s/rsYqHdr7GQldbfsZS8zrca2zY5jNRopfoTEmrCLFFUbHcXZNQzZObh2JZ892p EfjHfHMqAC6e0ZnvKWgWPyRMGnsh7+H5U3EXiob9F4+YXC3SQRqzuwg0K9Tmk2uE CpB/zBxI5BcYdEA/VD5uJxle6H49JdUXO64oDxTwMaJZuJKoiBGWX0iBhGeZEjcm gPX5LuwVoc80HZquVqTGik3hwrlESYAwGN1GaicibHUR0f4CFrxFDxyEd3bZ8fGO 9+ScuO0vZmUDSal2tHjRsbKmcEdwtpI8JHn3tDdLljRoDOHrssMq2P4= =v33H -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-07-06' into staging Block patches for 5.1: - LUKS keyslot amendment (+ patches to make the iotests pass on non-Linux systems, and to keep the tests passing for qcow v1, and to skip LUKS tests (including qcow2 LUKS) when the built qemu does not support it) - Refactoring in the block layer: Drop the basically unnecessary unallocated_blocks_are_zero field from BlockDriverInfo - Fix qcow2 preallocation when the image size is not a multiple of the cluster size - Fix in block-copy code # gpg: Signature made Mon 06 Jul 2020 11:02:53 BST # gpg: using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40 # gpg: issuer "mreitz@redhat.com" # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full] # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * remotes/maxreitz/tags/pull-block-2020-07-06: (31 commits) qed: Simplify backing reads block: drop unallocated_blocks_are_zero block/vhdx: drop unallocated_blocks_are_zero block/file-posix: drop unallocated_blocks_are_zero block/iscsi: drop unallocated_blocks_are_zero block/crypto: drop unallocated_blocks_are_zero block/vpc: return ZERO block-status when appropriate block/vdi: return ZERO block-status when appropriate block: inline bdrv_unallocated_blocks_are_zero() qemu-img: convert: don't use unallocated_blocks_are_zero iotests: add tests for blockdev-amend block/qcow2: implement blockdev-amend block/crypto: implement blockdev-amend block/core: add generic infrastructure for x-blockdev-amend qmp command iotests: qemu-img tests for luks key management block/qcow2: extend qemu-img amend interface with crypto options block/crypto: implement the encryption key management block/crypto: rename two functions block/amend: refactor qcow2 amend options block/amend: separate amend and create options for qemu-img ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
eb2c66b10e
19
block.c
19
block.c
@ -5408,21 +5408,6 @@ int bdrv_has_zero_init(BlockDriverState *bs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
BlockDriverInfo bdi;
|
|
||||||
|
|
||||||
if (bs->backing) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bdrv_get_info(bs, &bdi) == 0) {
|
|
||||||
return bdi.unallocated_blocks_are_zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
|
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
||||||
@ -6482,6 +6467,7 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
|
|||||||
|
|
||||||
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||||
|
bool force,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (!bs->drv) {
|
if (!bs->drv) {
|
||||||
@ -6493,7 +6479,8 @@ int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
bs->drv->format_name);
|
bs->drv->format_name);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque, errp);
|
return bs->drv->bdrv_amend_options(bs, opts, status_cb,
|
||||||
|
cb_opaque, force, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -19,7 +19,7 @@ block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
|
|||||||
block-obj-$(CONFIG_POSIX) += file-posix.o
|
block-obj-$(CONFIG_POSIX) += file-posix.o
|
||||||
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
||||||
block-obj-$(CONFIG_LINUX_IO_URING) += io_uring.o
|
block-obj-$(CONFIG_LINUX_IO_URING) += io_uring.o
|
||||||
block-obj-y += null.o mirror.o commit.o io.o create.o
|
block-obj-y += null.o mirror.o commit.o io.o create.o amend.o
|
||||||
block-obj-y += throttle-groups.o
|
block-obj-y += throttle-groups.o
|
||||||
block-obj-$(CONFIG_LINUX) += nvme.o
|
block-obj-$(CONFIG_LINUX) += nvme.o
|
||||||
|
|
||||||
|
113
block/amend.c
Normal file
113
block/amend.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Block layer code related to image options amend
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
|
||||||
|
* Copyright (c) 2020 Red Hat. Inc
|
||||||
|
*
|
||||||
|
* Heavily based on create.c
|
||||||
|
*
|
||||||
|
* 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 "block/block_int.h"
|
||||||
|
#include "qemu/job.h"
|
||||||
|
#include "qemu/main-loop.h"
|
||||||
|
#include "qapi/qapi-commands-block-core.h"
|
||||||
|
#include "qapi/qapi-visit-block-core.h"
|
||||||
|
#include "qapi/clone-visitor.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
typedef struct BlockdevAmendJob {
|
||||||
|
Job common;
|
||||||
|
BlockdevAmendOptions *opts;
|
||||||
|
BlockDriverState *bs;
|
||||||
|
bool force;
|
||||||
|
} BlockdevAmendJob;
|
||||||
|
|
||||||
|
static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
|
||||||
|
{
|
||||||
|
BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
job_progress_set_remaining(&s->common, 1);
|
||||||
|
ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp);
|
||||||
|
job_progress_update(&s->common, 1);
|
||||||
|
qapi_free_BlockdevAmendOptions(s->opts);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JobDriver blockdev_amend_job_driver = {
|
||||||
|
.instance_size = sizeof(BlockdevAmendJob),
|
||||||
|
.job_type = JOB_TYPE_AMEND,
|
||||||
|
.run = blockdev_amend_run,
|
||||||
|
};
|
||||||
|
|
||||||
|
void qmp_x_blockdev_amend(const char *job_id,
|
||||||
|
const char *node_name,
|
||||||
|
BlockdevAmendOptions *options,
|
||||||
|
bool has_force,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockdevAmendJob *s;
|
||||||
|
const char *fmt = BlockdevDriver_str(options->driver);
|
||||||
|
BlockDriver *drv = bdrv_find_format(fmt);
|
||||||
|
BlockDriverState *bs = bdrv_find_node(node_name);
|
||||||
|
|
||||||
|
|
||||||
|
if (!drv) {
|
||||||
|
error_setg(errp, "Block driver '%s' not found or not supported", fmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the driver is in the schema, we know that it exists. But it may not
|
||||||
|
* be whitelisted.
|
||||||
|
*/
|
||||||
|
if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
|
||||||
|
error_setg(errp, "Driver is not whitelisted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->drv != drv) {
|
||||||
|
error_setg(errp,
|
||||||
|
"x-blockdev-amend doesn't support changing the block driver");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error out if the driver doesn't support .bdrv_co_amend */
|
||||||
|
if (!drv->bdrv_co_amend) {
|
||||||
|
error_setg(errp, "Driver does not support x-blockdev-amend");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the block job */
|
||||||
|
s = job_create(job_id, &blockdev_amend_job_driver, NULL,
|
||||||
|
bdrv_get_aio_context(bs), JOB_DEFAULT | JOB_MANUAL_DISMISS,
|
||||||
|
NULL, NULL, errp);
|
||||||
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->bs = bs,
|
||||||
|
s->opts = QAPI_CLONE(BlockdevAmendOptions, options),
|
||||||
|
s->force = has_force ? force : false;
|
||||||
|
job_start(&s->common);
|
||||||
|
}
|
@ -622,8 +622,10 @@ out:
|
|||||||
* block_copy_task_run. If it fails, it means some task already failed
|
* block_copy_task_run. If it fails, it means some task already failed
|
||||||
* for real reason, let's return first failure.
|
* for real reason, let's return first failure.
|
||||||
* Still, assert that we don't rewrite failure by success.
|
* Still, assert that we don't rewrite failure by success.
|
||||||
|
*
|
||||||
|
* Note: ret may be positive here because of block-status result.
|
||||||
*/
|
*/
|
||||||
assert(ret == 0 || aio_task_pool_status(aio) < 0);
|
assert(ret >= 0 || aio_task_pool_status(aio) < 0);
|
||||||
ret = aio_task_pool_status(aio);
|
ret = aio_task_pool_status(aio);
|
||||||
|
|
||||||
aio_task_pool_free(aio);
|
aio_task_pool_free(aio);
|
||||||
|
207
block/crypto.c
207
block/crypto.c
@ -37,6 +37,7 @@ typedef struct BlockCrypto BlockCrypto;
|
|||||||
|
|
||||||
struct BlockCrypto {
|
struct BlockCrypto {
|
||||||
QCryptoBlock *block;
|
QCryptoBlock *block;
|
||||||
|
bool updating_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -71,6 +72,24 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t block_crypto_write_func(QCryptoBlock *block,
|
||||||
|
size_t offset,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t buflen,
|
||||||
|
void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs = opaque;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
ret = bdrv_pwrite(bs->file, offset, buf, buflen);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not write encryption header");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct BlockCryptoCreateData {
|
struct BlockCryptoCreateData {
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
@ -79,12 +98,12 @@ struct BlockCryptoCreateData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static ssize_t block_crypto_write_func(QCryptoBlock *block,
|
static ssize_t block_crypto_create_write_func(QCryptoBlock *block,
|
||||||
size_t offset,
|
size_t offset,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
size_t buflen,
|
size_t buflen,
|
||||||
void *opaque,
|
void *opaque,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
struct BlockCryptoCreateData *data = opaque;
|
struct BlockCryptoCreateData *data = opaque;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
@ -97,11 +116,10 @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t block_crypto_create_init_func(QCryptoBlock *block,
|
||||||
static ssize_t block_crypto_init_func(QCryptoBlock *block,
|
size_t headerlen,
|
||||||
size_t headerlen,
|
void *opaque,
|
||||||
void *opaque,
|
Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
struct BlockCryptoCreateData *data = opaque;
|
struct BlockCryptoCreateData *data = opaque;
|
||||||
Error *local_error = NULL;
|
Error *local_error = NULL;
|
||||||
@ -167,6 +185,19 @@ static QemuOptsList block_crypto_create_opts_luks = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static QemuOptsList block_crypto_amend_opts_luks = {
|
||||||
|
.name = "crypto",
|
||||||
|
.head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
|
||||||
|
.desc = {
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(""),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(""),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(""),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(""),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
|
||||||
|
{ /* end of list */ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
QCryptoBlockOpenOptions *
|
QCryptoBlockOpenOptions *
|
||||||
block_crypto_open_opts_init(QDict *opts, Error **errp)
|
block_crypto_open_opts_init(QDict *opts, Error **errp)
|
||||||
{
|
{
|
||||||
@ -202,6 +233,23 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCryptoBlockAmendOptions *
|
||||||
|
block_crypto_amend_opts_init(QDict *opts, Error **errp)
|
||||||
|
{
|
||||||
|
Visitor *v;
|
||||||
|
QCryptoBlockAmendOptions *ret;
|
||||||
|
|
||||||
|
v = qobject_input_visitor_new_flat_confused(opts, errp);
|
||||||
|
if (!v) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_type_QCryptoBlockAmendOptions(v, NULL, &ret, errp);
|
||||||
|
|
||||||
|
visit_free(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int block_crypto_open_generic(QCryptoBlockFormat format,
|
static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
QemuOptsList *opts_spec,
|
QemuOptsList *opts_spec,
|
||||||
@ -296,8 +344,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
|
|||||||
};
|
};
|
||||||
|
|
||||||
crypto = qcrypto_block_create(opts, NULL,
|
crypto = qcrypto_block_create(opts, NULL,
|
||||||
block_crypto_init_func,
|
block_crypto_create_init_func,
|
||||||
block_crypto_write_func,
|
block_crypto_create_write_func,
|
||||||
&data,
|
&data,
|
||||||
errp);
|
errp);
|
||||||
|
|
||||||
@ -710,7 +758,6 @@ static int block_crypto_get_info_luks(BlockDriverState *bs,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdi->unallocated_blocks_are_zero = false;
|
|
||||||
bdi->cluster_size = subbdi.cluster_size;
|
bdi->cluster_size = subbdi.cluster_size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -742,6 +789,131 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
|
|||||||
return spec_info;
|
return spec_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
block_crypto_amend_options_generic_luks(BlockDriverState *bs,
|
||||||
|
QCryptoBlockAmendOptions *amend_options,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockCrypto *crypto = bs->opaque;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(crypto);
|
||||||
|
assert(crypto->block);
|
||||||
|
|
||||||
|
/* apply for exclusive read/write permissions to the underlying file*/
|
||||||
|
crypto->updating_keys = true;
|
||||||
|
ret = bdrv_child_refresh_perms(bs, bs->file, errp);
|
||||||
|
if (ret) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qcrypto_block_amend_options(crypto->block,
|
||||||
|
block_crypto_read_func,
|
||||||
|
block_crypto_write_func,
|
||||||
|
bs,
|
||||||
|
amend_options,
|
||||||
|
force,
|
||||||
|
errp);
|
||||||
|
cleanup:
|
||||||
|
/* release exclusive read/write permissions to the underlying file*/
|
||||||
|
crypto->updating_keys = false;
|
||||||
|
bdrv_child_refresh_perms(bs, bs->file, errp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
block_crypto_amend_options_luks(BlockDriverState *bs,
|
||||||
|
QemuOpts *opts,
|
||||||
|
BlockDriverAmendStatusCB *status_cb,
|
||||||
|
void *cb_opaque,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockCrypto *crypto = bs->opaque;
|
||||||
|
QDict *cryptoopts = NULL;
|
||||||
|
QCryptoBlockAmendOptions *amend_options = NULL;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
assert(crypto);
|
||||||
|
assert(crypto->block);
|
||||||
|
|
||||||
|
cryptoopts = qemu_opts_to_qdict(opts, NULL);
|
||||||
|
qdict_put_str(cryptoopts, "format", "luks");
|
||||||
|
amend_options = block_crypto_amend_opts_init(cryptoopts, errp);
|
||||||
|
qobject_unref(cryptoopts);
|
||||||
|
if (!amend_options) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ret = block_crypto_amend_options_generic_luks(bs, amend_options,
|
||||||
|
force, errp);
|
||||||
|
cleanup:
|
||||||
|
qapi_free_QCryptoBlockAmendOptions(amend_options);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
coroutine_fn block_crypto_co_amend_luks(BlockDriverState *bs,
|
||||||
|
BlockdevAmendOptions *opts,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockAmendOptions amend_opts;
|
||||||
|
|
||||||
|
amend_opts = (QCryptoBlockAmendOptions) {
|
||||||
|
.format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
|
||||||
|
.u.luks = *qapi_BlockdevAmendOptionsLUKS_base(&opts->u.luks),
|
||||||
|
};
|
||||||
|
return block_crypto_amend_options_generic_luks(bs, &amend_opts,
|
||||||
|
force, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
block_crypto_child_perms(BlockDriverState *bs, BdrvChild *c,
|
||||||
|
const BdrvChildRole role,
|
||||||
|
BlockReopenQueue *reopen_queue,
|
||||||
|
uint64_t perm, uint64_t shared,
|
||||||
|
uint64_t *nperm, uint64_t *nshared)
|
||||||
|
{
|
||||||
|
|
||||||
|
BlockCrypto *crypto = bs->opaque;
|
||||||
|
|
||||||
|
bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm, nshared);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For backward compatibility, manually share the write
|
||||||
|
* and resize permission
|
||||||
|
*/
|
||||||
|
*nshared |= (BLK_PERM_WRITE | BLK_PERM_RESIZE);
|
||||||
|
/*
|
||||||
|
* Since we are not fully a format driver, don't always request
|
||||||
|
* the read/resize permission but only when explicitly
|
||||||
|
* requested
|
||||||
|
*/
|
||||||
|
*nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
|
||||||
|
*nperm |= perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This driver doesn't modify LUKS metadata except
|
||||||
|
* when updating the encryption slots.
|
||||||
|
* Thus unlike a proper format driver we don't ask for
|
||||||
|
* shared write/read permission. However we need it
|
||||||
|
* when we are updating the keys, to ensure that only we
|
||||||
|
* have access to the device.
|
||||||
|
*
|
||||||
|
* Encryption update will set the crypto->updating_keys
|
||||||
|
* during that period and refresh permissions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (crypto->updating_keys) {
|
||||||
|
/* need exclusive write access for header update */
|
||||||
|
*nperm |= BLK_PERM_WRITE;
|
||||||
|
/* unshare read and write permission */
|
||||||
|
*nshared &= ~(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *const block_crypto_strong_runtime_opts[] = {
|
static const char *const block_crypto_strong_runtime_opts[] = {
|
||||||
BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
|
BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
|
||||||
|
|
||||||
@ -754,13 +926,12 @@ static BlockDriver bdrv_crypto_luks = {
|
|||||||
.bdrv_probe = block_crypto_probe_luks,
|
.bdrv_probe = block_crypto_probe_luks,
|
||||||
.bdrv_open = block_crypto_open_luks,
|
.bdrv_open = block_crypto_open_luks,
|
||||||
.bdrv_close = block_crypto_close,
|
.bdrv_close = block_crypto_close,
|
||||||
/* This driver doesn't modify LUKS metadata except when creating image.
|
.bdrv_child_perm = block_crypto_child_perms,
|
||||||
* Allow share-rw=on as a special case. */
|
|
||||||
.bdrv_child_perm = bdrv_default_perms,
|
|
||||||
.bdrv_co_create = block_crypto_co_create_luks,
|
.bdrv_co_create = block_crypto_co_create_luks,
|
||||||
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
|
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
|
||||||
.bdrv_co_truncate = block_crypto_co_truncate,
|
.bdrv_co_truncate = block_crypto_co_truncate,
|
||||||
.create_opts = &block_crypto_create_opts_luks,
|
.create_opts = &block_crypto_create_opts_luks,
|
||||||
|
.amend_opts = &block_crypto_amend_opts_luks,
|
||||||
|
|
||||||
.bdrv_reopen_prepare = block_crypto_reopen_prepare,
|
.bdrv_reopen_prepare = block_crypto_reopen_prepare,
|
||||||
.bdrv_refresh_limits = block_crypto_refresh_limits,
|
.bdrv_refresh_limits = block_crypto_refresh_limits,
|
||||||
@ -770,6 +941,8 @@ static BlockDriver bdrv_crypto_luks = {
|
|||||||
.bdrv_measure = block_crypto_measure,
|
.bdrv_measure = block_crypto_measure,
|
||||||
.bdrv_get_info = block_crypto_get_info_luks,
|
.bdrv_get_info = block_crypto_get_info_luks,
|
||||||
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
|
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
|
||||||
|
.bdrv_amend_options = block_crypto_amend_options_luks,
|
||||||
|
.bdrv_co_amend = block_crypto_co_amend_luks,
|
||||||
|
|
||||||
.is_format = true,
|
.is_format = true,
|
||||||
|
|
||||||
|
@ -41,6 +41,11 @@
|
|||||||
#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-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_HASH_ALG "hash-alg"
|
||||||
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
|
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
|
||||||
|
#define BLOCK_CRYPTO_OPT_LUKS_KEYSLOT "keyslot"
|
||||||
|
#define BLOCK_CRYPTO_OPT_LUKS_STATE "state"
|
||||||
|
#define BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET "old-secret"
|
||||||
|
#define BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET "new-secret"
|
||||||
|
|
||||||
|
|
||||||
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
|
||||||
BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
|
BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
|
||||||
@ -88,9 +93,41 @@
|
|||||||
.help = "Time to spend in PBKDF in milliseconds", \
|
.help = "Time to spend in PBKDF in milliseconds", \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(prefix) \
|
||||||
|
{ \
|
||||||
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_STATE, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Select new state of affected keyslots (active/inactive)",\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(prefix) \
|
||||||
|
{ \
|
||||||
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_KEYSLOT, \
|
||||||
|
.type = QEMU_OPT_NUMBER, \
|
||||||
|
.help = "Select a single keyslot to modify explicitly",\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(prefix) \
|
||||||
|
{ \
|
||||||
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Select all keyslots that match this password", \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(prefix) \
|
||||||
|
{ \
|
||||||
|
.name = prefix BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "New secret to set in the matching keyslots. " \
|
||||||
|
"Empty string to erase", \
|
||||||
|
}
|
||||||
|
|
||||||
QCryptoBlockCreateOptions *
|
QCryptoBlockCreateOptions *
|
||||||
block_crypto_create_opts_init(QDict *opts, Error **errp);
|
block_crypto_create_opts_init(QDict *opts, Error **errp);
|
||||||
|
|
||||||
|
QCryptoBlockAmendOptions *
|
||||||
|
block_crypto_amend_opts_init(QDict *opts, Error **errp);
|
||||||
|
|
||||||
QCryptoBlockOpenOptions *
|
QCryptoBlockOpenOptions *
|
||||||
block_crypto_open_opts_init(QDict *opts, Error **errp);
|
block_crypto_open_opts_init(QDict *opts, Error **errp);
|
||||||
|
|
||||||
|
@ -2878,9 +2878,6 @@ static int coroutine_fn raw_co_pwrite_zeroes(
|
|||||||
|
|
||||||
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
|
||||||
|
|
||||||
bdi->unallocated_blocks_are_zero = s->discard_zeroes;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2406,16 +2406,16 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
|||||||
|
|
||||||
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
|
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
|
||||||
ret |= BDRV_BLOCK_ALLOCATED;
|
ret |= BDRV_BLOCK_ALLOCATED;
|
||||||
} else if (want_zero) {
|
} else if (want_zero && bs->drv->supports_backing) {
|
||||||
if (bdrv_unallocated_blocks_are_zero(bs)) {
|
if (bs->backing) {
|
||||||
ret |= BDRV_BLOCK_ZERO;
|
|
||||||
} else if (bs->backing) {
|
|
||||||
BlockDriverState *bs2 = bs->backing->bs;
|
BlockDriverState *bs2 = bs->backing->bs;
|
||||||
int64_t size2 = bdrv_getlength(bs2);
|
int64_t size2 = bdrv_getlength(bs2);
|
||||||
|
|
||||||
if (size2 >= 0 && offset >= size2) {
|
if (size2 >= 0 && offset >= size2) {
|
||||||
ret |= BDRV_BLOCK_ZERO;
|
ret |= BDRV_BLOCK_ZERO;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ret |= BDRV_BLOCK_ZERO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2163,7 +2163,6 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||||
{
|
{
|
||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
bdi->unallocated_blocks_are_zero = iscsilun->lbprz;
|
|
||||||
bdi->cluster_size = iscsilun->cluster_size;
|
bdi->cluster_size = iscsilun->cluster_size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
354
block/qcow2.c
354
block/qcow2.c
@ -176,6 +176,19 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QDict*
|
||||||
|
qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp)
|
||||||
|
{
|
||||||
|
QDict *cryptoopts_qdict;
|
||||||
|
QDict *opts_qdict;
|
||||||
|
|
||||||
|
/* Extract "encrypt." options into a qdict */
|
||||||
|
opts_qdict = qemu_opts_to_qdict(opts, NULL);
|
||||||
|
qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
|
||||||
|
qobject_unref(opts_qdict);
|
||||||
|
qdict_put_str(cryptoopts_qdict, "format", fmt);
|
||||||
|
return cryptoopts_qdict;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read qcow2 extension and fill bs
|
* read qcow2 extension and fill bs
|
||||||
@ -3042,17 +3055,6 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
|
|||||||
return qcow2_update_header(bs);
|
return qcow2_update_header(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,
|
static int qcow2_set_up_encryption(BlockDriverState *bs,
|
||||||
QCryptoBlockCreateOptions *cryptoopts,
|
QCryptoBlockCreateOptions *cryptoopts,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
@ -4239,8 +4241,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
|
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
|
nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) -
|
||||||
s->cluster_size);
|
start_of_cluster(s, old_length)) >> s->cluster_bits;
|
||||||
|
|
||||||
/* This is an overestimation; we will not actually allocate space for
|
/* This is an overestimation; we will not actually allocate space for
|
||||||
* these in the file but just make sure the new refcount structures are
|
* these in the file but just make sure the new refcount structures are
|
||||||
@ -4317,10 +4319,21 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
int64_t nb_clusters = MIN(
|
int64_t nb_clusters = MIN(
|
||||||
nb_new_data_clusters,
|
nb_new_data_clusters,
|
||||||
s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
|
s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
|
||||||
QCowL2Meta allocation = {
|
unsigned cow_start_length = offset_into_cluster(s, guest_offset);
|
||||||
|
QCowL2Meta allocation;
|
||||||
|
guest_offset = start_of_cluster(s, guest_offset);
|
||||||
|
allocation = (QCowL2Meta) {
|
||||||
.offset = guest_offset,
|
.offset = guest_offset,
|
||||||
.alloc_offset = host_offset,
|
.alloc_offset = host_offset,
|
||||||
.nb_clusters = nb_clusters,
|
.nb_clusters = nb_clusters,
|
||||||
|
.cow_start = {
|
||||||
|
.offset = 0,
|
||||||
|
.nb_bytes = cow_start_length,
|
||||||
|
},
|
||||||
|
.cow_end = {
|
||||||
|
.offset = nb_clusters << s->cluster_bits,
|
||||||
|
.nb_bytes = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
qemu_co_queue_init(&allocation.dependent_requests);
|
qemu_co_queue_init(&allocation.dependent_requests);
|
||||||
|
|
||||||
@ -4860,16 +4873,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
|
|||||||
|
|
||||||
if (has_luks) {
|
if (has_luks) {
|
||||||
g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
|
g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
|
||||||
QDict *opts_qdict;
|
QDict *cryptoopts = qcow2_extract_crypto_opts(opts, "luks", errp);
|
||||||
QDict *cryptoopts;
|
|
||||||
size_t headerlen;
|
size_t headerlen;
|
||||||
|
|
||||||
opts_qdict = qemu_opts_to_qdict(opts, NULL);
|
|
||||||
qdict_extract_subqdict(opts_qdict, &cryptoopts, "encrypt.");
|
|
||||||
qobject_unref(opts_qdict);
|
|
||||||
|
|
||||||
qdict_put_str(cryptoopts, "format", "luks");
|
|
||||||
|
|
||||||
create_opts = block_crypto_create_opts_init(cryptoopts, errp);
|
create_opts = block_crypto_create_opts_init(cryptoopts, errp);
|
||||||
qobject_unref(cryptoopts);
|
qobject_unref(cryptoopts);
|
||||||
if (!create_opts) {
|
if (!create_opts) {
|
||||||
@ -4981,7 +4987,6 @@ err:
|
|||||||
static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
bdi->unallocated_blocks_are_zero = true;
|
|
||||||
bdi->cluster_size = s->cluster_size;
|
bdi->cluster_size = s->cluster_size;
|
||||||
bdi->vm_state_offset = qcow2_vm_state_offset(s);
|
bdi->vm_state_offset = qcow2_vm_state_offset(s);
|
||||||
return 0;
|
return 0;
|
||||||
@ -5273,6 +5278,7 @@ typedef enum Qcow2AmendOperation {
|
|||||||
QCOW2_NO_OPERATION = 0,
|
QCOW2_NO_OPERATION = 0,
|
||||||
|
|
||||||
QCOW2_UPGRADING,
|
QCOW2_UPGRADING,
|
||||||
|
QCOW2_UPDATING_ENCRYPTION,
|
||||||
QCOW2_CHANGING_REFCOUNT_ORDER,
|
QCOW2_CHANGING_REFCOUNT_ORDER,
|
||||||
QCOW2_DOWNGRADING,
|
QCOW2_DOWNGRADING,
|
||||||
} Qcow2AmendOperation;
|
} Qcow2AmendOperation;
|
||||||
@ -5340,6 +5346,7 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
|
|||||||
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
BlockDriverAmendStatusCB *status_cb,
|
BlockDriverAmendStatusCB *status_cb,
|
||||||
void *cb_opaque,
|
void *cb_opaque,
|
||||||
|
bool force,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
@ -5349,13 +5356,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
bool lazy_refcounts = s->use_lazy_refcounts;
|
bool lazy_refcounts = s->use_lazy_refcounts;
|
||||||
bool data_file_raw = data_file_is_raw(bs);
|
bool data_file_raw = data_file_is_raw(bs);
|
||||||
const char *compat = NULL;
|
const char *compat = NULL;
|
||||||
uint64_t cluster_size = s->cluster_size;
|
|
||||||
bool encrypt;
|
|
||||||
int encformat;
|
|
||||||
int refcount_bits = s->refcount_bits;
|
int refcount_bits = s->refcount_bits;
|
||||||
int ret;
|
int ret;
|
||||||
QemuOptDesc *desc = opts->list->desc;
|
QemuOptDesc *desc = opts->list->desc;
|
||||||
Qcow2AmendHelperCBInfo helper_cb_info;
|
Qcow2AmendHelperCBInfo helper_cb_info;
|
||||||
|
bool encryption_update = false;
|
||||||
|
|
||||||
while (desc && desc->name) {
|
while (desc && desc->name) {
|
||||||
if (!qemu_opt_find(opts, desc->name)) {
|
if (!qemu_opt_find(opts, desc->name)) {
|
||||||
@ -5376,44 +5381,24 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
error_setg(errp, "Unknown compatibility level %s", compat);
|
error_setg(errp, "Unknown compatibility level %s", compat);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {
|
|
||||||
error_setg(errp, "Cannot change preallocation mode");
|
|
||||||
return -ENOTSUP;
|
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
|
||||||
new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
|
new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FILE)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FILE)) {
|
||||||
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {
|
||||||
backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
|
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->crypto);
|
|
||||||
|
|
||||||
if (encrypt != !!s->crypto) {
|
|
||||||
error_setg(errp,
|
|
||||||
"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_setg(errp,
|
|
||||||
"Changing the encryption format is not supported");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
} else if (g_str_has_prefix(desc->name, "encrypt.")) {
|
} else if (g_str_has_prefix(desc->name, "encrypt.")) {
|
||||||
error_setg(errp,
|
if (!s->crypto) {
|
||||||
"Changing the encryption parameters is not supported");
|
error_setg(errp,
|
||||||
return -ENOTSUP;
|
"Can't amend encryption options - encryption not present");
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
return -EINVAL;
|
||||||
cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
|
}
|
||||||
cluster_size);
|
if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
|
||||||
if (cluster_size != s->cluster_size) {
|
error_setg(errp,
|
||||||
error_setg(errp, "Changing the cluster size is not supported");
|
"Only LUKS encryption options can be amended");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
encryption_update = true;
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
||||||
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
||||||
lazy_refcounts);
|
lazy_refcounts);
|
||||||
@ -5443,22 +5428,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
"images");
|
"images");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_COMPRESSION_TYPE)) {
|
|
||||||
const char *ct_name =
|
|
||||||
qemu_opt_get(opts, BLOCK_OPT_COMPRESSION_TYPE);
|
|
||||||
int compression_type =
|
|
||||||
qapi_enum_parse(&Qcow2CompressionType_lookup, ct_name, -1,
|
|
||||||
NULL);
|
|
||||||
if (compression_type == -1) {
|
|
||||||
error_setg(errp, "Unknown compression type: %s", ct_name);
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compression_type != s->compression_type) {
|
|
||||||
error_setg(errp, "Changing the compression type "
|
|
||||||
"is not supported");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* if this point is reached, this probably means a new option was
|
/* if this point is reached, this probably means a new option was
|
||||||
* added without having it covered here */
|
* added without having it covered here */
|
||||||
@ -5472,7 +5441,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
.original_status_cb = status_cb,
|
.original_status_cb = status_cb,
|
||||||
.original_cb_opaque = cb_opaque,
|
.original_cb_opaque = cb_opaque,
|
||||||
.total_operations = (new_version != old_version)
|
.total_operations = (new_version != old_version)
|
||||||
+ (s->refcount_bits != refcount_bits)
|
+ (s->refcount_bits != refcount_bits) +
|
||||||
|
(encryption_update == true)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Upgrade first (some features may require compat=1.1) */
|
/* Upgrade first (some features may require compat=1.1) */
|
||||||
@ -5485,6 +5455,33 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (encryption_update) {
|
||||||
|
QDict *amend_opts_dict;
|
||||||
|
QCryptoBlockAmendOptions *amend_opts;
|
||||||
|
|
||||||
|
helper_cb_info.current_operation = QCOW2_UPDATING_ENCRYPTION;
|
||||||
|
amend_opts_dict = qcow2_extract_crypto_opts(opts, "luks", errp);
|
||||||
|
if (!amend_opts_dict) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
amend_opts = block_crypto_amend_opts_init(amend_opts_dict, errp);
|
||||||
|
qobject_unref(amend_opts_dict);
|
||||||
|
if (!amend_opts) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ret = qcrypto_block_amend_options(s->crypto,
|
||||||
|
qcow2_crypto_hdr_read_func,
|
||||||
|
qcow2_crypto_hdr_write_func,
|
||||||
|
bs,
|
||||||
|
amend_opts,
|
||||||
|
force,
|
||||||
|
errp);
|
||||||
|
qapi_free_QCryptoBlockAmendOptions(amend_opts);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (s->refcount_bits != refcount_bits) {
|
if (s->refcount_bits != refcount_bits) {
|
||||||
int refcount_order = ctz32(refcount_bits);
|
int refcount_order = ctz32(refcount_bits);
|
||||||
|
|
||||||
@ -5598,6 +5595,44 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn qcow2_co_amend(BlockDriverState *bs,
|
||||||
|
BlockdevAmendOptions *opts,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
BlockdevAmendOptionsQcow2 *qopts = &opts->u.qcow2;
|
||||||
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (qopts->has_encrypt) {
|
||||||
|
if (!s->crypto) {
|
||||||
|
error_setg(errp, "image is not encrypted, can't amend");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qopts->encrypt->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Amend can't be used to change the qcow2 encryption format");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Only LUKS encryption options can be amended for qcow2 with blockdev-amend");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qcrypto_block_amend_options(s->crypto,
|
||||||
|
qcow2_crypto_hdr_read_func,
|
||||||
|
qcow2_crypto_hdr_write_func,
|
||||||
|
bs,
|
||||||
|
qopts->encrypt,
|
||||||
|
force,
|
||||||
|
errp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If offset or size are negative, respectively, they will not be included in
|
* If offset or size are negative, respectively, they will not be included in
|
||||||
* the BLOCK_IMAGE_CORRUPTED event emitted.
|
* the BLOCK_IMAGE_CORRUPTED event emitted.
|
||||||
@ -5648,89 +5683,108 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
|
|||||||
s->signaled_corruption = true;
|
s->signaled_corruption = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define QCOW_COMMON_OPTIONS \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_SIZE, \
|
||||||
|
.type = QEMU_OPT_SIZE, \
|
||||||
|
.help = "Virtual disk size" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_COMPAT_LEVEL, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Compatibility level (v2 [0.10] or v3 [1.1])" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_BACKING_FILE, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "File name of a base image" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_BACKING_FMT, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Image format of the base image" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_DATA_FILE, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "File name of an external data file" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_DATA_FILE_RAW, \
|
||||||
|
.type = QEMU_OPT_BOOL, \
|
||||||
|
.help = "The external data file must stay valid " \
|
||||||
|
"as a raw image" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_LAZY_REFCOUNTS, \
|
||||||
|
.type = QEMU_OPT_BOOL, \
|
||||||
|
.help = "Postpone refcount updates", \
|
||||||
|
.def_value_str = "off" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_REFCOUNT_BITS, \
|
||||||
|
.type = QEMU_OPT_NUMBER, \
|
||||||
|
.help = "Width of a reference count entry in bits", \
|
||||||
|
.def_value_str = "16" \
|
||||||
|
}
|
||||||
|
|
||||||
static QemuOptsList qcow2_create_opts = {
|
static QemuOptsList qcow2_create_opts = {
|
||||||
.name = "qcow2-create-opts",
|
.name = "qcow2-create-opts",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
|
||||||
.desc = {
|
.desc = {
|
||||||
{
|
{ \
|
||||||
.name = BLOCK_OPT_SIZE,
|
.name = BLOCK_OPT_ENCRYPT, \
|
||||||
.type = QEMU_OPT_SIZE,
|
.type = QEMU_OPT_BOOL, \
|
||||||
.help = "Virtual disk size"
|
.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", \
|
||||||
|
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE) \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_PREALLOC, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Preallocation mode (allowed values: off, " \
|
||||||
|
"metadata, falloc, full)" \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.name = BLOCK_OPT_COMPRESSION_TYPE, \
|
||||||
|
.type = QEMU_OPT_STRING, \
|
||||||
|
.help = "Compression method used for image cluster " \
|
||||||
|
"compression", \
|
||||||
|
.def_value_str = "zlib" \
|
||||||
},
|
},
|
||||||
{
|
QCOW_COMMON_OPTIONS,
|
||||||
.name = BLOCK_OPT_COMPAT_LEVEL,
|
{ /* end of list */ }
|
||||||
.type = QEMU_OPT_STRING,
|
}
|
||||||
.help = "Compatibility level (v2 [0.10] or v3 [1.1])"
|
};
|
||||||
},
|
|
||||||
{
|
static QemuOptsList qcow2_amend_opts = {
|
||||||
.name = BLOCK_OPT_BACKING_FILE,
|
.name = "qcow2-amend-opts",
|
||||||
.type = QEMU_OPT_STRING,
|
.head = QTAILQ_HEAD_INITIALIZER(qcow2_amend_opts.head),
|
||||||
.help = "File name of a base image"
|
.desc = {
|
||||||
},
|
BLOCK_CRYPTO_OPT_DEF_LUKS_STATE("encrypt."),
|
||||||
{
|
BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT("encrypt."),
|
||||||
.name = BLOCK_OPT_BACKING_FMT,
|
BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET("encrypt."),
|
||||||
.type = QEMU_OPT_STRING,
|
BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET("encrypt."),
|
||||||
.help = "Image format of the base image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_DATA_FILE,
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "File name of an external data file"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_DATA_FILE_RAW,
|
|
||||||
.type = QEMU_OPT_BOOL,
|
|
||||||
.help = "The external data file must stay valid as a raw image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_ENCRYPT,
|
|
||||||
.type = QEMU_OPT_BOOL,
|
|
||||||
.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."),
|
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."),
|
||||||
{
|
QCOW_COMMON_OPTIONS,
|
||||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
|
||||||
.type = QEMU_OPT_SIZE,
|
|
||||||
.help = "qcow2 cluster size",
|
|
||||||
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_PREALLOC,
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "Preallocation mode (allowed values: off, metadata, "
|
|
||||||
"falloc, full)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_LAZY_REFCOUNTS,
|
|
||||||
.type = QEMU_OPT_BOOL,
|
|
||||||
.help = "Postpone refcount updates",
|
|
||||||
.def_value_str = "off"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_REFCOUNT_BITS,
|
|
||||||
.type = QEMU_OPT_NUMBER,
|
|
||||||
.help = "Width of a reference count entry in bits",
|
|
||||||
.def_value_str = "16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = BLOCK_OPT_COMPRESSION_TYPE,
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "Compression method used for image cluster compression",
|
|
||||||
.def_value_str = "zlib"
|
|
||||||
},
|
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -5791,10 +5845,12 @@ BlockDriver bdrv_qcow2 = {
|
|||||||
.bdrv_inactivate = qcow2_inactivate,
|
.bdrv_inactivate = qcow2_inactivate,
|
||||||
|
|
||||||
.create_opts = &qcow2_create_opts,
|
.create_opts = &qcow2_create_opts,
|
||||||
|
.amend_opts = &qcow2_amend_opts,
|
||||||
.strong_runtime_opts = qcow2_strong_runtime_opts,
|
.strong_runtime_opts = qcow2_strong_runtime_opts,
|
||||||
.mutable_opts = mutable_opts,
|
.mutable_opts = mutable_opts,
|
||||||
.bdrv_co_check = qcow2_co_check,
|
.bdrv_co_check = qcow2_co_check,
|
||||||
.bdrv_amend_options = qcow2_amend_options,
|
.bdrv_amend_options = qcow2_amend_options,
|
||||||
|
.bdrv_co_amend = qcow2_co_amend,
|
||||||
|
|
||||||
.bdrv_detach_aio_context = qcow2_detach_aio_context,
|
.bdrv_detach_aio_context = qcow2_detach_aio_context,
|
||||||
.bdrv_attach_aio_context = qcow2_attach_aio_context,
|
.bdrv_attach_aio_context = qcow2_attach_aio_context,
|
||||||
|
65
block/qed.c
65
block/qed.c
@ -849,56 +849,18 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
|
|||||||
* @s: QED state
|
* @s: QED state
|
||||||
* @pos: Byte position in device
|
* @pos: Byte position in device
|
||||||
* @qiov: Destination I/O vector
|
* @qiov: Destination I/O vector
|
||||||
* @backing_qiov: Possibly shortened copy of qiov, to be allocated here
|
|
||||||
* @cb: Completion function
|
|
||||||
* @opaque: User data for completion function
|
|
||||||
*
|
*
|
||||||
* This function reads qiov->size bytes starting at pos from the backing file.
|
* This function reads qiov->size bytes starting at pos from the backing file.
|
||||||
* If there is no backing file then zeroes are read.
|
* If there is no backing file then zeroes are read.
|
||||||
*/
|
*/
|
||||||
static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
|
static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
|
||||||
QEMUIOVector *qiov,
|
QEMUIOVector *qiov)
|
||||||
QEMUIOVector **backing_qiov)
|
|
||||||
{
|
{
|
||||||
uint64_t backing_length = 0;
|
|
||||||
size_t size;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* If there is a backing file, get its length. Treat the absence of a
|
|
||||||
* backing file like a zero length backing file.
|
|
||||||
*/
|
|
||||||
if (s->bs->backing) {
|
if (s->bs->backing) {
|
||||||
int64_t l = bdrv_getlength(s->bs->backing->bs);
|
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
|
||||||
if (l < 0) {
|
return bdrv_co_preadv(s->bs->backing, pos, qiov->size, qiov, 0);
|
||||||
return l;
|
|
||||||
}
|
|
||||||
backing_length = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero all sectors if reading beyond the end of the backing file */
|
|
||||||
if (pos >= backing_length ||
|
|
||||||
pos + qiov->size > backing_length) {
|
|
||||||
qemu_iovec_memset(qiov, 0, 0, qiov->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Complete now if there are no backing file sectors to read */
|
|
||||||
if (pos >= backing_length) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the read straddles the end of the backing file, shorten it */
|
|
||||||
size = MIN((uint64_t)backing_length - pos, qiov->size);
|
|
||||||
|
|
||||||
assert(*backing_qiov == NULL);
|
|
||||||
*backing_qiov = g_new(QEMUIOVector, 1);
|
|
||||||
qemu_iovec_init(*backing_qiov, qiov->niov);
|
|
||||||
qemu_iovec_concat(*backing_qiov, qiov, 0, size);
|
|
||||||
|
|
||||||
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
|
|
||||||
ret = bdrv_co_preadv(s->bs->backing, pos, size, *backing_qiov, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
qemu_iovec_memset(qiov, 0, 0, qiov->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,7 +877,6 @@ static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
|
|||||||
uint64_t offset)
|
uint64_t offset)
|
||||||
{
|
{
|
||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
QEMUIOVector *backing_qiov = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Skip copy entirely if there is no work to do */
|
/* Skip copy entirely if there is no work to do */
|
||||||
@ -925,13 +886,7 @@ static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
|
|||||||
|
|
||||||
qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len);
|
qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len);
|
||||||
|
|
||||||
ret = qed_read_backing_file(s, pos, &qiov, &backing_qiov);
|
ret = qed_read_backing_file(s, pos, &qiov);
|
||||||
|
|
||||||
if (backing_qiov) {
|
|
||||||
qemu_iovec_destroy(backing_qiov);
|
|
||||||
g_free(backing_qiov);
|
|
||||||
backing_qiov = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto out;
|
goto out;
|
||||||
@ -1339,8 +1294,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
|
|||||||
qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size);
|
qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size);
|
||||||
r = 0;
|
r = 0;
|
||||||
} else if (ret != QED_CLUSTER_FOUND) {
|
} else if (ret != QED_CLUSTER_FOUND) {
|
||||||
r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
|
r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov);
|
||||||
&acb->backing_qiov);
|
|
||||||
} else {
|
} else {
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||||
r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size,
|
r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size,
|
||||||
@ -1365,12 +1319,6 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
|
|||||||
while (1) {
|
while (1) {
|
||||||
trace_qed_aio_next_io(s, acb, 0, acb->cur_pos + acb->cur_qiov.size);
|
trace_qed_aio_next_io(s, acb, 0, acb->cur_pos + acb->cur_qiov.size);
|
||||||
|
|
||||||
if (acb->backing_qiov) {
|
|
||||||
qemu_iovec_destroy(acb->backing_qiov);
|
|
||||||
g_free(acb->backing_qiov);
|
|
||||||
acb->backing_qiov = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
acb->qiov_offset += acb->cur_qiov.size;
|
acb->qiov_offset += acb->cur_qiov.size;
|
||||||
acb->cur_pos += acb->cur_qiov.size;
|
acb->cur_pos += acb->cur_qiov.size;
|
||||||
qemu_iovec_reset(&acb->cur_qiov);
|
qemu_iovec_reset(&acb->cur_qiov);
|
||||||
@ -1514,7 +1462,6 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
memset(bdi, 0, sizeof(*bdi));
|
memset(bdi, 0, sizeof(*bdi));
|
||||||
bdi->cluster_size = s->header.cluster_size;
|
bdi->cluster_size = s->header.cluster_size;
|
||||||
bdi->is_dirty = s->header.features & QED_F_NEED_CHECK;
|
bdi->is_dirty = s->header.features & QED_F_NEED_CHECK;
|
||||||
bdi->unallocated_blocks_are_zero = true;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,6 @@ typedef struct QEDAIOCB {
|
|||||||
|
|
||||||
/* Current cluster scatter-gather list */
|
/* Current cluster scatter-gather list */
|
||||||
QEMUIOVector cur_qiov;
|
QEMUIOVector cur_qiov;
|
||||||
QEMUIOVector *backing_qiov;
|
|
||||||
uint64_t cur_pos; /* position on block device, in bytes */
|
uint64_t cur_pos; /* position on block device, in bytes */
|
||||||
uint64_t cur_cluster; /* cluster offset in image file */
|
uint64_t cur_cluster; /* cluster offset in image file */
|
||||||
unsigned int cur_nclusters; /* number of clusters being accessed */
|
unsigned int cur_nclusters; /* number of clusters being accessed */
|
||||||
|
@ -334,7 +334,6 @@ static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
logout("\n");
|
logout("\n");
|
||||||
bdi->cluster_size = s->block_size;
|
bdi->cluster_size = s->block_size;
|
||||||
bdi->vm_state_offset = 0;
|
bdi->vm_state_offset = 0;
|
||||||
bdi->unallocated_blocks_are_zero = true;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +535,7 @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
|
|||||||
*pnum = MIN(s->block_size - index_in_block, bytes);
|
*pnum = MIN(s->block_size - index_in_block, bytes);
|
||||||
result = VDI_IS_ALLOCATED(bmap_entry);
|
result = VDI_IS_ALLOCATED(bmap_entry);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return 0;
|
return BDRV_BLOCK_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
|
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
|
||||||
|
@ -1164,9 +1164,6 @@ static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
|
|
||||||
bdi->cluster_size = s->block_size;
|
bdi->cluster_size = s->block_size;
|
||||||
|
|
||||||
bdi->unallocated_blocks_are_zero =
|
|
||||||
(s->params.data_bits & VHDX_PARAMS_HAS_PARENT) == 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,7 +606,6 @@ static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
bdi->cluster_size = s->block_size;
|
bdi->cluster_size = s->block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdi->unallocated_blocks_are_zero = true;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +744,7 @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
|
|||||||
image_offset = get_image_offset(bs, offset, false, NULL);
|
image_offset = get_image_offset(bs, offset, false, NULL);
|
||||||
allocated = (image_offset != -1);
|
allocated = (image_offset != -1);
|
||||||
*pnum = 0;
|
*pnum = 0;
|
||||||
ret = 0;
|
ret = BDRV_BLOCK_ZERO;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* All sectors in a block are contiguous (without using the bitmap) */
|
/* All sectors in a block are contiguous (without using the bitmap) */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "qemu/uuid.h"
|
#include "qemu/uuid.h"
|
||||||
|
|
||||||
#include "qemu/coroutine.h"
|
#include "qemu/coroutine.h"
|
||||||
|
#include "qemu/bitmap.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reference for the LUKS format implemented here is
|
* Reference for the LUKS format implemented here is
|
||||||
@ -70,6 +71,9 @@ typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot;
|
|||||||
|
|
||||||
#define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
|
#define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
|
||||||
|
|
||||||
|
#define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000
|
||||||
|
#define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40
|
||||||
|
|
||||||
static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
|
static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
|
||||||
'L', 'U', 'K', 'S', 0xBA, 0xBE
|
'L', 'U', 'K', 'S', 0xBA, 0xBE
|
||||||
};
|
};
|
||||||
@ -219,6 +223,9 @@ struct QCryptoBlockLUKS {
|
|||||||
|
|
||||||
/* Hash algorithm used in pbkdf2 function */
|
/* Hash algorithm used in pbkdf2 function */
|
||||||
QCryptoHashAlgorithm hash_alg;
|
QCryptoHashAlgorithm hash_alg;
|
||||||
|
|
||||||
|
/* Name of the secret that was used to open the image */
|
||||||
|
char *secret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -720,7 +727,7 @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoBlockLUKS *luks = block->opaque;
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
|
QCryptoBlockLUKSKeySlot *slot;
|
||||||
g_autofree uint8_t *splitkey = NULL;
|
g_autofree uint8_t *splitkey = NULL;
|
||||||
size_t splitkeylen;
|
size_t splitkeylen;
|
||||||
g_autofree uint8_t *slotkey = NULL;
|
g_autofree uint8_t *slotkey = NULL;
|
||||||
@ -730,6 +737,8 @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
|
|||||||
uint64_t iters;
|
uint64_t iters;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
|
assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
slot = &luks->header.key_slots[slot_idx];
|
||||||
if (qcrypto_random_bytes(slot->salt,
|
if (qcrypto_random_bytes(slot->salt,
|
||||||
QCRYPTO_BLOCK_LUKS_SALT_LEN,
|
QCRYPTO_BLOCK_LUKS_SALT_LEN,
|
||||||
errp) < 0) {
|
errp) < 0) {
|
||||||
@ -890,7 +899,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoBlockLUKS *luks = block->opaque;
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
|
const QCryptoBlockLUKSKeySlot *slot;
|
||||||
g_autofree uint8_t *splitkey = NULL;
|
g_autofree uint8_t *splitkey = NULL;
|
||||||
size_t splitkeylen;
|
size_t splitkeylen;
|
||||||
g_autofree uint8_t *possiblekey = NULL;
|
g_autofree uint8_t *possiblekey = NULL;
|
||||||
@ -900,6 +909,8 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
|
|||||||
g_autoptr(QCryptoIVGen) ivgen = NULL;
|
g_autoptr(QCryptoIVGen) ivgen = NULL;
|
||||||
size_t niv;
|
size_t niv;
|
||||||
|
|
||||||
|
assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
slot = &luks->header.key_slots[slot_idx];
|
||||||
if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
|
if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1069,6 +1080,126 @@ qcrypto_block_luks_find_key(QCryptoBlock *block,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if a slot i is marked as active
|
||||||
|
* (contains encrypted copy of the master key)
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks,
|
||||||
|
unsigned int slot_idx)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
val = luks->header.key_slots[slot_idx].active;
|
||||||
|
return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the number of slots that are marked as active
|
||||||
|
* (slots that contain encrypted copy of the master key)
|
||||||
|
*/
|
||||||
|
static unsigned int
|
||||||
|
qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
unsigned int ret = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||||
|
if (qcrypto_block_luks_slot_active(luks, i)) {
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds first key slot which is not active
|
||||||
|
* Returns the key slot index, or -1 if it doesn't exist
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||||
|
if (!qcrypto_block_luks_slot_active(luks, i)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erases an keyslot given its index
|
||||||
|
* Returns:
|
||||||
|
* 0 if the keyslot was erased successfully
|
||||||
|
* -1 if a error occurred while erasing the keyslot
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qcrypto_block_luks_erase_key(QCryptoBlock *block,
|
||||||
|
unsigned int slot_idx,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
|
QCryptoBlockLUKSKeySlot *slot;
|
||||||
|
g_autofree uint8_t *garbagesplitkey = NULL;
|
||||||
|
size_t splitkeylen;
|
||||||
|
size_t i;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
slot = &luks->header.key_slots[slot_idx];
|
||||||
|
|
||||||
|
splitkeylen = luks->header.master_key_len * slot->stripes;
|
||||||
|
assert(splitkeylen > 0);
|
||||||
|
|
||||||
|
garbagesplitkey = g_new0(uint8_t, splitkeylen);
|
||||||
|
|
||||||
|
/* Reset the key slot header */
|
||||||
|
memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN);
|
||||||
|
slot->iterations = 0;
|
||||||
|
slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
|
||||||
|
|
||||||
|
ret = qcrypto_block_luks_store_header(block, writefunc,
|
||||||
|
opaque, &local_err);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Now try to erase the key material, even if the header
|
||||||
|
* update failed
|
||||||
|
*/
|
||||||
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) {
|
||||||
|
if (qcrypto_random_bytes(garbagesplitkey,
|
||||||
|
splitkeylen, &local_err) < 0) {
|
||||||
|
/*
|
||||||
|
* If we failed to get the random data, still write
|
||||||
|
* at least zeros to the key slot at least once
|
||||||
|
*/
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writefunc(block,
|
||||||
|
slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
|
||||||
|
garbagesplitkey,
|
||||||
|
splitkeylen,
|
||||||
|
opaque,
|
||||||
|
&local_err) != splitkeylen) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qcrypto_block_luks_open(QCryptoBlock *block,
|
qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
@ -1099,6 +1230,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
|||||||
|
|
||||||
luks = g_new0(QCryptoBlockLUKS, 1);
|
luks = g_new0(QCryptoBlockLUKS, 1);
|
||||||
block->opaque = luks;
|
block->opaque = luks;
|
||||||
|
luks->secret = g_strdup(options->u.luks.key_secret);
|
||||||
|
|
||||||
if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
|
if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1164,6 +1296,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
|||||||
fail:
|
fail:
|
||||||
qcrypto_block_free_cipher(block);
|
qcrypto_block_free_cipher(block);
|
||||||
qcrypto_ivgen_free(block->ivgen);
|
qcrypto_ivgen_free(block->ivgen);
|
||||||
|
g_free(luks->secret);
|
||||||
g_free(luks);
|
g_free(luks);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1204,7 +1337,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
|||||||
|
|
||||||
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
|
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
|
||||||
if (!luks_opts.has_iter_time) {
|
if (!luks_opts.has_iter_time) {
|
||||||
luks_opts.iter_time = 2000;
|
luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
|
||||||
}
|
}
|
||||||
if (!luks_opts.has_cipher_alg) {
|
if (!luks_opts.has_cipher_alg) {
|
||||||
luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
|
luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
|
||||||
@ -1244,6 +1377,8 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
|||||||
optprefix ? optprefix : "");
|
optprefix ? optprefix : "");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
luks->secret = g_strdup(options->u.luks.key_secret);
|
||||||
|
|
||||||
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
|
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
|
||||||
if (!password) {
|
if (!password) {
|
||||||
goto error;
|
goto error;
|
||||||
@ -1471,10 +1606,278 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
|||||||
qcrypto_block_free_cipher(block);
|
qcrypto_block_free_cipher(block);
|
||||||
qcrypto_ivgen_free(block->ivgen);
|
qcrypto_ivgen_free(block->ivgen);
|
||||||
|
|
||||||
|
g_free(luks->secret);
|
||||||
g_free(luks);
|
g_free(luks);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptionsLUKS *opts_luks,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
|
uint64_t iter_time = opts_luks->has_iter_time ?
|
||||||
|
opts_luks->iter_time :
|
||||||
|
QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
|
||||||
|
int keyslot;
|
||||||
|
g_autofree char *old_password = NULL;
|
||||||
|
g_autofree char *new_password = NULL;
|
||||||
|
g_autofree uint8_t *master_key = NULL;
|
||||||
|
|
||||||
|
char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret;
|
||||||
|
|
||||||
|
if (!opts_luks->has_new_secret) {
|
||||||
|
error_setg(errp, "'new-secret' is required to activate a keyslot");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (opts_luks->has_old_secret) {
|
||||||
|
error_setg(errp,
|
||||||
|
"'old-secret' must not be given when activating keyslots");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts_luks->has_keyslot) {
|
||||||
|
keyslot = opts_luks->keyslot;
|
||||||
|
if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Invalid keyslot %u specified, must be between 0 and %u",
|
||||||
|
keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keyslot = qcrypto_block_luks_find_free_keyslot(luks);
|
||||||
|
if (keyslot == -1) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Can't add a keyslot - all keyslots are in use");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Refusing to overwrite active keyslot %i - "
|
||||||
|
"please erase it first",
|
||||||
|
keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate the password that will be used to retrieve the master key */
|
||||||
|
old_password = qcrypto_secret_lookup_as_utf8(secret, errp);
|
||||||
|
if (!old_password) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the master key */
|
||||||
|
master_key = g_new0(uint8_t, luks->header.master_key_len);
|
||||||
|
|
||||||
|
if (qcrypto_block_luks_find_key(block, old_password, master_key,
|
||||||
|
readfunc, opaque, errp) < 0) {
|
||||||
|
error_append_hint(errp, "Failed to retrieve the master key");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Locate the new password*/
|
||||||
|
new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp);
|
||||||
|
if (!new_password) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now set the new keyslots */
|
||||||
|
if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key,
|
||||||
|
iter_time, writefunc, opaque, errp)) {
|
||||||
|
error_append_hint(errp, "Failed to write to keyslot %i", keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptionsLUKS *opts_luks,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
|
g_autofree uint8_t *tmpkey = NULL;
|
||||||
|
g_autofree char *old_password = NULL;
|
||||||
|
|
||||||
|
if (opts_luks->has_new_secret) {
|
||||||
|
error_setg(errp,
|
||||||
|
"'new-secret' must not be given when erasing keyslots");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (opts_luks->has_iter_time) {
|
||||||
|
error_setg(errp,
|
||||||
|
"'iter-time' must not be given when erasing keyslots");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (opts_luks->has_secret) {
|
||||||
|
error_setg(errp,
|
||||||
|
"'secret' must not be given when erasing keyslots");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the old password if given */
|
||||||
|
if (opts_luks->has_old_secret) {
|
||||||
|
old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret,
|
||||||
|
errp);
|
||||||
|
if (!old_password) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a temporary key buffer that we will need when
|
||||||
|
* checking if slot matches the given old password
|
||||||
|
*/
|
||||||
|
tmpkey = g_new0(uint8_t, luks->header.master_key_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Erase an explicitly given keyslot */
|
||||||
|
if (opts_luks->has_keyslot) {
|
||||||
|
int keyslot = opts_luks->keyslot;
|
||||||
|
|
||||||
|
if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Invalid keyslot %i specified, must be between 0 and %i",
|
||||||
|
keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts_luks->has_old_secret) {
|
||||||
|
int rv = qcrypto_block_luks_load_key(block,
|
||||||
|
keyslot,
|
||||||
|
old_password,
|
||||||
|
tmpkey,
|
||||||
|
readfunc,
|
||||||
|
opaque,
|
||||||
|
errp);
|
||||||
|
if (rv == -1) {
|
||||||
|
return -1;
|
||||||
|
} else if (rv == 0) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Given keyslot %i doesn't contain the given "
|
||||||
|
"old password for erase operation",
|
||||||
|
keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Given keyslot %i is already erased (inactive) ",
|
||||||
|
keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Attempt to erase the only active keyslot %i "
|
||||||
|
"which will erase all the data in the image "
|
||||||
|
"irreversibly - refusing operation",
|
||||||
|
keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qcrypto_block_luks_erase_key(block, keyslot,
|
||||||
|
writefunc, opaque, errp)) {
|
||||||
|
error_append_hint(errp, "Failed to erase keyslot %i", keyslot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Erase all keyslots that match the given old password */
|
||||||
|
} else if (opts_luks->has_old_secret) {
|
||||||
|
|
||||||
|
unsigned long slots_to_erase_bitmap = 0;
|
||||||
|
size_t i;
|
||||||
|
int slot_count;
|
||||||
|
|
||||||
|
assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <=
|
||||||
|
sizeof(slots_to_erase_bitmap) * 8);
|
||||||
|
|
||||||
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||||
|
int rv = qcrypto_block_luks_load_key(block,
|
||||||
|
i,
|
||||||
|
old_password,
|
||||||
|
tmpkey,
|
||||||
|
readfunc,
|
||||||
|
opaque,
|
||||||
|
errp);
|
||||||
|
if (rv == -1) {
|
||||||
|
return -1;
|
||||||
|
} else if (rv == 1) {
|
||||||
|
bitmap_set(&slots_to_erase_bitmap, i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_count = bitmap_count_one(&slots_to_erase_bitmap,
|
||||||
|
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
if (slot_count == 0) {
|
||||||
|
error_setg(errp,
|
||||||
|
"No keyslots match given (old) password for erase operation");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force &&
|
||||||
|
slot_count == qcrypto_block_luks_count_active_slots(luks)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"All the active keyslots match the (old) password that "
|
||||||
|
"was given and erasing them will erase all the data in "
|
||||||
|
"the image irreversibly - refusing operation");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now apply the update */
|
||||||
|
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||||
|
if (!test_bit(i, &slots_to_erase_bitmap)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (qcrypto_block_luks_erase_key(block, i, writefunc,
|
||||||
|
opaque, errp)) {
|
||||||
|
error_append_hint(errp, "Failed to erase keyslot %zu", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error_setg(errp,
|
||||||
|
"To erase keyslot(s), either explicit keyslot index "
|
||||||
|
"or the password currently contained in them must be given");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qcrypto_block_luks_amend_options(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptions *options,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks;
|
||||||
|
|
||||||
|
switch (opts_luks->state) {
|
||||||
|
case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE:
|
||||||
|
return qcrypto_block_luks_amend_add_keyslot(block, readfunc,
|
||||||
|
writefunc, opaque,
|
||||||
|
opts_luks, force, errp);
|
||||||
|
case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE:
|
||||||
|
return qcrypto_block_luks_amend_erase_keyslots(block, readfunc,
|
||||||
|
writefunc, opaque,
|
||||||
|
opts_luks, force, errp);
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int qcrypto_block_luks_get_info(QCryptoBlock *block,
|
static int qcrypto_block_luks_get_info(QCryptoBlock *block,
|
||||||
QCryptoBlockInfo *info,
|
QCryptoBlockInfo *info,
|
||||||
@ -1523,7 +1926,11 @@ static int qcrypto_block_luks_get_info(QCryptoBlock *block,
|
|||||||
|
|
||||||
static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
|
static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
|
||||||
{
|
{
|
||||||
g_free(block->opaque);
|
QCryptoBlockLUKS *luks = block->opaque;
|
||||||
|
if (luks) {
|
||||||
|
g_free(luks->secret);
|
||||||
|
g_free(luks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1560,6 +1967,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
|
|||||||
const QCryptoBlockDriver qcrypto_block_driver_luks = {
|
const QCryptoBlockDriver qcrypto_block_driver_luks = {
|
||||||
.open = qcrypto_block_luks_open,
|
.open = qcrypto_block_luks_open,
|
||||||
.create = qcrypto_block_luks_create,
|
.create = qcrypto_block_luks_create,
|
||||||
|
.amend = qcrypto_block_luks_amend_options,
|
||||||
.get_info = qcrypto_block_luks_get_info,
|
.get_info = qcrypto_block_luks_get_info,
|
||||||
.cleanup = qcrypto_block_luks_cleanup,
|
.cleanup = qcrypto_block_luks_cleanup,
|
||||||
.decrypt = qcrypto_block_luks_decrypt,
|
.decrypt = qcrypto_block_luks_decrypt,
|
||||||
|
@ -150,6 +150,35 @@ qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
|
|||||||
return crypto != NULL;
|
return crypto != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qcrypto_block_amend_options(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptions *options,
|
||||||
|
bool force,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
if (options->format != block->format) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Cannot amend encryption format");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block->driver->amend) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Crypto format %s doesn't support format options amendment",
|
||||||
|
QCryptoBlockFormat_str(block->format));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block->driver->amend(block,
|
||||||
|
readfunc,
|
||||||
|
writefunc,
|
||||||
|
opaque,
|
||||||
|
options,
|
||||||
|
force,
|
||||||
|
errp);
|
||||||
|
}
|
||||||
|
|
||||||
QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
|
QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
|
@ -62,6 +62,14 @@ struct QCryptoBlockDriver {
|
|||||||
void *opaque,
|
void *opaque,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
int (*amend)(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptions *options,
|
||||||
|
bool force,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
int (*get_info)(QCryptoBlock *block,
|
int (*get_info)(QCryptoBlock *block,
|
||||||
QCryptoBlockInfo *info,
|
QCryptoBlockInfo *info,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
@ -253,11 +253,14 @@ Command description:
|
|||||||
|
|
||||||
.. program:: qemu-img-commands
|
.. program:: qemu-img-commands
|
||||||
|
|
||||||
.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] -o OPTIONS FILENAME
|
.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] [--force] -o OPTIONS FILENAME
|
||||||
|
|
||||||
Amends the image format specific *OPTIONS* for the image file
|
Amends the image format specific *OPTIONS* for the image file
|
||||||
*FILENAME*. Not all file formats support this operation.
|
*FILENAME*. Not all file formats support this operation.
|
||||||
|
|
||||||
|
--force allows some unsafe operations. Currently for -f luks, it allows to
|
||||||
|
erase the last encryption key, and to overwrite an active encryption key.
|
||||||
|
|
||||||
.. option:: bench [-c COUNT] [-d DEPTH] [-f FMT] [--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET] [--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U] FILENAME
|
.. option:: bench [-c COUNT] [-d DEPTH] [-f FMT] [--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET] [--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U] FILENAME
|
||||||
|
|
||||||
Run a simple sequential I/O benchmark on the specified image. If ``-w`` is
|
Run a simple sequential I/O benchmark on the specified image. If ``-w`` is
|
||||||
|
@ -21,11 +21,6 @@ typedef struct BlockDriverInfo {
|
|||||||
/* offset at which the VM state can be saved (0 if not possible) */
|
/* offset at which the VM state can be saved (0 if not possible) */
|
||||||
int64_t vm_state_offset;
|
int64_t vm_state_offset;
|
||||||
bool is_dirty;
|
bool is_dirty;
|
||||||
/*
|
|
||||||
* True if unallocated blocks read back as zeroes. This is equivalent
|
|
||||||
* to the LBPRZ flag in the SCSI logical block provisioning page.
|
|
||||||
*/
|
|
||||||
bool unallocated_blocks_are_zero;
|
|
||||||
/*
|
/*
|
||||||
* True if this block driver only supports compressed writes
|
* True if this block driver only supports compressed writes
|
||||||
*/
|
*/
|
||||||
@ -450,6 +445,7 @@ typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
|
|||||||
int64_t total_work_size, void *opaque);
|
int64_t total_work_size, void *opaque);
|
||||||
int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
|
int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
|
||||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||||
|
bool force,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
/* check if a named node can be replaced when doing drive-mirror */
|
/* check if a named node can be replaced when doing drive-mirror */
|
||||||
@ -488,7 +484,6 @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
|||||||
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
||||||
int bdrv_has_zero_init_1(BlockDriverState *bs);
|
int bdrv_has_zero_init_1(BlockDriverState *bs);
|
||||||
int bdrv_has_zero_init(BlockDriverState *bs);
|
int bdrv_has_zero_init(BlockDriverState *bs);
|
||||||
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
|
|
||||||
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
|
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
|
||||||
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
|
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
|
||||||
int64_t bytes, int64_t *pnum, int64_t *map,
|
int64_t bytes, int64_t *pnum, int64_t *map,
|
||||||
|
@ -123,7 +123,17 @@ struct BlockDriver {
|
|||||||
*/
|
*/
|
||||||
bool bdrv_needs_filename;
|
bool bdrv_needs_filename;
|
||||||
|
|
||||||
/* Set if a driver can support backing files */
|
/*
|
||||||
|
* Set if a driver can support backing files. This also implies the
|
||||||
|
* following semantics:
|
||||||
|
*
|
||||||
|
* - Return status 0 of .bdrv_co_block_status means that corresponding
|
||||||
|
* blocks are not allocated in this layer of backing-chain
|
||||||
|
* - For such (unallocated) blocks, read will:
|
||||||
|
* - fill buffer with zeros if there is no backing file
|
||||||
|
* - read from the backing file otherwise, where the block layer
|
||||||
|
* takes care of reading zeros beyond EOF if backing file is short
|
||||||
|
*/
|
||||||
bool supports_backing;
|
bool supports_backing;
|
||||||
|
|
||||||
/* For handling image reopen for split or non-split files */
|
/* For handling image reopen for split or non-split files */
|
||||||
@ -141,12 +151,27 @@ struct BlockDriver {
|
|||||||
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
|
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void (*bdrv_close)(BlockDriverState *bs);
|
void (*bdrv_close)(BlockDriverState *bs);
|
||||||
|
|
||||||
|
|
||||||
int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
|
int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv,
|
int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
QemuOpts *opts,
|
QemuOpts *opts,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
int coroutine_fn (*bdrv_co_amend)(BlockDriverState *bs,
|
||||||
|
BlockdevAmendOptions *opts,
|
||||||
|
bool force,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
int (*bdrv_amend_options)(BlockDriverState *bs,
|
||||||
|
QemuOpts *opts,
|
||||||
|
BlockDriverAmendStatusCB *status_cb,
|
||||||
|
void *cb_opaque,
|
||||||
|
bool force,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
int (*bdrv_make_empty)(BlockDriverState *bs);
|
int (*bdrv_make_empty)(BlockDriverState *bs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -420,6 +445,10 @@ struct BlockDriver {
|
|||||||
|
|
||||||
/* List of options for creating images, terminated by name == NULL */
|
/* List of options for creating images, terminated by name == NULL */
|
||||||
QemuOptsList *create_opts;
|
QemuOptsList *create_opts;
|
||||||
|
|
||||||
|
/* List of options for image amend */
|
||||||
|
QemuOptsList *amend_opts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this driver supports reopening images this contains a
|
* If this driver supports reopening images this contains a
|
||||||
* NULL-terminated list of the runtime options that can be
|
* NULL-terminated list of the runtime options that can be
|
||||||
@ -437,11 +466,6 @@ struct BlockDriver {
|
|||||||
BdrvCheckResult *result,
|
BdrvCheckResult *result,
|
||||||
BdrvCheckMode fix);
|
BdrvCheckMode fix);
|
||||||
|
|
||||||
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
|
|
||||||
BlockDriverAmendStatusCB *status_cb,
|
|
||||||
void *cb_opaque,
|
|
||||||
Error **errp);
|
|
||||||
|
|
||||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
|
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
|
||||||
|
|
||||||
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
|
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
|
||||||
|
@ -144,6 +144,28 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
|||||||
void *opaque,
|
void *opaque,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_block_amend_options:
|
||||||
|
* @block: the block encryption object
|
||||||
|
*
|
||||||
|
* @readfunc: callback for reading data from the volume header
|
||||||
|
* @writefunc: callback for writing data to the volume header
|
||||||
|
* @opaque: data to pass to @readfunc and @writefunc
|
||||||
|
* @options: the new/amended encryption options
|
||||||
|
* @force: hint for the driver to allow unsafe operation
|
||||||
|
* @errp: error pointer
|
||||||
|
*
|
||||||
|
* Changes the crypto options of the encryption format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int qcrypto_block_amend_options(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
QCryptoBlockWriteFunc writefunc,
|
||||||
|
void *opaque,
|
||||||
|
QCryptoBlockAmendOptions *options,
|
||||||
|
bool force,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_block_calculate_payload_offset:
|
* qcrypto_block_calculate_payload_offset:
|
||||||
|
@ -4674,6 +4674,74 @@
|
|||||||
'data': { 'job-id': 'str',
|
'data': { 'job-id': 'str',
|
||||||
'options': 'BlockdevCreateOptions' } }
|
'options': 'BlockdevCreateOptions' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @BlockdevAmendOptionsLUKS:
|
||||||
|
#
|
||||||
|
# Driver specific image amend options for LUKS.
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'BlockdevAmendOptionsLUKS',
|
||||||
|
'base': 'QCryptoBlockAmendOptionsLUKS',
|
||||||
|
'data': { }
|
||||||
|
}
|
||||||
|
|
||||||
|
##
|
||||||
|
# @BlockdevAmendOptionsQcow2:
|
||||||
|
#
|
||||||
|
# Driver specific image amend options for qcow2.
|
||||||
|
# For now, only encryption options can be amended
|
||||||
|
#
|
||||||
|
# @encrypt Encryption options to be amended
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'BlockdevAmendOptionsQcow2',
|
||||||
|
'data': { '*encrypt': 'QCryptoBlockAmendOptions' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @BlockdevAmendOptions:
|
||||||
|
#
|
||||||
|
# Options for amending an image format
|
||||||
|
#
|
||||||
|
# @driver: Block driver of the node to amend.
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'union': 'BlockdevAmendOptions',
|
||||||
|
'base': {
|
||||||
|
'driver': 'BlockdevDriver' },
|
||||||
|
'discriminator': 'driver',
|
||||||
|
'data': {
|
||||||
|
'luks': 'BlockdevAmendOptionsLUKS',
|
||||||
|
'qcow2': 'BlockdevAmendOptionsQcow2' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @x-blockdev-amend:
|
||||||
|
#
|
||||||
|
# Starts a job to amend format specific options of an existing open block device
|
||||||
|
# The job is automatically finalized, but a manual job-dismiss is required.
|
||||||
|
#
|
||||||
|
# @job-id: Identifier for the newly created job.
|
||||||
|
#
|
||||||
|
# @node-name: Name of the block node to work on
|
||||||
|
#
|
||||||
|
# @options: Options (driver specific)
|
||||||
|
#
|
||||||
|
# @force: Allow unsafe operations, format specific
|
||||||
|
# For luks that allows erase of the last active keyslot
|
||||||
|
# (permanent loss of data),
|
||||||
|
# and replacement of an active keyslot
|
||||||
|
# (possible loss of data if IO error happens)
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'command': 'x-blockdev-amend',
|
||||||
|
'data': { 'job-id': 'str',
|
||||||
|
'node-name': 'str',
|
||||||
|
'options': 'BlockdevAmendOptions',
|
||||||
|
'*force': 'bool' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @BlockErrorAction:
|
# @BlockErrorAction:
|
||||||
#
|
#
|
||||||
|
@ -297,7 +297,6 @@
|
|||||||
'uuid': 'str',
|
'uuid': 'str',
|
||||||
'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }}
|
'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }}
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# @QCryptoBlockInfo:
|
# @QCryptoBlockInfo:
|
||||||
#
|
#
|
||||||
@ -309,3 +308,75 @@
|
|||||||
'base': 'QCryptoBlockInfoBase',
|
'base': 'QCryptoBlockInfoBase',
|
||||||
'discriminator': 'format',
|
'discriminator': 'format',
|
||||||
'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
|
'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @QCryptoBlockLUKSKeyslotState:
|
||||||
|
#
|
||||||
|
# Defines state of keyslots that are affected by the update
|
||||||
|
#
|
||||||
|
# @active: The slots contain the given password and marked as active
|
||||||
|
# @inactive: The slots are erased (contain garbage) and marked as inactive
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'enum': 'QCryptoBlockLUKSKeyslotState',
|
||||||
|
'data': [ 'active', 'inactive' ] }
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# @QCryptoBlockAmendOptionsLUKS:
|
||||||
|
#
|
||||||
|
# This struct defines the update parameters that activate/de-activate set
|
||||||
|
# of keyslots
|
||||||
|
#
|
||||||
|
# @state: the desired state of the keyslots
|
||||||
|
#
|
||||||
|
# @new-secret: The ID of a QCryptoSecret object providing the password to be
|
||||||
|
# written into added active keyslots
|
||||||
|
#
|
||||||
|
# @old-secret: Optional (for deactivation only)
|
||||||
|
# If given will deactive all keyslots that
|
||||||
|
# match password located in QCryptoSecret with this ID
|
||||||
|
#
|
||||||
|
# @iter-time: Optional (for activation only)
|
||||||
|
# Number of milliseconds to spend in
|
||||||
|
# PBKDF passphrase processing for the newly activated keyslot.
|
||||||
|
# Currently defaults to 2000.
|
||||||
|
#
|
||||||
|
# @keyslot: Optional. ID of the keyslot to activate/deactivate.
|
||||||
|
# For keyslot activation, keyslot should not be active already
|
||||||
|
# (this is unsafe to update an active keyslot),
|
||||||
|
# but possible if 'force' parameter is given.
|
||||||
|
# If keyslot is not given, first free keyslot will be written.
|
||||||
|
#
|
||||||
|
# For keyslot deactivation, this parameter specifies the exact
|
||||||
|
# keyslot to deactivate
|
||||||
|
#
|
||||||
|
# @secret: Optional. The ID of a QCryptoSecret object providing the
|
||||||
|
# password to use to retrive current master key.
|
||||||
|
# Defaults to the same secret that was used to open the image
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Since 5.1
|
||||||
|
##
|
||||||
|
{ 'struct': 'QCryptoBlockAmendOptionsLUKS',
|
||||||
|
'data': { 'state': 'QCryptoBlockLUKSKeyslotState',
|
||||||
|
'*new-secret': 'str',
|
||||||
|
'*old-secret': 'str',
|
||||||
|
'*keyslot': 'int',
|
||||||
|
'*iter-time': 'int',
|
||||||
|
'*secret': 'str' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @QCryptoBlockAmendOptions:
|
||||||
|
#
|
||||||
|
# The options that are available for all encryption formats
|
||||||
|
# when amending encryption settings
|
||||||
|
#
|
||||||
|
# Since: 5.1
|
||||||
|
##
|
||||||
|
{ 'union': 'QCryptoBlockAmendOptions',
|
||||||
|
'base': 'QCryptoBlockOptionsBase',
|
||||||
|
'discriminator': 'format',
|
||||||
|
'data': {
|
||||||
|
'luks': 'QCryptoBlockAmendOptionsLUKS' } }
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
#
|
#
|
||||||
# @create: image creation job type, see "blockdev-create" (since 3.0)
|
# @create: image creation job type, see "blockdev-create" (since 3.0)
|
||||||
#
|
#
|
||||||
|
# @amend: image options amend job type, see "x-blockdev-amend" (since 5.1)
|
||||||
|
#
|
||||||
# Since: 1.7
|
# Since: 1.7
|
||||||
##
|
##
|
||||||
{ 'enum': 'JobType',
|
{ 'enum': 'JobType',
|
||||||
'data': ['commit', 'stream', 'mirror', 'backup', 'create'] }
|
'data': ['commit', 'stream', 'mirror', 'backup', 'create', 'amend'] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @JobStatus:
|
# @JobStatus:
|
||||||
|
@ -10,9 +10,9 @@ HXCOMM When amending the rST sections, please remember to copy the usage
|
|||||||
HXCOMM over to the per-command sections in docs/tools/qemu-img.rst.
|
HXCOMM over to the per-command sections in docs/tools/qemu-img.rst.
|
||||||
|
|
||||||
DEF("amend", img_amend,
|
DEF("amend", img_amend,
|
||||||
"amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename")
|
"amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] [--force] -o options filename")
|
||||||
SRST
|
SRST
|
||||||
.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] -o OPTIONS FILENAME
|
.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t CACHE] [--force] -o OPTIONS FILENAME
|
||||||
ERST
|
ERST
|
||||||
|
|
||||||
DEF("bench", img_bench,
|
DEF("bench", img_bench,
|
||||||
|
48
qemu-img.c
48
qemu-img.c
@ -79,6 +79,7 @@ enum {
|
|||||||
OPTION_DISABLE = 273,
|
OPTION_DISABLE = 273,
|
||||||
OPTION_MERGE = 274,
|
OPTION_MERGE = 274,
|
||||||
OPTION_BITMAPS = 275,
|
OPTION_BITMAPS = 275,
|
||||||
|
OPTION_FORCE = 276,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum OutputFormat {
|
typedef enum OutputFormat {
|
||||||
@ -1680,7 +1681,6 @@ typedef struct ImgConvertState {
|
|||||||
BlockBackend *target;
|
BlockBackend *target;
|
||||||
bool has_zero_init;
|
bool has_zero_init;
|
||||||
bool compressed;
|
bool compressed;
|
||||||
bool unallocated_blocks_are_zero;
|
|
||||||
bool target_is_new;
|
bool target_is_new;
|
||||||
bool target_has_backing;
|
bool target_has_backing;
|
||||||
int64_t target_backing_sectors; /* negative if unknown */
|
int64_t target_backing_sectors; /* negative if unknown */
|
||||||
@ -1725,7 +1725,7 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
|||||||
|
|
||||||
if (s->target_backing_sectors >= 0) {
|
if (s->target_backing_sectors >= 0) {
|
||||||
if (sector_num >= s->target_backing_sectors) {
|
if (sector_num >= s->target_backing_sectors) {
|
||||||
post_backing_zero = s->unallocated_blocks_are_zero;
|
post_backing_zero = true;
|
||||||
} else if (sector_num + n > s->target_backing_sectors) {
|
} else if (sector_num + n > s->target_backing_sectors) {
|
||||||
/* Split requests around target_backing_sectors (because
|
/* Split requests around target_backing_sectors (because
|
||||||
* starting from there, zeros are handled differently) */
|
* starting from there, zeros are handled differently) */
|
||||||
@ -2677,7 +2677,6 @@ static int img_convert(int argc, char **argv)
|
|||||||
} else {
|
} else {
|
||||||
s.compressed = s.compressed || bdi.needs_compressed_writes;
|
s.compressed = s.compressed || bdi.needs_compressed_writes;
|
||||||
s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
|
s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
|
||||||
s.unallocated_blocks_are_zero = bdi.unallocated_blocks_are_zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = convert_do_copy(&s);
|
ret = convert_do_copy(&s);
|
||||||
@ -4067,12 +4066,11 @@ static int print_amend_option_help(const char *format)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every driver supporting amendment must have create_opts */
|
/* Every driver supporting amendment must have amend_opts */
|
||||||
assert(drv->create_opts);
|
assert(drv->amend_opts);
|
||||||
|
|
||||||
printf("Creation options for '%s':\n", format);
|
printf("Amend options for '%s':\n", format);
|
||||||
qemu_opts_print_help(drv->create_opts, false);
|
qemu_opts_print_help(drv->amend_opts, false);
|
||||||
printf("\nNote that not all of these options may be amendable.\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4081,7 +4079,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
int c, ret = 0;
|
int c, ret = 0;
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
QemuOptsList *create_opts = NULL;
|
QemuOptsList *amend_opts = NULL;
|
||||||
QemuOpts *opts = NULL;
|
QemuOpts *opts = NULL;
|
||||||
const char *fmt = NULL, *filename, *cache;
|
const char *fmt = NULL, *filename, *cache;
|
||||||
int flags;
|
int flags;
|
||||||
@ -4090,6 +4088,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
BlockBackend *blk = NULL;
|
BlockBackend *blk = NULL;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
bool image_opts = false;
|
bool image_opts = false;
|
||||||
|
bool force = false;
|
||||||
|
|
||||||
cache = BDRV_DEFAULT_CACHE;
|
cache = BDRV_DEFAULT_CACHE;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -4097,6 +4096,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"object", required_argument, 0, OPTION_OBJECT},
|
{"object", required_argument, 0, OPTION_OBJECT},
|
||||||
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
|
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
|
||||||
|
{"force", no_argument, 0, OPTION_FORCE},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
c = getopt_long(argc, argv, ":ho:f:t:pq",
|
c = getopt_long(argc, argv, ":ho:f:t:pq",
|
||||||
@ -4144,6 +4144,9 @@ static int img_amend(int argc, char **argv)
|
|||||||
case OPTION_IMAGE_OPTS:
|
case OPTION_IMAGE_OPTS:
|
||||||
image_opts = true;
|
image_opts = true;
|
||||||
break;
|
break;
|
||||||
|
case OPTION_FORCE:
|
||||||
|
force = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4207,13 +4210,28 @@ static int img_amend(int argc, char **argv)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every driver supporting amendment must have create_opts */
|
/* Every driver supporting amendment must have amend_opts */
|
||||||
assert(bs->drv->create_opts);
|
assert(bs->drv->amend_opts);
|
||||||
|
|
||||||
create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
|
amend_opts = qemu_opts_append(amend_opts, bs->drv->amend_opts);
|
||||||
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
|
opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort);
|
||||||
qemu_opts_do_parse(opts, options, NULL, &err);
|
qemu_opts_do_parse(opts, options, NULL, &err);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
/* Try to parse options using the create options */
|
||||||
|
Error *err1 = NULL;
|
||||||
|
amend_opts = qemu_opts_append(amend_opts, bs->drv->create_opts);
|
||||||
|
qemu_opts_del(opts);
|
||||||
|
opts = qemu_opts_create(amend_opts, NULL, 0, &error_abort);
|
||||||
|
qemu_opts_do_parse(opts, options, NULL, &err1);
|
||||||
|
|
||||||
|
if (!err1) {
|
||||||
|
error_append_hint(&err,
|
||||||
|
"This option is only supported for image creation\n");
|
||||||
|
} else {
|
||||||
|
error_free(err1);
|
||||||
|
}
|
||||||
|
|
||||||
error_report_err(err);
|
error_report_err(err);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@ -4221,7 +4239,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
|
|
||||||
/* In case the driver does not call amend_status_cb() */
|
/* In case the driver does not call amend_status_cb() */
|
||||||
qemu_progress_print(0.f, 0);
|
qemu_progress_print(0.f, 0);
|
||||||
ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, &err);
|
ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, force, &err);
|
||||||
qemu_progress_print(100.f, 0);
|
qemu_progress_print(100.f, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report_err(err);
|
error_report_err(err);
|
||||||
@ -4234,7 +4252,7 @@ out:
|
|||||||
out_no_progress:
|
out_no_progress:
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
qemu_opts_free(create_opts);
|
qemu_opts_free(amend_opts);
|
||||||
g_free(options);
|
g_free(options);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -4,90 +4,90 @@ QA output created by 049
|
|||||||
== 1. Traditional size parameter ==
|
== 1. Traditional size parameter ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
|
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== 2. Specifying size via -o ==
|
== 2. Specifying size via -o ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
|
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== 3. Invalid sizes ==
|
== 3. Invalid sizes ==
|
||||||
|
|
||||||
@ -129,84 +129,84 @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once
|
|||||||
== Check correct interpretation of suffixes for cluster size ==
|
== Check correct interpretation of suffixes for cluster size ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== Check compat level option ==
|
== Check compat level option ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
|
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 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
|
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 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
|
||||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
|
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
|
||||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
|
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== Check preallocation option ==
|
== Check preallocation option ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
|
||||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
|
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== Check encryption option ==
|
== Check encryption option ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
|
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 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 compression_type=zlib size=67108864 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
|
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 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== Check lazy_refcounts option (only with v3) ==
|
== Check lazy_refcounts option (only with v3) ==
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
|
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 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
|
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 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
|
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 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 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 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 version=v3 or greater)
|
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
|
||||||
|
|
||||||
*** done
|
*** done
|
||||||
|
@ -381,16 +381,20 @@ qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (
|
|||||||
qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
|
qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
|
||||||
qemu-img: Unknown compatibility level 0.42
|
qemu-img: Unknown compatibility level 0.42
|
||||||
qemu-img: Invalid parameter 'foo'
|
qemu-img: Invalid parameter 'foo'
|
||||||
qemu-img: Changing the cluster size is not supported
|
qemu-img: Invalid parameter 'cluster_size'
|
||||||
qemu-img: Changing the encryption flag is not supported
|
This option is only supported for image creation
|
||||||
qemu-img: Cannot change preallocation mode
|
qemu-img: Invalid parameter 'encryption'
|
||||||
|
This option is only supported for image creation
|
||||||
|
qemu-img: Invalid parameter 'preallocation'
|
||||||
|
This option is only supported for image creation
|
||||||
|
|
||||||
=== Testing correct handling of unset value ===
|
=== Testing correct handling of unset value ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
Should work:
|
Should work:
|
||||||
Should not work:
|
Should not work:
|
||||||
qemu-img: Changing the cluster size is not supported
|
qemu-img: Invalid parameter 'cluster_size'
|
||||||
|
This option is only supported for image creation
|
||||||
|
|
||||||
=== Testing zero expansion on inactive clusters ===
|
=== Testing zero expansion on inactive clusters ===
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@ QA output created by 082
|
|||||||
=== create: Options specified more than once ===
|
=== create: Options specified more than once ===
|
||||||
|
|
||||||
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
|
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 128 MiB (134217728 bytes)
|
virtual size: 128 MiB (134217728 bytes)
|
||||||
cluster_size: 65536
|
cluster_size: 65536
|
||||||
|
|
||||||
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M
|
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 cluster_size=4096 lazy_refcounts=on refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=4096 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 128 MiB (134217728 bytes)
|
virtual size: 128 MiB (134217728 bytes)
|
||||||
@ -23,7 +23,7 @@ Format specific information:
|
|||||||
corrupt: false
|
corrupt: false
|
||||||
|
|
||||||
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M
|
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 cluster_size=8192 lazy_refcounts=on refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 128 MiB (134217728 bytes)
|
virtual size: 128 MiB (134217728 bytes)
|
||||||
@ -36,7 +36,7 @@ Format specific information:
|
|||||||
corrupt: false
|
corrupt: false
|
||||||
|
|
||||||
Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M
|
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 cluster_size=8192 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
image: TEST_DIR/t.IMGFMT
|
image: TEST_DIR/t.IMGFMT
|
||||||
file format: IMGFMT
|
file format: IMGFMT
|
||||||
virtual size: 128 MiB (134217728 bytes)
|
virtual size: 128 MiB (134217728 bytes)
|
||||||
@ -237,10 +237,10 @@ Supported options:
|
|||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
|
Testing: create -f qcow2 -u -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 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
|
Testing: create -f qcow2 -u -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,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
|
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,
|
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
|
||||||
@ -290,7 +290,7 @@ qemu-img: Format driver 'bochs' does not support image creation
|
|||||||
=== convert: Options specified more than once ===
|
=== convert: Options specified more than once ===
|
||||||
|
|
||||||
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
|
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
|
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
|
||||||
image: TEST_DIR/t.IMGFMT.base
|
image: TEST_DIR/t.IMGFMT.base
|
||||||
@ -639,205 +639,133 @@ cluster_size: 65536
|
|||||||
=== amend: help for -o ===
|
=== amend: help for -o ===
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
|
Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
|
||||||
|
|
||||||
Testing: rebase -u -b -f qcow2 TEST_DIR/t.qcow2
|
Testing: rebase -u -b -f qcow2 TEST_DIR/t.qcow2
|
||||||
@ -856,30 +784,21 @@ Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2 -o ,, -o help TEST_DIR/
|
|||||||
qemu-img: Invalid option list: ,,
|
qemu-img: Invalid option list: ,,
|
||||||
|
|
||||||
Testing: amend -f qcow2 -o help
|
Testing: amend -f qcow2 -o help
|
||||||
Creation options for 'qcow2':
|
Amend options for 'qcow2':
|
||||||
backing_file=<str> - File name of a base image
|
backing_file=<str> - File name of a base image
|
||||||
backing_fmt=<str> - Image format of the base image
|
backing_fmt=<str> - Image format of the base image
|
||||||
cluster_size=<size> - qcow2 cluster size
|
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
compression_type=<str> - Compression method used for image cluster compression
|
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
|
|
||||||
encrypt.cipher-mode=<str> - Name of encryption cipher mode
|
|
||||||
encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
|
|
||||||
encrypt.hash-alg=<str> - Name of encryption hash algorithm
|
|
||||||
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
encrypt.ivgen-alg=<str> - Name of IV generator algorithm
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
|
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
||||||
Note that not all of these options may be amendable.
|
|
||||||
|
|
||||||
Testing: amend -o help
|
Testing: amend -o help
|
||||||
qemu-img: Expecting one image file name
|
qemu-img: Expecting one image file name
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
|
|||||||
=== Create a single snapshot on virtio0 ===
|
=== Create a single snapshot on virtio0 ===
|
||||||
|
|
||||||
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
|
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
=== Invalid command - missing device and nodename ===
|
=== Invalid command - missing device and nodename ===
|
||||||
@ -30,40 +30,40 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file
|
|||||||
=== Create several transactional group snapshots ===
|
=== Create several transactional group snapshots ===
|
||||||
|
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
|
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 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 compression_type=zlib
|
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
=== Create a couple of snapshots using blockdev-snapshot ===
|
=== Create a couple of snapshots using blockdev-snapshot ===
|
||||||
|
@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto file
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
do_run_qemu()
|
do_run_qemu()
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ QMP_VERSION
|
|||||||
|
|
||||||
=== Encrypted image QCow ===
|
=== Encrypted image QCow ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
Testing:
|
Testing:
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
@ -46,7 +46,7 @@ QMP_VERSION
|
|||||||
|
|
||||||
=== Encrypted image LUKS ===
|
=== Encrypted image LUKS ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encrypt.format=luks encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
Testing:
|
Testing:
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
@ -58,7 +58,7 @@ QMP_VERSION
|
|||||||
|
|
||||||
=== Missing driver ===
|
=== Missing driver ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
Testing: -S
|
Testing: -S
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
@ -5,7 +5,7 @@ QA output created by 112
|
|||||||
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount_bits=-1
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits
|
||||||
|
@ -164,6 +164,30 @@ for GROWTH_SIZE in 16 48 80; do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Test image resizing using preallocation and unaligned offsets
|
||||||
|
$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create
|
||||||
|
$QEMU_IO -c 'write -q -P 1 0 128k' -f raw "$TEST_IMG.base"
|
||||||
|
for orig_size in 31k 33k; do
|
||||||
|
echo "--- Resizing image from $orig_size to 96k ---"
|
||||||
|
_make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size"
|
||||||
|
$QEMU_IMG resize -f "$IMGFMT" --preallocation=full "$TEST_IMG" 96k
|
||||||
|
# The first part of the image should contain data from the backing file
|
||||||
|
$QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG"
|
||||||
|
# The resized part of the image should contain zeroes
|
||||||
|
$QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG"
|
||||||
|
# If the image does not have an external data file we can also verify its
|
||||||
|
# actual size. The resized image should have 7 clusters:
|
||||||
|
# header, L1 table, L2 table, refcount table, refcount block, 2 data clusters
|
||||||
|
if ! _get_data_file "$TEST_IMG" > /dev/null; then
|
||||||
|
expected_file_length=$((65536 * 7))
|
||||||
|
file_length=$(stat -c '%s' "$TEST_IMG_FILE")
|
||||||
|
if [ "$file_length" != "$expected_file_length" ]; then
|
||||||
|
echo "ERROR: file length $file_length (expected $expected_file_length)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo '*** done'
|
echo '*** done'
|
||||||
rm -f $seq.full
|
rm -f $seq.full
|
||||||
|
@ -767,4 +767,13 @@ wrote 2048000/2048000 bytes at offset 0
|
|||||||
wrote 81920/81920 bytes at offset 2048000
|
wrote 81920/81920 bytes at offset 2048000
|
||||||
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072
|
||||||
|
--- Resizing image from 31k to 96k ---
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
|
||||||
|
Image resized.
|
||||||
|
|
||||||
|
--- Resizing image from 33k to 96k ---
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
|
||||||
|
Image resized.
|
||||||
|
|
||||||
*** done
|
*** done
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
QA output created by 134
|
QA output created by 134
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
|
|
||||||
== reading whole image ==
|
== reading whole image ==
|
||||||
read 134217728/134217728 bytes at offset 0
|
read 134217728/134217728 bytes at offset 0
|
||||||
|
@ -68,7 +68,7 @@ test_blockjob()
|
|||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
"$1" \
|
"$1" \
|
||||||
"$2" \
|
"$2" \
|
||||||
| _filter_img_create | _filter_qmp_empty_return
|
| _filter_img_create_in_qmp | _filter_qmp_empty_return
|
||||||
|
|
||||||
# We want this to return an error because the block job is still running
|
# We want this to return an error because the block job is still running
|
||||||
_send_qemu_cmd $QEMU_HANDLE \
|
_send_qemu_cmd $QEMU_HANDLE \
|
||||||
|
@ -9,7 +9,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
|
|||||||
{ 'execute': 'qmp_capabilities' }
|
{ 'execute': 'qmp_capabilities' }
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
|
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
=== Performing block-commit on active layer ===
|
=== Performing block-commit on active layer ===
|
||||||
@ -31,6 +31,6 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/
|
|||||||
=== Performing Live Snapshot 2 ===
|
=== Performing Live Snapshot 2 ===
|
||||||
|
|
||||||
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
|
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
*** done
|
*** done
|
||||||
|
@ -51,19 +51,25 @@ echo === Testing VPC Autodetect ===
|
|||||||
echo
|
echo
|
||||||
_use_sample_img virtualpc-dynamic.vhd.bz2
|
_use_sample_img virtualpc-dynamic.vhd.bz2
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing VPC with current_size force ===
|
echo === Testing VPC with current_size force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing VPC with chs force ===
|
echo === Testing VPC with chs force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
_cleanup_test_img
|
_cleanup_test_img
|
||||||
|
|
||||||
@ -72,19 +78,25 @@ echo === Testing Hyper-V Autodetect ===
|
|||||||
echo
|
echo
|
||||||
_use_sample_img hyperv2012r2-dynamic.vhd.bz2
|
_use_sample_img hyperv2012r2-dynamic.vhd.bz2
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing Hyper-V with current_size force ===
|
echo === Testing Hyper-V with current_size force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing Hyper-V with chs force ===
|
echo === Testing Hyper-V with chs force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
_cleanup_test_img
|
_cleanup_test_img
|
||||||
|
|
||||||
@ -93,19 +105,25 @@ echo === Testing d2v Autodetect ===
|
|||||||
echo
|
echo
|
||||||
_use_sample_img d2v-zerofilled.vhd.bz2
|
_use_sample_img d2v-zerofilled.vhd.bz2
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing d2v with current_size force ===
|
echo === Testing d2v with current_size force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing d2v with chs force ===
|
echo === Testing d2v with chs force ===
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
_cleanup_test_img
|
_cleanup_test_img
|
||||||
|
|
||||||
@ -121,19 +139,25 @@ echo
|
|||||||
echo === Read created image, default opts ====
|
echo === Read created image, default opts ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Read created image, force_size_calc=chs ====
|
echo === Read created image, force_size_calc=chs ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Read created image, force_size_calc=current_size ====
|
echo === Read created image, force_size_calc=current_size ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Testing Image create, force_size ===
|
echo === Testing Image create, force_size ===
|
||||||
@ -145,19 +169,25 @@ echo
|
|||||||
echo === Read created image, default opts ====
|
echo === Read created image, default opts ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Read created image, force_size_calc=chs ====
|
echo === Read created image, force_size_calc=chs ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=chs,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo === Read created image, force_size_calc=current_size ====
|
echo === Read created image, force_size_calc=current_size ====
|
||||||
echo
|
echo
|
||||||
|
|
||||||
${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
|
$QEMU_IMG map --output=json --image-opts \
|
||||||
|
"driver=vpc,force_size_calc=current_size,file.filename=$TEST_IMG" \
|
||||||
|
| _filter_qemu_img_map
|
||||||
|
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
rm -f $seq.full
|
rm -f $seq.full
|
||||||
|
@ -2,39 +2,414 @@ QA output created by 146
|
|||||||
|
|
||||||
=== Testing VPC Autodetect ===
|
=== Testing VPC Autodetect ===
|
||||||
|
|
||||||
126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing VPC with current_size force ===
|
=== Testing VPC with current_size force ===
|
||||||
|
|
||||||
127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing VPC with chs force ===
|
=== Testing VPC with chs force ===
|
||||||
|
|
||||||
126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing Hyper-V Autodetect ===
|
=== Testing Hyper-V Autodetect ===
|
||||||
|
|
||||||
127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing Hyper-V with current_size force ===
|
=== Testing Hyper-V with current_size force ===
|
||||||
|
|
||||||
127 GiB (0x1fc0000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing Hyper-V with chs force ===
|
=== Testing Hyper-V with chs force ===
|
||||||
|
|
||||||
126.998 GiB (0x1fbfe04000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing d2v Autodetect ===
|
=== Testing d2v Autodetect ===
|
||||||
|
|
||||||
251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
|
||||||
|
|
||||||
=== Testing d2v with current_size force ===
|
=== Testing d2v with current_size force ===
|
||||||
|
|
||||||
251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
|
||||||
|
|
||||||
=== Testing d2v with chs force ===
|
=== Testing d2v with chs force ===
|
||||||
|
|
||||||
251.250 MiB (0xfb40000) bytes allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
|
||||||
|
{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
|
||||||
|
|
||||||
=== Testing Image create, default ===
|
=== Testing Image create, default ===
|
||||||
|
|
||||||
@ -42,15 +417,15 @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
|
|||||||
|
|
||||||
=== Read created image, default opts ====
|
=== Read created image, default opts ====
|
||||||
|
|
||||||
4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Read created image, force_size_calc=chs ====
|
=== Read created image, force_size_calc=chs ====
|
||||||
|
|
||||||
4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Read created image, force_size_calc=current_size ====
|
=== Read created image, force_size_calc=current_size ====
|
||||||
|
|
||||||
4 GiB (0x10007a000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Testing Image create, force_size ===
|
=== Testing Image create, force_size ===
|
||||||
|
|
||||||
@ -58,13 +433,13 @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
|
|||||||
|
|
||||||
=== Read created image, default opts ====
|
=== Read created image, default opts ====
|
||||||
|
|
||||||
4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Read created image, force_size_calc=chs ====
|
=== Read created image, force_size_calc=chs ====
|
||||||
|
|
||||||
4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
|
||||||
|
|
||||||
=== Read created image, force_size_calc=current_size ====
|
=== Read created image, force_size_calc=current_size ====
|
||||||
|
|
||||||
4 GiB (0x100000000) bytes not allocated at offset 0 bytes (0x0)
|
[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
|
||||||
*** done
|
*** done
|
||||||
|
@ -167,11 +167,10 @@ done
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir
|
echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir
|
||||||
(
|
$QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}" | _filter_img_create
|
||||||
$QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}"
|
$QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}" | _filter_img_create
|
||||||
$QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}"
|
$QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b" \
|
||||||
$QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b"
|
| _filter_img_create
|
||||||
) | _filter_img_create
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== Two devices sharing the same file in backing chain =="
|
echo "== Two devices sharing the same file in backing chain =="
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
QA output created by 158
|
QA output created by 158
|
||||||
== create base ==
|
== create base ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on
|
||||||
|
|
||||||
== writing whole image ==
|
== writing whole image ==
|
||||||
wrote 134217728/134217728 bytes at offset 0
|
wrote 134217728/134217728 bytes at offset 0
|
||||||
@ -10,7 +10,7 @@ wrote 134217728/134217728 bytes at offset 0
|
|||||||
read 134217728/134217728 bytes at offset 0
|
read 134217728/134217728 bytes at offset 0
|
||||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
== create overlay ==
|
== create overlay ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on
|
||||||
|
|
||||||
== writing part of a cluster ==
|
== writing part of a cluster ==
|
||||||
wrote 1024/1024 bytes at offset 0
|
wrote 1024/1024 bytes at offset 0
|
||||||
|
@ -41,6 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt raw qcow2
|
_supported_fmt raw qcow2
|
||||||
_supported_proto file
|
_supported_proto file
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
echo "== Input validation =="
|
echo "== Input validation =="
|
||||||
echo
|
echo
|
||||||
|
@ -13,7 +13,7 @@ Is another process using the image [TEST_DIR/t.qcow2]?
|
|||||||
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
|
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
|
{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
|
||||||
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
|
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
@ -9,14 +9,14 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
|
|||||||
=== Creating backing chain ===
|
=== Creating backing chain ===
|
||||||
|
|
||||||
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
|
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
|
{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
|
||||||
wrote 4194304/4194304 bytes at offset 0
|
wrote 4194304/4194304 bytes at offset 0
|
||||||
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
{"return": ""}
|
{"return": ""}
|
||||||
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
|
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
|
||||||
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 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
|
||||||
=== Start commit job and exit qemu ===
|
=== Start commit job and exit qemu ===
|
||||||
@ -48,7 +48,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q
|
|||||||
{ 'execute': 'qmp_capabilities' }
|
{ 'execute': 'qmp_capabilities' }
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
|
{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
|
||||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
@ -62,7 +62,7 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
|
|||||||
{ 'execute': 'qmp_capabilities' }
|
{ 'execute': 'qmp_capabilities' }
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
|
{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
|
||||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
||||||
|
@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
|
||||||
size=16M
|
size=16M
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
QA output created by 188
|
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
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216
|
||||||
|
|
||||||
== reading whole image ==
|
== reading whole image ==
|
||||||
read 16777216/16777216 bytes at offset 0
|
read 16777216/16777216 bytes at offset 0
|
||||||
|
@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
|
||||||
size=16M
|
size=16M
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
QA output created by 189
|
QA output created by 189
|
||||||
== create base ==
|
== create base ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216
|
||||||
|
|
||||||
== writing whole image ==
|
== writing whole image ==
|
||||||
wrote 16777216/16777216 bytes at offset 0
|
wrote 16777216/16777216 bytes at offset 0
|
||||||
@ -10,7 +10,7 @@ wrote 16777216/16777216 bytes at offset 0
|
|||||||
read 16777216/16777216 bytes at offset 0
|
read 16777216/16777216 bytes at offset 0
|
||||||
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
== create overlay ==
|
== 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
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base
|
||||||
|
|
||||||
== writing part of a cluster ==
|
== writing part of a cluster ==
|
||||||
wrote 1024/1024 bytes at offset 0
|
wrote 1024/1024 bytes at offset 0
|
||||||
|
@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
|
||||||
size=16M
|
size=16M
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
QA output created by 198
|
QA output created by 198
|
||||||
== create base ==
|
== create base ==
|
||||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216
|
||||||
|
|
||||||
== writing whole image base ==
|
== writing whole image base ==
|
||||||
wrote 16777216/16777216 bytes at offset 0
|
wrote 16777216/16777216 bytes at offset 0
|
||||||
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
== create overlay ==
|
== 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
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base
|
||||||
|
|
||||||
== writing whole image layer ==
|
== writing whole image layer ==
|
||||||
wrote 16777216/16777216 bytes at offset 0
|
wrote 16777216/16777216 bytes at offset 0
|
||||||
|
@ -24,6 +24,7 @@ import iotests
|
|||||||
from iotests import imgfmt
|
from iotests import imgfmt
|
||||||
|
|
||||||
iotests.script_initialize(supported_fmts=['qcow2'])
|
iotests.script_initialize(supported_fmts=['qcow2'])
|
||||||
|
iotests.verify_working_luks()
|
||||||
|
|
||||||
with iotests.FilePath('t.qcow2') as disk_path, \
|
with iotests.FilePath('t.qcow2') as disk_path, \
|
||||||
iotests.FilePath('t.qcow2.base') as backing_path, \
|
iotests.FilePath('t.qcow2.base') as backing_path, \
|
||||||
|
@ -3,9 +3,9 @@ Finishing a commit job with background reads
|
|||||||
|
|
||||||
=== Create backing chain and start VM ===
|
=== Create backing chain and start VM ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
=== Start background read requests ===
|
=== Start background read requests ===
|
||||||
|
|
||||||
@ -23,9 +23,9 @@ Closing the VM while a job is being cancelled
|
|||||||
|
|
||||||
=== Create images and start VM ===
|
=== Create images and start VM ===
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 1048576/1048576 bytes at offset 0
|
wrote 1048576/1048576 bytes at offset 0
|
||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
|
||||||
size=1M
|
size=1M
|
||||||
|
@ -2,7 +2,7 @@ QA output created by 263
|
|||||||
|
|
||||||
testing LUKS qcow2 encryption
|
testing LUKS qcow2 encryption
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||||
== reading the whole image ==
|
== reading the whole image ==
|
||||||
read 1048576/1048576 bytes at offset 0
|
read 1048576/1048576 bytes at offset 0
|
||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -21,7 +21,7 @@ read 982528/982528 bytes at offset 66048
|
|||||||
|
|
||||||
testing legacy AES qcow2 encryption
|
testing legacy AES qcow2 encryption
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=aes encrypt.key-secret=sec0
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||||
== reading the whole image ==
|
== reading the whole image ==
|
||||||
read 1048576/1048576 bytes at offset 0
|
read 1048576/1048576 bytes at offset 0
|
||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
== Commit tests ==
|
== Commit tests ==
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 2097152/2097152 bytes at offset 0
|
wrote 2097152/2097152 bytes at offset 0
|
||||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -64,11 +64,11 @@ read 1048576/1048576 bytes at offset 1048576
|
|||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
=== Testing HMP commit (top -> mid) ===
|
=== Testing HMP commit (top -> mid) ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 2097152/2097152 bytes at offset 0
|
wrote 2097152/2097152 bytes at offset 0
|
||||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -94,11 +94,11 @@ read 1048576/1048576 bytes at offset 1048576
|
|||||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
=== Testing QMP active commit (top -> mid) ===
|
=== Testing QMP active commit (top -> mid) ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 2097152/2097152 bytes at offset 0
|
wrote 2097152/2097152 bytes at offset 0
|
||||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -131,9 +131,9 @@ read 1048576/1048576 bytes at offset 1048576
|
|||||||
|
|
||||||
== Resize tests ==
|
== Resize tests ==
|
||||||
=== preallocation=off ===
|
=== preallocation=off ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 5368709120
|
wrote 65536/65536 bytes at offset 5368709120
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -150,9 +150,9 @@ read 65536/65536 bytes at offset 5368709120
|
|||||||
{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
|
{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
|
||||||
|
|
||||||
=== preallocation=metadata ===
|
=== preallocation=metadata ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 33285996544
|
wrote 65536/65536 bytes at offset 33285996544
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -174,9 +174,9 @@ read 65536/65536 bytes at offset 33285996544
|
|||||||
{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
|
{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
|
||||||
|
|
||||||
=== preallocation=falloc ===
|
=== preallocation=falloc ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 9437184
|
wrote 65536/65536 bytes at offset 9437184
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -193,9 +193,9 @@ read 65536/65536 bytes at offset 9437184
|
|||||||
{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
|
{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
|
||||||
|
|
||||||
=== preallocation=full ===
|
=== preallocation=full ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 11534336
|
wrote 65536/65536 bytes at offset 11534336
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -212,9 +212,9 @@ read 65536/65536 bytes at offset 11534336
|
|||||||
{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
|
{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
|
||||||
|
|
||||||
=== preallocation=off ===
|
=== preallocation=off ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 259072
|
wrote 65536/65536 bytes at offset 259072
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -232,9 +232,9 @@ read 65536/65536 bytes at offset 259072
|
|||||||
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
|
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
|
||||||
|
|
||||||
=== preallocation=off ===
|
=== preallocation=off ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 344064
|
wrote 65536/65536 bytes at offset 344064
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
@ -251,9 +251,9 @@ read 65536/65536 bytes at offset 344064
|
|||||||
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
|
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
|
||||||
|
|
||||||
=== preallocation=off ===
|
=== preallocation=off ===
|
||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
wrote 65536/65536 bytes at offset 446464
|
wrote 65536/65536 bytes at offset 446464
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
|
Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
=== Launch VM ===
|
=== Launch VM ===
|
||||||
Enabling migration QMP events on VM...
|
Enabling migration QMP events on VM...
|
||||||
|
@ -39,6 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||||||
_supported_fmt qcow2
|
_supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
|
||||||
size=1M
|
size=1M
|
||||||
|
@ -2,7 +2,7 @@ QA output created by 284
|
|||||||
|
|
||||||
testing LUKS qcow2 encryption
|
testing LUKS qcow2 encryption
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||||
|
|
||||||
== cluster size 512
|
== cluster size 512
|
||||||
== checking image refcounts ==
|
== checking image refcounts ==
|
||||||
@ -21,7 +21,7 @@ wrote 1/1 bytes at offset 512
|
|||||||
|
|
||||||
== rechecking image refcounts ==
|
== rechecking image refcounts ==
|
||||||
No errors were found on the image.
|
No errors were found on the image.
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||||
|
|
||||||
== cluster size 2048
|
== cluster size 2048
|
||||||
== checking image refcounts ==
|
== checking image refcounts ==
|
||||||
@ -40,7 +40,7 @@ wrote 1/1 bytes at offset 2048
|
|||||||
|
|
||||||
== rechecking image refcounts ==
|
== rechecking image refcounts ==
|
||||||
No errors were found on the image.
|
No errors were found on the image.
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||||
|
|
||||||
== cluster size 32768
|
== cluster size 32768
|
||||||
== checking image refcounts ==
|
== checking image refcounts ==
|
||||||
|
208
tests/qemu-iotests/293
Executable file
208
tests/qemu-iotests/293
Executable file
@ -0,0 +1,208 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Test encryption key management with luks
|
||||||
|
# Based on 134
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 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=mlevitsk@redhat.com
|
||||||
|
|
||||||
|
seq=`basename $0`
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
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 luks
|
||||||
|
_supported_proto file #TODO
|
||||||
|
_require_working_luks
|
||||||
|
|
||||||
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||||
|
|
||||||
|
if [ "$IMGFMT" = "qcow2" ] ; then
|
||||||
|
PR="encrypt."
|
||||||
|
EXTRA_IMG_ARGS="-o encrypt.format=luks"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# secrets: you are supposed to see the password as *******, see :-)
|
||||||
|
S0="--object secret,id=sec0,data=hunter0"
|
||||||
|
S1="--object secret,id=sec1,data=hunter1"
|
||||||
|
S2="--object secret,id=sec2,data=hunter2"
|
||||||
|
S3="--object secret,id=sec3,data=hunter3"
|
||||||
|
S4="--object secret,id=sec4,data=hunter4"
|
||||||
|
SECRETS="$S0 $S1 $S2 $S3 $S4"
|
||||||
|
|
||||||
|
# image with given secret
|
||||||
|
IMGS0="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec0"
|
||||||
|
IMGS1="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec1"
|
||||||
|
IMGS2="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec2"
|
||||||
|
IMGS3="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec3"
|
||||||
|
IMGS4="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec4"
|
||||||
|
|
||||||
|
|
||||||
|
echo "== creating a test image =="
|
||||||
|
_make_test_img $S0 $EXTRA_IMG_ARGS -o ${PR}key-secret=sec0,${PR}iter-time=10 32M
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== test that key 0 opens the image =="
|
||||||
|
$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== adding a password to slot 4 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec4,${PR}iter-time=10,${PR}keyslot=4
|
||||||
|
echo "== adding a password to slot 1 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10
|
||||||
|
echo "== adding a password to slot 3 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10,${PR}keyslot=3
|
||||||
|
|
||||||
|
echo "== adding a password to slot 2 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10
|
||||||
|
|
||||||
|
|
||||||
|
echo "== erase slot 4 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=4 | _filter_img_create
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== all secrets should work =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== erase slot 0 and try it =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 | _filter_img_create
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== erase slot 2 and try it =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=2 | _filter_img_create
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS2 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
|
||||||
|
# at this point slots 1 and 3 should be active
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== filling 4 slots with secret 2 =="
|
||||||
|
for ((i = 0; i < 4; i++)); do
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== adding secret 0 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== adding secret 3 (last slot) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== trying to add another slot (should fail) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS2 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== all secrets should work again =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "== erase all keys of secret 2=="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec2
|
||||||
|
|
||||||
|
echo "== erase all keys of secret 1=="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1
|
||||||
|
|
||||||
|
echo "== erase all keys of secret 0=="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec0
|
||||||
|
|
||||||
|
echo "== erasing secret3 will fail now since it is the only secret (in 3 slots) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=inactive,${PR}old-secret=sec3
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== only secret3 should work now =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== add secret0 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10
|
||||||
|
|
||||||
|
echo "== erase secret3 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec3
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== only secret0 should work now =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== replace secret0 with secret1 (should fail) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}keyslot=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== replace secret0 with secret1 with force (should work) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10,${PR}keyslot=0 --force
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== only secret1 should work now =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== erase last secret (should fail) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1
|
||||||
|
|
||||||
|
|
||||||
|
echo "== erase non existing secrets (should fail) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec5 --force
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 --force
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=1 --force
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== erase last secret with force by slot (should work) =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0 --force
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== we have no secrets now, data is lost forever =="
|
||||||
|
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
|
||||||
|
done
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo "*** done"
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
||||||
|
|
99
tests/qemu-iotests/293.out
Normal file
99
tests/qemu-iotests/293.out
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
QA output created by 293
|
||||||
|
== creating a test image ==
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432
|
||||||
|
|
||||||
|
== test that key 0 opens the image ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
== adding a password to slot 4 ==
|
||||||
|
== adding a password to slot 1 ==
|
||||||
|
== adding a password to slot 3 ==
|
||||||
|
== adding a password to slot 2 ==
|
||||||
|
== erase slot 4 ==
|
||||||
|
|
||||||
|
== all secrets should work ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
== erase slot 0 and try it ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== erase slot 2 and try it ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== filling 4 slots with secret 2 ==
|
||||||
|
|
||||||
|
== adding secret 0 ==
|
||||||
|
|
||||||
|
== adding secret 3 (last slot) ==
|
||||||
|
|
||||||
|
== trying to add another slot (should fail) ==
|
||||||
|
qemu-img: Can't add a keyslot - all keyslots are in use
|
||||||
|
|
||||||
|
== all secrets should work again ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
== erase all keys of secret 2==
|
||||||
|
== erase all keys of secret 1==
|
||||||
|
== erase all keys of secret 0==
|
||||||
|
== erasing secret3 will fail now since it is the only secret (in 3 slots) ==
|
||||||
|
qemu-img: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation
|
||||||
|
|
||||||
|
== only secret3 should work now ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
== add secret0 ==
|
||||||
|
== erase secret3 ==
|
||||||
|
|
||||||
|
== only secret0 should work now ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== replace secret0 with secret1 (should fail) ==
|
||||||
|
qemu-img: Refusing to overwrite active keyslot 0 - please erase it first
|
||||||
|
|
||||||
|
== replace secret0 with secret1 with force (should work) ==
|
||||||
|
|
||||||
|
== only secret1 should work now ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== erase last secret (should fail) ==
|
||||||
|
qemu-img: Attempt to erase the only active keyslot 0 which will erase all the data in the image irreversibly - refusing operation
|
||||||
|
qemu-img: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation
|
||||||
|
== erase non existing secrets (should fail) ==
|
||||||
|
qemu-img: No secret with id 'sec5'
|
||||||
|
qemu-img: No keyslots match given (old) password for erase operation
|
||||||
|
|
||||||
|
== erase last secret with force by slot (should work) ==
|
||||||
|
|
||||||
|
== we have no secrets now, data is lost forever ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
*** done
|
90
tests/qemu-iotests/294
Executable file
90
tests/qemu-iotests/294
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2019 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=mlevitsk@redhat.com
|
||||||
|
|
||||||
|
seq=`basename $0`
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
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 luks
|
||||||
|
_supported_proto file #TODO
|
||||||
|
|
||||||
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||||
|
|
||||||
|
# you are supposed to see the password as *******, see :-)
|
||||||
|
S0="--object secret,id=sec0,data=hunter0"
|
||||||
|
S1="--object secret,id=sec1,data=hunter1"
|
||||||
|
SECRETS="$S0 $S1"
|
||||||
|
|
||||||
|
|
||||||
|
IMGS0="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,key-secret=sec0"
|
||||||
|
IMGS1="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,key-secret=sec1"
|
||||||
|
|
||||||
|
echo "== creating a test image =="
|
||||||
|
_make_test_img $S0 -o "key-secret=sec0,iter-time=10" 32M
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== test that key 0 opens the image =="
|
||||||
|
$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== adding a password to slot 1 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS0 -o state=active,new-secret=sec1,keyslot=1,iter-time=10
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== 'backup' the image header =="
|
||||||
|
dd if=$TEST_IMG_FILE of=${TEST_IMG_FILE}.bk bs=4K skip=0 count=1
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== erase slot 0 =="
|
||||||
|
$QEMU_IMG amend $SECRETS $IMGS1 -o state=inactive,keyslot=0 | _filter_img_create
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== test that key 0 doesn't open the image =="
|
||||||
|
$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== 'restore' the image header =="
|
||||||
|
dd if=${TEST_IMG_FILE}.bk of=${TEST_IMG_FILE} bs=4K skip=0 count=1 conv=notrunc
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== test that key 0 still doesn't open the image (key material is erased) =="
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== test that key 1 still works =="
|
||||||
|
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS1 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
|
echo "*** done"
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
||||||
|
|
||||||
|
|
||||||
|
exit 0
|
30
tests/qemu-iotests/294.out
Normal file
30
tests/qemu-iotests/294.out
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
QA output created by 294
|
||||||
|
== creating a test image ==
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432
|
||||||
|
|
||||||
|
== test that key 0 opens the image ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
|
||||||
|
== adding a password to slot 1 ==
|
||||||
|
|
||||||
|
== 'backup' the image header ==
|
||||||
|
1+0 records in
|
||||||
|
1+0 records out
|
||||||
|
|
||||||
|
== erase slot 0 ==
|
||||||
|
|
||||||
|
== test that key 0 doesn't open the image ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== 'restore' the image header ==
|
||||||
|
1+0 records in
|
||||||
|
1+0 records out
|
||||||
|
|
||||||
|
== test that key 0 still doesn't open the image (key material is erased) ==
|
||||||
|
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||||
|
|
||||||
|
== test that key 1 still works ==
|
||||||
|
read 4096/4096 bytes at offset 0
|
||||||
|
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
*** done
|
280
tests/qemu-iotests/295
Executable file
280
tests/qemu-iotests/295
Executable file
@ -0,0 +1,280 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Test case QMP's encrypted key management
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import iotests
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
test_img = os.path.join(iotests.test_dir, 'test.img')
|
||||||
|
|
||||||
|
class Secret:
|
||||||
|
def __init__(self, index):
|
||||||
|
self._id = "keysec" + str(index)
|
||||||
|
# you are not supposed to see the password...
|
||||||
|
self._secret = "hunter" + str(index)
|
||||||
|
|
||||||
|
def id(self):
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
def secret(self):
|
||||||
|
return self._secret
|
||||||
|
|
||||||
|
def to_cmdline_object(self):
|
||||||
|
return [ "secret,id=" + self._id + ",data=" + self._secret]
|
||||||
|
|
||||||
|
def to_qmp_object(self):
|
||||||
|
return { "qom_type" : "secret", "id": self.id(),
|
||||||
|
"props": { "data": self.secret() } }
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
class EncryptionSetupTestCase(iotests.QMPTestCase):
|
||||||
|
|
||||||
|
# test case startup
|
||||||
|
def setUp(self):
|
||||||
|
# start the VM
|
||||||
|
self.vm = iotests.VM()
|
||||||
|
self.vm.launch()
|
||||||
|
|
||||||
|
# create the secrets and load 'em into the VM
|
||||||
|
self.secrets = [ Secret(i) for i in range(0, 6) ]
|
||||||
|
for secret in self.secrets:
|
||||||
|
result = self.vm.qmp("object-add", **secret.to_qmp_object())
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
if iotests.imgfmt == "qcow2":
|
||||||
|
self.pfx = "encrypt."
|
||||||
|
self.img_opts = [ '-o', "encrypt.format=luks" ]
|
||||||
|
else:
|
||||||
|
self.pfx = ""
|
||||||
|
self.img_opts = []
|
||||||
|
|
||||||
|
# test case shutdown
|
||||||
|
def tearDown(self):
|
||||||
|
# stop the VM
|
||||||
|
self.vm.shutdown()
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# create the encrypted block device
|
||||||
|
def createImg(self, file, secret):
|
||||||
|
|
||||||
|
iotests.qemu_img(
|
||||||
|
'create',
|
||||||
|
'--object', *secret.to_cmdline_object(),
|
||||||
|
'-f', iotests.imgfmt,
|
||||||
|
'-o', self.pfx + 'key-secret=' + secret.id(),
|
||||||
|
'-o', self.pfx + 'iter-time=10',
|
||||||
|
*self.img_opts,
|
||||||
|
file,
|
||||||
|
'1M')
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# open an encrypted block device
|
||||||
|
def openImageQmp(self, id, file, secret, read_only = False):
|
||||||
|
|
||||||
|
encrypt_options = {
|
||||||
|
'key-secret' : secret.id()
|
||||||
|
}
|
||||||
|
|
||||||
|
if iotests.imgfmt == "qcow2":
|
||||||
|
encrypt_options = {
|
||||||
|
'encrypt': {
|
||||||
|
'format':'luks',
|
||||||
|
**encrypt_options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.vm.qmp('blockdev-add', **
|
||||||
|
{
|
||||||
|
'driver': iotests.imgfmt,
|
||||||
|
'node-name': id,
|
||||||
|
'read-only': read_only,
|
||||||
|
|
||||||
|
**encrypt_options,
|
||||||
|
|
||||||
|
'file': {
|
||||||
|
'driver': 'file',
|
||||||
|
'filename': test_img,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
# close the encrypted block device
|
||||||
|
def closeImageQmp(self, id):
|
||||||
|
result = self.vm.qmp('blockdev-del', **{ 'node-name': id })
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# add a key to an encrypted block device
|
||||||
|
def addKeyQmp(self, id, new_secret, secret = None,
|
||||||
|
slot = None, force = False):
|
||||||
|
|
||||||
|
crypt_options = {
|
||||||
|
'state' : 'active',
|
||||||
|
'new-secret' : new_secret.id(),
|
||||||
|
'iter-time' : 10
|
||||||
|
}
|
||||||
|
|
||||||
|
if slot != None:
|
||||||
|
crypt_options['keyslot'] = slot
|
||||||
|
|
||||||
|
|
||||||
|
if secret != None:
|
||||||
|
crypt_options['secret'] = secret.id()
|
||||||
|
|
||||||
|
if iotests.imgfmt == "qcow2":
|
||||||
|
crypt_options['format'] = 'luks'
|
||||||
|
crypt_options = {
|
||||||
|
'encrypt': crypt_options
|
||||||
|
}
|
||||||
|
|
||||||
|
args = {
|
||||||
|
'node-name': id,
|
||||||
|
'job-id' : 'job_add_key',
|
||||||
|
'options' : {
|
||||||
|
'driver' : iotests.imgfmt,
|
||||||
|
**crypt_options
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if force == True:
|
||||||
|
args['force'] = True
|
||||||
|
|
||||||
|
#TODO: check what jobs return
|
||||||
|
result = self.vm.qmp('x-blockdev-amend', **args)
|
||||||
|
assert result['return'] == {}
|
||||||
|
self.vm.run_job('job_add_key')
|
||||||
|
|
||||||
|
# erase a key from an encrypted block device
|
||||||
|
def eraseKeyQmp(self, id, old_secret = None, slot = None, force = False):
|
||||||
|
|
||||||
|
crypt_options = {
|
||||||
|
'state' : 'inactive',
|
||||||
|
}
|
||||||
|
|
||||||
|
if slot != None:
|
||||||
|
crypt_options['keyslot'] = slot
|
||||||
|
if old_secret != None:
|
||||||
|
crypt_options['old-secret'] = old_secret.id()
|
||||||
|
|
||||||
|
if iotests.imgfmt == "qcow2":
|
||||||
|
crypt_options['format'] = 'luks'
|
||||||
|
crypt_options = {
|
||||||
|
'encrypt': crypt_options
|
||||||
|
}
|
||||||
|
|
||||||
|
args = {
|
||||||
|
'node-name': id,
|
||||||
|
'job-id' : 'job_erase_key',
|
||||||
|
'options' : {
|
||||||
|
'driver' : iotests.imgfmt,
|
||||||
|
**crypt_options
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if force == True:
|
||||||
|
args['force'] = True
|
||||||
|
|
||||||
|
result = self.vm.qmp('x-blockdev-amend', **args)
|
||||||
|
assert result['return'] == {}
|
||||||
|
self.vm.run_job('job_erase_key')
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# create image, and change its key
|
||||||
|
def testChangeKey(self):
|
||||||
|
|
||||||
|
# create the image with secret0 and open it
|
||||||
|
self.createImg(test_img, self.secrets[0]);
|
||||||
|
self.openImageQmp("testdev", test_img, self.secrets[0])
|
||||||
|
|
||||||
|
# add key to slot 1
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[1])
|
||||||
|
|
||||||
|
# add key to slot 5
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[2], slot=5)
|
||||||
|
|
||||||
|
# erase key from slot 0
|
||||||
|
self.eraseKeyQmp("testdev", old_secret = self.secrets[0])
|
||||||
|
|
||||||
|
#reopen the image with secret1
|
||||||
|
self.closeImageQmp("testdev")
|
||||||
|
self.openImageQmp("testdev", test_img, self.secrets[1])
|
||||||
|
|
||||||
|
# close and erase the image for good
|
||||||
|
self.closeImageQmp("testdev")
|
||||||
|
os.remove(test_img)
|
||||||
|
|
||||||
|
# test that if we erase the old password,
|
||||||
|
# we can still change the encryption keys using 'old-secret'
|
||||||
|
def testOldPassword(self):
|
||||||
|
|
||||||
|
# create the image with secret0 and open it
|
||||||
|
self.createImg(test_img, self.secrets[0]);
|
||||||
|
self.openImageQmp("testdev", test_img, self.secrets[0])
|
||||||
|
|
||||||
|
# add key to slot 1
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[1])
|
||||||
|
|
||||||
|
# erase key from slot 0
|
||||||
|
self.eraseKeyQmp("testdev", old_secret = self.secrets[0])
|
||||||
|
|
||||||
|
# this will fail as the old password is no longer valid
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
# this will work
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[2], secret = self.secrets[1])
|
||||||
|
|
||||||
|
# close and erase the image for good
|
||||||
|
self.closeImageQmp("testdev")
|
||||||
|
os.remove(test_img)
|
||||||
|
|
||||||
|
def testUseForceLuke(self):
|
||||||
|
|
||||||
|
self.createImg(test_img, self.secrets[0]);
|
||||||
|
self.openImageQmp("testdev", test_img, self.secrets[0])
|
||||||
|
|
||||||
|
# Add bunch of secrets
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[1], slot=4)
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[4], slot=2)
|
||||||
|
|
||||||
|
# overwrite an active secret
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[5], slot=2)
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[5], slot=2, force=True)
|
||||||
|
|
||||||
|
self.addKeyQmp("testdev", new_secret = self.secrets[0])
|
||||||
|
|
||||||
|
# Now erase all the secrets
|
||||||
|
self.eraseKeyQmp("testdev", old_secret = self.secrets[5])
|
||||||
|
self.eraseKeyQmp("testdev", slot=4)
|
||||||
|
|
||||||
|
# erase last keyslot
|
||||||
|
self.eraseKeyQmp("testdev", old_secret = self.secrets[0])
|
||||||
|
self.eraseKeyQmp("testdev", old_secret = self.secrets[0], force=True)
|
||||||
|
|
||||||
|
self.closeImageQmp("testdev")
|
||||||
|
os.remove(test_img)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
iotests.verify_working_luks()
|
||||||
|
# Encrypted formats support
|
||||||
|
iotests.activate_logging()
|
||||||
|
iotests.main(supported_fmts = ['qcow2', 'luks'])
|
40
tests/qemu-iotests/295.out
Normal file
40
tests/qemu-iotests/295.out
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Invalid password, cannot unlock any keyslot
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Refusing to overwrite active keyslot 2 - please erase it first
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: All the active keyslots match the (old) password that was given and erasing them will erase all the data in the image irreversibly - refusing operation
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
|
||||||
|
{"return": {}}
|
||||||
|
...
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 3 tests
|
||||||
|
|
||||||
|
OK
|
234
tests/qemu-iotests/296
Executable file
234
tests/qemu-iotests/296
Executable file
@ -0,0 +1,234 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Test case for encryption key management versus image sharing
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import iotests
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
test_img = os.path.join(iotests.test_dir, 'test.img')
|
||||||
|
|
||||||
|
class Secret:
|
||||||
|
def __init__(self, index):
|
||||||
|
self._id = "keysec" + str(index)
|
||||||
|
# you are not supposed to see the password...
|
||||||
|
self._secret = "hunter" + str(index)
|
||||||
|
|
||||||
|
def id(self):
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
def secret(self):
|
||||||
|
return self._secret
|
||||||
|
|
||||||
|
def to_cmdline_object(self):
|
||||||
|
return [ "secret,id=" + self._id + ",data=" + self._secret]
|
||||||
|
|
||||||
|
def to_qmp_object(self):
|
||||||
|
return { "qom_type" : "secret", "id": self.id(),
|
||||||
|
"props": { "data": self.secret() } }
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
class EncryptionSetupTestCase(iotests.QMPTestCase):
|
||||||
|
|
||||||
|
# test case startup
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
# start the VMs
|
||||||
|
self.vm1 = iotests.VM(path_suffix = 'VM1')
|
||||||
|
self.vm2 = iotests.VM(path_suffix = 'VM2')
|
||||||
|
self.vm1.launch()
|
||||||
|
self.vm2.launch()
|
||||||
|
|
||||||
|
# create the secrets and load 'em into the VMs
|
||||||
|
self.secrets = [ Secret(i) for i in range(0, 4) ]
|
||||||
|
for secret in self.secrets:
|
||||||
|
result = self.vm1.qmp("object-add", **secret.to_qmp_object())
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
result = self.vm2.qmp("object-add", **secret.to_qmp_object())
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
# test case shutdown
|
||||||
|
def tearDown(self):
|
||||||
|
# stop the VM
|
||||||
|
self.vm1.shutdown()
|
||||||
|
self.vm2.shutdown()
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# create the encrypted block device using qemu-img
|
||||||
|
def createImg(self, file, secret):
|
||||||
|
|
||||||
|
output = iotests.qemu_img_pipe(
|
||||||
|
'create',
|
||||||
|
'--object', *secret.to_cmdline_object(),
|
||||||
|
'-f', iotests.imgfmt,
|
||||||
|
'-o', 'key-secret=' + secret.id(),
|
||||||
|
'-o', 'iter-time=10',
|
||||||
|
file,
|
||||||
|
'1M')
|
||||||
|
|
||||||
|
iotests.log(output, filters=[iotests.filter_test_dir])
|
||||||
|
|
||||||
|
# attempts to add a key using qemu-img
|
||||||
|
def addKey(self, file, secret, new_secret):
|
||||||
|
|
||||||
|
image_options = {
|
||||||
|
'key-secret' : secret.id(),
|
||||||
|
'driver' : iotests.imgfmt,
|
||||||
|
'file' : {
|
||||||
|
'driver':'file',
|
||||||
|
'filename': file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output = iotests.qemu_img_pipe(
|
||||||
|
'amend',
|
||||||
|
'--object', *secret.to_cmdline_object(),
|
||||||
|
'--object', *new_secret.to_cmdline_object(),
|
||||||
|
|
||||||
|
'-o', 'state=active',
|
||||||
|
'-o', 'new-secret=' + new_secret.id(),
|
||||||
|
'-o', 'iter-time=10',
|
||||||
|
|
||||||
|
"json:" + json.dumps(image_options)
|
||||||
|
)
|
||||||
|
|
||||||
|
iotests.log(output, filters=[iotests.filter_test_dir])
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# open an encrypted block device
|
||||||
|
def openImageQmp(self, vm, id, file, secret,
|
||||||
|
readOnly = False, reOpen = False):
|
||||||
|
|
||||||
|
command = 'x-blockdev-reopen' if reOpen else 'blockdev-add'
|
||||||
|
|
||||||
|
result = vm.qmp(command, **
|
||||||
|
{
|
||||||
|
'driver': iotests.imgfmt,
|
||||||
|
'node-name': id,
|
||||||
|
'read-only': readOnly,
|
||||||
|
'key-secret' : secret.id(),
|
||||||
|
'file': {
|
||||||
|
'driver': 'file',
|
||||||
|
'filename': test_img,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
# close the encrypted block device
|
||||||
|
def closeImageQmp(self, vm, id):
|
||||||
|
result = vm.qmp('blockdev-del', **{ 'node-name': id })
|
||||||
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
# add a key to an encrypted block device
|
||||||
|
def addKeyQmp(self, vm, id, new_secret):
|
||||||
|
|
||||||
|
args = {
|
||||||
|
'node-name': id,
|
||||||
|
'job-id' : 'job0',
|
||||||
|
'options' : {
|
||||||
|
'state' : 'active',
|
||||||
|
'driver' : iotests.imgfmt,
|
||||||
|
'new-secret': new_secret.id(),
|
||||||
|
'iter-time' : 10
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result = vm.qmp('x-blockdev-amend', **args)
|
||||||
|
assert result['return'] == {}
|
||||||
|
vm.run_job('job0')
|
||||||
|
|
||||||
|
# test that when the image opened by two qemu processes,
|
||||||
|
# neither of them can update the image
|
||||||
|
def test1(self):
|
||||||
|
self.createImg(test_img, self.secrets[0]);
|
||||||
|
|
||||||
|
# VM1 opens the image and adds a key
|
||||||
|
self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0])
|
||||||
|
self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[1])
|
||||||
|
|
||||||
|
|
||||||
|
# VM2 opens the image
|
||||||
|
self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0])
|
||||||
|
|
||||||
|
|
||||||
|
# neither VMs now should be able to add a key
|
||||||
|
self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2])
|
||||||
|
self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
|
||||||
|
# VM 1 closes the image
|
||||||
|
self.closeImageQmp(self.vm1, "testdev")
|
||||||
|
|
||||||
|
|
||||||
|
# now VM2 can add the key
|
||||||
|
self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
|
||||||
|
# qemu-img should also not be able to add a key
|
||||||
|
self.addKey(test_img, self.secrets[0], self.secrets[2])
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
self.closeImageQmp(self.vm2, "testdev")
|
||||||
|
os.remove(test_img)
|
||||||
|
|
||||||
|
|
||||||
|
def test2(self):
|
||||||
|
self.createImg(test_img, self.secrets[0]);
|
||||||
|
|
||||||
|
# VM1 opens the image readonly
|
||||||
|
self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0],
|
||||||
|
readOnly = True)
|
||||||
|
|
||||||
|
# VM2 opens the image
|
||||||
|
self.openImageQmp(self.vm2, "testdev", test_img, self.secrets[0])
|
||||||
|
|
||||||
|
# VM1 can't add a key since image is readonly
|
||||||
|
self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
# VM2 can't add a key since VM is has the image opened
|
||||||
|
self.addKeyQmp(self.vm2, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
|
||||||
|
#VM1 reopens the image read-write
|
||||||
|
self.openImageQmp(self.vm1, "testdev", test_img, self.secrets[0],
|
||||||
|
reOpen = True, readOnly = False)
|
||||||
|
|
||||||
|
# VM1 still can't add the key
|
||||||
|
self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
# VM2 gets away
|
||||||
|
self.closeImageQmp(self.vm2, "testdev")
|
||||||
|
|
||||||
|
# VM1 now can add the key
|
||||||
|
self.addKeyQmp(self.vm1, "testdev", new_secret = self.secrets[2])
|
||||||
|
|
||||||
|
self.closeImageQmp(self.vm1, "testdev")
|
||||||
|
os.remove(test_img)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# support only raw luks since luks encrypted qcow2 is a proper
|
||||||
|
# format driver which doesn't allow any sharing
|
||||||
|
iotests.activate_logging()
|
||||||
|
iotests.main(supported_fmts = ['luks'])
|
33
tests/qemu-iotests/296.out
Normal file
33
tests/qemu-iotests/296.out
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
|
||||||
|
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Failed to get shared "consistent read" lock
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Failed to get shared "consistent read" lock
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
qemu-img: Failed to get shared "consistent read" lock
|
||||||
|
Is another process using the image [TEST_DIR/test.img]?
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
|
||||||
|
|
||||||
|
Job failed: Block node is read-only
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Failed to get shared "consistent read" lock
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
Job failed: Failed to get shared "consistent read" lock
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
|
||||||
|
{"return": {}}
|
||||||
|
..
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Ran 2 tests
|
||||||
|
|
||||||
|
OK
|
@ -122,38 +122,96 @@ _filter_actual_image_size()
|
|||||||
# replace driver-specific options in the "Formatting..." line
|
# replace driver-specific options in the "Formatting..." line
|
||||||
_filter_img_create()
|
_filter_img_create()
|
||||||
{
|
{
|
||||||
data_file_filter=()
|
# Split the line into the pre-options part ($filename_part, which
|
||||||
if data_file=$(_get_data_file "$TEST_IMG"); then
|
# precedes ", fmt=") and the options part ($options, which starts
|
||||||
data_file_filter=(-e "s# data_file=$data_file##")
|
# with "fmt=")
|
||||||
|
# (And just echo everything before the first "^Formatting")
|
||||||
|
readarray formatting_line < <($SED -e 's/, fmt=/\n/')
|
||||||
|
|
||||||
|
filename_part=''
|
||||||
|
options=''
|
||||||
|
lines=${#formatting_line[@]}
|
||||||
|
for ((i = 0; i < $lines; i++)); do
|
||||||
|
line=${formatting_line[i]}
|
||||||
|
unset formatting_line[i]
|
||||||
|
|
||||||
|
filename_part="$filename_part$line"
|
||||||
|
|
||||||
|
if echo "$line" | grep -q '^Formatting'; then
|
||||||
|
next_i=$((i + 1))
|
||||||
|
if [ -n "${formatting_line[next_i]}" ]; then
|
||||||
|
options="fmt=${formatting_line[@]}"
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Set grep_data_file to '\|data_file' to keep it; make it empty
|
||||||
|
# to drop it.
|
||||||
|
# We want to drop it if it is part of the global $IMGOPTS, and we
|
||||||
|
# want to keep it otherwise (if the test specifically wants to
|
||||||
|
# test data files).
|
||||||
|
grep_data_file=(-e data_file)
|
||||||
|
if _get_data_file "$TEST_IMG" > /dev/null; then
|
||||||
|
grep_data_file=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$SED "${data_file_filter[@]}" \
|
filename_filters=(
|
||||||
-e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
|
-e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
|
||||||
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
|
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
|
||||||
-e "s#$TEST_DIR#TEST_DIR#g" \
|
-e "s#$TEST_DIR#TEST_DIR#g" \
|
||||||
-e "s#$SOCK_DIR#SOCK_DIR#g" \
|
-e "s#$SOCK_DIR#SOCK_DIR#g" \
|
||||||
-e "s#$IMGFMT#IMGFMT#g" \
|
-e "s#$IMGFMT#IMGFMT#g" \
|
||||||
-e 's#nbd:127.0.0.1:[0-9]\\+#TEST_DIR/t.IMGFMT#g' \
|
-e 's#nbd:127.0.0.1:[0-9]\\+#TEST_DIR/t.IMGFMT#g' \
|
||||||
-e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g' \
|
-e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g'
|
||||||
-e "s# encryption=off##g" \
|
)
|
||||||
-e "s# cluster_size=[0-9]\\+##g" \
|
|
||||||
-e "s# table_size=[0-9]\\+##g" \
|
filename_part=$(echo "$filename_part" | $SED "${filename_filters[@]}")
|
||||||
-e "s# compat=[^ ]*##g" \
|
|
||||||
-e "s# compat6=\\(on\\|off\\)##g" \
|
# Break the option line before each option (preserving pre-existing
|
||||||
-e "s# static=\\(on\\|off\\)##g" \
|
# line breaks by replacing them by \0 and restoring them at the end),
|
||||||
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
|
# then filter out the options we want to keep and sort them according
|
||||||
-e "s# subformat=[^ ]*##g" \
|
# to some order that all block drivers used at the time of writing
|
||||||
-e "s# adapter_type=[^ ]*##g" \
|
# this function.
|
||||||
-e "s# hwversion=[^ ]*##g" \
|
options=$(
|
||||||
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
|
echo "$options" \
|
||||||
-e "s# block_size=[0-9]\\+##g" \
|
| tr '\n' '\0' \
|
||||||
-e "s# block_state_zero=\\(on\\|off\\)##g" \
|
| $SED -e 's/ \([a-z0-9_.-]*\)=/\n\1=/g' \
|
||||||
-e "s# log_size=[0-9]\\+##g" \
|
| grep -a -e '^fmt' -e '^size' -e '^backing' -e '^preallocation' \
|
||||||
-e "s# refcount_bits=[0-9]\\+##g" \
|
-e '^encryption' "${grep_data_file[@]}" \
|
||||||
-e "s# key-secret=[a-zA-Z0-9]\\+##g" \
|
| $SED "${filename_filters[@]}" \
|
||||||
-e "s# iter-time=[0-9]\\+##g" \
|
-e 's/^\(fmt\)/0-\1/' \
|
||||||
-e "s# force_size=\\(on\\|off\\)##g" \
|
-e 's/^\(size\)/1-\1/' \
|
||||||
-e "s# compression_type=[a-zA-Z0-9]\\+##g"
|
-e 's/^\(backing\)/2-\1/' \
|
||||||
|
-e 's/^\(data_file\)/3-\1/' \
|
||||||
|
-e 's/^\(encryption\)/4-\1/' \
|
||||||
|
-e 's/^\(preallocation\)/8-\1/' \
|
||||||
|
| sort \
|
||||||
|
| $SED -e 's/^[0-9]-//' \
|
||||||
|
| tr '\n\0' ' \n' \
|
||||||
|
| $SED -e 's/^ *$//' -e 's/ *$//'
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$options" ]; then
|
||||||
|
echo "$filename_part, $options"
|
||||||
|
elif [ -n "$filename_part" ]; then
|
||||||
|
echo "$filename_part"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Filter the "Formatting..." line in QMP output (leaving the QMP output
|
||||||
|
# untouched)
|
||||||
|
# (In contrast to _filter_img_create(), this function does not support
|
||||||
|
# multi-line Formatting output)
|
||||||
|
_filter_img_create_in_qmp()
|
||||||
|
{
|
||||||
|
while read -r line; do
|
||||||
|
if echo "$line" | grep -q '^Formatting'; then
|
||||||
|
echo "$line" | _filter_img_create
|
||||||
|
else
|
||||||
|
echo "$line"
|
||||||
|
fi
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
_filter_img_create_size()
|
_filter_img_create_size()
|
||||||
|
@ -605,6 +605,9 @@ _supported_fmt()
|
|||||||
# setting IMGFMT_GENERIC to false.
|
# setting IMGFMT_GENERIC to false.
|
||||||
for f; do
|
for f; do
|
||||||
if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
|
if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
|
||||||
|
if [ "$IMGFMT" = "luks" ]; then
|
||||||
|
_require_working_luks
|
||||||
|
fi
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -740,6 +743,33 @@ _unsupported_imgopts()
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Caution: Overwrites $TEST_DIR/t.luks
|
||||||
|
_require_working_luks()
|
||||||
|
{
|
||||||
|
file="$TEST_DIR/t.luks"
|
||||||
|
|
||||||
|
output=$(
|
||||||
|
$QEMU_IMG create -f luks \
|
||||||
|
--object secret,id=sec0,data=hunter0 \
|
||||||
|
-o key-secret=sec0 \
|
||||||
|
-o iter-time=10 \
|
||||||
|
"$file" \
|
||||||
|
1M \
|
||||||
|
2>&1
|
||||||
|
)
|
||||||
|
status=$?
|
||||||
|
|
||||||
|
IMGFMT='luks' _rm_test_img "$file"
|
||||||
|
|
||||||
|
if [ $status != 0 ]; then
|
||||||
|
reason=$(echo "$output" | grep "$file:" | $SED -e "s#.*$file: *##")
|
||||||
|
if [ -z "$reason" ]; then
|
||||||
|
reason="Failed to create a LUKS image"
|
||||||
|
fi
|
||||||
|
_notrun "$reason"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# this test requires that a specified command (executable) exists
|
# this test requires that a specified command (executable) exists
|
||||||
#
|
#
|
||||||
_require_command()
|
_require_command()
|
||||||
|
@ -301,4 +301,8 @@
|
|||||||
290 rw auto quick
|
290 rw auto quick
|
||||||
291 rw quick
|
291 rw quick
|
||||||
292 rw auto quick
|
292 rw auto quick
|
||||||
|
293 rw
|
||||||
|
294 rw quick
|
||||||
|
295 rw
|
||||||
|
296 rw
|
||||||
297 meta
|
297 meta
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import (Any, Callable, Dict, Iterable,
|
from typing import (Any, Callable, Dict, Iterable,
|
||||||
List, Optional, Sequence, TypeVar)
|
List, Optional, Sequence, Tuple, TypeVar)
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
# pylint: disable=import-error, wrong-import-position
|
# pylint: disable=import-error, wrong-import-position
|
||||||
@ -90,15 +90,24 @@
|
|||||||
luks_default_key_secret_opt = 'key-secret=keysec0'
|
luks_default_key_secret_opt = 'key-secret=keysec0'
|
||||||
|
|
||||||
|
|
||||||
def qemu_img(*args):
|
def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]:
|
||||||
'''Run qemu-img and return the exit code'''
|
"""
|
||||||
devnull = open('/dev/null', 'r+')
|
Run qemu-img and return both its output and its exit code
|
||||||
exitcode = subprocess.call(qemu_img_args + list(args),
|
"""
|
||||||
stdin=devnull, stdout=devnull)
|
subp = subprocess.Popen(qemu_img_args + list(args),
|
||||||
if exitcode < 0:
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
universal_newlines=True)
|
||||||
|
output = subp.communicate()[0]
|
||||||
|
if subp.returncode < 0:
|
||||||
sys.stderr.write('qemu-img received signal %i: %s\n'
|
sys.stderr.write('qemu-img received signal %i: %s\n'
|
||||||
% (-exitcode, ' '.join(qemu_img_args + list(args))))
|
% (-subp.returncode,
|
||||||
return exitcode
|
' '.join(qemu_img_args + list(args))))
|
||||||
|
return (output, subp.returncode)
|
||||||
|
|
||||||
|
def qemu_img(*args: str) -> int:
|
||||||
|
'''Run qemu-img and return the exit code'''
|
||||||
|
return qemu_img_pipe_and_status(*args)[1]
|
||||||
|
|
||||||
def ordered_qmp(qmsg, conv_keys=True):
|
def ordered_qmp(qmsg, conv_keys=True):
|
||||||
# Dictionaries are not ordered prior to 3.6, therefore:
|
# Dictionaries are not ordered prior to 3.6, therefore:
|
||||||
@ -140,18 +149,9 @@ def qemu_img_verbose(*args):
|
|||||||
% (-exitcode, ' '.join(qemu_img_args + list(args))))
|
% (-exitcode, ' '.join(qemu_img_args + list(args))))
|
||||||
return exitcode
|
return exitcode
|
||||||
|
|
||||||
def qemu_img_pipe(*args):
|
def qemu_img_pipe(*args: str) -> str:
|
||||||
'''Run qemu-img and return its output'''
|
'''Run qemu-img and return its output'''
|
||||||
subp = subprocess.Popen(qemu_img_args + list(args),
|
return qemu_img_pipe_and_status(*args)[0]
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT,
|
|
||||||
universal_newlines=True)
|
|
||||||
output = subp.communicate()[0]
|
|
||||||
if subp.returncode < 0:
|
|
||||||
sys.stderr.write('qemu-img received signal %i: %s\n'
|
|
||||||
% (-subp.returncode,
|
|
||||||
' '.join(qemu_img_args + list(args))))
|
|
||||||
return output
|
|
||||||
|
|
||||||
def qemu_img_log(*args):
|
def qemu_img_log(*args):
|
||||||
result = qemu_img_pipe(*args)
|
result = qemu_img_pipe(*args)
|
||||||
@ -1010,12 +1010,17 @@ def _verify_image_format(supported_fmts: Sequence[str] = (),
|
|||||||
# similar to
|
# similar to
|
||||||
# _supported_fmt generic
|
# _supported_fmt generic
|
||||||
# for bash tests
|
# for bash tests
|
||||||
|
if imgfmt == 'luks':
|
||||||
|
verify_working_luks()
|
||||||
return
|
return
|
||||||
|
|
||||||
not_sup = supported_fmts and (imgfmt not in supported_fmts)
|
not_sup = supported_fmts and (imgfmt not in supported_fmts)
|
||||||
if not_sup or (imgfmt in unsupported_fmts):
|
if not_sup or (imgfmt in unsupported_fmts):
|
||||||
notrun('not suitable for this image format: %s' % imgfmt)
|
notrun('not suitable for this image format: %s' % imgfmt)
|
||||||
|
|
||||||
|
if imgfmt == 'luks':
|
||||||
|
verify_working_luks()
|
||||||
|
|
||||||
def _verify_protocol(supported: Sequence[str] = (),
|
def _verify_protocol(supported: Sequence[str] = (),
|
||||||
unsupported: Sequence[str] = ()) -> None:
|
unsupported: Sequence[str] = ()) -> None:
|
||||||
assert not (supported and unsupported)
|
assert not (supported and unsupported)
|
||||||
@ -1052,6 +1057,45 @@ def verify_quorum():
|
|||||||
if not supports_quorum():
|
if not supports_quorum():
|
||||||
notrun('quorum support missing')
|
notrun('quorum support missing')
|
||||||
|
|
||||||
|
def has_working_luks() -> Tuple[bool, str]:
|
||||||
|
"""
|
||||||
|
Check whether our LUKS driver can actually create images
|
||||||
|
(this extends to LUKS encryption for qcow2).
|
||||||
|
|
||||||
|
If not, return the reason why.
|
||||||
|
"""
|
||||||
|
|
||||||
|
img_file = f'{test_dir}/luks-test.luks'
|
||||||
|
(output, status) = \
|
||||||
|
qemu_img_pipe_and_status('create', '-f', 'luks',
|
||||||
|
'--object', luks_default_secret_object,
|
||||||
|
'-o', luks_default_key_secret_opt,
|
||||||
|
'-o', 'iter-time=10',
|
||||||
|
img_file, '1G')
|
||||||
|
try:
|
||||||
|
os.remove(img_file)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if status != 0:
|
||||||
|
reason = output
|
||||||
|
for line in output.splitlines():
|
||||||
|
if img_file + ':' in line:
|
||||||
|
reason = line.split(img_file + ':', 1)[1].strip()
|
||||||
|
break
|
||||||
|
|
||||||
|
return (False, reason)
|
||||||
|
else:
|
||||||
|
return (True, '')
|
||||||
|
|
||||||
|
def verify_working_luks():
|
||||||
|
"""
|
||||||
|
Skip test suite if LUKS does not work
|
||||||
|
"""
|
||||||
|
(working, reason) = has_working_luks()
|
||||||
|
if not working:
|
||||||
|
notrun(reason)
|
||||||
|
|
||||||
def qemu_pipe(*args):
|
def qemu_pipe(*args):
|
||||||
"""
|
"""
|
||||||
Run qemu with an option to print something and exit (e.g. a help option).
|
Run qemu with an option to print something and exit (e.g. a help option).
|
||||||
|
Loading…
Reference in New Issue
Block a user