mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-26 07:27:39 +00:00
Block patches:
- qemu-img convert: New --target-is-zero parameter - qcow2: Specify non-default compression type flag - optionally flat output for query-named-block-nodes - some fixes - pseudo-creation of images on block devices is now done by a generic block layer function -----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl5Ork4SHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9A7XYH/RFs+kxf+v9V1qE1rwdbJCXdA36/JIoF AW6CtPk47vEodvssjgPBygs/GBqQDdkpZKyA42ZxrE3dPeyRCusncYKRRFPbP4Oq pXj/ZYy9YBn0LIqK41kmXgMdm9HZ113WcG5/rNuh5DOtwX7e688tmHXOHbT8MKAR q/nBK1AVNVxFyBRnRow/YK1jGXmA5rIoONVd6Spkj/5xmKZJ6RtpQb1+WnD7HI3j TVvDcEnKGCT/qZ73rJ6UFRIUdllAQ7fJAOLnXYFwcwkErq3fMEwLpq3syuiuks+B KoFlUzCsM3xiASGnz5MgZI7EVhjGzruneVoBrSyhjlRqNaOB2pYeBwQ= =4/ZP -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-02-20' into staging Block patches: - qemu-img convert: New --target-is-zero parameter - qcow2: Specify non-default compression type flag - optionally flat output for query-named-block-nodes - some fixes - pseudo-creation of images on block devices is now done by a generic block layer function # gpg: Signature made Thu 20 Feb 2020 16:05:34 GMT # 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-02-20: iotests: Test snapshot -l field separation block: Fix VM size field width in snapshot dump iotests: Test convert -n -B to backing-less target qemu-img: Fix convert -n -B for backing-less targets iotests: Add test for image creation fallback iscsi: Drop iscsi_co_create_opts() file-posix: Drop hdev_co_create_opts() block: Generic file creation fallback block/nbd: Fix hang in .bdrv_close() iotests/279: Fix for non-qcow2 formats block/backup-top: fix flags handling block: always fill entire LUKS header space with zeros qemu-img: Add --target-is-zero to convert qapi: Allow getting flat output from 'query-named-block-nodes' iotests/147: Fix drive parameters iotests: Remove the superfluous 2nd check for the availability of quorum docs: qcow2: introduce compression type feature docs: improve qcow2 spec about extending image header Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9e6b7f7eb8
164
block.c
164
block.c
@ -532,20 +532,139 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for bdrv_create_file_fallback(): Resize @blk to at
|
||||
* least the given @minimum_size.
|
||||
*
|
||||
* On success, return @blk's actual length.
|
||||
* Otherwise, return -errno.
|
||||
*/
|
||||
static int64_t create_file_fallback_truncate(BlockBackend *blk,
|
||||
int64_t minimum_size, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int64_t size;
|
||||
int ret;
|
||||
|
||||
ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
|
||||
if (ret < 0 && ret != -ENOTSUP) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size = blk_getlength(blk);
|
||||
if (size < 0) {
|
||||
error_free(local_err);
|
||||
error_setg_errno(errp, -size,
|
||||
"Failed to inquire the new image file's length");
|
||||
return size;
|
||||
}
|
||||
|
||||
if (size < minimum_size) {
|
||||
/* Need to grow the image, but we failed to do that */
|
||||
error_propagate(errp, local_err);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
error_free(local_err);
|
||||
local_err = NULL;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for bdrv_create_file_fallback(): Zero the first
|
||||
* sector to remove any potentially pre-existing image header.
|
||||
*/
|
||||
static int create_file_fallback_zero_first_sector(BlockBackend *blk,
|
||||
int64_t current_size,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t bytes_to_clear;
|
||||
int ret;
|
||||
|
||||
bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE);
|
||||
if (bytes_to_clear) {
|
||||
ret = blk_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"Failed to clear the new image's first sector");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv,
|
||||
QemuOpts *opts, Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
QDict *options = qdict_new();
|
||||
int64_t size = 0;
|
||||
char *buf = NULL;
|
||||
PreallocMode prealloc;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
g_free(buf);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF) {
|
||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||
PreallocMode_str(prealloc));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
qdict_put_str(options, "driver", drv->format_name);
|
||||
|
||||
blk = blk_new_open(filename, NULL, options,
|
||||
BDRV_O_RDWR | BDRV_O_RESIZE, errp);
|
||||
if (!blk) {
|
||||
error_prepend(errp, "Protocol driver '%s' does not support image "
|
||||
"creation, and opening the image failed: ",
|
||||
drv->format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = create_file_fallback_truncate(blk, size, errp);
|
||||
if (size < 0) {
|
||||
ret = size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = create_file_fallback_zero_first_sector(blk, size, errp);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_unref(blk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
drv = bdrv_find_protocol(filename, true, errp);
|
||||
if (drv == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = bdrv_create(drv, filename, opts, &local_err);
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
if (drv->bdrv_co_create_opts) {
|
||||
return bdrv_create(drv, filename, opts, errp);
|
||||
} else {
|
||||
return bdrv_create_file_fallback(filename, drv, opts, errp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1444,6 +1563,24 @@ QemuOptsList bdrv_runtime_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static QemuOptsList fallback_create_opts = {
|
||||
.name = "fallback-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(fallback_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off)"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Common part for opening disk images and files
|
||||
*
|
||||
@ -4807,14 +4944,15 @@ BlockDriverState *bdrv_find_node(const char *node_name)
|
||||
}
|
||||
|
||||
/* Put this QMP function here so it can access the static graph_bdrv_states. */
|
||||
BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp)
|
||||
BlockDeviceInfoList *bdrv_named_nodes_list(bool flat,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDeviceInfoList *list, *entry;
|
||||
BlockDriverState *bs;
|
||||
|
||||
list = NULL;
|
||||
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
|
||||
BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, errp);
|
||||
BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, flat, errp);
|
||||
if (!info) {
|
||||
qapi_free_BlockDeviceInfoList(list);
|
||||
return NULL;
|
||||
@ -5771,15 +5909,13 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!proto_drv->create_opts) {
|
||||
error_setg(errp, "Protocol driver '%s' does not support image creation",
|
||||
proto_drv->format_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create parameter list */
|
||||
create_opts = qemu_opts_append(create_opts, drv->create_opts);
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
if (proto_drv->create_opts) {
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
} else {
|
||||
create_opts = qemu_opts_append(create_opts, &fallback_create_opts);
|
||||
}
|
||||
|
||||
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
|
||||
|
||||
|
@ -48,11 +48,17 @@ static coroutine_fn int backup_top_co_preadv(
|
||||
}
|
||||
|
||||
static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t bytes)
|
||||
uint64_t bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
BDRVBackupTopState *s = bs->opaque;
|
||||
uint64_t end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
|
||||
uint64_t off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
|
||||
uint64_t off, end;
|
||||
|
||||
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
|
||||
end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
|
||||
|
||||
return block_copy(s->bcs, off, end - off, NULL);
|
||||
}
|
||||
@ -60,7 +66,7 @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
|
||||
static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
|
||||
int64_t offset, int bytes)
|
||||
{
|
||||
int ret = backup_top_cbw(bs, offset, bytes);
|
||||
int ret = backup_top_cbw(bs, offset, bytes, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -71,7 +77,7 @@ static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
|
||||
static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
int ret = backup_top_cbw(bs, offset, bytes);
|
||||
int ret = backup_top_cbw(bs, offset, bytes, flags);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -84,11 +90,9 @@ static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
|
||||
uint64_t bytes,
|
||||
QEMUIOVector *qiov, int flags)
|
||||
{
|
||||
if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) {
|
||||
int ret = backup_top_cbw(bs, offset, bytes);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
int ret = backup_top_cbw(bs, offset, bytes, flags);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
|
||||
@ -196,8 +200,13 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
top->total_sectors = source->total_sectors;
|
||||
state = top->opaque;
|
||||
top->total_sectors = source->total_sectors;
|
||||
top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
|
||||
(BDRV_REQ_FUA & source->supported_write_flags);
|
||||
top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
|
||||
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
|
||||
source->supported_zero_flags);
|
||||
|
||||
bdrv_ref(target);
|
||||
state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
|
||||
|
@ -3477,67 +3477,6 @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
return raw_do_pwrite_zeroes(bs, offset, bytes, flags, true);
|
||||
}
|
||||
|
||||
static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int ret = 0;
|
||||
struct stat stat_buf;
|
||||
int64_t total_size = 0;
|
||||
bool has_prefix;
|
||||
|
||||
/* This function is used by both protocol block drivers and therefore either
|
||||
* of these prefixes may be given.
|
||||
* The return value has to be stored somewhere, otherwise this is an error
|
||||
* due to -Werror=unused-value. */
|
||||
has_prefix =
|
||||
strstart(filename, "host_device:", &filename) ||
|
||||
strstart(filename, "host_cdrom:" , &filename);
|
||||
|
||||
(void)has_prefix;
|
||||
|
||||
ret = raw_normalize_devicepath(&filename, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read out options */
|
||||
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
||||
BDRV_SECTOR_SIZE);
|
||||
|
||||
fd = qemu_open(filename, O_WRONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, -ret, "Could not open device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, -ret, "Could not stat device");
|
||||
} else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) {
|
||||
error_setg(errp,
|
||||
"The given file is neither a block nor a character device");
|
||||
ret = -ENODEV;
|
||||
} else if (lseek(fd, 0, SEEK_END) < total_size) {
|
||||
error_setg(errp, "Device is too small");
|
||||
ret = -ENOSPC;
|
||||
}
|
||||
|
||||
if (!ret && total_size) {
|
||||
uint8_t buf[BDRV_SECTOR_SIZE] = { 0 };
|
||||
int64_t zero_size = MIN(BDRV_SECTOR_SIZE, total_size);
|
||||
if (lseek(fd, 0, SEEK_SET) == -1) {
|
||||
ret = -errno;
|
||||
} else {
|
||||
ret = qemu_write_full(fd, buf, zero_size);
|
||||
ret = ret == zero_size ? 0 : -errno;
|
||||
}
|
||||
}
|
||||
qemu_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_host_device = {
|
||||
.format_name = "host_device",
|
||||
.protocol_name = "host_device",
|
||||
@ -3550,8 +3489,6 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
.mutable_opts = mutable_opts,
|
||||
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
|
||||
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
|
||||
@ -3678,8 +3615,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
.mutable_opts = mutable_opts,
|
||||
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
|
||||
|
||||
@ -3812,8 +3747,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
.mutable_opts = mutable_opts,
|
||||
|
||||
.bdrv_co_preadv = raw_co_preadv,
|
||||
|
@ -2164,58 +2164,6 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t total_size = 0;
|
||||
BlockDriverState *bs;
|
||||
IscsiLun *iscsilun = NULL;
|
||||
QDict *bs_options;
|
||||
Error *local_err = NULL;
|
||||
|
||||
bs = bdrv_new();
|
||||
|
||||
/* Read out options */
|
||||
total_size = DIV_ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
||||
BDRV_SECTOR_SIZE);
|
||||
bs->opaque = g_new0(struct IscsiLun, 1);
|
||||
iscsilun = bs->opaque;
|
||||
|
||||
bs_options = qdict_new();
|
||||
iscsi_parse_filename(filename, bs_options, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = iscsi_open(bs, bs_options, 0, NULL);
|
||||
}
|
||||
qobject_unref(bs_options);
|
||||
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
iscsi_detach_aio_context(bs);
|
||||
if (iscsilun->type != TYPE_DISK) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (bs->total_sectors < total_size) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (iscsilun->iscsi != NULL) {
|
||||
iscsi_destroy_context(iscsilun->iscsi);
|
||||
}
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
bdrv_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
@ -2486,8 +2434,6 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_parse_filename = iscsi_parse_filename,
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_co_create_opts = iscsi_co_create_opts,
|
||||
.create_opts = &iscsi_create_opts,
|
||||
.bdrv_reopen_prepare = iscsi_reopen_prepare,
|
||||
.bdrv_reopen_commit = iscsi_reopen_commit,
|
||||
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
|
||||
@ -2525,8 +2471,6 @@ static BlockDriver bdrv_iser = {
|
||||
.bdrv_parse_filename = iscsi_parse_filename,
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_co_create_opts = iscsi_co_create_opts,
|
||||
.create_opts = &iscsi_create_opts,
|
||||
.bdrv_reopen_prepare = iscsi_reopen_prepare,
|
||||
.bdrv_reopen_commit = iscsi_reopen_commit,
|
||||
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
|
||||
|
14
block/nbd.c
14
block/nbd.c
@ -70,6 +70,7 @@ typedef struct BDRVNBDState {
|
||||
CoMutex send_mutex;
|
||||
CoQueue free_sema;
|
||||
Coroutine *connection_co;
|
||||
Coroutine *teardown_co;
|
||||
QemuCoSleepState *connection_co_sleep_ns_state;
|
||||
bool drained;
|
||||
bool wait_drained_end;
|
||||
@ -203,7 +204,15 @@ static void nbd_teardown_connection(BlockDriverState *bs)
|
||||
qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
|
||||
}
|
||||
}
|
||||
BDRV_POLL_WHILE(bs, s->connection_co);
|
||||
if (qemu_in_coroutine()) {
|
||||
s->teardown_co = qemu_coroutine_self();
|
||||
/* connection_co resumes us when it terminates */
|
||||
qemu_coroutine_yield();
|
||||
s->teardown_co = NULL;
|
||||
} else {
|
||||
BDRV_POLL_WHILE(bs, s->connection_co);
|
||||
}
|
||||
assert(!s->connection_co);
|
||||
}
|
||||
|
||||
static bool nbd_client_connecting(BDRVNBDState *s)
|
||||
@ -395,6 +404,9 @@ static coroutine_fn void nbd_connection_entry(void *opaque)
|
||||
s->ioc = NULL;
|
||||
}
|
||||
|
||||
if (s->teardown_co) {
|
||||
aio_co_wake(s->teardown_co);
|
||||
}
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
|
15
block/qapi.c
15
block/qapi.c
@ -42,7 +42,9 @@
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs, Error **errp)
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
{
|
||||
ImageInfo **p_image_info;
|
||||
BlockDriverState *bs0;
|
||||
@ -156,6 +158,11 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* stop gathering data for flat output */
|
||||
if (flat) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (bs0->drv && bs0->backing) {
|
||||
info->backing_file_depth++;
|
||||
bs0 = bs0->backing->bs;
|
||||
@ -389,7 +396,7 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
|
||||
|
||||
if (bs && bs->drv) {
|
||||
info->has_inserted = true;
|
||||
info->inserted = bdrv_block_device_info(blk, bs, errp);
|
||||
info->inserted = bdrv_block_device_info(blk, bs, false, errp);
|
||||
if (info->inserted == NULL) {
|
||||
goto err;
|
||||
}
|
||||
@ -657,7 +664,7 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
|
||||
char *sizing = NULL;
|
||||
|
||||
if (!sn) {
|
||||
qemu_printf("%-10s%-20s%7s%20s%15s",
|
||||
qemu_printf("%-10s%-20s%11s%20s%15s",
|
||||
"ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
|
||||
} else {
|
||||
ti = sn->date_sec;
|
||||
@ -672,7 +679,7 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
|
||||
(int)(secs % 60),
|
||||
(int)((sn->vm_clock_nsec / 1000000) % 1000));
|
||||
sizing = size_to_str(sn->vm_state_size);
|
||||
qemu_printf("%-10s%-20s%7s%20s%15s",
|
||||
qemu_printf("%-10s%-20s%11s%20s%15s",
|
||||
sn->id_str, sn->name,
|
||||
sizing,
|
||||
date_buf,
|
||||
|
@ -135,13 +135,16 @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
|
||||
s->crypto_header.length = headerlen;
|
||||
s->crypto_header.offset = ret;
|
||||
|
||||
/* Zero fill remaining space in cluster so it has predictable
|
||||
* content in case of future spec changes */
|
||||
/*
|
||||
* Zero fill all space in cluster so it has predictable
|
||||
* content, as we may not initialize some regions of the
|
||||
* header (eg only 1 out of 8 key slots will be initialized)
|
||||
*/
|
||||
clusterlen = size_to_clusters(s, headerlen) * s->cluster_size;
|
||||
assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen, false) == 0);
|
||||
ret = bdrv_pwrite_zeroes(bs->file,
|
||||
ret + headerlen,
|
||||
clusterlen - headerlen, 0);
|
||||
ret,
|
||||
clusterlen, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not zero fill encryption header");
|
||||
return -1;
|
||||
|
@ -3734,9 +3734,13 @@ void qmp_drive_backup(DriveBackup *backup, Error **errp)
|
||||
blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
||||
BlockDeviceInfoList *qmp_query_named_block_nodes(bool has_flat,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
{
|
||||
return bdrv_named_nodes_list(errp);
|
||||
bool return_flat = has_flat && flat;
|
||||
|
||||
return bdrv_named_nodes_list(return_flat, errp);
|
||||
}
|
||||
|
||||
XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
|
||||
|
@ -79,9 +79,9 @@ The first cluster of a qcow2 image contains the file header:
|
||||
Offset into the image file at which the snapshot table
|
||||
starts. Must be aligned to a cluster boundary.
|
||||
|
||||
If the version is 3 or higher, the header has the following additional fields.
|
||||
For version 2, the values are assumed to be zero, unless specified otherwise
|
||||
in the description of a field.
|
||||
For version 2, the header is exactly 72 bytes in length, and finishes here.
|
||||
For version 3 or higher, the header length is at least 104 bytes, including
|
||||
the next fields through header_length.
|
||||
|
||||
72 - 79: incompatible_features
|
||||
Bitmask of incompatible features. An implementation must
|
||||
@ -109,7 +109,12 @@ in the description of a field.
|
||||
An External Data File Name header extension may
|
||||
be present if this bit is set.
|
||||
|
||||
Bits 3-63: Reserved (set to 0)
|
||||
Bit 3: Compression type bit. If this bit is set,
|
||||
a non-default compression is used for compressed
|
||||
clusters. The compression_type field must be
|
||||
present and not zero.
|
||||
|
||||
Bits 4-63: Reserved (set to 0)
|
||||
|
||||
80 - 87: compatible_features
|
||||
Bitmask of compatible features. An implementation can
|
||||
@ -164,6 +169,57 @@ in the description of a field.
|
||||
100 - 103: header_length
|
||||
Length of the header structure in bytes. For version 2
|
||||
images, the length is always assumed to be 72 bytes.
|
||||
For version 3 it's at least 104 bytes and must be a multiple
|
||||
of 8.
|
||||
|
||||
|
||||
=== Additional fields (version 3 and higher) ===
|
||||
|
||||
In general, these fields are optional and may be safely ignored by the software,
|
||||
as well as filled by zeros (which is equal to field absence), if software needs
|
||||
to set field B, but does not care about field A which precedes B. More
|
||||
formally, additional fields have the following compatibility rules:
|
||||
|
||||
1. If the value of the additional field must not be ignored for correct
|
||||
handling of the file, it will be accompanied by a corresponding incompatible
|
||||
feature bit.
|
||||
|
||||
2. If there are no unrecognized incompatible feature bits set, an unknown
|
||||
additional field may be safely ignored other than preserving its value when
|
||||
rewriting the image header.
|
||||
|
||||
3. An explicit value of 0 will have the same behavior as when the field is not
|
||||
present*, if not altered by a specific incompatible bit.
|
||||
|
||||
*. A field is considered not present when header_length is less than or equal
|
||||
to the field's offset. Also, all additional fields are not present for
|
||||
version 2.
|
||||
|
||||
104: compression_type
|
||||
|
||||
Defines the compression method used for compressed clusters.
|
||||
All compressed clusters in an image use the same compression
|
||||
type.
|
||||
|
||||
If the incompatible bit "Compression type" is set: the field
|
||||
must be present and non-zero (which means non-zlib
|
||||
compression type). Otherwise, this field must not be present
|
||||
or must be zero (which means zlib).
|
||||
|
||||
Available compression type values:
|
||||
0: zlib <https://www.zlib.net/>
|
||||
|
||||
|
||||
=== Header padding ===
|
||||
|
||||
@header_length must be a multiple of 8, which means that if the end of the last
|
||||
additional field is not aligned, some padding is needed. This padding must be
|
||||
zeroed, so that if some existing (or future) additional field will fall into
|
||||
the padding, it will be interpreted accordingly to point [3.] of the previous
|
||||
paragraph, i.e. in the same manner as when this field is not present.
|
||||
|
||||
|
||||
=== Header extensions ===
|
||||
|
||||
Directly after the image header, optional sections called header extensions can
|
||||
be stored. Each extension has a structure like the following:
|
||||
|
@ -214,6 +214,13 @@ Parameters to convert subcommand:
|
||||
will still be printed. Areas that cannot be read from the source will be
|
||||
treated as containing only zeroes.
|
||||
|
||||
.. option:: --target-is-zero
|
||||
|
||||
Assume that reading the destination image will always return
|
||||
zeros. This parameter is mutually exclusive with a destination image
|
||||
that has a backing file. It is required to also use the ``-n``
|
||||
parameter to skip image creation.
|
||||
|
||||
Parameters to dd subcommand:
|
||||
|
||||
.. program:: qemu-img-dd
|
||||
@ -366,7 +373,7 @@ Command description:
|
||||
4
|
||||
Error on reading data
|
||||
|
||||
.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
|
||||
.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
|
||||
|
||||
Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
|
||||
to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
|
||||
|
@ -454,7 +454,7 @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked);
|
||||
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
|
||||
const char *bdrv_get_format_name(BlockDriverState *bs);
|
||||
BlockDriverState *bdrv_find_node(const char *node_name);
|
||||
BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp);
|
||||
BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp);
|
||||
XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp);
|
||||
BlockDriverState *bdrv_lookup_bs(const char *device,
|
||||
const char *node_name,
|
||||
|
@ -29,7 +29,9 @@
|
||||
#include "block/snapshot.h"
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs, Error **errp);
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp);
|
||||
int bdrv_query_snapshot_info_list(BlockDriverState *bs,
|
||||
SnapshotInfoList **p_list,
|
||||
Error **errp);
|
||||
|
@ -620,7 +620,7 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
|
||||
/* Print node information */
|
||||
blockdev_list = qmp_query_named_block_nodes(NULL);
|
||||
blockdev_list = qmp_query_named_block_nodes(false, false, NULL);
|
||||
for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) {
|
||||
assert(blockdev->value->has_node_name);
|
||||
if (device && strcmp(device, blockdev->value->node_name)) {
|
||||
|
@ -1758,6 +1758,9 @@
|
||||
#
|
||||
# Get the named block driver list
|
||||
#
|
||||
# @flat: Omit the nested data about backing image ("backing-image" key) if true.
|
||||
# Default is false (Since 5.0)
|
||||
#
|
||||
# Returns: the list of BlockDeviceInfo
|
||||
#
|
||||
# Since: 2.0
|
||||
@ -1811,7 +1814,9 @@
|
||||
# } } ] }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ] }
|
||||
{ 'command': 'query-named-block-nodes',
|
||||
'returns': [ 'BlockDeviceInfo' ],
|
||||
'data': { '*flat': 'bool' } }
|
||||
|
||||
##
|
||||
# @XDbgBlockGraphNodeType:
|
||||
|
@ -39,9 +39,9 @@ SRST
|
||||
ERST
|
||||
|
||||
DEF("convert", img_convert,
|
||||
"convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename")
|
||||
"convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename")
|
||||
SRST
|
||||
.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
|
||||
.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
|
||||
ERST
|
||||
|
||||
DEF("create", img_create,
|
||||
|
28
qemu-img.c
28
qemu-img.c
@ -70,6 +70,7 @@ enum {
|
||||
OPTION_PREALLOCATION = 265,
|
||||
OPTION_SHRINK = 266,
|
||||
OPTION_SALVAGE = 267,
|
||||
OPTION_TARGET_IS_ZERO = 268,
|
||||
};
|
||||
|
||||
typedef enum OutputFormat {
|
||||
@ -1984,10 +1985,9 @@ static int convert_do_copy(ImgConvertState *s)
|
||||
int64_t sector_num = 0;
|
||||
|
||||
/* Check whether we have zero initialisation or can get it efficiently */
|
||||
if (s->target_is_new && s->min_sparse && !s->target_has_backing) {
|
||||
if (!s->has_zero_init && s->target_is_new && s->min_sparse &&
|
||||
!s->target_has_backing) {
|
||||
s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target));
|
||||
} else {
|
||||
s->has_zero_init = false;
|
||||
}
|
||||
|
||||
if (!s->has_zero_init && !s->target_has_backing &&
|
||||
@ -2086,6 +2086,7 @@ static int img_convert(int argc, char **argv)
|
||||
{"force-share", no_argument, 0, 'U'},
|
||||
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
|
||||
{"salvage", no_argument, 0, OPTION_SALVAGE},
|
||||
{"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU",
|
||||
@ -2209,6 +2210,14 @@ static int img_convert(int argc, char **argv)
|
||||
case OPTION_TARGET_IMAGE_OPTS:
|
||||
tgt_image_opts = true;
|
||||
break;
|
||||
case OPTION_TARGET_IS_ZERO:
|
||||
/*
|
||||
* The user asserting that the target is blank has the
|
||||
* same effect as the target driver supporting zero
|
||||
* initialisation.
|
||||
*/
|
||||
s.has_zero_init = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2247,6 +2256,11 @@ static int img_convert(int argc, char **argv)
|
||||
warn_report("This will become an error in future QEMU versions.");
|
||||
}
|
||||
|
||||
if (s.has_zero_init && !skip_create) {
|
||||
error_report("--target-is-zero requires use of -n flag");
|
||||
goto fail_getopt;
|
||||
}
|
||||
|
||||
s.src_num = argc - optind - 1;
|
||||
out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL;
|
||||
|
||||
@ -2380,6 +2394,12 @@ static int img_convert(int argc, char **argv)
|
||||
}
|
||||
s.target_has_backing = (bool) out_baseimg;
|
||||
|
||||
if (s.has_zero_init && s.target_has_backing) {
|
||||
error_report("Cannot use --target-is-zero when the destination "
|
||||
"image has a backing file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (s.src_num > 1 && out_baseimg) {
|
||||
error_report("Having a backing file for the target makes no sense when "
|
||||
"concatenating multiple input images");
|
||||
@ -2503,7 +2523,7 @@ static int img_convert(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (s.target_has_backing) {
|
||||
if (s.target_has_backing && s.target_is_new) {
|
||||
/* Errors are treated as "backing length unknown" (which means
|
||||
* s.target_backing_sectors has to be negative, which it will
|
||||
* be automatically). The backing file length is used only
|
||||
|
@ -276,6 +276,20 @@ $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig
|
||||
|
||||
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig
|
||||
|
||||
echo
|
||||
echo '=== -n -B to an image without a backing file ==='
|
||||
echo
|
||||
|
||||
# Base for the output
|
||||
TEST_IMG="$TEST_IMG".base _make_test_img 64M
|
||||
|
||||
# Output that does have $TEST_IMG.base set as its (implicit) backing file
|
||||
TEST_IMG="$TEST_IMG".orig _make_test_img 64M
|
||||
|
||||
# Convert with -n, which should not confuse -B with "target BDS has a
|
||||
# backing file"
|
||||
$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -n "$TEST_IMG" "$TEST_IMG".orig
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
|
@ -228,4 +228,9 @@ Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Images are identical.
|
||||
|
||||
=== -n -B to an image without a backing file ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
|
||||
Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
|
||||
*** done
|
||||
|
@ -344,9 +344,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||
|
||||
@iotests.skip_if_unsupported(['quorum'])
|
||||
def testQuorum(self):
|
||||
if not iotests.supports_quorum():
|
||||
return
|
||||
|
||||
self.addQuorum('quorum0', 'node0', 'node1')
|
||||
# We cannot remove the children of a Quorum device
|
||||
self.delBlockDriverState('node0', expect_error = True)
|
||||
|
@ -134,7 +134,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
self.server.add_drive_raw('if=none,id=nbd-export,' +
|
||||
'file=%s,' % test_img +
|
||||
'format=%s,' % imgfmt +
|
||||
'cache=%s' % cachemode +
|
||||
'cache=%s,' % cachemode +
|
||||
'aio=%s' % aiomode)
|
||||
self.server.launch()
|
||||
|
||||
|
62
tests/qemu-iotests/259
Executable file
62
tests/qemu-iotests/259
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Test generic image creation fallback (by using NBD)
|
||||
#
|
||||
# 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=mreitz@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 raw
|
||||
_supported_proto nbd
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
_make_test_img 64M
|
||||
|
||||
echo
|
||||
echo '--- Testing creation ---'
|
||||
|
||||
$QEMU_IMG create -f qcow2 "$TEST_IMG" 64M | _filter_img_create
|
||||
$QEMU_IMG info "$TEST_IMG" | _filter_img_info
|
||||
|
||||
echo
|
||||
echo '--- Testing creation for which the node would need to grow ---'
|
||||
|
||||
# NBD does not support resizing, so this will fail
|
||||
$QEMU_IMG create -f qcow2 -o preallocation=metadata "$TEST_IMG" 64M 2>&1 \
|
||||
| _filter_img_create
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
14
tests/qemu-iotests/259.out
Normal file
14
tests/qemu-iotests/259.out
Normal file
@ -0,0 +1,14 @@
|
||||
QA output created by 259
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
||||
--- Testing creation ---
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=qcow2 size=67108864
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: qcow2
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
disk size: unavailable
|
||||
|
||||
--- Testing creation for which the node would need to grow ---
|
||||
qemu-img: TEST_DIR/t.IMGFMT: Could not resize image: Image format driver does not support resize
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=qcow2 size=67108864 preallocation=metadata
|
||||
*** done
|
@ -38,6 +38,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
_supported_fmt qcow qcow2 vmdk qed
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
_unsupported_imgopts "subformat=monolithicFlat" \
|
||||
"subformat=twoGbMaxExtentFlat" \
|
||||
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
|
||||
TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
|
||||
@ -45,11 +47,12 @@ _make_test_img -b "$TEST_IMG.mid"
|
||||
|
||||
echo
|
||||
echo '== qemu-img info --backing-chain =='
|
||||
_img_info --backing-chain | _filter_img_info
|
||||
_img_info --backing-chain | _filter_img_info | grep -v 'backing file format'
|
||||
|
||||
echo
|
||||
echo '== qemu-img info --backing-chain --image-opts =='
|
||||
TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info
|
||||
TEST_IMG="driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts \
|
||||
| _filter_img_info | grep -v 'backing file format'
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
|
97
tests/qemu-iotests/284
Executable file
97
tests/qemu-iotests/284
Executable file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Test ref count checks on encrypted images
|
||||
#
|
||||
# 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=berrange@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
|
||||
_supported_proto generic
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
size=1M
|
||||
|
||||
SECRET="secret,id=sec0,data=astrochicken"
|
||||
|
||||
IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
|
||||
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||
|
||||
_run_test()
|
||||
{
|
||||
IMGOPTSSYNTAX=true
|
||||
OLD_TEST_IMG="$TEST_IMG"
|
||||
TEST_IMG="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
|
||||
QEMU_IMG_EXTRA_ARGS="--image-opts --object $SECRET"
|
||||
|
||||
echo
|
||||
echo "== cluster size $csize"
|
||||
echo "== checking image refcounts =="
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo "== writing some data =="
|
||||
$QEMU_IO -c "write -P 0x9 0 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir
|
||||
echo
|
||||
echo "== rechecking image refcounts =="
|
||||
_check_test_img
|
||||
|
||||
echo
|
||||
echo "== writing some more data =="
|
||||
$QEMU_IO -c "write -P 0x9 $csize 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir
|
||||
echo
|
||||
echo "== rechecking image refcounts =="
|
||||
_check_test_img
|
||||
|
||||
TEST_IMG="$OLD_TEST_IMG"
|
||||
QEMU_IMG_EXTRA_ARGS=
|
||||
IMGOPTSSYNTAX=
|
||||
}
|
||||
|
||||
|
||||
echo
|
||||
echo "testing LUKS qcow2 encryption"
|
||||
echo
|
||||
|
||||
for csize in 512 2048 32768
|
||||
do
|
||||
_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=$csize" $size
|
||||
_run_test
|
||||
_cleanup_test_img
|
||||
done
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
62
tests/qemu-iotests/284.out
Normal file
62
tests/qemu-iotests/284.out
Normal file
@ -0,0 +1,62 @@
|
||||
QA output created by 284
|
||||
|
||||
testing LUKS qcow2 encryption
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
||||
|
||||
== cluster size 512
|
||||
== checking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some data ==
|
||||
wrote 1/1 bytes at offset 0
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some more data ==
|
||||
wrote 1/1 bytes at offset 512
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
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
|
||||
|
||||
== cluster size 2048
|
||||
== checking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some data ==
|
||||
wrote 1/1 bytes at offset 0
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some more data ==
|
||||
wrote 1/1 bytes at offset 2048
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
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
|
||||
|
||||
== cluster size 32768
|
||||
== checking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some data ==
|
||||
wrote 1/1 bytes at offset 0
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
No errors were found on the image.
|
||||
|
||||
== writing some more data ==
|
||||
wrote 1/1 bytes at offset 32768
|
||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== rechecking image refcounts ==
|
||||
No errors were found on the image.
|
||||
*** done
|
76
tests/qemu-iotests/286
Executable file
76
tests/qemu-iotests/286
Executable file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Test qemu-img snapshot -l
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
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
|
||||
. ./common.qemu
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
# Internal snapshots are (currently) impossible with refcount_bits=1,
|
||||
# and generally impossible with external data files
|
||||
_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
|
||||
|
||||
_make_test_img 64M
|
||||
|
||||
# Should be so long as to take up the whole field width
|
||||
sn_name=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
|
||||
# More memory will give us a larger VM state, i.e. one above 1 MB.
|
||||
# This way, we get a number with a decimal point.
|
||||
qemu_comm_method=monitor _launch_qemu -m 512 "$TEST_IMG"
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE "savevm $sn_name" '(qemu)'
|
||||
_send_qemu_cmd $QEMU_HANDLE 'quit' '(qemu)'
|
||||
wait=yes _cleanup_qemu
|
||||
|
||||
# Check that all fields are separated by spaces.
|
||||
# We first collapse all space sequences into one space each;
|
||||
# then we turn every space-separated field into a '.';
|
||||
# and finally, we name the '.'s so the output is not just a confusing
|
||||
# sequence of dots.
|
||||
|
||||
echo 'Output structure:'
|
||||
$QEMU_IMG snapshot -l "$TEST_IMG" | tail -n 1 | tr -s ' ' \
|
||||
| sed -e 's/\S\+/./g' \
|
||||
| sed -e 's/\./(snapshot ID)/' \
|
||||
-e 's/\./(snapshot name)/' \
|
||||
-e 's/\./(VM state size value)/' \
|
||||
-e 's/\./(VM state size unit)/' \
|
||||
-e 's/\./(snapshot date)/' \
|
||||
-e 's/\./(snapshot time)/' \
|
||||
-e 's/\./(VM clock)/'
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
8
tests/qemu-iotests/286.out
Normal file
8
tests/qemu-iotests/286.out
Normal file
@ -0,0 +1,8 @@
|
||||
QA output created by 286
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) savevm abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
(qemu) quit
|
||||
Output structure:
|
||||
(snapshot ID) (snapshot name) (VM state size value) (VM state size unit) (snapshot date) (snapshot time) (VM clock)
|
||||
*** done
|
@ -273,6 +273,7 @@
|
||||
256 rw auto quick
|
||||
257 rw
|
||||
258 rw quick
|
||||
259 rw auto quick
|
||||
260 rw quick
|
||||
261 rw
|
||||
262 rw quick migration
|
||||
@ -290,3 +291,5 @@
|
||||
280 rw migration quick
|
||||
281 rw quick
|
||||
283 auto quick
|
||||
284 rw
|
||||
286 rw quick
|
||||
|
Loading…
x
Reference in New Issue
Block a user