mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-12 07:32:19 +00:00
Block patches for 6.0-rc1:
- Mark the qcow2 cache clean timer as external to fix record/replay - Fix the mirror filter node's permissions so that an external process cannot grab an image while it is used as the mirror source - Add documentation about FUSE exports to the storage daemon - When creating a qcow2 image with the data-file-raw option, all metadata structures should be preallocated - iotest fixes -----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAmBjG9ASHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9AVa4H/1NC4aTFi2sMzyQ8hkUck2llPiZdxP4V KZbyUay+z2pLPWMonyDP6szGv6444lHGBnGQWKZHcw4o5xWNu50jEB2YpkhXS9i1 8shkZNVGxy6CVxinhrFG9qMv7GuoX3vOsVu5HnBjgpM162ZVYR+Af/8erqG1A4js 9odM5Zl6hb+okbSovgucT3UxNeYvBDnhsKzpQnvUvsdJu3RKz6gSlTz+f6jJLLP/ +hK54CDkCpK4fY6W0QLcZcLmmhTHYZXgeKDAHWGAzBH5p3ARY6uAXGZ9+fLE88X4 fhgcuYeLMS+sJCzGXnEDAmGebGhEOzszvskBRIHdWK861zg0RssWQP4= =BdFo -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2021-03-30' into staging Block patches for 6.0-rc1: - Mark the qcow2 cache clean timer as external to fix record/replay - Fix the mirror filter node's permissions so that an external process cannot grab an image while it is used as the mirror source - Add documentation about FUSE exports to the storage daemon - When creating a qcow2 image with the data-file-raw option, all metadata structures should be preallocated - iotest fixes # gpg: Signature made Tue 30 Mar 2021 13:38:40 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-2021-03-30: iotests/244: Test preallocation for data-file-raw qcow2: Force preallocation with data-file-raw qsd: Document FUSE exports block/mirror: Fix mirror_top's permissions iotests/046: Filter request length qcow2: use external virtual timers iotests/116: Fix reference output iotests: fix 051.out expected output after error text touchups iotests: Fix typo in iotest 051 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
4a0ba67c77
@ -89,6 +89,7 @@ typedef struct MirrorBlockJob {
|
||||
typedef struct MirrorBDSOpaque {
|
||||
MirrorBlockJob *job;
|
||||
bool stop;
|
||||
bool is_commit;
|
||||
} MirrorBDSOpaque;
|
||||
|
||||
struct MirrorOp {
|
||||
@ -1522,13 +1523,27 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must be able to forward guest writes to the real image */
|
||||
*nperm = 0;
|
||||
if (perm & BLK_PERM_WRITE) {
|
||||
*nperm |= BLK_PERM_WRITE;
|
||||
}
|
||||
bdrv_default_perms(bs, c, role, reopen_queue,
|
||||
perm, shared, nperm, nshared);
|
||||
|
||||
*nshared = BLK_PERM_ALL;
|
||||
if (s->is_commit) {
|
||||
/*
|
||||
* For commit jobs, we cannot take CONSISTENT_READ, because
|
||||
* that permission is unshared for everything above the base
|
||||
* node (except for filters on the base node).
|
||||
* We also have to force-share the WRITE permission, or
|
||||
* otherwise we would block ourselves at the base node (if
|
||||
* writes are blocked for a node, they are also blocked for
|
||||
* its backing file).
|
||||
* (We could also share RESIZE, because it may be needed for
|
||||
* the target if its size is less than the top node's; but
|
||||
* bdrv_default_perms_for_cow() automatically shares RESIZE
|
||||
* for backing nodes if WRITE is shared, so there is no need
|
||||
* to do it here.)
|
||||
*/
|
||||
*nperm &= ~BLK_PERM_CONSISTENT_READ;
|
||||
*nshared |= BLK_PERM_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dummy node that provides consistent read to its users without requiring it
|
||||
@ -1591,6 +1606,8 @@ static BlockJob *mirror_start_job(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target_is_backing = bdrv_chain_contains(bs, target);
|
||||
|
||||
/* In the case of active commit, add dummy driver to provide consistent
|
||||
* reads on the top, while disabling it in the intermediate nodes, and make
|
||||
* the backing chain writable. */
|
||||
@ -1613,6 +1630,8 @@ static BlockJob *mirror_start_job(
|
||||
bs_opaque = g_new0(MirrorBDSOpaque, 1);
|
||||
mirror_top_bs->opaque = bs_opaque;
|
||||
|
||||
bs_opaque->is_commit = target_is_backing;
|
||||
|
||||
/* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
|
||||
* it alive until block_job_create() succeeds even if bs has no parent. */
|
||||
bdrv_ref(mirror_top_bs);
|
||||
@ -1653,7 +1672,6 @@ static BlockJob *mirror_start_job(
|
||||
target_perms = BLK_PERM_WRITE;
|
||||
target_shared_perms = BLK_PERM_WRITE_UNCHANGED;
|
||||
|
||||
target_is_backing = bdrv_chain_contains(bs, target);
|
||||
if (target_is_backing) {
|
||||
int64_t bs_size, target_size;
|
||||
bs_size = bdrv_getlength(bs);
|
||||
|
@ -840,9 +840,10 @@ static void cache_clean_timer_init(BlockDriverState *bs, AioContext *context)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
if (s->cache_clean_interval > 0) {
|
||||
s->cache_clean_timer = aio_timer_new(context, QEMU_CLOCK_VIRTUAL,
|
||||
SCALE_MS, cache_clean_timer_cb,
|
||||
bs);
|
||||
s->cache_clean_timer =
|
||||
aio_timer_new_with_attrs(context, QEMU_CLOCK_VIRTUAL,
|
||||
SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
|
||||
cache_clean_timer_cb, bs);
|
||||
timer_mod(s->cache_clean_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
||||
(int64_t) s->cache_clean_interval * 1000);
|
||||
}
|
||||
@ -3502,6 +3503,28 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (qcow2_opts->data_file_raw &&
|
||||
qcow2_opts->preallocation == PREALLOC_MODE_OFF)
|
||||
{
|
||||
/*
|
||||
* data-file-raw means that "the external data file can be
|
||||
* read as a consistent standalone raw image without looking
|
||||
* at the qcow2 metadata." It does not say that the metadata
|
||||
* must be ignored, though (and the qcow2 driver in fact does
|
||||
* not ignore it), so the L1/L2 tables must be present and
|
||||
* give a 1:1 mapping, so you get the same result regardless
|
||||
* of whether you look at the metadata or whether you ignore
|
||||
* it.
|
||||
*/
|
||||
qcow2_opts->preallocation = PREALLOC_MODE_METADATA;
|
||||
|
||||
/*
|
||||
* Cannot use preallocation with backing files, but giving a
|
||||
* backing file when specifying data_file_raw is an error
|
||||
* anyway.
|
||||
*/
|
||||
assert(!qcow2_opts->has_backing_file);
|
||||
}
|
||||
|
||||
if (qcow2_opts->data_file) {
|
||||
if (version < 3) {
|
||||
@ -4237,6 +4260,18 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (data_file_is_raw(bs) && prealloc == PREALLOC_MODE_OFF) {
|
||||
/*
|
||||
* When creating a qcow2 image with data-file-raw, we enforce
|
||||
* at least prealloc=metadata, so that the L1/L2 tables are
|
||||
* fully allocated and reading from the data file will return
|
||||
* the same data as reading from the qcow2 image. When the
|
||||
* image is grown, we must consequently preallocate the
|
||||
* metadata structures to cover the added area.
|
||||
*/
|
||||
prealloc = PREALLOC_MODE_METADATA;
|
||||
}
|
||||
}
|
||||
|
||||
switch (prealloc) {
|
||||
|
@ -74,6 +74,7 @@ Standard options:
|
||||
.. option:: --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>][,writable=on|off][,bitmap=<name>]
|
||||
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=unix,addr.path=<socket-path>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
|
||||
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=fd,addr.str=<fd>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
|
||||
--export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>[,growable=on|off][,writable=on|off]
|
||||
|
||||
is a block export definition. ``node-name`` is the block node that should be
|
||||
exported. ``writable`` determines whether or not the export allows write
|
||||
@ -92,6 +93,16 @@ Standard options:
|
||||
``logical-block-size`` sets the logical block size in bytes (the default is
|
||||
512). ``num-queues`` sets the number of virtqueues (the default is 1).
|
||||
|
||||
The ``fuse`` export type takes a mount point, which must be a regular file,
|
||||
on which to export the given block node. That file will not be changed, it
|
||||
will just appear to have the block node's content while the export is active
|
||||
(very much like mounting a filesystem on a directory does not change what the
|
||||
directory contains, it only shows a different content while the filesystem is
|
||||
mounted). Consequently, applications that have opened the given file before
|
||||
the export became active will continue to see its original content. If
|
||||
``growable`` is set, writes after the end of the exported file will grow the
|
||||
block node to fit.
|
||||
|
||||
.. option:: --monitor MONITORDEF
|
||||
|
||||
is a QMP monitor definition. See the :manpage:`qemu(1)` manual page for
|
||||
@ -196,6 +207,14 @@ domain socket ``vhost-user-blk.sock``::
|
||||
--blockdev driver=qcow2,node-name=qcow2,file=file \
|
||||
--export type=vhost-user-blk,id=export,addr.type=unix,addr.path=vhost-user-blk.sock,node-name=qcow2
|
||||
|
||||
Export a qcow2 image file ``disk.qcow2`` via FUSE on itself, so the disk image
|
||||
file will then appear as a raw image::
|
||||
|
||||
$ qemu-storage-daemon \
|
||||
--blockdev driver=file,node-name=file,filename=disk.qcow2 \
|
||||
--blockdev driver=qcow2,node-name=qcow2,file=file \
|
||||
--export type=fuse,id=export,node-name=qcow2,mountpoint=disk.qcow2,writable=on
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
|
@ -98,6 +98,10 @@ static void help(void)
|
||||
" export the specified block node over NBD\n"
|
||||
" (requires --nbd-server)\n"
|
||||
"\n"
|
||||
" --export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>\n"
|
||||
" [,growable=on|off][,writable=on|off]\n"
|
||||
" export the specified block node over FUSE\n"
|
||||
"\n"
|
||||
" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
|
||||
" configure a QMP monitor\n"
|
||||
"\n"
|
||||
|
@ -187,7 +187,8 @@ EOF
|
||||
}
|
||||
|
||||
overlay_io | $QEMU_IO blkdebug::"$TEST_IMG" | _filter_qemu_io |\
|
||||
sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g'
|
||||
sed -e 's/[0-9]*\/[0-9]* bytes at offset [0-9]*/XXX\/XXX bytes at offset XXX/g' \
|
||||
-e 's/^[0-9]* KiB/XXX KiB/g'
|
||||
|
||||
echo
|
||||
echo "== Verify image content =="
|
||||
|
@ -71,74 +71,74 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR
|
||||
== Some concurrent requests touching the same cluster ==
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset XXX
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset XXX
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 32768/32768 bytes at offset XXX
|
||||
32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 57344/57344 bytes at offset XXX
|
||||
56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 4096/4096 bytes at offset XXX
|
||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 32768/32768 bytes at offset XXX
|
||||
32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard 65536/65536 bytes at offset XXX
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 57344/57344 bytes at offset XXX
|
||||
56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 4096/4096 bytes at offset XXX
|
||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset XXX
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard 65536/65536 bytes at offset XXX
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 57344/57344 bytes at offset XXX
|
||||
56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 98304/98304 bytes at offset XXX
|
||||
96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 8192/8192 bytes at offset XXX
|
||||
8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 81920/81920 bytes at offset XXX
|
||||
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
blkdebug: Suspended request 'A'
|
||||
blkdebug: Resuming request 'A'
|
||||
wrote 32768/32768 bytes at offset XXX
|
||||
32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 98304/98304 bytes at offset XXX
|
||||
96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote XXX/XXX bytes at offset XXX
|
||||
XXX KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== Verify image content ==
|
||||
read 65536/65536 bytes at offset 0
|
||||
|
@ -199,7 +199,7 @@ case "$QEMU_DEFAULT_MACHINE" in
|
||||
# virtio-blk enables the iothread only when the driver initialises the
|
||||
# device, so a second virtio-blk device can't be added even with the
|
||||
# same iothread. virtio-scsi allows this.
|
||||
run_qemu $iothread -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on
|
||||
run_qemu $iothread -device virtio-blk-pci,drive=disk,iothread=iothread0,share-rw=on
|
||||
run_qemu $iothread -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
|
||||
;;
|
||||
*)
|
||||
|
@ -61,13 +61,13 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) quit
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,node-name=123foo
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=123foo: Invalid node name
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=123foo: Invalid node-name: '123foo'
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,node-name=_foo
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=_foo: Invalid node name
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=_foo: Invalid node-name: '_foo'
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,node-name=foo#12
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node name
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node-name: 'foo#12'
|
||||
|
||||
|
||||
=== Device without drive ===
|
||||
|
@ -183,9 +183,9 @@ Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on: Cannot change iothread of active block backend
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iothread=iothread0,share-rw=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on: Cannot change iothread of active block backend
|
||||
(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,iothread=iothread0,share-rw=on: Cannot change iothread of active block backend
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
@ -2,7 +2,7 @@ QA output created by 116
|
||||
|
||||
== truncated header cluster ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED table offset is invalid
|
||||
|
||||
== invalid header magic ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
@ -10,21 +10,21 @@ qemu-io: can't open device TEST_DIR/t.qed: Image not in QED format
|
||||
|
||||
== invalid cluster size ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED cluster size is invalid
|
||||
|
||||
== invalid table size ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED table size is invalid
|
||||
|
||||
== invalid header size ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED table offset is invalid
|
||||
|
||||
== invalid L1 table offset ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED table offset is invalid
|
||||
|
||||
== invalid image size ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
|
||||
qemu-io: can't open device TEST_DIR/t.qed: QED image size is invalid
|
||||
*** done
|
||||
|
@ -38,6 +38,7 @@ 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
|
||||
@ -267,6 +268,109 @@ case $result in
|
||||
;;
|
||||
esac
|
||||
|
||||
echo
|
||||
echo '=== Preallocation with data-file-raw ==='
|
||||
|
||||
echo
|
||||
echo '--- Using a non-zeroed data file ---'
|
||||
|
||||
# Using data-file-raw must enforce at least metadata preallocation so
|
||||
# that it does not matter whether one reads the raw file or the qcow2
|
||||
# file
|
||||
|
||||
# Pre-create the data file, write some data. Real-world use cases for
|
||||
# this are adding a qcow2 metadata file to a block device (i.e., using
|
||||
# the device as the data file) or adding qcow2 features to pre-existing
|
||||
# raw images (e.g. because the user now wants persistent dirty bitmaps).
|
||||
truncate -s 1M "$TEST_IMG.data"
|
||||
$QEMU_IO -f raw -c 'write -P 42 0 1M' "$TEST_IMG.data" | _filter_qemu_io
|
||||
|
||||
# We cannot use qemu-img to create the qcow2 image, because it would
|
||||
# clear the data file. Use the blockdev-create job instead, which will
|
||||
# only format the qcow2 image file.
|
||||
touch "$TEST_IMG"
|
||||
_launch_qemu \
|
||||
-blockdev file,node-name=data,filename="$TEST_IMG.data" \
|
||||
-blockdev file,node-name=meta,filename="$TEST_IMG"
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE '{ "execute": "qmp_capabilities" }' 'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
'{ "execute": "blockdev-create",
|
||||
"arguments": {
|
||||
"job-id": "create",
|
||||
"options": {
|
||||
"driver": "qcow2",
|
||||
"size": '"$((1 * 1024 * 1024))"',
|
||||
"file": "meta",
|
||||
"data-file": "data",
|
||||
"data-file-raw": true
|
||||
} } }' \
|
||||
'"status": "concluded"'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
'{ "execute": "job-dismiss", "arguments": { "id": "create" } }' \
|
||||
'return'
|
||||
|
||||
_cleanup_qemu
|
||||
|
||||
echo
|
||||
echo 'Comparing pattern:'
|
||||
|
||||
# Reading from either the qcow2 file or the data file should return
|
||||
# the same result:
|
||||
$QEMU_IO -f raw -c 'read -P 42 0 1M' "$TEST_IMG.data" | _filter_qemu_io
|
||||
$QEMU_IO -f $IMGFMT -c 'read -P 42 0 1M' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# For good measure
|
||||
$QEMU_IMG compare -f raw "$TEST_IMG.data" "$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo '--- Truncation (growing) ---'
|
||||
|
||||
# Append some new data to the raw file, then resize the qcow2 image
|
||||
# accordingly and see whether the new data is visible. Technically
|
||||
# that is not allowed, but it is reasonable behavior, so test it.
|
||||
truncate -s 2M "$TEST_IMG.data"
|
||||
$QEMU_IO -f raw -c 'write -P 84 1M 1M' "$TEST_IMG.data" | _filter_qemu_io
|
||||
|
||||
$QEMU_IMG resize "$TEST_IMG" 2M
|
||||
|
||||
echo
|
||||
echo 'Comparing pattern:'
|
||||
|
||||
$QEMU_IO -f raw -c 'read -P 42 0 1M' -c 'read -P 84 1M 1M' "$TEST_IMG.data" \
|
||||
| _filter_qemu_io
|
||||
$QEMU_IO -f $IMGFMT -c 'read -P 42 0 1M' -c 'read -P 84 1M 1M' "$TEST_IMG" \
|
||||
| _filter_qemu_io
|
||||
|
||||
$QEMU_IMG compare -f raw "$TEST_IMG.data" "$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo '--- Giving a backing file at runtime ---'
|
||||
|
||||
# qcow2 files with data-file-raw cannot have backing files given by
|
||||
# their image header, but qemu will allow you to set a backing node at
|
||||
# runtime -- it should not have any effect, though (because reading
|
||||
# from the qcow2 node should return the same data as reading from the
|
||||
# raw node).
|
||||
|
||||
_make_test_img -o "data_file=$TEST_IMG.data,data_file_raw=on" 1M
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img 1M
|
||||
|
||||
# Write something that is not zero into the base image
|
||||
$QEMU_IO -c 'write -P 42 0 1M' "$TEST_IMG.base" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo 'Comparing qcow2 image and raw data file:'
|
||||
|
||||
# $TEST_IMG and $TEST_IMG.data must show the same data at all times;
|
||||
# that is, the qcow2 node must not fall through to the backing image
|
||||
# at any point
|
||||
$QEMU_IMG compare --image-opts \
|
||||
"driver=raw,file.filename=$TEST_IMG.data" \
|
||||
"file.filename=$TEST_IMG,backing.file.filename=$TEST_IMG.base"
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
|
@ -83,7 +83,7 @@ qcow2 file size after I/O: 327680
|
||||
=== Standalone image with external data file (valid raw) ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data data_file_raw=on
|
||||
qcow2 file size before I/O: 196616
|
||||
qcow2 file size before I/O: 327680
|
||||
|
||||
wrote 4194304/4194304 bytes at offset 1048576
|
||||
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
@ -93,11 +93,10 @@ wrote 3145728/3145728 bytes at offset 3145728
|
||||
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
No errors were found on the image.
|
||||
|
||||
[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false},
|
||||
{ "start": 1048576, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": 1048576},
|
||||
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 0},
|
||||
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": true, "data": false},
|
||||
{ "start": 4194304, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": 4194304},
|
||||
{ "start": 5242880, "length": 61865984, "depth": 0, "zero": true, "data": false}]
|
||||
{ "start": 4194304, "length": 2097152, "depth": 0, "zero": true, "data": false, "offset": 4194304},
|
||||
{ "start": 6291456, "length": 60817408, "depth": 0, "zero": false, "data": true, "offset": 6291456}]
|
||||
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
@ -138,4 +137,63 @@ wrote 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
Success: qemu-io failed, so the data file was flushed
|
||||
|
||||
=== Preallocation with data-file-raw ===
|
||||
|
||||
--- Using a non-zeroed data file ---
|
||||
wrote 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{"return": {}}
|
||||
{ "execute": "blockdev-create",
|
||||
"arguments": {
|
||||
"job-id": "create",
|
||||
"options": {
|
||||
"driver": "IMGFMT",
|
||||
"size": 1048576,
|
||||
"file": "meta",
|
||||
"data-file": "data",
|
||||
"data-file-raw": true
|
||||
} } }
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "create"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "create"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "create"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "create"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "create"}}
|
||||
{ "execute": "job-dismiss", "arguments": { "id": "create" } }
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}}
|
||||
{"return": {}}
|
||||
|
||||
Comparing pattern:
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Images are identical.
|
||||
|
||||
--- Truncation (growing) ---
|
||||
wrote 1048576/1048576 bytes at offset 1048576
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image resized.
|
||||
|
||||
Comparing pattern:
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 1048576/1048576 bytes at offset 1048576
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 1048576/1048576 bytes at offset 1048576
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Images are identical.
|
||||
|
||||
--- Giving a backing file at runtime ---
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 data_file=TEST_DIR/t.IMGFMT.data data_file_raw=on
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||
wrote 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
Comparing qcow2 image and raw data file:
|
||||
Images are identical.
|
||||
*** done
|
||||
|
Loading…
x
Reference in New Issue
Block a user