1
The following changes since commit bf159f0bdc7b8e7aa8342dedb3829ca744c1b612:
1
The following changes since commit 281f327487c9c9b1599f93c589a408bbf4a651b8:
2
2
3
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2021-01-27.for-upstream' into staging (2021-01-27 17:40:25 +0000)
3
Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.12-pull-request' into staging (2017-12-22 00:11:36 +0000)
4
4
5
are available in the Git repository at:
5
are available in the git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to a44be0334beae3a9affb4a3a92cc6852993d7a84:
9
for you to fetch changes up to 1a63a907507fbbcfaee3f622907ec244b7eabda8:
10
10
11
iotests: rename and move 169 and 199 tests (2021-01-27 20:53:14 +0100)
11
block: Keep nodes drained between reopen_queue/multiple (2017-12-22 15:05:32 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
16
- Fix crash on write to read-only devices
17
- iotests: Rewrite 'check' in Python, get rid of 'groups' and allow
18
non-numeric test case names
19
15
20
----------------------------------------------------------------
16
----------------------------------------------------------------
21
Kevin Wolf (2):
17
Doug Gale (1):
22
block: Separate blk_is_writable() and blk_supports_write_perm()
18
nvme: Add tracing
23
virtio-scsi-test: Test writing to scsi-cd device
24
19
25
Vladimir Sementsov-Ogievskiy (6):
20
Edgar Kaziakhmedov (1):
26
iotests: 146: drop extra whitespaces from .out file
21
qcow2: get rid of qcow2_backing_read1 routine
27
iotests: add findtests.py
28
iotests: add testenv.py
29
iotests: add testrunner.py
30
iotests: rewrite check into python
31
iotests: rename and move 169 and 199 tests
32
22
33
docs/devel/testing.rst | 50 +-
23
Fam Zheng (2):
34
include/sysemu/block-backend.h | 3 +-
24
block: Open backing image in force share mode for size probe
35
block/block-backend.c | 19 +-
25
block: Remove unused bdrv_requests_pending
36
hw/block/dataplane/xen-block.c | 2 +-
37
hw/block/fdc.c | 9 +-
38
hw/block/m25p80.c | 6 +-
39
hw/block/nand.c | 2 +-
40
hw/block/nvme-ns.c | 7 +-
41
hw/block/onenand.c | 2 +-
42
hw/block/pflash_cfi01.c | 2 +-
43
hw/block/pflash_cfi02.c | 2 +-
44
hw/block/swim.c | 6 +-
45
hw/block/virtio-blk.c | 6 +-
46
hw/block/xen-block.c | 2 +-
47
hw/ide/core.c | 2 +-
48
hw/misc/sifive_u_otp.c | 2 +-
49
hw/ppc/pnv_pnor.c | 2 +-
50
hw/scsi/scsi-disk.c | 10 +-
51
hw/scsi/scsi-generic.c | 4 +-
52
hw/sd/sd.c | 6 +-
53
hw/usb/dev-storage.c | 4 +-
54
tests/qtest/virtio-scsi-test.c | 39 +
55
tests/qemu-iotests/findtests.py | 159 +++
56
tests/qemu-iotests/iotests.py | 8 +
57
tests/qemu-iotests/testenv.py | 281 +++++
58
tests/qemu-iotests/testrunner.py | 367 +++++++
59
Makefile | 1 -
60
tests/check-block.sh | 3 +-
61
tests/qemu-iotests/146.out | 780 +++++++-------
62
tests/qemu-iotests/check | 1095 +++-----------------
63
tests/qemu-iotests/common.env.in | 3 -
64
tests/qemu-iotests/group | 323 ------
65
tests/qemu-iotests/meson.build | 3 -
66
.../{199 => tests/migrate-bitmaps-postcopy-test} | 0
67
.../migrate-bitmaps-postcopy-test.out} | 0
68
.../{169 => tests/migrate-bitmaps-test} | 0
69
.../{169.out => tests/migrate-bitmaps-test.out} | 0
70
37 files changed, 1481 insertions(+), 1729 deletions(-)
71
create mode 100644 tests/qemu-iotests/findtests.py
72
create mode 100644 tests/qemu-iotests/testenv.py
73
create mode 100644 tests/qemu-iotests/testrunner.py
74
delete mode 100644 tests/qemu-iotests/common.env.in
75
delete mode 100644 tests/qemu-iotests/group
76
rename tests/qemu-iotests/{199 => tests/migrate-bitmaps-postcopy-test} (100%)
77
rename tests/qemu-iotests/{199.out => tests/migrate-bitmaps-postcopy-test.out} (100%)
78
rename tests/qemu-iotests/{169 => tests/migrate-bitmaps-test} (100%)
79
rename tests/qemu-iotests/{169.out => tests/migrate-bitmaps-test.out} (100%)
80
26
27
John Snow (1):
28
iotests: fix 197 for vpc
81
29
30
Kevin Wolf (27):
31
block: Formats don't need CONSISTENT_READ with NO_IO
32
block: Make bdrv_drain_invoke() recursive
33
block: Call .drain_begin only once in bdrv_drain_all_begin()
34
test-bdrv-drain: Test BlockDriver callbacks for drain
35
block: bdrv_drain_recurse(): Remove unused begin parameter
36
block: Don't wait for requests in bdrv_drain*_end()
37
block: Unify order in drain functions
38
block: Don't acquire AioContext in hmp_qemu_io()
39
block: Document that x-blockdev-change breaks quorum children list
40
block: Assert drain_all is only called from main AioContext
41
block: Make bdrv_drain() driver callbacks non-recursive
42
test-bdrv-drain: Test callback for bdrv_drain
43
test-bdrv-drain: Test bs->quiesce_counter
44
blockjob: Pause job on draining any job BDS
45
test-bdrv-drain: Test drain vs. block jobs
46
block: Don't block_job_pause_all() in bdrv_drain_all()
47
block: Nested drain_end must still call callbacks
48
test-bdrv-drain: Test nested drain sections
49
block: Don't notify parents in drain call chain
50
block: Add bdrv_subtree_drained_begin/end()
51
test-bdrv-drain: Tests for bdrv_subtree_drain
52
test-bdrv-drain: Test behaviour in coroutine context
53
test-bdrv-drain: Recursive draining with multiple parents
54
block: Allow graph changes in subtree drained section
55
test-bdrv-drain: Test graph changes in drained section
56
commit: Simplify reopen of base
57
block: Keep nodes drained between reopen_queue/multiple
58
59
Thomas Huth (3):
60
block: Remove the obsolete -drive boot=on|off parameter
61
block: Remove the deprecated -hdachs option
62
block: Mention -drive cyls/heads/secs/trans/serial/addr in deprecation chapter
63
64
qapi/block-core.json | 4 +
65
block/qcow2.h | 3 -
66
include/block/block.h | 15 +-
67
include/block/block_int.h | 6 +-
68
block.c | 75 ++++-
69
block/commit.c | 8 +-
70
block/io.c | 164 +++++++---
71
block/qcow2.c | 51 +--
72
block/replication.c | 6 +
73
blockdev.c | 11 -
74
blockjob.c | 22 +-
75
hmp.c | 6 -
76
hw/block/nvme.c | 349 +++++++++++++++++----
77
qemu-io-cmds.c | 3 +
78
tests/test-bdrv-drain.c | 651 +++++++++++++++++++++++++++++++++++++++
79
vl.c | 86 +-----
80
hw/block/trace-events | 93 ++++++
81
qemu-doc.texi | 29 +-
82
qemu-options.hx | 19 +-
83
tests/Makefile.include | 2 +
84
tests/qemu-iotests/197 | 4 +
85
tests/qemu-iotests/common.filter | 3 +-
86
22 files changed, 1294 insertions(+), 316 deletions(-)
87
create mode 100644 tests/test-bdrv-drain.c
88
diff view generated by jsdifflib
New patch
1
Commit 1f4ad7d fixed 'qemu-img info' for raw images that are currently
2
in use as a mirror target. It is not enough for image formats, though,
3
as these still unconditionally request BLK_PERM_CONSISTENT_READ.
1
4
5
As this permission is geared towards whether the guest-visible data is
6
consistent, and has no impact on whether the metadata is sane, and
7
'qemu-img info' does not read guest-visible data (except for the raw
8
format), it makes sense to not require BLK_PERM_CONSISTENT_READ if there
9
is not going to be any guest I/O performed, regardless of image format.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block.c | 6 +++++-
14
1 file changed, 5 insertions(+), 1 deletion(-)
15
16
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
21
assert(role == &child_backing || role == &child_file);
22
23
if (!backing) {
24
+ int flags = bdrv_reopen_get_flags(reopen_queue, bs);
25
+
26
/* Apart from the modifications below, the same permissions are
27
* forwarded and left alone as for filters */
28
bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
29
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
30
31
/* bs->file always needs to be consistent because of the metadata. We
32
* can never allow other users to resize or write to it. */
33
- perm |= BLK_PERM_CONSISTENT_READ;
34
+ if (!(flags & BDRV_O_NO_IO)) {
35
+ perm |= BLK_PERM_CONSISTENT_READ;
36
+ }
37
shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
38
} else {
39
/* We want consistent read from backing files if the parent needs it.
40
--
41
2.13.6
42
43
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
VPC has some difficulty creating geometries of particular size.
4
However, we can indeed force it to use a literal one, so let's
5
do that for the sake of test 197, which is testing some specific
6
offsets.
7
8
Signed-off-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Lukáš Doktor <ldoktor@redhat.com>
13
---
14
tests/qemu-iotests/197 | 4 ++++
15
tests/qemu-iotests/common.filter | 3 ++-
16
2 files changed, 6 insertions(+), 1 deletion(-)
17
18
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/197
21
+++ b/tests/qemu-iotests/197
22
@@ -XXX,XX +XXX,XX @@ echo '=== Copy-on-read ==='
23
echo
24
25
# Prep the images
26
+# VPC rounds image sizes to a specific geometry, force a specific size.
27
+if [ "$IMGFMT" = "vpc" ]; then
28
+ IMGOPTS=$(_optstr_add "$IMGOPTS" "force_size")
29
+fi
30
_make_test_img 4G
31
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
32
IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
33
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
34
index XXXXXXX..XXXXXXX 100644
35
--- a/tests/qemu-iotests/common.filter
36
+++ b/tests/qemu-iotests/common.filter
37
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
38
-e "s# log_size=[0-9]\\+##g" \
39
-e "s# refcount_bits=[0-9]\\+##g" \
40
-e "s# key-secret=[a-zA-Z0-9]\\+##g" \
41
- -e "s# iter-time=[0-9]\\+##g"
42
+ -e "s# iter-time=[0-9]\\+##g" \
43
+ -e "s# force_size=\\(on\\|off\\)##g"
44
}
45
46
_filter_img_info()
47
--
48
2.13.6
49
50
diff view generated by jsdifflib
New patch
1
This change separates bdrv_drain_invoke(), which calls the BlockDriver
2
drain callbacks, from bdrv_drain_recurse(). Instead, the function
3
performs its own recursion now.
1
4
5
One reason for this is that bdrv_drain_recurse() can be called multiple
6
times by bdrv_drain_all_begin(), but the callbacks may only be called
7
once. The separation is necessary to fix this bug.
8
9
The other reason is that we intend to go to a model where we call all
10
driver callbacks first, and only then start polling. This is not fully
11
achieved yet with this patch, as bdrv_drain_invoke() contains a
12
BDRV_POLL_WHILE() loop for the block driver callbacks, which can still
13
call callbacks for any unrelated event. It's a step in this direction
14
anyway.
15
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
20
block/io.c | 14 +++++++++++---
21
1 file changed, 11 insertions(+), 3 deletions(-)
22
23
diff --git a/block/io.c b/block/io.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/io.c
26
+++ b/block/io.c
27
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
28
bdrv_wakeup(bs);
29
}
30
31
+/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
32
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
33
{
34
+ BdrvChild *child, *tmp;
35
BdrvCoDrainData data = { .bs = bs, .done = false, .begin = begin};
36
37
if (!bs->drv || (begin && !bs->drv->bdrv_co_drain_begin) ||
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
39
data.co = qemu_coroutine_create(bdrv_drain_invoke_entry, &data);
40
bdrv_coroutine_enter(bs, data.co);
41
BDRV_POLL_WHILE(bs, !data.done);
42
+
43
+ QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) {
44
+ bdrv_drain_invoke(child->bs, begin);
45
+ }
46
}
47
48
static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
49
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
50
BdrvChild *child, *tmp;
51
bool waited;
52
53
- /* Ensure any pending metadata writes are submitted to bs->file. */
54
- bdrv_drain_invoke(bs, begin);
55
-
56
/* Wait for drained requests to finish */
57
waited = BDRV_POLL_WHILE(bs, atomic_read(&bs->in_flight) > 0);
58
59
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs)
60
bdrv_parent_drained_begin(bs);
61
}
62
63
+ bdrv_drain_invoke(bs, true);
64
bdrv_drain_recurse(bs, true);
65
}
66
67
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
68
}
69
70
bdrv_parent_drained_end(bs);
71
+ bdrv_drain_invoke(bs, false);
72
bdrv_drain_recurse(bs, false);
73
aio_enable_external(bdrv_get_aio_context(bs));
74
}
75
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
76
aio_context_acquire(aio_context);
77
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
78
if (aio_context == bdrv_get_aio_context(bs)) {
79
+ /* FIXME Calling this multiple times is wrong */
80
+ bdrv_drain_invoke(bs, true);
81
waited |= bdrv_drain_recurse(bs, true);
82
}
83
}
84
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
85
aio_context_acquire(aio_context);
86
aio_enable_external(aio_context);
87
bdrv_parent_drained_end(bs);
88
+ bdrv_drain_invoke(bs, false);
89
bdrv_drain_recurse(bs, false);
90
aio_context_release(aio_context);
91
}
92
--
93
2.13.6
94
95
diff view generated by jsdifflib
New patch
1
bdrv_drain_all_begin() used to call the .bdrv_co_drain_begin() driver
2
callback inside its polling loop. This means that how many times it got
3
called for each node depended on long it had to poll the event loop.
1
4
5
This is obviously not right and results in nodes that stay drained even
6
after bdrv_drain_all_end(), which calls .bdrv_co_drain_begin() once per
7
node.
8
9
Fix bdrv_drain_all_begin() to call the callback only once, too.
10
11
Cc: qemu-stable@nongnu.org
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
---
15
block/io.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/io.c
21
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
23
aio_context_acquire(aio_context);
24
bdrv_parent_drained_begin(bs);
25
aio_disable_external(aio_context);
26
+ bdrv_drain_invoke(bs, true);
27
aio_context_release(aio_context);
28
29
if (!g_slist_find(aio_ctxs, aio_context)) {
30
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
31
aio_context_acquire(aio_context);
32
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
33
if (aio_context == bdrv_get_aio_context(bs)) {
34
- /* FIXME Calling this multiple times is wrong */
35
- bdrv_drain_invoke(bs, true);
36
waited |= bdrv_drain_recurse(bs, true);
37
}
38
}
39
--
40
2.13.6
41
42
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This adds a test case that the BlockDriver callbacks for drain are
2
called in bdrv_drained_all_begin/end(), and that both of them are called
3
exactly once.
2
4
3
Add TestEnv class, which will handle test environment in a new python
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
iotests running framework.
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
9
tests/test-bdrv-drain.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++
10
tests/Makefile.include | 2 +
11
2 files changed, 139 insertions(+)
12
create mode 100644 tests/test-bdrv-drain.c
5
13
6
Don't add compat=1.1 for qcow2 IMGOPTS, as v3 is default anyway.
14
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-Id: <20210125185056.129513-4-vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
tests/qemu-iotests/testenv.py | 281 ++++++++++++++++++++++++++++++++++
13
1 file changed, 281 insertions(+)
14
create mode 100644 tests/qemu-iotests/testenv.py
15
16
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
17
new file mode 100644
15
new file mode 100644
18
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
19
--- /dev/null
17
--- /dev/null
20
+++ b/tests/qemu-iotests/testenv.py
18
+++ b/tests/test-bdrv-drain.c
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
22
+# TestEnv class to manage test environment variables.
20
+/*
23
+#
21
+ * Block node draining tests
24
+# Copyright (c) 2020-2021 Virtuozzo International GmbH
22
+ *
25
+#
23
+ * Copyright (c) 2017 Kevin Wolf <kwolf@redhat.com>
26
+# This program is free software; you can redistribute it and/or modify
24
+ *
27
+# it under the terms of the GNU General Public License as published by
25
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
28
+# the Free Software Foundation; either version 2 of the License, or
26
+ * of this software and associated documentation files (the "Software"), to deal
29
+# (at your option) any later version.
27
+ * in the Software without restriction, including without limitation the rights
30
+#
28
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31
+# This program is distributed in the hope that it will be useful,
29
+ * copies of the Software, and to permit persons to whom the Software is
32
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+ * furnished to do so, subject to the following conditions:
33
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+ *
34
+# GNU General Public License for more details.
32
+ * The above copyright notice and this permission notice shall be included in
35
+#
33
+ * all copies or substantial portions of the Software.
36
+# You should have received a copy of the GNU General Public License
34
+ *
37
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+#
36
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41
+ * THE SOFTWARE.
42
+ */
39
+
43
+
40
+import os
44
+#include "qemu/osdep.h"
41
+import sys
45
+#include "block/block.h"
42
+import tempfile
46
+#include "sysemu/block-backend.h"
43
+from pathlib import Path
47
+#include "qapi/error.h"
44
+import shutil
45
+import collections
46
+import random
47
+import subprocess
48
+import glob
49
+from typing import Dict, Any, Optional, ContextManager
50
+
48
+
49
+typedef struct BDRVTestState {
50
+ int drain_count;
51
+} BDRVTestState;
51
+
52
+
52
+def isxfile(path: str) -> bool:
53
+static void coroutine_fn bdrv_test_co_drain_begin(BlockDriverState *bs)
53
+ return os.path.isfile(path) and os.access(path, os.X_OK)
54
+{
55
+ BDRVTestState *s = bs->opaque;
56
+ s->drain_count++;
57
+}
54
+
58
+
59
+static void coroutine_fn bdrv_test_co_drain_end(BlockDriverState *bs)
60
+{
61
+ BDRVTestState *s = bs->opaque;
62
+ s->drain_count--;
63
+}
55
+
64
+
56
+def get_default_machine(qemu_prog: str) -> str:
65
+static void bdrv_test_close(BlockDriverState *bs)
57
+ outp = subprocess.run([qemu_prog, '-machine', 'help'], check=True,
66
+{
58
+ universal_newlines=True,
67
+ BDRVTestState *s = bs->opaque;
59
+ stdout=subprocess.PIPE).stdout
68
+ g_assert_cmpint(s->drain_count, >, 0);
69
+}
60
+
70
+
61
+ machines = outp.split('\n')
71
+static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
62
+ try:
72
+ uint64_t offset, uint64_t bytes,
63
+ default_machine = next(m for m in machines if m.endswith(' (default)'))
73
+ QEMUIOVector *qiov, int flags)
64
+ except StopIteration:
74
+{
65
+ return ''
75
+ /* We want this request to stay until the polling loop in drain waits for
66
+ default_machine = default_machine.split(' ', 1)[0]
76
+ * it to complete. We need to sleep a while as bdrv_drain_invoke() comes
77
+ * first and polls its result, too, but it shouldn't accidentally complete
78
+ * this request yet. */
79
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000);
67
+
80
+
68
+ alias_suf = ' (alias of {})'.format(default_machine)
81
+ return 0;
69
+ alias = next((m for m in machines if m.endswith(alias_suf)), None)
82
+}
70
+ if alias is not None:
71
+ default_machine = alias.split(' ', 1)[0]
72
+
83
+
73
+ return default_machine
84
+static BlockDriver bdrv_test = {
85
+ .format_name = "test",
86
+ .instance_size = sizeof(BDRVTestState),
74
+
87
+
88
+ .bdrv_close = bdrv_test_close,
89
+ .bdrv_co_preadv = bdrv_test_co_preadv,
75
+
90
+
76
+class TestEnv(ContextManager['TestEnv']):
91
+ .bdrv_co_drain_begin = bdrv_test_co_drain_begin,
77
+ """
92
+ .bdrv_co_drain_end = bdrv_test_co_drain_end,
78
+ Manage system environment for running tests
93
+};
79
+
94
+
80
+ The following variables are supported/provided. They are represented by
95
+static void aio_ret_cb(void *opaque, int ret)
81
+ lower-cased TestEnv attributes.
96
+{
82
+ """
97
+ int *aio_ret = opaque;
98
+ *aio_ret = ret;
99
+}
83
+
100
+
84
+ # We store environment variables as instance attributes, and there are a
101
+static void test_drv_cb_drain_all(void)
85
+ # lot of them. Silence pylint:
102
+{
86
+ # pylint: disable=too-many-instance-attributes
103
+ BlockBackend *blk;
104
+ BlockDriverState *bs;
105
+ BDRVTestState *s;
106
+ BlockAIOCB *acb;
107
+ int aio_ret;
87
+
108
+
88
+ env_variables = ['PYTHONPATH', 'TEST_DIR', 'SOCK_DIR', 'SAMPLE_IMG_DIR',
109
+ QEMUIOVector qiov;
89
+ 'OUTPUT_DIR', 'PYTHON', 'QEMU_PROG', 'QEMU_IMG_PROG',
110
+ struct iovec iov = {
90
+ 'QEMU_IO_PROG', 'QEMU_NBD_PROG', 'QSD_PROG',
111
+ .iov_base = NULL,
91
+ 'SOCKET_SCM_HELPER', 'QEMU_OPTIONS', 'QEMU_IMG_OPTIONS',
112
+ .iov_len = 0,
92
+ 'QEMU_IO_OPTIONS', 'QEMU_IO_OPTIONS_NO_FMT',
113
+ };
93
+ 'QEMU_NBD_OPTIONS', 'IMGOPTS', 'IMGFMT', 'IMGPROTO',
114
+ qemu_iovec_init_external(&qiov, &iov, 1);
94
+ 'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU',
95
+ 'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
96
+ 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_']
97
+
115
+
98
+ def get_env(self) -> Dict[str, str]:
116
+ blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
99
+ env = {}
117
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
100
+ for v in self.env_variables:
118
+ &error_abort);
101
+ val = getattr(self, v.lower(), None)
119
+ s = bs->opaque;
102
+ if val is not None:
120
+ blk_insert_bs(blk, bs, &error_abort);
103
+ env[v] = val
104
+
121
+
105
+ return env
122
+ /* Simple bdrv_drain_all_begin/end pair, check that CBs are called */
123
+ g_assert_cmpint(s->drain_count, ==, 0);
124
+ bdrv_drain_all_begin();
125
+ g_assert_cmpint(s->drain_count, ==, 1);
126
+ bdrv_drain_all_end();
127
+ g_assert_cmpint(s->drain_count, ==, 0);
106
+
128
+
107
+ def init_directories(self) -> None:
129
+ /* Now do the same while a request is pending */
108
+ """Init directory variables:
130
+ aio_ret = -EINPROGRESS;
109
+ PYTHONPATH
131
+ acb = blk_aio_preadv(blk, 0, &qiov, 0, aio_ret_cb, &aio_ret);
110
+ TEST_DIR
132
+ g_assert(acb != NULL);
111
+ SOCK_DIR
133
+ g_assert_cmpint(aio_ret, ==, -EINPROGRESS);
112
+ SAMPLE_IMG_DIR
113
+ OUTPUT_DIR
114
+ """
115
+ self.pythonpath = os.getenv('PYTHONPATH')
116
+ if self.pythonpath:
117
+ self.pythonpath = self.source_iotests + os.pathsep + \
118
+ self.pythonpath
119
+ else:
120
+ self.pythonpath = self.source_iotests
121
+
134
+
122
+ self.test_dir = os.getenv('TEST_DIR',
135
+ g_assert_cmpint(s->drain_count, ==, 0);
123
+ os.path.join(os.getcwd(), 'scratch'))
136
+ bdrv_drain_all_begin();
124
+ Path(self.test_dir).mkdir(parents=True, exist_ok=True)
137
+ g_assert_cmpint(aio_ret, ==, 0);
138
+ g_assert_cmpint(s->drain_count, ==, 1);
139
+ bdrv_drain_all_end();
140
+ g_assert_cmpint(s->drain_count, ==, 0);
125
+
141
+
126
+ try:
142
+ bdrv_unref(bs);
127
+ self.sock_dir = os.environ['SOCK_DIR']
143
+ blk_unref(blk);
128
+ self.tmp_sock_dir = False
144
+}
129
+ Path(self.test_dir).mkdir(parents=True, exist_ok=True)
130
+ except KeyError:
131
+ self.sock_dir = tempfile.mkdtemp()
132
+ self.tmp_sock_dir = True
133
+
145
+
134
+ self.sample_img_dir = os.getenv('SAMPLE_IMG_DIR',
146
+int main(int argc, char **argv)
135
+ os.path.join(self.source_iotests,
147
+{
136
+ 'sample_images'))
148
+ bdrv_init();
149
+ qemu_init_main_loop(&error_abort);
137
+
150
+
138
+ self.output_dir = os.getcwd() # OUTPUT_DIR
151
+ g_test_init(&argc, &argv, NULL);
139
+
152
+
140
+ def init_binaries(self) -> None:
153
+ g_test_add_func("/bdrv-drain/driver-cb/drain_all", test_drv_cb_drain_all);
141
+ """Init binary path variables:
142
+ PYTHON (for bash tests)
143
+ QEMU_PROG, QEMU_IMG_PROG, QEMU_IO_PROG, QEMU_NBD_PROG, QSD_PROG
144
+ SOCKET_SCM_HELPER
145
+ """
146
+ self.python = sys.executable
147
+
154
+
148
+ def root(*names: str) -> str:
155
+ return g_test_run();
149
+ return os.path.join(self.build_root, *names)
156
+}
150
+
157
diff --git a/tests/Makefile.include b/tests/Makefile.include
151
+ arch = os.uname().machine
158
index XXXXXXX..XXXXXXX 100644
152
+ if 'ppc64' in arch:
159
--- a/tests/Makefile.include
153
+ arch = 'ppc64'
160
+++ b/tests/Makefile.include
154
+
161
@@ -XXX,XX +XXX,XX @@ gcov-files-test-thread-pool-y = thread-pool.c
155
+ self.qemu_prog = os.getenv('QEMU_PROG', root(f'qemu-system-{arch}'))
162
gcov-files-test-hbitmap-y = util/hbitmap.c
156
+ if not os.path.exists(self.qemu_prog):
163
check-unit-y += tests/test-hbitmap$(EXESUF)
157
+ pattern = root('qemu-system-*')
164
gcov-files-test-hbitmap-y = blockjob.c
158
+ try:
165
+check-unit-y += tests/test-bdrv-drain$(EXESUF)
159
+ progs = glob.iglob(pattern)
166
check-unit-y += tests/test-blockjob$(EXESUF)
160
+ self.qemu_prog = next(p for p in progs if isxfile(p))
167
check-unit-y += tests/test-blockjob-txn$(EXESUF)
161
+ except StopIteration:
168
check-unit-y += tests/test-x86-cpuid$(EXESUF)
162
+ sys.exit("Not found any Qemu executable binary by pattern "
169
@@ -XXX,XX +XXX,XX @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
163
+ f"'{pattern}'")
170
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
164
+
171
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
165
+ self.qemu_img_prog = os.getenv('QEMU_IMG_PROG', root('qemu-img'))
172
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
166
+ self.qemu_io_prog = os.getenv('QEMU_IO_PROG', root('qemu-io'))
173
+tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
167
+ self.qemu_nbd_prog = os.getenv('QEMU_NBD_PROG', root('qemu-nbd'))
174
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
168
+ self.qsd_prog = os.getenv('QSD_PROG', root('storage-daemon',
175
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
169
+ 'qemu-storage-daemon'))
176
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
170
+
171
+ for b in [self.qemu_img_prog, self.qemu_io_prog, self.qemu_nbd_prog,
172
+ self.qemu_prog, self.qsd_prog]:
173
+ if not os.path.exists(b):
174
+ sys.exit('No such file: ' + b)
175
+ if not isxfile(b):
176
+ sys.exit('Not executable: ' + b)
177
+
178
+ helper_path = os.path.join(self.build_iotests, 'socket_scm_helper')
179
+ if isxfile(helper_path):
180
+ self.socket_scm_helper = helper_path # SOCKET_SCM_HELPER
181
+
182
+ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
183
+ cachemode: Optional[str] = None,
184
+ imgopts: Optional[str] = None,
185
+ misalign: bool = False,
186
+ debug: bool = False,
187
+ valgrind: bool = False) -> None:
188
+ self.imgfmt = imgfmt
189
+ self.imgproto = imgproto
190
+ self.aiomode = aiomode
191
+ self.imgopts = imgopts
192
+ self.misalign = misalign
193
+ self.debug = debug
194
+
195
+ if valgrind:
196
+ self.valgrind_qemu = 'y'
197
+
198
+ if cachemode is None:
199
+ self.cachemode_is_default = 'true'
200
+ self.cachemode = 'writeback'
201
+ else:
202
+ self.cachemode_is_default = 'false'
203
+ self.cachemode = cachemode
204
+
205
+ # Initialize generic paths: build_root, build_iotests, source_iotests,
206
+ # which are needed to initialize some environment variables. They are
207
+ # used by init_*() functions as well.
208
+
209
+ if os.path.islink(sys.argv[0]):
210
+ # called from the build tree
211
+ self.source_iotests = os.path.dirname(os.readlink(sys.argv[0]))
212
+ self.build_iotests = os.path.dirname(os.path.abspath(sys.argv[0]))
213
+ else:
214
+ # called from the source tree
215
+ self.source_iotests = os.getcwd()
216
+ self.build_iotests = self.source_iotests
217
+
218
+ self.build_root = os.path.join(self.build_iotests, '..', '..')
219
+
220
+ self.init_directories()
221
+ self.init_binaries()
222
+
223
+ self.malloc_perturb_ = os.getenv('MALLOC_PERTURB_',
224
+ str(random.randrange(1, 255)))
225
+
226
+ # QEMU_OPTIONS
227
+ self.qemu_options = '-nodefaults -display none -accel qtest'
228
+ machine_map = (
229
+ ('arm', 'virt'),
230
+ ('aarch64', 'virt'),
231
+ ('avr', 'mega2560'),
232
+ ('rx', 'gdbsim-r5f562n8'),
233
+ ('tricore', 'tricore_testboard')
234
+ )
235
+ for suffix, machine in machine_map:
236
+ if self.qemu_prog.endswith(f'qemu-system-{suffix}'):
237
+ self.qemu_options += f' -machine {machine}'
238
+
239
+ # QEMU_DEFAULT_MACHINE
240
+ self.qemu_default_machine = get_default_machine(self.qemu_prog)
241
+
242
+ self.qemu_img_options = os.getenv('QEMU_IMG_OPTIONS')
243
+ self.qemu_nbd_options = os.getenv('QEMU_NBD_OPTIONS')
244
+
245
+ is_generic = self.imgfmt not in ['bochs', 'cloop', 'dmg']
246
+ self.imgfmt_generic = 'true' if is_generic else 'false'
247
+
248
+ self.qemu_io_options = f'--cache {self.cachemode} --aio {self.aiomode}'
249
+ if self.misalign:
250
+ self.qemu_io_options += ' --misalign'
251
+
252
+ self.qemu_io_options_no_fmt = self.qemu_io_options
253
+
254
+ if self.imgfmt == 'luks':
255
+ self.imgoptssyntax = 'true'
256
+ self.imgkeysecret = '123456'
257
+ if not self.imgopts:
258
+ self.imgopts = 'iter-time=10'
259
+ elif 'iter-time=' not in self.imgopts:
260
+ self.imgopts += ',iter-time=10'
261
+ else:
262
+ self.imgoptssyntax = 'false'
263
+ self.qemu_io_options += ' -f ' + self.imgfmt
264
+
265
+ if self.imgfmt == 'vmdk':
266
+ if not self.imgopts:
267
+ self.imgopts = 'zeroed_grain=on'
268
+ elif 'zeroed_grain=' not in self.imgopts:
269
+ self.imgopts += ',zeroed_grain=on'
270
+
271
+ def close(self) -> None:
272
+ if self.tmp_sock_dir:
273
+ shutil.rmtree(self.sock_dir)
274
+
275
+ def __enter__(self) -> 'TestEnv':
276
+ return self
277
+
278
+ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
279
+ self.close()
280
+
281
+ def print_env(self) -> None:
282
+ template = """\
283
+QEMU -- "{QEMU_PROG}" {QEMU_OPTIONS}
284
+QEMU_IMG -- "{QEMU_IMG_PROG}" {QEMU_IMG_OPTIONS}
285
+QEMU_IO -- "{QEMU_IO_PROG}" {QEMU_IO_OPTIONS}
286
+QEMU_NBD -- "{QEMU_NBD_PROG}" {QEMU_NBD_OPTIONS}
287
+IMGFMT -- {IMGFMT}{imgopts}
288
+IMGPROTO -- {IMGPROTO}
289
+PLATFORM -- {platform}
290
+TEST_DIR -- {TEST_DIR}
291
+SOCK_DIR -- {SOCK_DIR}
292
+SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}"""
293
+
294
+ args = collections.defaultdict(str, self.get_env())
295
+
296
+ if 'IMGOPTS' in args:
297
+ args['imgopts'] = f" ({args['IMGOPTS']})"
298
+
299
+ u = os.uname()
300
+ args['platform'] = f'{u.sysname}/{u.machine} {u.nodename} {u.release}'
301
+
302
+ print(template.format_map(args))
303
--
177
--
304
2.29.2
178
2.13.6
305
179
306
180
diff view generated by jsdifflib
New patch
1
Now that the bdrv_drain_invoke() calls are pulled up to the callers of
2
bdrv_drain_recurse(), the 'begin' parameter isn't needed any more.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
block/io.c | 12 ++++++------
8
1 file changed, 6 insertions(+), 6 deletions(-)
9
10
diff --git a/block/io.c b/block/io.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/io.c
13
+++ b/block/io.c
14
@@ -XXX,XX +XXX,XX @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
15
}
16
}
17
18
-static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
19
+static bool bdrv_drain_recurse(BlockDriverState *bs)
20
{
21
BdrvChild *child, *tmp;
22
bool waited;
23
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
24
*/
25
bdrv_ref(bs);
26
}
27
- waited |= bdrv_drain_recurse(bs, begin);
28
+ waited |= bdrv_drain_recurse(bs);
29
if (in_main_loop) {
30
bdrv_unref(bs);
31
}
32
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs)
33
}
34
35
bdrv_drain_invoke(bs, true);
36
- bdrv_drain_recurse(bs, true);
37
+ bdrv_drain_recurse(bs);
38
}
39
40
void bdrv_drained_end(BlockDriverState *bs)
41
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
42
43
bdrv_parent_drained_end(bs);
44
bdrv_drain_invoke(bs, false);
45
- bdrv_drain_recurse(bs, false);
46
+ bdrv_drain_recurse(bs);
47
aio_enable_external(bdrv_get_aio_context(bs));
48
}
49
50
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
51
aio_context_acquire(aio_context);
52
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
53
if (aio_context == bdrv_get_aio_context(bs)) {
54
- waited |= bdrv_drain_recurse(bs, true);
55
+ waited |= bdrv_drain_recurse(bs);
56
}
57
}
58
aio_context_release(aio_context);
59
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
60
aio_enable_external(aio_context);
61
bdrv_parent_drained_end(bs);
62
bdrv_drain_invoke(bs, false);
63
- bdrv_drain_recurse(bs, false);
64
+ bdrv_drain_recurse(bs);
65
aio_context_release(aio_context);
66
}
67
68
--
69
2.13.6
70
71
diff view generated by jsdifflib
New patch
1
The device is drained, so there is no point in waiting for requests at
2
the end of the drained section. Remove the bdrv_drain_recurse() calls
3
there.
1
4
5
The bdrv_drain_recurse() calls were introduced in commit 481cad48e5e
6
in order to call the .bdrv_co_drain_end() driver callback. This is now
7
done by a separate bdrv_drain_invoke() call.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
13
block/io.c | 2 --
14
1 file changed, 2 deletions(-)
15
16
diff --git a/block/io.c b/block/io.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/io.c
19
+++ b/block/io.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
21
22
bdrv_parent_drained_end(bs);
23
bdrv_drain_invoke(bs, false);
24
- bdrv_drain_recurse(bs);
25
aio_enable_external(bdrv_get_aio_context(bs));
26
}
27
28
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
29
aio_enable_external(aio_context);
30
bdrv_parent_drained_end(bs);
31
bdrv_drain_invoke(bs, false);
32
- bdrv_drain_recurse(bs);
33
aio_context_release(aio_context);
34
}
35
36
--
37
2.13.6
38
39
diff view generated by jsdifflib
New patch
1
Drain requests are propagated to child nodes, parent nodes and directly
2
to the AioContext. The order in which this happened was different
3
between all combinations of drain/drain_all and begin/end.
1
4
5
The correct order is to keep children only drained when their parents
6
are also drained. This means that at the start of a drained section, the
7
AioContext needs to be drained first, the parents second and only then
8
the children. The correct order for the end of a drained section is the
9
opposite.
10
11
This patch changes the three other functions to follow the example of
12
bdrv_drained_begin(), which is the only one that got it right.
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
block/io.c | 12 ++++++++----
18
1 file changed, 8 insertions(+), 4 deletions(-)
19
20
diff --git a/block/io.c b/block/io.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/io.c
23
+++ b/block/io.c
24
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs)
25
return;
26
}
27
28
+ /* Stop things in parent-to-child order */
29
if (atomic_fetch_inc(&bs->quiesce_counter) == 0) {
30
aio_disable_external(bdrv_get_aio_context(bs));
31
bdrv_parent_drained_begin(bs);
32
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
33
return;
34
}
35
36
- bdrv_parent_drained_end(bs);
37
+ /* Re-enable things in child-to-parent order */
38
bdrv_drain_invoke(bs, false);
39
+ bdrv_parent_drained_end(bs);
40
aio_enable_external(bdrv_get_aio_context(bs));
41
}
42
43
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
44
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
45
AioContext *aio_context = bdrv_get_aio_context(bs);
46
47
+ /* Stop things in parent-to-child order */
48
aio_context_acquire(aio_context);
49
- bdrv_parent_drained_begin(bs);
50
aio_disable_external(aio_context);
51
+ bdrv_parent_drained_begin(bs);
52
bdrv_drain_invoke(bs, true);
53
aio_context_release(aio_context);
54
55
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
56
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
57
AioContext *aio_context = bdrv_get_aio_context(bs);
58
59
+ /* Re-enable things in child-to-parent order */
60
aio_context_acquire(aio_context);
61
- aio_enable_external(aio_context);
62
- bdrv_parent_drained_end(bs);
63
bdrv_drain_invoke(bs, false);
64
+ bdrv_parent_drained_end(bs);
65
+ aio_enable_external(aio_context);
66
aio_context_release(aio_context);
67
}
68
69
--
70
2.13.6
71
72
diff view generated by jsdifflib
New patch
1
Commit 15afd94a047 added code to acquire and release the AioContext in
2
qemuio_command(). This means that the lock is taken twice now in the
3
call path from hmp_qemu_io(). This causes BDRV_POLL_WHILE() to hang for
4
any requests issued to nodes in a non-mainloop AioContext.
1
5
6
Dropping the first locking from hmp_qemu_io() fixes the problem.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
hmp.c | 6 ------
12
1 file changed, 6 deletions(-)
13
14
diff --git a/hmp.c b/hmp.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hmp.c
17
+++ b/hmp.c
18
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
19
{
20
BlockBackend *blk;
21
BlockBackend *local_blk = NULL;
22
- AioContext *aio_context;
23
const char* device = qdict_get_str(qdict, "device");
24
const char* command = qdict_get_str(qdict, "command");
25
Error *err = NULL;
26
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
27
}
28
}
29
30
- aio_context = blk_get_aio_context(blk);
31
- aio_context_acquire(aio_context);
32
-
33
/*
34
* Notably absent: Proper permission management. This is sad, but it seems
35
* almost impossible to achieve without changing the semantics and thereby
36
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
37
*/
38
qemuio_command(blk, command);
39
40
- aio_context_release(aio_context);
41
-
42
fail:
43
blk_unref(local_blk);
44
hmp_handle_error(mon, &err);
45
--
46
2.13.6
47
48
diff view generated by jsdifflib
New patch
1
From: Edgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
1
2
3
Since bdrv_co_preadv does all neccessary checks including
4
reading after the end of the backing file, avoid duplication
5
of verification before bdrv_co_preadv call.
6
7
Signed-off-by: Edgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/qcow2.h | 3 ---
13
block/qcow2.c | 51 ++++++++-------------------------------------------
14
2 files changed, 8 insertions(+), 46 deletions(-)
15
16
diff --git a/block/qcow2.h b/block/qcow2.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.h
19
+++ b/block/qcow2.h
20
@@ -XXX,XX +XXX,XX @@ uint32_t offset_to_reftable_index(BDRVQcow2State *s, uint64_t offset)
21
}
22
23
/* qcow2.c functions */
24
-int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
25
- int64_t sector_num, int nb_sectors);
26
-
27
int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size,
28
int refcount_order, bool generous_increase,
29
uint64_t *refblock_count);
30
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
35
return status;
36
}
37
38
-/* handle reading after the end of the backing file */
39
-int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
40
- int64_t offset, int bytes)
41
-{
42
- uint64_t bs_size = bs->total_sectors * BDRV_SECTOR_SIZE;
43
- int n1;
44
-
45
- if ((offset + bytes) <= bs_size) {
46
- return bytes;
47
- }
48
-
49
- if (offset >= bs_size) {
50
- n1 = 0;
51
- } else {
52
- n1 = bs_size - offset;
53
- }
54
-
55
- qemu_iovec_memset(qiov, n1, 0, bytes - n1);
56
-
57
- return n1;
58
-}
59
-
60
static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
61
uint64_t bytes, QEMUIOVector *qiov,
62
int flags)
63
{
64
BDRVQcow2State *s = bs->opaque;
65
- int offset_in_cluster, n1;
66
+ int offset_in_cluster;
67
int ret;
68
unsigned int cur_bytes; /* number of bytes in current iteration */
69
uint64_t cluster_offset = 0;
70
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
71
case QCOW2_CLUSTER_UNALLOCATED:
72
73
if (bs->backing) {
74
- /* read from the base image */
75
- n1 = qcow2_backing_read1(bs->backing->bs, &hd_qiov,
76
- offset, cur_bytes);
77
- if (n1 > 0) {
78
- QEMUIOVector local_qiov;
79
-
80
- qemu_iovec_init(&local_qiov, hd_qiov.niov);
81
- qemu_iovec_concat(&local_qiov, &hd_qiov, 0, n1);
82
-
83
- BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
84
- qemu_co_mutex_unlock(&s->lock);
85
- ret = bdrv_co_preadv(bs->backing, offset, n1,
86
- &local_qiov, 0);
87
- qemu_co_mutex_lock(&s->lock);
88
-
89
- qemu_iovec_destroy(&local_qiov);
90
-
91
- if (ret < 0) {
92
- goto fail;
93
- }
94
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
95
+ qemu_co_mutex_unlock(&s->lock);
96
+ ret = bdrv_co_preadv(bs->backing, offset, cur_bytes,
97
+ &hd_qiov, 0);
98
+ qemu_co_mutex_lock(&s->lock);
99
+ if (ret < 0) {
100
+ goto fail;
101
}
102
} else {
103
/* Note: in this case, no need to wait */
104
--
105
2.13.6
106
107
diff view generated by jsdifflib
New patch
1
Removing a quorum child node with x-blockdev-change results in a quorum
2
driver state that cannot be recreated with create options because it
3
would require a list with gaps. This causes trouble in at least
4
.bdrv_refresh_filename().
1
5
6
Document this problem so that we won't accidentally mark the command
7
stable without having addressed it.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
---
12
qapi/block-core.json | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
16
index XXXXXXX..XXXXXXX 100644
17
--- a/qapi/block-core.json
18
+++ b/qapi/block-core.json
19
@@ -XXX,XX +XXX,XX @@
20
# does not support all kinds of operations, all kinds of children, nor
21
# all block drivers.
22
#
23
+# FIXME Removing children from a quorum node means introducing gaps in the
24
+# child indices. This cannot be represented in the 'children' list of
25
+# BlockdevOptionsQuorum, as returned by .bdrv_refresh_filename().
26
+#
27
# Warning: The data in a new quorum child MUST be consistent with that of
28
# the rest of the array.
29
#
30
--
31
2.13.6
32
33
diff view generated by jsdifflib
New patch
1
From: Doug Gale <doug16k@gmail.com>
1
2
3
Add trace output for commands, errors, and undefined behavior.
4
Add guest error log output for undefined behavior.
5
Report invalid undefined accesses to MMIO.
6
Annotate unlikely error checks with unlikely.
7
8
Signed-off-by: Doug Gale <doug16k@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
hw/block/nvme.c | 349 ++++++++++++++++++++++++++++++++++++++++++--------
14
hw/block/trace-events | 93 ++++++++++++++
15
2 files changed, 390 insertions(+), 52 deletions(-)
16
17
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/block/nvme.c
20
+++ b/hw/block/nvme.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "qapi/visitor.h"
23
#include "sysemu/block-backend.h"
24
25
+#include "qemu/log.h"
26
+#include "trace.h"
27
#include "nvme.h"
28
29
+#define NVME_GUEST_ERR(trace, fmt, ...) \
30
+ do { \
31
+ (trace_##trace)(__VA_ARGS__); \
32
+ qemu_log_mask(LOG_GUEST_ERROR, #trace \
33
+ " in %s: " fmt "\n", __func__, ## __VA_ARGS__); \
34
+ } while (0)
35
+
36
static void nvme_process_sq(void *opaque);
37
38
static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
39
@@ -XXX,XX +XXX,XX @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
40
{
41
if (cq->irq_enabled) {
42
if (msix_enabled(&(n->parent_obj))) {
43
+ trace_nvme_irq_msix(cq->vector);
44
msix_notify(&(n->parent_obj), cq->vector);
45
} else {
46
+ trace_nvme_irq_pin();
47
pci_irq_pulse(&n->parent_obj);
48
}
49
+ } else {
50
+ trace_nvme_irq_masked();
51
}
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
55
trans_len = MIN(len, trans_len);
56
int num_prps = (len >> n->page_bits) + 1;
57
58
- if (!prp1) {
59
+ if (unlikely(!prp1)) {
60
+ trace_nvme_err_invalid_prp();
61
return NVME_INVALID_FIELD | NVME_DNR;
62
} else if (n->cmbsz && prp1 >= n->ctrl_mem.addr &&
63
prp1 < n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size)) {
64
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
65
}
66
len -= trans_len;
67
if (len) {
68
- if (!prp2) {
69
+ if (unlikely(!prp2)) {
70
+ trace_nvme_err_invalid_prp2_missing();
71
goto unmap;
72
}
73
if (len > n->page_size) {
74
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
75
uint64_t prp_ent = le64_to_cpu(prp_list[i]);
76
77
if (i == n->max_prp_ents - 1 && len > n->page_size) {
78
- if (!prp_ent || prp_ent & (n->page_size - 1)) {
79
+ if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
80
+ trace_nvme_err_invalid_prplist_ent(prp_ent);
81
goto unmap;
82
}
83
84
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
85
prp_ent = le64_to_cpu(prp_list[i]);
86
}
87
88
- if (!prp_ent || prp_ent & (n->page_size - 1)) {
89
+ if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
90
+ trace_nvme_err_invalid_prplist_ent(prp_ent);
91
goto unmap;
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
95
i++;
96
}
97
} else {
98
- if (prp2 & (n->page_size - 1)) {
99
+ if (unlikely(prp2 & (n->page_size - 1))) {
100
+ trace_nvme_err_invalid_prp2_align(prp2);
101
goto unmap;
102
}
103
if (qsg->nsg) {
104
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
105
QEMUIOVector iov;
106
uint16_t status = NVME_SUCCESS;
107
108
+ trace_nvme_dma_read(prp1, prp2);
109
+
110
if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) {
111
return NVME_INVALID_FIELD | NVME_DNR;
112
}
113
if (qsg.nsg > 0) {
114
- if (dma_buf_read(ptr, len, &qsg)) {
115
+ if (unlikely(dma_buf_read(ptr, len, &qsg))) {
116
+ trace_nvme_err_invalid_dma();
117
status = NVME_INVALID_FIELD | NVME_DNR;
118
}
119
qemu_sglist_destroy(&qsg);
120
} else {
121
- if (qemu_iovec_to_buf(&iov, 0, ptr, len) != len) {
122
+ if (unlikely(qemu_iovec_to_buf(&iov, 0, ptr, len) != len)) {
123
+ trace_nvme_err_invalid_dma();
124
status = NVME_INVALID_FIELD | NVME_DNR;
125
}
126
qemu_iovec_destroy(&iov);
127
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
128
uint64_t aio_slba = slba << (data_shift - BDRV_SECTOR_BITS);
129
uint32_t aio_nlb = nlb << (data_shift - BDRV_SECTOR_BITS);
130
131
- if (slba + nlb > ns->id_ns.nsze) {
132
+ if (unlikely(slba + nlb > ns->id_ns.nsze)) {
133
+ trace_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze);
134
return NVME_LBA_RANGE | NVME_DNR;
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
138
int is_write = rw->opcode == NVME_CMD_WRITE ? 1 : 0;
139
enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ;
140
141
- if ((slba + nlb) > ns->id_ns.nsze) {
142
+ trace_nvme_rw(is_write ? "write" : "read", nlb, data_size, slba);
143
+
144
+ if (unlikely((slba + nlb) > ns->id_ns.nsze)) {
145
block_acct_invalid(blk_get_stats(n->conf.blk), acct);
146
+ trace_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze);
147
return NVME_LBA_RANGE | NVME_DNR;
148
}
149
150
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
151
NvmeNamespace *ns;
152
uint32_t nsid = le32_to_cpu(cmd->nsid);
153
154
- if (nsid == 0 || nsid > n->num_namespaces) {
155
+ if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
156
+ trace_nvme_err_invalid_ns(nsid, n->num_namespaces);
157
return NVME_INVALID_NSID | NVME_DNR;
158
}
159
160
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
161
case NVME_CMD_READ:
162
return nvme_rw(n, ns, cmd, req);
163
default:
164
+ trace_nvme_err_invalid_opc(cmd->opcode);
165
return NVME_INVALID_OPCODE | NVME_DNR;
166
}
167
}
168
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd)
169
NvmeCQueue *cq;
170
uint16_t qid = le16_to_cpu(c->qid);
171
172
- if (!qid || nvme_check_sqid(n, qid)) {
173
+ if (unlikely(!qid || nvme_check_sqid(n, qid))) {
174
+ trace_nvme_err_invalid_del_sq(qid);
175
return NVME_INVALID_QID | NVME_DNR;
176
}
177
178
+ trace_nvme_del_sq(qid);
179
+
180
sq = n->sq[qid];
181
while (!QTAILQ_EMPTY(&sq->out_req_list)) {
182
req = QTAILQ_FIRST(&sq->out_req_list);
183
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd)
184
uint16_t qflags = le16_to_cpu(c->sq_flags);
185
uint64_t prp1 = le64_to_cpu(c->prp1);
186
187
- if (!cqid || nvme_check_cqid(n, cqid)) {
188
+ trace_nvme_create_sq(prp1, sqid, cqid, qsize, qflags);
189
+
190
+ if (unlikely(!cqid || nvme_check_cqid(n, cqid))) {
191
+ trace_nvme_err_invalid_create_sq_cqid(cqid);
192
return NVME_INVALID_CQID | NVME_DNR;
193
}
194
- if (!sqid || !nvme_check_sqid(n, sqid)) {
195
+ if (unlikely(!sqid || !nvme_check_sqid(n, sqid))) {
196
+ trace_nvme_err_invalid_create_sq_sqid(sqid);
197
return NVME_INVALID_QID | NVME_DNR;
198
}
199
- if (!qsize || qsize > NVME_CAP_MQES(n->bar.cap)) {
200
+ if (unlikely(!qsize || qsize > NVME_CAP_MQES(n->bar.cap))) {
201
+ trace_nvme_err_invalid_create_sq_size(qsize);
202
return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR;
203
}
204
- if (!prp1 || prp1 & (n->page_size - 1)) {
205
+ if (unlikely(!prp1 || prp1 & (n->page_size - 1))) {
206
+ trace_nvme_err_invalid_create_sq_addr(prp1);
207
return NVME_INVALID_FIELD | NVME_DNR;
208
}
209
- if (!(NVME_SQ_FLAGS_PC(qflags))) {
210
+ if (unlikely(!(NVME_SQ_FLAGS_PC(qflags)))) {
211
+ trace_nvme_err_invalid_create_sq_qflags(NVME_SQ_FLAGS_PC(qflags));
212
return NVME_INVALID_FIELD | NVME_DNR;
213
}
214
sq = g_malloc0(sizeof(*sq));
215
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd)
216
NvmeCQueue *cq;
217
uint16_t qid = le16_to_cpu(c->qid);
218
219
- if (!qid || nvme_check_cqid(n, qid)) {
220
+ if (unlikely(!qid || nvme_check_cqid(n, qid))) {
221
+ trace_nvme_err_invalid_del_cq_cqid(qid);
222
return NVME_INVALID_CQID | NVME_DNR;
223
}
224
225
cq = n->cq[qid];
226
- if (!QTAILQ_EMPTY(&cq->sq_list)) {
227
+ if (unlikely(!QTAILQ_EMPTY(&cq->sq_list))) {
228
+ trace_nvme_err_invalid_del_cq_notempty(qid);
229
return NVME_INVALID_QUEUE_DEL;
230
}
231
+ trace_nvme_del_cq(qid);
232
nvme_free_cq(cq, n);
233
return NVME_SUCCESS;
234
}
235
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd)
236
uint16_t qflags = le16_to_cpu(c->cq_flags);
237
uint64_t prp1 = le64_to_cpu(c->prp1);
238
239
- if (!cqid || !nvme_check_cqid(n, cqid)) {
240
+ trace_nvme_create_cq(prp1, cqid, vector, qsize, qflags,
241
+ NVME_CQ_FLAGS_IEN(qflags) != 0);
242
+
243
+ if (unlikely(!cqid || !nvme_check_cqid(n, cqid))) {
244
+ trace_nvme_err_invalid_create_cq_cqid(cqid);
245
return NVME_INVALID_CQID | NVME_DNR;
246
}
247
- if (!qsize || qsize > NVME_CAP_MQES(n->bar.cap)) {
248
+ if (unlikely(!qsize || qsize > NVME_CAP_MQES(n->bar.cap))) {
249
+ trace_nvme_err_invalid_create_cq_size(qsize);
250
return NVME_MAX_QSIZE_EXCEEDED | NVME_DNR;
251
}
252
- if (!prp1) {
253
+ if (unlikely(!prp1)) {
254
+ trace_nvme_err_invalid_create_cq_addr(prp1);
255
return NVME_INVALID_FIELD | NVME_DNR;
256
}
257
- if (vector > n->num_queues) {
258
+ if (unlikely(vector > n->num_queues)) {
259
+ trace_nvme_err_invalid_create_cq_vector(vector);
260
return NVME_INVALID_IRQ_VECTOR | NVME_DNR;
261
}
262
- if (!(NVME_CQ_FLAGS_PC(qflags))) {
263
+ if (unlikely(!(NVME_CQ_FLAGS_PC(qflags)))) {
264
+ trace_nvme_err_invalid_create_cq_qflags(NVME_CQ_FLAGS_PC(qflags));
265
return NVME_INVALID_FIELD | NVME_DNR;
266
}
267
268
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeIdentify *c)
269
uint64_t prp1 = le64_to_cpu(c->prp1);
270
uint64_t prp2 = le64_to_cpu(c->prp2);
271
272
+ trace_nvme_identify_ctrl();
273
+
274
return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl),
275
prp1, prp2);
276
}
277
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c)
278
uint64_t prp1 = le64_to_cpu(c->prp1);
279
uint64_t prp2 = le64_to_cpu(c->prp2);
280
281
- if (nsid == 0 || nsid > n->num_namespaces) {
282
+ trace_nvme_identify_ns(nsid);
283
+
284
+ if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
285
+ trace_nvme_err_invalid_ns(nsid, n->num_namespaces);
286
return NVME_INVALID_NSID | NVME_DNR;
287
}
288
289
ns = &n->namespaces[nsid - 1];
290
+
291
return nvme_dma_read_prp(n, (uint8_t *)&ns->id_ns, sizeof(ns->id_ns),
292
prp1, prp2);
293
}
294
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c)
295
uint16_t ret;
296
int i, j = 0;
297
298
+ trace_nvme_identify_nslist(min_nsid);
299
+
300
list = g_malloc0(data_len);
301
for (i = 0; i < n->num_namespaces; i++) {
302
if (i < min_nsid) {
303
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
304
case 0x02:
305
return nvme_identify_nslist(n, c);
306
default:
307
+ trace_nvme_err_invalid_identify_cns(le32_to_cpu(c->cns));
308
return NVME_INVALID_FIELD | NVME_DNR;
309
}
310
}
311
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
312
switch (dw10) {
313
case NVME_VOLATILE_WRITE_CACHE:
314
result = blk_enable_write_cache(n->conf.blk);
315
+ trace_nvme_getfeat_vwcache(result ? "enabled" : "disabled");
316
break;
317
case NVME_NUMBER_OF_QUEUES:
318
result = cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16));
319
+ trace_nvme_getfeat_numq(result);
320
break;
321
default:
322
+ trace_nvme_err_invalid_getfeat(dw10);
323
return NVME_INVALID_FIELD | NVME_DNR;
324
}
325
326
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
327
blk_set_enable_write_cache(n->conf.blk, dw11 & 1);
328
break;
329
case NVME_NUMBER_OF_QUEUES:
330
+ trace_nvme_setfeat_numq((dw11 & 0xFFFF) + 1,
331
+ ((dw11 >> 16) & 0xFFFF) + 1,
332
+ n->num_queues - 1, n->num_queues - 1);
333
req->cqe.result =
334
cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16));
335
break;
336
default:
337
+ trace_nvme_err_invalid_setfeat(dw10);
338
return NVME_INVALID_FIELD | NVME_DNR;
339
}
340
return NVME_SUCCESS;
341
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
342
case NVME_ADM_CMD_GET_FEATURES:
343
return nvme_get_feature(n, cmd, req);
344
default:
345
+ trace_nvme_err_invalid_admin_opc(cmd->opcode);
346
return NVME_INVALID_OPCODE | NVME_DNR;
347
}
348
}
349
@@ -XXX,XX +XXX,XX @@ static int nvme_start_ctrl(NvmeCtrl *n)
350
uint32_t page_bits = NVME_CC_MPS(n->bar.cc) + 12;
351
uint32_t page_size = 1 << page_bits;
352
353
- if (n->cq[0] || n->sq[0] || !n->bar.asq || !n->bar.acq ||
354
- n->bar.asq & (page_size - 1) || n->bar.acq & (page_size - 1) ||
355
- NVME_CC_MPS(n->bar.cc) < NVME_CAP_MPSMIN(n->bar.cap) ||
356
- NVME_CC_MPS(n->bar.cc) > NVME_CAP_MPSMAX(n->bar.cap) ||
357
- NVME_CC_IOCQES(n->bar.cc) < NVME_CTRL_CQES_MIN(n->id_ctrl.cqes) ||
358
- NVME_CC_IOCQES(n->bar.cc) > NVME_CTRL_CQES_MAX(n->id_ctrl.cqes) ||
359
- NVME_CC_IOSQES(n->bar.cc) < NVME_CTRL_SQES_MIN(n->id_ctrl.sqes) ||
360
- NVME_CC_IOSQES(n->bar.cc) > NVME_CTRL_SQES_MAX(n->id_ctrl.sqes) ||
361
- !NVME_AQA_ASQS(n->bar.aqa) || !NVME_AQA_ACQS(n->bar.aqa)) {
362
+ if (unlikely(n->cq[0])) {
363
+ trace_nvme_err_startfail_cq();
364
+ return -1;
365
+ }
366
+ if (unlikely(n->sq[0])) {
367
+ trace_nvme_err_startfail_sq();
368
+ return -1;
369
+ }
370
+ if (unlikely(!n->bar.asq)) {
371
+ trace_nvme_err_startfail_nbarasq();
372
+ return -1;
373
+ }
374
+ if (unlikely(!n->bar.acq)) {
375
+ trace_nvme_err_startfail_nbaracq();
376
+ return -1;
377
+ }
378
+ if (unlikely(n->bar.asq & (page_size - 1))) {
379
+ trace_nvme_err_startfail_asq_misaligned(n->bar.asq);
380
+ return -1;
381
+ }
382
+ if (unlikely(n->bar.acq & (page_size - 1))) {
383
+ trace_nvme_err_startfail_acq_misaligned(n->bar.acq);
384
+ return -1;
385
+ }
386
+ if (unlikely(NVME_CC_MPS(n->bar.cc) <
387
+ NVME_CAP_MPSMIN(n->bar.cap))) {
388
+ trace_nvme_err_startfail_page_too_small(
389
+ NVME_CC_MPS(n->bar.cc),
390
+ NVME_CAP_MPSMIN(n->bar.cap));
391
+ return -1;
392
+ }
393
+ if (unlikely(NVME_CC_MPS(n->bar.cc) >
394
+ NVME_CAP_MPSMAX(n->bar.cap))) {
395
+ trace_nvme_err_startfail_page_too_large(
396
+ NVME_CC_MPS(n->bar.cc),
397
+ NVME_CAP_MPSMAX(n->bar.cap));
398
+ return -1;
399
+ }
400
+ if (unlikely(NVME_CC_IOCQES(n->bar.cc) <
401
+ NVME_CTRL_CQES_MIN(n->id_ctrl.cqes))) {
402
+ trace_nvme_err_startfail_cqent_too_small(
403
+ NVME_CC_IOCQES(n->bar.cc),
404
+ NVME_CTRL_CQES_MIN(n->bar.cap));
405
+ return -1;
406
+ }
407
+ if (unlikely(NVME_CC_IOCQES(n->bar.cc) >
408
+ NVME_CTRL_CQES_MAX(n->id_ctrl.cqes))) {
409
+ trace_nvme_err_startfail_cqent_too_large(
410
+ NVME_CC_IOCQES(n->bar.cc),
411
+ NVME_CTRL_CQES_MAX(n->bar.cap));
412
+ return -1;
413
+ }
414
+ if (unlikely(NVME_CC_IOSQES(n->bar.cc) <
415
+ NVME_CTRL_SQES_MIN(n->id_ctrl.sqes))) {
416
+ trace_nvme_err_startfail_sqent_too_small(
417
+ NVME_CC_IOSQES(n->bar.cc),
418
+ NVME_CTRL_SQES_MIN(n->bar.cap));
419
+ return -1;
420
+ }
421
+ if (unlikely(NVME_CC_IOSQES(n->bar.cc) >
422
+ NVME_CTRL_SQES_MAX(n->id_ctrl.sqes))) {
423
+ trace_nvme_err_startfail_sqent_too_large(
424
+ NVME_CC_IOSQES(n->bar.cc),
425
+ NVME_CTRL_SQES_MAX(n->bar.cap));
426
+ return -1;
427
+ }
428
+ if (unlikely(!NVME_AQA_ASQS(n->bar.aqa))) {
429
+ trace_nvme_err_startfail_asqent_sz_zero();
430
+ return -1;
431
+ }
432
+ if (unlikely(!NVME_AQA_ACQS(n->bar.aqa))) {
433
+ trace_nvme_err_startfail_acqent_sz_zero();
434
return -1;
435
}
436
437
@@ -XXX,XX +XXX,XX @@ static int nvme_start_ctrl(NvmeCtrl *n)
438
static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
439
unsigned size)
440
{
441
+ if (unlikely(offset & (sizeof(uint32_t) - 1))) {
442
+ NVME_GUEST_ERR(nvme_ub_mmiowr_misaligned32,
443
+ "MMIO write not 32-bit aligned,"
444
+ " offset=0x%"PRIx64"", offset);
445
+ /* should be ignored, fall through for now */
446
+ }
447
+
448
+ if (unlikely(size < sizeof(uint32_t))) {
449
+ NVME_GUEST_ERR(nvme_ub_mmiowr_toosmall,
450
+ "MMIO write smaller than 32-bits,"
451
+ " offset=0x%"PRIx64", size=%u",
452
+ offset, size);
453
+ /* should be ignored, fall through for now */
454
+ }
455
+
456
switch (offset) {
457
- case 0xc:
458
+ case 0xc: /* INTMS */
459
+ if (unlikely(msix_enabled(&(n->parent_obj)))) {
460
+ NVME_GUEST_ERR(nvme_ub_mmiowr_intmask_with_msix,
461
+ "undefined access to interrupt mask set"
462
+ " when MSI-X is enabled");
463
+ /* should be ignored, fall through for now */
464
+ }
465
n->bar.intms |= data & 0xffffffff;
466
n->bar.intmc = n->bar.intms;
467
+ trace_nvme_mmio_intm_set(data & 0xffffffff,
468
+ n->bar.intmc);
469
break;
470
- case 0x10:
471
+ case 0x10: /* INTMC */
472
+ if (unlikely(msix_enabled(&(n->parent_obj)))) {
473
+ NVME_GUEST_ERR(nvme_ub_mmiowr_intmask_with_msix,
474
+ "undefined access to interrupt mask clr"
475
+ " when MSI-X is enabled");
476
+ /* should be ignored, fall through for now */
477
+ }
478
n->bar.intms &= ~(data & 0xffffffff);
479
n->bar.intmc = n->bar.intms;
480
+ trace_nvme_mmio_intm_clr(data & 0xffffffff,
481
+ n->bar.intmc);
482
break;
483
- case 0x14:
484
+ case 0x14: /* CC */
485
+ trace_nvme_mmio_cfg(data & 0xffffffff);
486
/* Windows first sends data, then sends enable bit */
487
if (!NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc) &&
488
!NVME_CC_SHN(data) && !NVME_CC_SHN(n->bar.cc))
489
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
490
491
if (NVME_CC_EN(data) && !NVME_CC_EN(n->bar.cc)) {
492
n->bar.cc = data;
493
- if (nvme_start_ctrl(n)) {
494
+ if (unlikely(nvme_start_ctrl(n))) {
495
+ trace_nvme_err_startfail();
496
n->bar.csts = NVME_CSTS_FAILED;
497
} else {
498
+ trace_nvme_mmio_start_success();
499
n->bar.csts = NVME_CSTS_READY;
500
}
501
} else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) {
502
+ trace_nvme_mmio_stopped();
503
nvme_clear_ctrl(n);
504
n->bar.csts &= ~NVME_CSTS_READY;
505
}
506
if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) {
507
- nvme_clear_ctrl(n);
508
- n->bar.cc = data;
509
- n->bar.csts |= NVME_CSTS_SHST_COMPLETE;
510
+ trace_nvme_mmio_shutdown_set();
511
+ nvme_clear_ctrl(n);
512
+ n->bar.cc = data;
513
+ n->bar.csts |= NVME_CSTS_SHST_COMPLETE;
514
} else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) {
515
- n->bar.csts &= ~NVME_CSTS_SHST_COMPLETE;
516
- n->bar.cc = data;
517
+ trace_nvme_mmio_shutdown_cleared();
518
+ n->bar.csts &= ~NVME_CSTS_SHST_COMPLETE;
519
+ n->bar.cc = data;
520
+ }
521
+ break;
522
+ case 0x1C: /* CSTS */
523
+ if (data & (1 << 4)) {
524
+ NVME_GUEST_ERR(nvme_ub_mmiowr_ssreset_w1c_unsupported,
525
+ "attempted to W1C CSTS.NSSRO"
526
+ " but CAP.NSSRS is zero (not supported)");
527
+ } else if (data != 0) {
528
+ NVME_GUEST_ERR(nvme_ub_mmiowr_ro_csts,
529
+ "attempted to set a read only bit"
530
+ " of controller status");
531
+ }
532
+ break;
533
+ case 0x20: /* NSSR */
534
+ if (data == 0x4E564D65) {
535
+ trace_nvme_ub_mmiowr_ssreset_unsupported();
536
+ } else {
537
+ /* The spec says that writes of other values have no effect */
538
+ return;
539
}
540
break;
541
- case 0x24:
542
+ case 0x24: /* AQA */
543
n->bar.aqa = data & 0xffffffff;
544
+ trace_nvme_mmio_aqattr(data & 0xffffffff);
545
break;
546
- case 0x28:
547
+ case 0x28: /* ASQ */
548
n->bar.asq = data;
549
+ trace_nvme_mmio_asqaddr(data);
550
break;
551
- case 0x2c:
552
+ case 0x2c: /* ASQ hi */
553
n->bar.asq |= data << 32;
554
+ trace_nvme_mmio_asqaddr_hi(data, n->bar.asq);
555
break;
556
- case 0x30:
557
+ case 0x30: /* ACQ */
558
+ trace_nvme_mmio_acqaddr(data);
559
n->bar.acq = data;
560
break;
561
- case 0x34:
562
+ case 0x34: /* ACQ hi */
563
n->bar.acq |= data << 32;
564
+ trace_nvme_mmio_acqaddr_hi(data, n->bar.acq);
565
break;
566
+ case 0x38: /* CMBLOC */
567
+ NVME_GUEST_ERR(nvme_ub_mmiowr_cmbloc_reserved,
568
+ "invalid write to reserved CMBLOC"
569
+ " when CMBSZ is zero, ignored");
570
+ return;
571
+ case 0x3C: /* CMBSZ */
572
+ NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
573
+ "invalid write to read only CMBSZ, ignored");
574
+ return;
575
default:
576
+ NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
577
+ "invalid MMIO write,"
578
+ " offset=0x%"PRIx64", data=%"PRIx64"",
579
+ offset, data);
580
break;
581
}
582
}
583
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
584
uint8_t *ptr = (uint8_t *)&n->bar;
585
uint64_t val = 0;
586
587
+ if (unlikely(addr & (sizeof(uint32_t) - 1))) {
588
+ NVME_GUEST_ERR(nvme_ub_mmiord_misaligned32,
589
+ "MMIO read not 32-bit aligned,"
590
+ " offset=0x%"PRIx64"", addr);
591
+ /* should RAZ, fall through for now */
592
+ } else if (unlikely(size < sizeof(uint32_t))) {
593
+ NVME_GUEST_ERR(nvme_ub_mmiord_toosmall,
594
+ "MMIO read smaller than 32-bits,"
595
+ " offset=0x%"PRIx64"", addr);
596
+ /* should RAZ, fall through for now */
597
+ }
598
+
599
if (addr < sizeof(n->bar)) {
600
memcpy(&val, ptr + addr, size);
601
+ } else {
602
+ NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
603
+ "MMIO read beyond last register,"
604
+ " offset=0x%"PRIx64", returning 0", addr);
605
}
606
+
607
return val;
608
}
609
610
@@ -XXX,XX +XXX,XX @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
611
{
612
uint32_t qid;
613
614
- if (addr & ((1 << 2) - 1)) {
615
+ if (unlikely(addr & ((1 << 2) - 1))) {
616
+ NVME_GUEST_ERR(nvme_ub_db_wr_misaligned,
617
+ "doorbell write not 32-bit aligned,"
618
+ " offset=0x%"PRIx64", ignoring", addr);
619
return;
620
}
621
622
if (((addr - 0x1000) >> 2) & 1) {
623
+ /* Completion queue doorbell write */
624
+
625
uint16_t new_head = val & 0xffff;
626
int start_sqs;
627
NvmeCQueue *cq;
628
629
qid = (addr - (0x1000 + (1 << 2))) >> 3;
630
- if (nvme_check_cqid(n, qid)) {
631
+ if (unlikely(nvme_check_cqid(n, qid))) {
632
+ NVME_GUEST_ERR(nvme_ub_db_wr_invalid_cq,
633
+ "completion queue doorbell write"
634
+ " for nonexistent queue,"
635
+ " sqid=%"PRIu32", ignoring", qid);
636
return;
637
}
638
639
cq = n->cq[qid];
640
- if (new_head >= cq->size) {
641
+ if (unlikely(new_head >= cq->size)) {
642
+ NVME_GUEST_ERR(nvme_ub_db_wr_invalid_cqhead,
643
+ "completion queue doorbell write value"
644
+ " beyond queue size, sqid=%"PRIu32","
645
+ " new_head=%"PRIu16", ignoring",
646
+ qid, new_head);
647
return;
648
}
649
650
@@ -XXX,XX +XXX,XX @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
651
nvme_isr_notify(n, cq);
652
}
653
} else {
654
+ /* Submission queue doorbell write */
655
+
656
uint16_t new_tail = val & 0xffff;
657
NvmeSQueue *sq;
658
659
qid = (addr - 0x1000) >> 3;
660
- if (nvme_check_sqid(n, qid)) {
661
+ if (unlikely(nvme_check_sqid(n, qid))) {
662
+ NVME_GUEST_ERR(nvme_ub_db_wr_invalid_sq,
663
+ "submission queue doorbell write"
664
+ " for nonexistent queue,"
665
+ " sqid=%"PRIu32", ignoring", qid);
666
return;
667
}
668
669
sq = n->sq[qid];
670
- if (new_tail >= sq->size) {
671
+ if (unlikely(new_tail >= sq->size)) {
672
+ NVME_GUEST_ERR(nvme_ub_db_wr_invalid_sqtail,
673
+ "submission queue doorbell write value"
674
+ " beyond queue size, sqid=%"PRIu32","
675
+ " new_tail=%"PRIu16", ignoring",
676
+ qid, new_tail);
677
return;
678
}
679
680
diff --git a/hw/block/trace-events b/hw/block/trace-events
681
index XXXXXXX..XXXXXXX 100644
682
--- a/hw/block/trace-events
683
+++ b/hw/block/trace-events
684
@@ -XXX,XX +XXX,XX @@ virtio_blk_submit_multireq(void *vdev, void *mrb, int start, int num_reqs, uint6
685
hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
686
hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
687
688
+# hw/block/nvme.c
689
+# nvme traces for successful events
690
+nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ vector %u"
691
+nvme_irq_pin(void) "pulsing IRQ pin"
692
+nvme_irq_masked(void) "IRQ is masked"
693
+nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2=0x%"PRIx64""
694
+nvme_rw(char const *verb, uint32_t blk_count, uint64_t byte_count, uint64_t lba) "%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64""
695
+nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16""
696
+nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d"
697
+nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16""
698
+nvme_del_cq(uint16_t cqid) "deleted completion queue, sqid=%"PRIu16""
699
+nvme_identify_ctrl(void) "identify controller"
700
+nvme_identify_ns(uint16_t ns) "identify namespace, nsid=%"PRIu16""
701
+nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16""
702
+nvme_getfeat_vwcache(char const* result) "get feature volatile write cache, result=%s"
703
+nvme_getfeat_numq(int result) "get feature number of queues, result=%d"
704
+nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d"
705
+nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64""
706
+nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64""
707
+nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64""
708
+nvme_mmio_aqattr(uint64_t data) "wrote MMIO, admin queue attributes=0x%"PRIx64""
709
+nvme_mmio_asqaddr(uint64_t data) "wrote MMIO, admin submission queue address=0x%"PRIx64""
710
+nvme_mmio_acqaddr(uint64_t data) "wrote MMIO, admin completion queue address=0x%"PRIx64""
711
+nvme_mmio_asqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin submission queue high half=0x%"PRIx64", new_address=0x%"PRIx64""
712
+nvme_mmio_acqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin completion queue high half=0x%"PRIx64", new_address=0x%"PRIx64""
713
+nvme_mmio_start_success(void) "setting controller enable bit succeeded"
714
+nvme_mmio_stopped(void) "cleared controller enable bit"
715
+nvme_mmio_shutdown_set(void) "shutdown bit set"
716
+nvme_mmio_shutdown_cleared(void) "shutdown bit cleared"
717
+
718
+# nvme traces for error conditions
719
+nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size"
720
+nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64""
721
+nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64""
722
+nvme_err_invalid_prp2_missing(void) "PRP2 is null and more data to be transferred"
723
+nvme_err_invalid_field(void) "invalid field"
724
+nvme_err_invalid_prp(void) "invalid PRP"
725
+nvme_err_invalid_sgl(void) "invalid SGL"
726
+nvme_err_invalid_ns(uint32_t ns, uint32_t limit) "invalid namespace %u not within 1-%u"
727
+nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8""
728
+nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8""
729
+nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit) "Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64""
730
+nvme_err_invalid_del_sq(uint16_t qid) "invalid submission queue deletion, sid=%"PRIu16""
731
+nvme_err_invalid_create_sq_cqid(uint16_t cqid) "failed creating submission queue, invalid cqid=%"PRIu16""
732
+nvme_err_invalid_create_sq_sqid(uint16_t sqid) "failed creating submission queue, invalid sqid=%"PRIu16""
733
+nvme_err_invalid_create_sq_size(uint16_t qsize) "failed creating submission queue, invalid qsize=%"PRIu16""
734
+nvme_err_invalid_create_sq_addr(uint64_t addr) "failed creating submission queue, addr=0x%"PRIx64""
735
+nvme_err_invalid_create_sq_qflags(uint16_t qflags) "failed creating submission queue, qflags=%"PRIu16""
736
+nvme_err_invalid_del_cq_cqid(uint16_t cqid) "failed deleting completion queue, cqid=%"PRIu16""
737
+nvme_err_invalid_del_cq_notempty(uint16_t cqid) "failed deleting completion queue, it is not empty, cqid=%"PRIu16""
738
+nvme_err_invalid_create_cq_cqid(uint16_t cqid) "failed creating completion queue, cqid=%"PRIu16""
739
+nvme_err_invalid_create_cq_size(uint16_t size) "failed creating completion queue, size=%"PRIu16""
740
+nvme_err_invalid_create_cq_addr(uint64_t addr) "failed creating completion queue, addr=0x%"PRIx64""
741
+nvme_err_invalid_create_cq_vector(uint16_t vector) "failed creating completion queue, vector=%"PRIu16""
742
+nvme_err_invalid_create_cq_qflags(uint16_t qflags) "failed creating completion queue, qflags=%"PRIu16""
743
+nvme_err_invalid_identify_cns(uint16_t cns) "identify, invalid cns=0x%"PRIx16""
744
+nvme_err_invalid_getfeat(int dw10) "invalid get features, dw10=0x%"PRIx32""
745
+nvme_err_invalid_setfeat(uint32_t dw10) "invalid set features, dw10=0x%"PRIx32""
746
+nvme_err_startfail_cq(void) "nvme_start_ctrl failed because there are non-admin completion queues"
747
+nvme_err_startfail_sq(void) "nvme_start_ctrl failed because there are non-admin submission queues"
748
+nvme_err_startfail_nbarasq(void) "nvme_start_ctrl failed because the admin submission queue address is null"
749
+nvme_err_startfail_nbaracq(void) "nvme_start_ctrl failed because the admin completion queue address is null"
750
+nvme_err_startfail_asq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin submission queue address is misaligned: 0x%"PRIx64""
751
+nvme_err_startfail_acq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin completion queue address is misaligned: 0x%"PRIx64""
752
+nvme_err_startfail_page_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too small: log2size=%u, min=%u"
753
+nvme_err_startfail_page_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too large: log2size=%u, max=%u"
754
+nvme_err_startfail_cqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too small: log2size=%u, min=%u"
755
+nvme_err_startfail_cqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too large: log2size=%u, max=%u"
756
+nvme_err_startfail_sqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too small: log2size=%u, min=%u"
757
+nvme_err_startfail_sqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too large: log2size=%u, max=%u"
758
+nvme_err_startfail_asqent_sz_zero(void) "nvme_start_ctrl failed because the admin submission queue size is zero"
759
+nvme_err_startfail_acqent_sz_zero(void) "nvme_start_ctrl failed because the admin completion queue size is zero"
760
+nvme_err_startfail(void) "setting controller enable bit failed"
761
+
762
+# Traces for undefined behavior
763
+nvme_ub_mmiowr_misaligned32(uint64_t offset) "MMIO write not 32-bit aligned, offset=0x%"PRIx64""
764
+nvme_ub_mmiowr_toosmall(uint64_t offset, unsigned size) "MMIO write smaller than 32 bits, offset=0x%"PRIx64", size=%u"
765
+nvme_ub_mmiowr_intmask_with_msix(void) "undefined access to interrupt mask set when MSI-X is enabled"
766
+nvme_ub_mmiowr_ro_csts(void) "attempted to set a read only bit of controller status"
767
+nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CAP.NSSRS is zero (not supported)"
768
+nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
769
+nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
770
+nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
771
+nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
772
+nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
773
+nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
774
+nvme_ub_mmiord_invalid_ofs(uint64_t offset) "MMIO read beyond last register, offset=0x%"PRIx64", returning 0"
775
+nvme_ub_db_wr_misaligned(uint64_t offset) "doorbell write not 32-bit aligned, offset=0x%"PRIx64", ignoring"
776
+nvme_ub_db_wr_invalid_cq(uint32_t qid) "completion queue doorbell write for nonexistent queue, cqid=%"PRIu32", ignoring"
777
+nvme_ub_db_wr_invalid_cqhead(uint32_t qid, uint16_t new_head) "completion queue doorbell write value beyond queue size, cqid=%"PRIu32", new_head=%"PRIu16", ignoring"
778
+nvme_ub_db_wr_invalid_sq(uint32_t qid) "submission queue doorbell write for nonexistent queue, sqid=%"PRIu32", ignoring"
779
+nvme_ub_db_wr_invalid_sqtail(uint32_t qid, uint16_t new_tail) "submission queue doorbell write value beyond queue size, sqid=%"PRIu32", new_head=%"PRIu16", ignoring"
780
+
781
# hw/block/xen_disk.c
782
xen_disk_alloc(char *name) "%s"
783
xen_disk_init(char *name) "%s"
784
--
785
2.13.6
786
787
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Fam Zheng <famz@redhat.com>
2
2
3
check script will be stricter soon about whitespaces, so fix 146.out
3
Management tools create overlays of running guests with qemu-img:
4
now.
5
4
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
$ qemu-img create -b /image/in/use.qcow2 -f qcow2 /overlay/image.qcow2
7
Message-Id: <20210125185056.129513-2-vsementsov@virtuozzo.com>
6
7
but this doesn't work anymore due to image locking:
8
9
qemu-img: /overlay/image.qcow2: Failed to get shared "write" lock
10
Is another process using the image?
11
Could not open backing image to determine size.
12
Use the force share option to allow this use case again.
13
14
Cc: qemu-stable@nongnu.org
15
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
18
---
11
tests/qemu-iotests/146.out | 780 ++++++++++++++++++-------------------
19
block.c | 3 ++-
12
1 file changed, 390 insertions(+), 390 deletions(-)
20
1 file changed, 2 insertions(+), 1 deletion(-)
13
21
14
diff --git a/tests/qemu-iotests/146.out b/tests/qemu-iotests/146.out
22
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/146.out
24
--- a/block.c
17
+++ b/tests/qemu-iotests/146.out
25
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ QA output created by 146
26
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
19
27
back_flags = flags;
20
=== Testing VPC Autodetect ===
28
back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
21
29
22
-[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
30
+ backing_options = qdict_new();
23
+[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false}]
31
if (backing_fmt) {
24
32
- backing_options = qdict_new();
25
=== Testing VPC with current_size force ===
33
qdict_put_str(backing_options, "driver", backing_fmt);
26
34
}
27
-[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
35
+ qdict_put_bool(backing_options, BDRV_OPT_FORCE_SHARE, true);
28
+[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false}]
36
29
37
bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
30
=== Testing VPC with chs force ===
38
&local_err);
31
32
-[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
33
+[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false}]
34
35
=== Testing Hyper-V Autodetect ===
36
37
-[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
38
+[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false}]
39
40
=== Testing Hyper-V with current_size force ===
41
42
-[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false }]
43
+[{ "start": 0, "length": 136365211648, "depth": 0, "zero": true, "data": false}]
44
45
=== Testing Hyper-V with chs force ===
46
47
-[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false }]
48
+[{ "start": 0, "length": 136363130880, "depth": 0, "zero": true, "data": false}]
49
50
=== Testing d2v Autodetect ===
51
52
-[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
53
-{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
54
-{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
55
-{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
56
-{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
57
-{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
58
-{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
59
-{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
60
-{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
61
-{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
62
-{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
63
-{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
64
-{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
65
-{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
66
-{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
67
-{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
68
-{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
69
-{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
70
-{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
71
-{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
72
-{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
73
-{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
74
-{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
75
-{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
76
-{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
77
-{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
78
-{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
79
-{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
80
-{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
81
-{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
82
-{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
83
-{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
84
-{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
85
-{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
86
-{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
87
-{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
88
-{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
89
-{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
90
-{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
91
-{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
92
-{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
93
-{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
94
-{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
95
-{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
96
-{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
97
-{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
98
-{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
99
-{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
100
-{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
101
-{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
102
-{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
103
-{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
104
-{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
105
-{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
106
-{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
107
-{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
108
-{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
109
-{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
110
-{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
111
-{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
112
-{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
113
-{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
114
-{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
115
-{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
116
-{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
117
-{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
118
-{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
119
-{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
120
-{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
121
-{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
122
-{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
123
-{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
124
-{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
125
-{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
126
-{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
127
-{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
128
-{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
129
-{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
130
-{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
131
-{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
132
-{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
133
-{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
134
-{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
135
-{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
136
-{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
137
-{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
138
-{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
139
-{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
140
-{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
141
-{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
142
-{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
143
-{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
144
-{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
145
-{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
146
-{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
147
-{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
148
-{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
149
-{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
150
-{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
151
-{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
152
-{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
153
-{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
154
-{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
155
-{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
156
-{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
157
-{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
158
-{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
159
-{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
160
-{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
161
-{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
162
-{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
163
-{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
164
-{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
165
-{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
166
-{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
167
-{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
168
-{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
169
-{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
170
-{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
171
-{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
172
-{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
173
-{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
174
-{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
175
-{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
176
-{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
177
-{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
178
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
179
+{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
180
+{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
181
+{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
182
+{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
183
+{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
184
+{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
185
+{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
186
+{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
187
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
188
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
189
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
190
+{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
191
+{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
192
+{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
193
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
194
+{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
195
+{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
196
+{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
197
+{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
198
+{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
199
+{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
200
+{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
201
+{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
202
+{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
203
+{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
204
+{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
205
+{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
206
+{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
207
+{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
208
+{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
209
+{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
210
+{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
211
+{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
212
+{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
213
+{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
214
+{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
215
+{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
216
+{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
217
+{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
218
+{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
219
+{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
220
+{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
221
+{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
222
+{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
223
+{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
224
+{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
225
+{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
226
+{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
227
+{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
228
+{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
229
+{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
230
+{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
231
+{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
232
+{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
233
+{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
234
+{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
235
+{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
236
+{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
237
+{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
238
+{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
239
+{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
240
+{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
241
+{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
242
+{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
243
+{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
244
+{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
245
+{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
246
+{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
247
+{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
248
+{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
249
+{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
250
+{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
251
+{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
252
+{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
253
+{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
254
+{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
255
+{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
256
+{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
257
+{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
258
+{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
259
+{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
260
+{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
261
+{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
262
+{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
263
+{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
264
+{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
265
+{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
266
+{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
267
+{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
268
+{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
269
+{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
270
+{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
271
+{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
272
+{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
273
+{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
274
+{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
275
+{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
276
+{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
277
+{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
278
+{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
279
+{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
280
+{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
281
+{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
282
+{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
283
+{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
284
+{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
285
+{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
286
+{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
287
+{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
288
+{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
289
+{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
290
+{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
291
+{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
292
+{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
293
+{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
294
+{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
295
+{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
296
+{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
297
+{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
298
+{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
299
+{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
300
+{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
301
+{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
302
+{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
303
+{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
304
305
=== Testing d2v with current_size force ===
306
307
-[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
308
-{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
309
-{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
310
-{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
311
-{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
312
-{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
313
-{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
314
-{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
315
-{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
316
-{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
317
-{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
318
-{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
319
-{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
320
-{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
321
-{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
322
-{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
323
-{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
324
-{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
325
-{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
326
-{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
327
-{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
328
-{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
329
-{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
330
-{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
331
-{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
332
-{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
333
-{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
334
-{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
335
-{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
336
-{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
337
-{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
338
-{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
339
-{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
340
-{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
341
-{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
342
-{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
343
-{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
344
-{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
345
-{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
346
-{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
347
-{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
348
-{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
349
-{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
350
-{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
351
-{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
352
-{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
353
-{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
354
-{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
355
-{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
356
-{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
357
-{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
358
-{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
359
-{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
360
-{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
361
-{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
362
-{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
363
-{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
364
-{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
365
-{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
366
-{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
367
-{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
368
-{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
369
-{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
370
-{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
371
-{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
372
-{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
373
-{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
374
-{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
375
-{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
376
-{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
377
-{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
378
-{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
379
-{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
380
-{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
381
-{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
382
-{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
383
-{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
384
-{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
385
-{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
386
-{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
387
-{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
388
-{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
389
-{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
390
-{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
391
-{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
392
-{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
393
-{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
394
-{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
395
-{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
396
-{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
397
-{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
398
-{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
399
-{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
400
-{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
401
-{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
402
-{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
403
-{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
404
-{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
405
-{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
406
-{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
407
-{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
408
-{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
409
-{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
410
-{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
411
-{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
412
-{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
413
-{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
414
-{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
415
-{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
416
-{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
417
-{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
418
-{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
419
-{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
420
-{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
421
-{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
422
-{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
423
-{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
424
-{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
425
-{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
426
-{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
427
-{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
428
-{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
429
-{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
430
-{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
431
-{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
432
-{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
433
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
434
+{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
435
+{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
436
+{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
437
+{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
438
+{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
439
+{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
440
+{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
441
+{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
442
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
443
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
444
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
445
+{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
446
+{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
447
+{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
448
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
449
+{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
450
+{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
451
+{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
452
+{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
453
+{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
454
+{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
455
+{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
456
+{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
457
+{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
458
+{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
459
+{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
460
+{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
461
+{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
462
+{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
463
+{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
464
+{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
465
+{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
466
+{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
467
+{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
468
+{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
469
+{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
470
+{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
471
+{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
472
+{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
473
+{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
474
+{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
475
+{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
476
+{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
477
+{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
478
+{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
479
+{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
480
+{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
481
+{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
482
+{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
483
+{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
484
+{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
485
+{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
486
+{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
487
+{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
488
+{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
489
+{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
490
+{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
491
+{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
492
+{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
493
+{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
494
+{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
495
+{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
496
+{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
497
+{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
498
+{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
499
+{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
500
+{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
501
+{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
502
+{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
503
+{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
504
+{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
505
+{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
506
+{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
507
+{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
508
+{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
509
+{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
510
+{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
511
+{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
512
+{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
513
+{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
514
+{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
515
+{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
516
+{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
517
+{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
518
+{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
519
+{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
520
+{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
521
+{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
522
+{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
523
+{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
524
+{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
525
+{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
526
+{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
527
+{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
528
+{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
529
+{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
530
+{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
531
+{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
532
+{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
533
+{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
534
+{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
535
+{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
536
+{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
537
+{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
538
+{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
539
+{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
540
+{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
541
+{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
542
+{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
543
+{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
544
+{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
545
+{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
546
+{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
547
+{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
548
+{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
549
+{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
550
+{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
551
+{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
552
+{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
553
+{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
554
+{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
555
+{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
556
+{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
557
+{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
558
+{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
559
560
=== Testing d2v with chs force ===
561
562
-[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
563
-{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
564
-{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
565
-{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
566
-{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
567
-{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
568
-{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
569
-{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
570
-{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
571
-{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
572
-{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
573
-{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
574
-{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
575
-{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
576
-{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
577
-{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
578
-{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
579
-{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
580
-{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
581
-{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
582
-{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
583
-{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
584
-{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
585
-{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
586
-{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
587
-{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
588
-{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
589
-{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
590
-{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
591
-{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
592
-{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
593
-{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
594
-{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
595
-{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
596
-{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
597
-{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
598
-{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
599
-{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
600
-{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
601
-{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
602
-{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
603
-{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
604
-{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
605
-{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
606
-{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
607
-{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
608
-{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
609
-{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
610
-{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
611
-{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
612
-{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
613
-{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
614
-{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
615
-{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
616
-{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
617
-{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
618
-{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
619
-{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
620
-{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
621
-{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
622
-{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
623
-{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
624
-{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
625
-{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
626
-{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
627
-{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
628
-{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
629
-{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
630
-{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
631
-{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
632
-{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
633
-{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
634
-{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
635
-{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
636
-{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
637
-{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
638
-{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
639
-{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
640
-{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
641
-{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
642
-{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
643
-{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
644
-{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
645
-{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
646
-{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
647
-{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
648
-{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
649
-{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
650
-{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
651
-{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
652
-{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
653
-{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
654
-{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
655
-{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
656
-{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
657
-{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
658
-{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
659
-{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
660
-{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
661
-{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
662
-{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
663
-{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
664
-{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
665
-{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
666
-{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
667
-{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
668
-{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
669
-{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
670
-{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
671
-{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
672
-{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
673
-{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
674
-{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
675
-{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
676
-{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
677
-{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
678
-{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
679
-{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
680
-{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
681
-{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
682
-{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
683
-{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
684
-{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
685
-{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
686
-{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET },
687
-{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET }]
688
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
689
+{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
690
+{ "start": 4194304, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
691
+{ "start": 6291456, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
692
+{ "start": 8388608, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
693
+{ "start": 10485760, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
694
+{ "start": 12582912, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
695
+{ "start": 14680064, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
696
+{ "start": 16777216, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
697
+{ "start": 18874368, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
698
+{ "start": 20971520, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
699
+{ "start": 23068672, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
700
+{ "start": 25165824, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
701
+{ "start": 27262976, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
702
+{ "start": 29360128, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
703
+{ "start": 31457280, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
704
+{ "start": 33554432, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
705
+{ "start": 35651584, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
706
+{ "start": 37748736, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
707
+{ "start": 39845888, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
708
+{ "start": 41943040, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
709
+{ "start": 44040192, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
710
+{ "start": 46137344, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
711
+{ "start": 48234496, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
712
+{ "start": 50331648, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
713
+{ "start": 52428800, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
714
+{ "start": 54525952, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
715
+{ "start": 56623104, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
716
+{ "start": 58720256, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
717
+{ "start": 60817408, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
718
+{ "start": 62914560, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
719
+{ "start": 65011712, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
720
+{ "start": 67108864, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
721
+{ "start": 69206016, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
722
+{ "start": 71303168, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
723
+{ "start": 73400320, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
724
+{ "start": 75497472, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
725
+{ "start": 77594624, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
726
+{ "start": 79691776, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
727
+{ "start": 81788928, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
728
+{ "start": 83886080, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
729
+{ "start": 85983232, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
730
+{ "start": 88080384, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
731
+{ "start": 90177536, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
732
+{ "start": 92274688, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
733
+{ "start": 94371840, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
734
+{ "start": 96468992, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
735
+{ "start": 98566144, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
736
+{ "start": 100663296, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
737
+{ "start": 102760448, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
738
+{ "start": 104857600, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
739
+{ "start": 106954752, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
740
+{ "start": 109051904, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
741
+{ "start": 111149056, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
742
+{ "start": 113246208, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
743
+{ "start": 115343360, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
744
+{ "start": 117440512, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
745
+{ "start": 119537664, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
746
+{ "start": 121634816, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
747
+{ "start": 123731968, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
748
+{ "start": 125829120, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
749
+{ "start": 127926272, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
750
+{ "start": 130023424, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
751
+{ "start": 132120576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
752
+{ "start": 134217728, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
753
+{ "start": 136314880, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
754
+{ "start": 138412032, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
755
+{ "start": 140509184, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
756
+{ "start": 142606336, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
757
+{ "start": 144703488, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
758
+{ "start": 146800640, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
759
+{ "start": 148897792, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
760
+{ "start": 150994944, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
761
+{ "start": 153092096, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
762
+{ "start": 155189248, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
763
+{ "start": 157286400, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
764
+{ "start": 159383552, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
765
+{ "start": 161480704, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
766
+{ "start": 163577856, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
767
+{ "start": 165675008, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
768
+{ "start": 167772160, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
769
+{ "start": 169869312, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
770
+{ "start": 171966464, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
771
+{ "start": 174063616, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
772
+{ "start": 176160768, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
773
+{ "start": 178257920, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
774
+{ "start": 180355072, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
775
+{ "start": 182452224, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
776
+{ "start": 184549376, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
777
+{ "start": 186646528, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
778
+{ "start": 188743680, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
779
+{ "start": 190840832, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
780
+{ "start": 192937984, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
781
+{ "start": 195035136, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
782
+{ "start": 197132288, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
783
+{ "start": 199229440, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
784
+{ "start": 201326592, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
785
+{ "start": 203423744, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
786
+{ "start": 205520896, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
787
+{ "start": 207618048, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
788
+{ "start": 209715200, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
789
+{ "start": 211812352, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
790
+{ "start": 213909504, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
791
+{ "start": 216006656, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
792
+{ "start": 218103808, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
793
+{ "start": 220200960, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
794
+{ "start": 222298112, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
795
+{ "start": 224395264, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
796
+{ "start": 226492416, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
797
+{ "start": 228589568, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
798
+{ "start": 230686720, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
799
+{ "start": 232783872, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
800
+{ "start": 234881024, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
801
+{ "start": 236978176, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
802
+{ "start": 239075328, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
803
+{ "start": 241172480, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
804
+{ "start": 243269632, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
805
+{ "start": 245366784, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
806
+{ "start": 247463936, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
807
+{ "start": 249561088, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
808
+{ "start": 251658240, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
809
+{ "start": 253755392, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
810
+{ "start": 255852544, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
811
+{ "start": 257949696, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
812
+{ "start": 260046848, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
813
+{ "start": 262144000, "length": 1310720, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
814
815
=== Testing Image create, default ===
816
817
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
818
819
=== Read created image, default opts ====
820
821
-[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
822
+[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false}]
823
824
=== Read created image, force_size_calc=chs ====
825
826
-[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
827
+[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false}]
828
829
=== Read created image, force_size_calc=current_size ====
830
831
-[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false }]
832
+[{ "start": 0, "length": 4295467008, "depth": 0, "zero": true, "data": false}]
833
834
=== Testing Image create, force_size ===
835
836
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
837
838
=== Read created image, default opts ====
839
840
-[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
841
+[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false}]
842
843
=== Read created image, force_size_calc=chs ====
844
845
-[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
846
+[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false}]
847
848
=== Read created image, force_size_calc=current_size ====
849
850
-[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false }]
851
+[{ "start": 0, "length": 4294967296, "depth": 0, "zero": true, "data": false}]
852
*** done
853
--
39
--
854
2.29.2
40
2.13.6
855
41
856
42
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
It's not working anymore since QEMU v1.3.0 - time to remove it now.
4
5
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Markus Armbruster <armbru@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
blockdev.c | 11 -----------
11
qemu-doc.texi | 6 ------
12
2 files changed, 17 deletions(-)
13
14
diff --git a/blockdev.c b/blockdev.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/blockdev.c
17
+++ b/blockdev.c
18
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_legacy_drive_opts = {
19
.type = QEMU_OPT_STRING,
20
.help = "chs translation (auto, lba, none)",
21
},{
22
- .name = "boot",
23
- .type = QEMU_OPT_BOOL,
24
- .help = "(deprecated, ignored)",
25
- },{
26
.name = "addr",
27
.type = QEMU_OPT_STRING,
28
.help = "pci address (virtio only)",
29
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
30
goto fail;
31
}
32
33
- /* Deprecated option boot=[on|off] */
34
- if (qemu_opt_get(legacy_opts, "boot") != NULL) {
35
- fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
36
- "ignored. Future versions will reject this parameter. Please "
37
- "update your scripts.\n");
38
- }
39
-
40
/* Other deprecated options */
41
if (!qtest_enabled()) {
42
for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
43
diff --git a/qemu-doc.texi b/qemu-doc.texi
44
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-doc.texi
46
+++ b/qemu-doc.texi
47
@@ -XXX,XX +XXX,XX @@ deprecated.
48
49
@section System emulator command line arguments
50
51
-@subsection -drive boot=on|off (since 1.3.0)
52
-
53
-The ``boot=on|off'' option to the ``-drive'' argument is
54
-ignored. Applications should use the ``bootindex=N'' parameter
55
-to set an absolute ordering between devices instead.
56
-
57
@subsection -tdf (since 1.3.0)
58
59
The ``-tdf'' argument is ignored. The behaviour implemented
60
--
61
2.13.6
62
63
diff view generated by jsdifflib
New patch
1
1
From: Thomas Huth <thuth@redhat.com>
2
3
It's been marked as deprecated since QEMU v2.10.0, and so far nobody
4
complained that we should keep it, so let's remove this legacy option
5
now to simplify the code quite a bit.
6
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
vl.c | 86 ++-------------------------------------------------------
13
qemu-doc.texi | 8 ------
14
qemu-options.hx | 19 ++-----------
15
3 files changed, 4 insertions(+), 109 deletions(-)
16
17
diff --git a/vl.c b/vl.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/vl.c
20
+++ b/vl.c
21
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
22
const char *boot_order = NULL;
23
const char *boot_once = NULL;
24
DisplayState *ds;
25
- int cyls, heads, secs, translation;
26
QemuOpts *opts, *machine_opts;
27
- QemuOpts *hda_opts = NULL, *icount_opts = NULL, *accel_opts = NULL;
28
+ QemuOpts *icount_opts = NULL, *accel_opts = NULL;
29
QemuOptsList *olist;
30
int optind;
31
const char *optarg;
32
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
33
34
cpu_model = NULL;
35
snapshot = 0;
36
- cyls = heads = secs = 0;
37
- translation = BIOS_ATA_TRANSLATION_AUTO;
38
39
nb_nics = 0;
40
41
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
42
if (optind >= argc)
43
break;
44
if (argv[optind][0] != '-') {
45
- hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
46
+ drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
47
} else {
48
const QEMUOption *popt;
49
50
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
51
cpu_model = optarg;
52
break;
53
case QEMU_OPTION_hda:
54
- {
55
- char buf[256];
56
- if (cyls == 0)
57
- snprintf(buf, sizeof(buf), "%s", HD_OPTS);
58
- else
59
- snprintf(buf, sizeof(buf),
60
- "%s,cyls=%d,heads=%d,secs=%d%s",
61
- HD_OPTS , cyls, heads, secs,
62
- translation == BIOS_ATA_TRANSLATION_LBA ?
63
- ",trans=lba" :
64
- translation == BIOS_ATA_TRANSLATION_NONE ?
65
- ",trans=none" : "");
66
- drive_add(IF_DEFAULT, 0, optarg, buf);
67
- break;
68
- }
69
case QEMU_OPTION_hdb:
70
case QEMU_OPTION_hdc:
71
case QEMU_OPTION_hdd:
72
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
73
case QEMU_OPTION_snapshot:
74
snapshot = 1;
75
break;
76
- case QEMU_OPTION_hdachs:
77
- {
78
- const char *p;
79
- p = optarg;
80
- cyls = strtol(p, (char **)&p, 0);
81
- if (cyls < 1 || cyls > 16383)
82
- goto chs_fail;
83
- if (*p != ',')
84
- goto chs_fail;
85
- p++;
86
- heads = strtol(p, (char **)&p, 0);
87
- if (heads < 1 || heads > 16)
88
- goto chs_fail;
89
- if (*p != ',')
90
- goto chs_fail;
91
- p++;
92
- secs = strtol(p, (char **)&p, 0);
93
- if (secs < 1 || secs > 63)
94
- goto chs_fail;
95
- if (*p == ',') {
96
- p++;
97
- if (!strcmp(p, "large")) {
98
- translation = BIOS_ATA_TRANSLATION_LARGE;
99
- } else if (!strcmp(p, "rechs")) {
100
- translation = BIOS_ATA_TRANSLATION_RECHS;
101
- } else if (!strcmp(p, "none")) {
102
- translation = BIOS_ATA_TRANSLATION_NONE;
103
- } else if (!strcmp(p, "lba")) {
104
- translation = BIOS_ATA_TRANSLATION_LBA;
105
- } else if (!strcmp(p, "auto")) {
106
- translation = BIOS_ATA_TRANSLATION_AUTO;
107
- } else {
108
- goto chs_fail;
109
- }
110
- } else if (*p != '\0') {
111
- chs_fail:
112
- error_report("invalid physical CHS format");
113
- exit(1);
114
- }
115
- if (hda_opts != NULL) {
116
- qemu_opt_set_number(hda_opts, "cyls", cyls,
117
- &error_abort);
118
- qemu_opt_set_number(hda_opts, "heads", heads,
119
- &error_abort);
120
- qemu_opt_set_number(hda_opts, "secs", secs,
121
- &error_abort);
122
- if (translation == BIOS_ATA_TRANSLATION_LARGE) {
123
- qemu_opt_set(hda_opts, "trans", "large",
124
- &error_abort);
125
- } else if (translation == BIOS_ATA_TRANSLATION_RECHS) {
126
- qemu_opt_set(hda_opts, "trans", "rechs",
127
- &error_abort);
128
- } else if (translation == BIOS_ATA_TRANSLATION_LBA) {
129
- qemu_opt_set(hda_opts, "trans", "lba",
130
- &error_abort);
131
- } else if (translation == BIOS_ATA_TRANSLATION_NONE) {
132
- qemu_opt_set(hda_opts, "trans", "none",
133
- &error_abort);
134
- }
135
- }
136
- }
137
- error_report("'-hdachs' is deprecated, please use '-device"
138
- " ide-hd,cyls=c,heads=h,secs=s,...' instead");
139
- break;
140
case QEMU_OPTION_numa:
141
opts = qemu_opts_parse_noisily(qemu_find_opts("numa"),
142
optarg, true);
143
diff --git a/qemu-doc.texi b/qemu-doc.texi
144
index XXXXXXX..XXXXXXX 100644
145
--- a/qemu-doc.texi
146
+++ b/qemu-doc.texi
147
@@ -XXX,XX +XXX,XX @@ The ``--net dump'' argument is now replaced with the
148
``-object filter-dump'' argument which works in combination
149
with the modern ``-netdev`` backends instead.
150
151
-@subsection -hdachs (since 2.10.0)
152
-
153
-The ``-hdachs'' argument is now a synonym for setting
154
-the ``cyls'', ``heads'', ``secs'', and ``trans'' properties
155
-on the ``ide-hd'' device using the ``-device'' argument.
156
-The new syntax allows different settings to be provided
157
-per disk.
158
-
159
@subsection -usbdevice (since 2.10.0)
160
161
The ``-usbdevice DEV'' argument is now a synonym for setting
162
diff --git a/qemu-options.hx b/qemu-options.hx
163
index XXXXXXX..XXXXXXX 100644
164
--- a/qemu-options.hx
165
+++ b/qemu-options.hx
166
@@ -XXX,XX +XXX,XX @@ of available connectors of a given interface type.
167
@item media=@var{media}
168
This option defines the type of the media: disk or cdrom.
169
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
170
-These options have the same definition as they have in @option{-hdachs}.
171
-These parameters are deprecated, use the corresponding parameters
172
+Force disk physical geometry and the optional BIOS translation (trans=none or
173
+lba). These parameters are deprecated, use the corresponding parameters
174
of @code{-device} instead.
175
@item snapshot=@var{snapshot}
176
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
177
@@ -XXX,XX +XXX,XX @@ the raw disk image you use is not written back. You can however force
178
the write back by pressing @key{C-a s} (@pxref{disk_images}).
179
ETEXI
180
181
-DEF("hdachs", HAS_ARG, QEMU_OPTION_hdachs, \
182
- "-hdachs c,h,s[,t]\n" \
183
- " force hard disk 0 physical geometry and the optional BIOS\n" \
184
- " translation (t=none or lba) (usually QEMU can guess them)\n",
185
- QEMU_ARCH_ALL)
186
-STEXI
187
-@item -hdachs @var{c},@var{h},@var{s},[,@var{t}]
188
-@findex -hdachs
189
-Force hard disk 0 physical geometry (1 <= @var{c} <= 16383, 1 <=
190
-@var{h} <= 16, 1 <= @var{s} <= 63) and optionally force the BIOS
191
-translation mode (@var{t}=none, lba or auto). Usually QEMU can guess
192
-all those parameters. This option is deprecated, please use
193
-@code{-device ide-hd,cyls=c,heads=h,secs=s,...} instead.
194
-ETEXI
195
-
196
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
197
"-fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}]\n"
198
" [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd][,fmode=fmode][,dmode=dmode]\n"
199
--
200
2.13.6
201
202
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
Looks like we forgot to announce the deprecation of these options in
4
the corresponding chapter of the qemu-doc text, so let's do that now.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Markus Armbruster <armbru@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
qemu-doc.texi | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
13
14
diff --git a/qemu-doc.texi b/qemu-doc.texi
15
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-doc.texi
17
+++ b/qemu-doc.texi
18
@@ -XXX,XX +XXX,XX @@ longer be directly supported in QEMU.
19
The ``-drive if=scsi'' argument is replaced by the the
20
``-device BUS-TYPE'' argument combined with ``-drive if=none''.
21
22
+@subsection -drive cyls=...,heads=...,secs=...,trans=... (since 2.10.0)
23
+
24
+The drive geometry arguments are replaced by the the geometry arguments
25
+that can be specified with the ``-device'' parameter.
26
+
27
+@subsection -drive serial=... (since 2.10.0)
28
+
29
+The drive serial argument is replaced by the the serial argument
30
+that can be specified with the ``-device'' parameter.
31
+
32
+@subsection -drive addr=... (since 2.10.0)
33
+
34
+The drive addr argument is replaced by the the addr argument
35
+that can be specified with the ``-device'' parameter.
36
+
37
@subsection -net dump (since 2.10.0)
38
39
The ``--net dump'' argument is now replaced with the
40
--
41
2.13.6
42
43
diff view generated by jsdifflib
New patch
1
From: Fam Zheng <famz@redhat.com>
1
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
include/block/block_int.h | 1 -
7
block/io.c | 18 ------------------
8
2 files changed, 19 deletions(-)
9
10
diff --git a/include/block/block_int.h b/include/block/block_int.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/block/block_int.h
13
+++ b/include/block/block_int.h
14
@@ -XXX,XX +XXX,XX @@ bool blk_dev_is_tray_open(BlockBackend *blk);
15
bool blk_dev_is_medium_locked(BlockBackend *blk);
16
17
void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes);
18
-bool bdrv_requests_pending(BlockDriverState *bs);
19
20
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
21
void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in);
22
diff --git a/block/io.c b/block/io.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/io.c
25
+++ b/block/io.c
26
@@ -XXX,XX +XXX,XX @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
27
assert(old >= 1);
28
}
29
30
-/* Check if any requests are in-flight (including throttled requests) */
31
-bool bdrv_requests_pending(BlockDriverState *bs)
32
-{
33
- BdrvChild *child;
34
-
35
- if (atomic_read(&bs->in_flight)) {
36
- return true;
37
- }
38
-
39
- QLIST_FOREACH(child, &bs->children, next) {
40
- if (bdrv_requests_pending(child->bs)) {
41
- return true;
42
- }
43
- }
44
-
45
- return false;
46
-}
47
-
48
typedef struct {
49
Coroutine *co;
50
BlockDriverState *bs;
51
--
52
2.13.6
53
54
diff view generated by jsdifflib
New patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Fam Zheng <famz@redhat.com>
3
---
4
block/io.c | 6 ++++++
5
1 file changed, 6 insertions(+)
1
6
7
diff --git a/block/io.c b/block/io.c
8
index XXXXXXX..XXXXXXX 100644
9
--- a/block/io.c
10
+++ b/block/io.c
11
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
12
BdrvNextIterator it;
13
GSList *aio_ctxs = NULL, *ctx;
14
15
+ /* BDRV_POLL_WHILE() for a node can only be called from its own I/O thread
16
+ * or the main loop AioContext. We potentially use BDRV_POLL_WHILE() on
17
+ * nodes in several different AioContexts, so make sure we're in the main
18
+ * context. */
19
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
20
+
21
block_job_pause_all();
22
23
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
24
--
25
2.13.6
26
27
diff view generated by jsdifflib
New patch
1
bdrv_drained_begin() doesn't increase bs->quiesce_counter recursively
2
and also doesn't notify other parent nodes of children, which both means
3
that the child nodes are not actually drained, and bdrv_drained_begin()
4
is providing useful functionality only on a single node.
1
5
6
To keep things consistent, we also shouldn't call the block driver
7
callbacks recursively.
8
9
A proper recursive drain version that provides an actually working
10
drained section for child nodes will be introduced later.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Fam Zheng <famz@redhat.com>
14
---
15
block/io.c | 16 +++++++++-------
16
1 file changed, 9 insertions(+), 7 deletions(-)
17
18
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/io.c
21
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
23
}
24
25
/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
26
-static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
27
+static void bdrv_drain_invoke(BlockDriverState *bs, bool begin, bool recursive)
28
{
29
BdrvChild *child, *tmp;
30
BdrvCoDrainData data = { .bs = bs, .done = false, .begin = begin};
31
@@ -XXX,XX +XXX,XX @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
32
bdrv_coroutine_enter(bs, data.co);
33
BDRV_POLL_WHILE(bs, !data.done);
34
35
- QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) {
36
- bdrv_drain_invoke(child->bs, begin);
37
+ if (recursive) {
38
+ QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) {
39
+ bdrv_drain_invoke(child->bs, begin, true);
40
+ }
41
}
42
}
43
44
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs)
45
bdrv_parent_drained_begin(bs);
46
}
47
48
- bdrv_drain_invoke(bs, true);
49
+ bdrv_drain_invoke(bs, true, false);
50
bdrv_drain_recurse(bs);
51
}
52
53
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
54
}
55
56
/* Re-enable things in child-to-parent order */
57
- bdrv_drain_invoke(bs, false);
58
+ bdrv_drain_invoke(bs, false, false);
59
bdrv_parent_drained_end(bs);
60
aio_enable_external(bdrv_get_aio_context(bs));
61
}
62
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
63
aio_context_acquire(aio_context);
64
aio_disable_external(aio_context);
65
bdrv_parent_drained_begin(bs);
66
- bdrv_drain_invoke(bs, true);
67
+ bdrv_drain_invoke(bs, true, true);
68
aio_context_release(aio_context);
69
70
if (!g_slist_find(aio_ctxs, aio_context)) {
71
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
72
73
/* Re-enable things in child-to-parent order */
74
aio_context_acquire(aio_context);
75
- bdrv_drain_invoke(bs, false);
76
+ bdrv_drain_invoke(bs, false, true);
77
bdrv_parent_drained_end(bs);
78
aio_enable_external(aio_context);
79
aio_context_release(aio_context);
80
--
81
2.13.6
82
83
diff view generated by jsdifflib
New patch
1
The existing test is for bdrv_drain_all_begin/end() only. Generalise the
2
test case so that it can be run for the other variants as well. At the
3
moment this is only bdrv_drain_begin/end(), but in a while, we'll add
4
another one.
1
5
6
Also, add a backing file to the test node to test whether the operations
7
work recursively.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/test-bdrv-drain.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-----
12
1 file changed, 62 insertions(+), 7 deletions(-)
13
14
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/test-bdrv-drain.c
17
+++ b/tests/test-bdrv-drain.c
18
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_test = {
19
20
.bdrv_co_drain_begin = bdrv_test_co_drain_begin,
21
.bdrv_co_drain_end = bdrv_test_co_drain_end,
22
+
23
+ .bdrv_child_perm = bdrv_format_default_perms,
24
};
25
26
static void aio_ret_cb(void *opaque, int ret)
27
@@ -XXX,XX +XXX,XX @@ static void aio_ret_cb(void *opaque, int ret)
28
*aio_ret = ret;
29
}
30
31
-static void test_drv_cb_drain_all(void)
32
+enum drain_type {
33
+ BDRV_DRAIN_ALL,
34
+ BDRV_DRAIN,
35
+};
36
+
37
+static void do_drain_begin(enum drain_type drain_type, BlockDriverState *bs)
38
+{
39
+ switch (drain_type) {
40
+ case BDRV_DRAIN_ALL: bdrv_drain_all_begin(); break;
41
+ case BDRV_DRAIN: bdrv_drained_begin(bs); break;
42
+ default: g_assert_not_reached();
43
+ }
44
+}
45
+
46
+static void do_drain_end(enum drain_type drain_type, BlockDriverState *bs)
47
+{
48
+ switch (drain_type) {
49
+ case BDRV_DRAIN_ALL: bdrv_drain_all_end(); break;
50
+ case BDRV_DRAIN: bdrv_drained_end(bs); break;
51
+ default: g_assert_not_reached();
52
+ }
53
+}
54
+
55
+static void test_drv_cb_common(enum drain_type drain_type, bool recursive)
56
{
57
BlockBackend *blk;
58
- BlockDriverState *bs;
59
- BDRVTestState *s;
60
+ BlockDriverState *bs, *backing;
61
+ BDRVTestState *s, *backing_s;
62
BlockAIOCB *acb;
63
int aio_ret;
64
65
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_drain_all(void)
66
s = bs->opaque;
67
blk_insert_bs(blk, bs, &error_abort);
68
69
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
70
+ backing_s = backing->opaque;
71
+ bdrv_set_backing_hd(bs, backing, &error_abort);
72
+
73
/* Simple bdrv_drain_all_begin/end pair, check that CBs are called */
74
g_assert_cmpint(s->drain_count, ==, 0);
75
- bdrv_drain_all_begin();
76
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
77
+
78
+ do_drain_begin(drain_type, bs);
79
+
80
g_assert_cmpint(s->drain_count, ==, 1);
81
- bdrv_drain_all_end();
82
+ g_assert_cmpint(backing_s->drain_count, ==, !!recursive);
83
+
84
+ do_drain_end(drain_type, bs);
85
+
86
g_assert_cmpint(s->drain_count, ==, 0);
87
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
88
89
/* Now do the same while a request is pending */
90
aio_ret = -EINPROGRESS;
91
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_drain_all(void)
92
g_assert_cmpint(aio_ret, ==, -EINPROGRESS);
93
94
g_assert_cmpint(s->drain_count, ==, 0);
95
- bdrv_drain_all_begin();
96
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
97
+
98
+ do_drain_begin(drain_type, bs);
99
+
100
g_assert_cmpint(aio_ret, ==, 0);
101
g_assert_cmpint(s->drain_count, ==, 1);
102
- bdrv_drain_all_end();
103
+ g_assert_cmpint(backing_s->drain_count, ==, !!recursive);
104
+
105
+ do_drain_end(drain_type, bs);
106
+
107
g_assert_cmpint(s->drain_count, ==, 0);
108
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
109
110
+ bdrv_unref(backing);
111
bdrv_unref(bs);
112
blk_unref(blk);
113
}
114
115
+static void test_drv_cb_drain_all(void)
116
+{
117
+ test_drv_cb_common(BDRV_DRAIN_ALL, true);
118
+}
119
+
120
+static void test_drv_cb_drain(void)
121
+{
122
+ test_drv_cb_common(BDRV_DRAIN, false);
123
+}
124
+
125
int main(int argc, char **argv)
126
{
127
bdrv_init();
128
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
129
g_test_init(&argc, &argv, NULL);
130
131
g_test_add_func("/bdrv-drain/driver-cb/drain_all", test_drv_cb_drain_all);
132
+ g_test_add_func("/bdrv-drain/driver-cb/drain", test_drv_cb_drain);
133
134
return g_test_run();
135
}
136
--
137
2.13.6
138
139
diff view generated by jsdifflib
New patch
1
This is currently only working correctly for bdrv_drain(), not for
2
bdrv_drain_all(). Leave a comment for the drain_all case, we'll address
3
it later.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/test-bdrv-drain.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
8
1 file changed, 45 insertions(+)
9
10
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/test-bdrv-drain.c
13
+++ b/tests/test-bdrv-drain.c
14
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_drain(void)
15
test_drv_cb_common(BDRV_DRAIN, false);
16
}
17
18
+static void test_quiesce_common(enum drain_type drain_type, bool recursive)
19
+{
20
+ BlockBackend *blk;
21
+ BlockDriverState *bs, *backing;
22
+
23
+ blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
24
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
25
+ &error_abort);
26
+ blk_insert_bs(blk, bs, &error_abort);
27
+
28
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
29
+ bdrv_set_backing_hd(bs, backing, &error_abort);
30
+
31
+ g_assert_cmpint(bs->quiesce_counter, ==, 0);
32
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
33
+
34
+ do_drain_begin(drain_type, bs);
35
+
36
+ g_assert_cmpint(bs->quiesce_counter, ==, 1);
37
+ g_assert_cmpint(backing->quiesce_counter, ==, !!recursive);
38
+
39
+ do_drain_end(drain_type, bs);
40
+
41
+ g_assert_cmpint(bs->quiesce_counter, ==, 0);
42
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
43
+
44
+ bdrv_unref(backing);
45
+ bdrv_unref(bs);
46
+ blk_unref(blk);
47
+}
48
+
49
+static void test_quiesce_drain_all(void)
50
+{
51
+ // XXX drain_all doesn't quiesce
52
+ //test_quiesce_common(BDRV_DRAIN_ALL, true);
53
+}
54
+
55
+static void test_quiesce_drain(void)
56
+{
57
+ test_quiesce_common(BDRV_DRAIN, false);
58
+}
59
+
60
int main(int argc, char **argv)
61
{
62
bdrv_init();
63
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
64
g_test_add_func("/bdrv-drain/driver-cb/drain_all", test_drv_cb_drain_all);
65
g_test_add_func("/bdrv-drain/driver-cb/drain", test_drv_cb_drain);
66
67
+ g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
68
+ g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
69
+
70
return g_test_run();
71
}
72
--
73
2.13.6
74
75
diff view generated by jsdifflib
New patch
1
Block jobs already paused themselves when their main BlockBackend
2
entered a drained section. This is not good enough: We also want to
3
pause a block job and may not submit new requests if, for example, the
4
mirror target node should be drained.
1
5
6
This implements .drained_begin/end callbacks in child_job in order to
7
consider all block nodes related to the job, and removes the
8
BlockBackend callbacks which are unnecessary now because the root of the
9
job main BlockBackend is always referenced with a child_job, too.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
blockjob.c | 22 +++++++++-------------
14
1 file changed, 9 insertions(+), 13 deletions(-)
15
16
diff --git a/blockjob.c b/blockjob.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/blockjob.c
19
+++ b/blockjob.c
20
@@ -XXX,XX +XXX,XX @@ static char *child_job_get_parent_desc(BdrvChild *c)
21
job->id);
22
}
23
24
-static const BdrvChildRole child_job = {
25
- .get_parent_desc = child_job_get_parent_desc,
26
- .stay_at_node = true,
27
-};
28
-
29
-static void block_job_drained_begin(void *opaque)
30
+static void child_job_drained_begin(BdrvChild *c)
31
{
32
- BlockJob *job = opaque;
33
+ BlockJob *job = c->opaque;
34
block_job_pause(job);
35
}
36
37
-static void block_job_drained_end(void *opaque)
38
+static void child_job_drained_end(BdrvChild *c)
39
{
40
- BlockJob *job = opaque;
41
+ BlockJob *job = c->opaque;
42
block_job_resume(job);
43
}
44
45
-static const BlockDevOps block_job_dev_ops = {
46
- .drained_begin = block_job_drained_begin,
47
- .drained_end = block_job_drained_end,
48
+static const BdrvChildRole child_job = {
49
+ .get_parent_desc = child_job_get_parent_desc,
50
+ .drained_begin = child_job_drained_begin,
51
+ .drained_end = child_job_drained_end,
52
+ .stay_at_node = true,
53
};
54
55
void block_job_remove_all_bdrv(BlockJob *job)
56
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
57
block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
58
bs->job = job;
59
60
- blk_set_dev_ops(blk, &block_job_dev_ops, job);
61
bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
62
63
QLIST_INSERT_HEAD(&block_jobs, job, job_list);
64
--
65
2.13.6
66
67
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Block jobs must be paused if any of the involved nodes are drained.
2
2
3
Just use classes introduced in previous three commits. Behavior
4
difference is described in these three commits.
5
6
Drop group file, as it becomes unused.
7
8
Drop common.env: now check is in python, and for tests we use same
9
python interpreter that runs the check itself. Use build environment
10
PYTHON in check-block instead, to keep "make check" use the same
11
python.
12
13
Checking for virtio-blk moved to iotests.py, as it actually iotests.py
14
dependency. Actually not all python iotests depend on it, so in future
15
it may be refactored to checked only when really needed.
16
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Message-Id: <20210125185056.129513-6-vsementsov@virtuozzo.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
4
---
21
tests/qemu-iotests/iotests.py | 8 +
5
tests/test-bdrv-drain.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
22
Makefile | 1 -
6
1 file changed, 121 insertions(+)
23
tests/check-block.sh | 3 +-
24
tests/qemu-iotests/check | 1095 ++++--------------------------
25
tests/qemu-iotests/common.env.in | 3 -
26
tests/qemu-iotests/group | 323 ---------
27
tests/qemu-iotests/meson.build | 3 -
28
7 files changed, 139 insertions(+), 1297 deletions(-)
29
delete mode 100644 tests/qemu-iotests/common.env.in
30
delete mode 100644 tests/qemu-iotests/group
31
7
32
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
8
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
33
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
34
--- a/tests/qemu-iotests/iotests.py
10
--- a/tests/test-bdrv-drain.c
35
+++ b/tests/qemu-iotests/iotests.py
11
+++ b/tests/test-bdrv-drain.c
36
@@ -XXX,XX +XXX,XX @@ def _verify_formats(required_formats: Sequence[str] = ()) -> None:
12
@@ -XXX,XX +XXX,XX @@
37
if usf_list:
13
38
notrun(f'formats {usf_list} are not whitelisted')
14
#include "qemu/osdep.h"
15
#include "block/block.h"
16
+#include "block/blockjob_int.h"
17
#include "sysemu/block-backend.h"
18
#include "qapi/error.h"
19
20
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_drain(void)
21
test_quiesce_common(BDRV_DRAIN, false);
22
}
39
23
40
+
24
+
41
+def _verify_virtio_blk() -> None:
25
+typedef struct TestBlockJob {
42
+ out = qemu_pipe('-M', 'none', '-device', 'help')
26
+ BlockJob common;
43
+ if 'virtio-blk' not in out:
27
+ bool should_complete;
44
+ notrun('Missing virtio-blk in QEMU binary')
28
+} TestBlockJob;
45
+
29
+
30
+static void test_job_completed(BlockJob *job, void *opaque)
31
+{
32
+ block_job_completed(job, 0);
33
+}
46
+
34
+
47
def supports_quorum():
35
+static void coroutine_fn test_job_start(void *opaque)
48
return 'quorum' in qemu_img_pipe('--help')
36
+{
49
37
+ TestBlockJob *s = opaque;
50
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
51
_verify_cache_mode(supported_cache_modes)
52
_verify_aio_mode(supported_aio_modes)
53
_verify_formats(required_fmts)
54
+ _verify_virtio_blk()
55
56
return debug
57
58
diff --git a/Makefile b/Makefile
59
index XXXXXXX..XXXXXXX 100644
60
--- a/Makefile
61
+++ b/Makefile
62
@@ -XXX,XX +XXX,XX @@ distclean: clean
63
    rm -f config-host.mak config-host.h*
64
    rm -f tests/tcg/config-*.mak
65
    rm -f config-all-disas.mak config.status
66
-    rm -f tests/qemu-iotests/common.env
67
    rm -f roms/seabios/config.mak roms/vgabios/config.mak
68
    rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
69
    rm -f *-config-target.h *-config-devices.mak *-config-devices.h
70
diff --git a/tests/check-block.sh b/tests/check-block.sh
71
index XXXXXXX..XXXXXXX 100755
72
--- a/tests/check-block.sh
73
+++ b/tests/check-block.sh
74
@@ -XXX,XX +XXX,XX @@ cd tests/qemu-iotests
75
76
# QEMU_CHECK_BLOCK_AUTO is used to disable some unstable sub-tests
77
export QEMU_CHECK_BLOCK_AUTO=1
78
+export PYTHONUTF8=1
79
80
ret=0
81
for fmt in $format_list ; do
82
- ./check -makecheck -$fmt $group || ret=1
83
+ ${PYTHON} ./check -makecheck -$fmt $group || ret=1
84
done
85
86
exit $ret
87
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
88
index XXXXXXX..XXXXXXX 100755
89
--- a/tests/qemu-iotests/check
90
+++ b/tests/qemu-iotests/check
91
@@ -XXX,XX +XXX,XX @@
92
-#!/usr/bin/env bash
93
+#!/usr/bin/env python3
94
#
95
-# Copyright (C) 2009 Red Hat, Inc.
96
-# Copyright (c) 2000-2002,2006 Silicon Graphics, Inc. All Rights Reserved.
97
+# Configure environment and run group of tests in it.
98
+#
99
+# Copyright (c) 2020-2021 Virtuozzo International GmbH
100
#
101
# This program is free software; you can redistribute it and/or
102
# modify it under the terms of the GNU General Public License as
103
@@ -XXX,XX +XXX,XX @@
104
#
105
# You should have received a copy of the GNU General Public License
106
# along with this program. If not, see <http://www.gnu.org/licenses/>.
107
-#
108
-#
109
-# Control script for QA
110
-#
111
-
112
-status=0
113
-needwrap=true
114
-try=0
115
-n_bad=0
116
-bad=""
117
-notrun=""
118
-casenotrun=""
119
-interrupt=true
120
-makecheck=false
121
-
122
-_init_error()
123
-{
124
- echo "check: $1" >&2
125
- exit 1
126
-}
127
-
128
-if [ -L "$0" ]
129
-then
130
- # called from the build tree
131
- source_iotests=$(dirname "$(readlink "$0")")
132
- if [ -z "$source_iotests" ]
133
- then
134
- _init_error "failed to obtain source tree name from check symlink"
135
- fi
136
- source_iotests=$(cd "$source_iotests"; pwd) || _init_error "failed to enter source tree"
137
- build_iotests=$(cd "$(dirname "$0")"; pwd)
138
-else
139
- # called from the source tree
140
- source_iotests=$PWD
141
- # this may be an in-tree build (note that in the following code we may not
142
- # assume that it truly is and have to test whether the build results
143
- # actually exist)
144
- build_iotests=$PWD
145
-fi
146
-
147
-build_root="$build_iotests/../.."
148
-
149
-# we need common.env
150
-if ! . "$build_iotests/common.env"
151
-then
152
- _init_error "failed to source common.env (make sure the qemu-iotests are run from tests/qemu-iotests in the build tree)"
153
-fi
154
-
155
-# we need common.config
156
-if ! . "$source_iotests/common.config"
157
-then
158
- _init_error "failed to source common.config"
159
-fi
160
-
161
-_full_imgfmt_details()
162
-{
163
- if [ -n "$IMGOPTS" ]; then
164
- echo "$IMGFMT ($IMGOPTS)"
165
- else
166
- echo "$IMGFMT"
167
- fi
168
-}
169
-
170
-_full_platform_details()
171
-{
172
- os=$(uname -s)
173
- host=$(hostname -s)
174
- kernel=$(uname -r)
175
- platform=$(uname -m)
176
- echo "$os/$platform $host $kernel"
177
-}
178
-
179
-_full_env_details()
180
-{
181
- cat <<EOF
182
-QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
183
-QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
184
-QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
185
-QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
186
-IMGFMT -- $FULL_IMGFMT_DETAILS
187
-IMGPROTO -- $IMGPROTO
188
-PLATFORM -- $FULL_HOST_DETAILS
189
-TEST_DIR -- $TEST_DIR
190
-SOCK_DIR -- $SOCK_DIR
191
-SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
192
-
193
-EOF
194
-}
195
-
196
-# $1 = prog to look for
197
-set_prog_path()
198
-{
199
- p=$(command -v $1 2> /dev/null)
200
- if [ -n "$p" -a -x "$p" ]; then
201
- type -p "$p"
202
- else
203
- return 1
204
- fi
205
-}
206
-
207
-if [ -z "$TEST_DIR" ]; then
208
- TEST_DIR=$PWD/scratch
209
-fi
210
-mkdir -p "$TEST_DIR" || _init_error 'Failed to create TEST_DIR'
211
-
212
-tmp_sock_dir=false
213
-if [ -z "$SOCK_DIR" ]; then
214
- SOCK_DIR=$(mktemp -d)
215
- tmp_sock_dir=true
216
-fi
217
-mkdir -p "$SOCK_DIR" || _init_error 'Failed to create SOCK_DIR'
218
-
219
-diff="diff -u"
220
-verbose=false
221
-debug=false
222
-group=false
223
-xgroup=false
224
-imgopts=false
225
-showme=false
226
-sortme=false
227
-expunge=true
228
-have_test_arg=false
229
-cachemode=false
230
-aiomode=false
231
-
232
-tmp="${TEST_DIR}"/$$
233
-rm -f $tmp.list $tmp.tmp $tmp.sed
234
-
235
-export IMGFMT=raw
236
-export IMGFMT_GENERIC=true
237
-export IMGPROTO=file
238
-export IMGOPTS=""
239
-export CACHEMODE="writeback"
240
-export AIOMODE="threads"
241
-export QEMU_IO_OPTIONS=""
242
-export QEMU_IO_OPTIONS_NO_FMT=""
243
-export CACHEMODE_IS_DEFAULT=true
244
-export VALGRIND_QEMU=
245
-export IMGKEYSECRET=
246
-export IMGOPTSSYNTAX=false
247
-
248
-# Save current tty settings, since an aborting qemu call may leave things
249
-# screwed up
250
-STTY_RESTORE=
251
-if test -t 0; then
252
- STTY_RESTORE=$(stty -g)
253
-fi
254
-
255
-for r
256
-do
257
-
258
- if $group
259
- then
260
- # arg after -g
261
- group_list=$(sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
262
-s/ .*//p
263
-}')
264
- if [ -z "$group_list" ]
265
- then
266
- echo "Group \"$r\" is empty or not defined?"
267
- exit 1
268
- fi
269
- [ ! -s $tmp.list ] && touch $tmp.list
270
- for t in $group_list
271
- do
272
- if grep -s "^$t\$" $tmp.list >/dev/null
273
- then
274
- :
275
- else
276
- echo "$t" >>$tmp.list
277
- fi
278
- done
279
- group=false
280
- continue
281
-
282
- elif $xgroup
283
- then
284
- # arg after -x
285
- # Populate $tmp.list with all tests
286
- awk '/^[0-9]{3,}/ {print $1}' "${source_iotests}/group" > $tmp.list 2>/dev/null
287
- group_list=$(sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
288
-s/ .*//p
289
-}')
290
- if [ -z "$group_list" ]
291
- then
292
- echo "Group \"$r\" is empty or not defined?"
293
- exit 1
294
- fi
295
- numsed=0
296
- rm -f $tmp.sed
297
- for t in $group_list
298
- do
299
- if [ $numsed -gt 100 ]
300
- then
301
- sed -f $tmp.sed <$tmp.list >$tmp.tmp
302
- mv $tmp.tmp $tmp.list
303
- numsed=0
304
- rm -f $tmp.sed
305
- fi
306
- echo "/^$t\$/d" >>$tmp.sed
307
- numsed=$(expr $numsed + 1)
308
- done
309
- sed -f $tmp.sed <$tmp.list >$tmp.tmp
310
- mv $tmp.tmp $tmp.list
311
- xgroup=false
312
- continue
313
-
314
- elif $imgopts
315
- then
316
- IMGOPTS="$r"
317
- imgopts=false
318
- continue
319
- elif $cachemode
320
- then
321
- CACHEMODE="$r"
322
- CACHEMODE_IS_DEFAULT=false
323
- cachemode=false
324
- continue
325
- elif $aiomode
326
- then
327
- AIOMODE="$r"
328
- aiomode=false
329
- continue
330
- fi
331
-
332
- xpand=true
333
- case "$r"
334
- in
335
-
336
- -\? | -h | --help) # usage
337
- echo "Usage: $0 [options] [testlist]"'
338
-
339
-common options
340
- -v verbose
341
- -d debug
342
-
343
-image format options
344
- -raw test raw (default)
345
- -bochs test bochs
346
- -cloop test cloop
347
- -parallels test parallels
348
- -qcow test qcow
349
- -qcow2 test qcow2
350
- -qed test qed
351
- -vdi test vdi
352
- -vpc test vpc
353
- -vhdx test vhdx
354
- -vmdk test vmdk
355
- -luks test luks
356
- -dmg test dmg
357
-
358
-image protocol options
359
- -file test file (default)
360
- -rbd test rbd
361
- -sheepdog test sheepdog
362
- -nbd test nbd
363
- -fuse test fuse
364
- -ssh test ssh
365
- -nfs test nfs
366
-
367
-other options
368
- -xdiff graphical mode diff
369
- -nocache use O_DIRECT on backing file
370
- -misalign misalign memory allocations
371
- -n show me, do not run tests
372
- -o options -o options to pass to qemu-img create/convert
373
- -c mode cache mode
374
- -i mode AIO mode
375
- -makecheck pretty print output for make check
376
-
377
-testlist options
378
- -g group[,group...] include tests from these groups
379
- -x group[,group...] exclude tests from these groups
380
- NNN include test NNN
381
- NNN-NNN include test range (eg. 012-021)
382
-'
383
- exit 0
384
- ;;
385
-
386
- -raw)
387
- IMGFMT=raw
388
- xpand=false
389
- ;;
390
-
391
- -bochs)
392
- IMGFMT=bochs
393
- IMGFMT_GENERIC=false
394
- xpand=false
395
- ;;
396
-
397
- -cloop)
398
- IMGFMT=cloop
399
- IMGFMT_GENERIC=false
400
- xpand=false
401
- ;;
402
-
403
- -parallels)
404
- IMGFMT=parallels
405
- xpand=false
406
- ;;
407
-
408
- -qcow)
409
- IMGFMT=qcow
410
- xpand=false
411
- ;;
412
-
413
- -qcow2)
414
- IMGFMT=qcow2
415
- xpand=false
416
- ;;
417
-
418
- -luks)
419
- IMGOPTSSYNTAX=true
420
- IMGFMT=luks
421
- IMGKEYSECRET=123456
422
- xpand=false
423
- ;;
424
-
425
- -dmg)
426
- IMGFMT=dmg
427
- IMGFMT_GENERIC=false
428
- xpand=false
429
- ;;
430
-
431
- -qed)
432
- IMGFMT=qed
433
- xpand=false
434
- ;;
435
-
436
- -vdi)
437
- IMGFMT=vdi
438
- xpand=false
439
- ;;
440
-
441
- -vmdk)
442
- IMGFMT=vmdk
443
- xpand=false
444
- ;;
445
-
446
- -vpc)
447
- IMGFMT=vpc
448
- xpand=false
449
- ;;
450
-
451
- -vhdx)
452
- IMGFMT=vhdx
453
- xpand=false
454
- ;;
455
-
456
- -file)
457
- IMGPROTO=file
458
- xpand=false
459
- ;;
460
-
461
- -rbd)
462
- IMGPROTO=rbd
463
- xpand=false
464
- ;;
465
-
466
- -sheepdog)
467
- IMGPROTO=sheepdog
468
- xpand=false
469
- ;;
470
-
471
- -nbd)
472
- IMGPROTO=nbd
473
- xpand=false
474
- ;;
475
-
476
- -fuse)
477
- IMGPROTO=fuse
478
- xpand=false
479
- ;;
480
-
481
- -ssh)
482
- IMGPROTO=ssh
483
- xpand=false
484
- ;;
485
-
486
- -nfs)
487
- IMGPROTO=nfs
488
- xpand=false
489
- ;;
490
-
491
- -nocache)
492
- CACHEMODE="none"
493
- CACHEMODE_IS_DEFAULT=false
494
- xpand=false
495
- ;;
496
-
497
- -misalign)
498
- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --misalign"
499
- xpand=false
500
- ;;
501
-
502
- -valgrind)
503
- VALGRIND_QEMU='y'
504
- xpand=false
505
- ;;
506
-
507
- -g) # -g group ... pick from group file
508
- group=true
509
- xpand=false
510
- ;;
511
-
512
- -xdiff) # graphical diff mode
513
- xpand=false
514
-
515
- if [ ! -z "$DISPLAY" ]
516
- then
517
- command -v xdiff >/dev/null 2>&1 && diff=xdiff
518
- command -v gdiff >/dev/null 2>&1 && diff=gdiff
519
- command -v tkdiff >/dev/null 2>&1 && diff=tkdiff
520
- command -v xxdiff >/dev/null 2>&1 && diff=xxdiff
521
- fi
522
- ;;
523
- -makecheck) # makecheck friendly output
524
- makecheck=true
525
- xpand=false
526
- ;;
527
- -n) # show me, don't do it
528
- showme=true
529
- xpand=false
530
- ;;
531
- -o)
532
- imgopts=true
533
- xpand=false
534
- ;;
535
- -c)
536
- cachemode=true
537
- xpand=false
538
- ;;
539
- -i)
540
- aiomode=true
541
- xpand=false
542
- ;;
543
- -T) # deprecated timestamp option
544
- xpand=false
545
- ;;
546
- -v)
547
- verbose=true
548
- xpand=false
549
- ;;
550
- -d)
551
- debug=true
552
- xpand=false
553
- ;;
554
- -x) # -x group ... exclude from group file
555
- xgroup=true
556
- xpand=false
557
- ;;
558
- '[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]')
559
- echo "No tests?"
560
- status=1
561
- exit $status
562
- ;;
563
-
564
- [0-9]*-[0-9]*)
565
- eval $(echo $r | sed -e 's/^/start=/' -e 's/-/ end=/')
566
- ;;
567
-
568
- [0-9]*-)
569
- eval $(echo $r | sed -e 's/^/start=/' -e 's/-//')
570
- end=$(echo [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] | sed -e 's/\[0-9]//g' -e 's/ *$//' -e 's/.* //')
571
- if [ -z "$end" ]
572
- then
573
- echo "No tests in range \"$r\"?"
574
- status=1
575
- exit $status
576
- fi
577
- ;;
578
-
579
- *)
580
- start=$r
581
- end=$r
582
- ;;
583
-
584
- esac
585
-
586
- # get rid of leading 0s as can be interpreted as octal
587
- start=$(echo $start | sed 's/^0*//')
588
- end=$(echo $end | sed 's/^0*//')
589
-
590
- if $xpand
591
- then
592
- have_test_arg=true
593
- awk </dev/null '
594
-BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
595
- | while read id
596
- do
597
- if grep -s "^$id\( \|\$\)" "$source_iotests/group" >/dev/null
598
- then
599
- # in group file ... OK
600
- echo $id >>$tmp.list
601
- else
602
- if [ -f expunged ] && $expunge && egrep "^$id([ ]|\$)" expunged >/dev/null
603
- then
604
- # expunged ... will be reported, but not run, later
605
- echo $id >>$tmp.list
606
- else
607
- # oops
608
- if [ "$start" == "$end" -a "$id" == "$end" ]
609
- then
610
- echo "$id - unknown test"
611
- exit 1
612
- else
613
- echo "$id - unknown test, ignored"
614
- fi
615
- fi
616
- fi
617
- done || exit 1
618
- fi
619
-
620
-done
621
-
622
-# Set qemu-io cache mode with $CACHEMODE we have
623
-QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
624
-# Set qemu-io aio mode with $AIOMODE we have
625
-QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --aio $AIOMODE"
626
-
627
-QEMU_IO_OPTIONS_NO_FMT="$QEMU_IO_OPTIONS"
628
-if [ "$IMGOPTSSYNTAX" != "true" ]; then
629
- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT"
630
-fi
631
-
632
-# Set default options for qemu-img create -o if they were not specified
633
-if [ "$IMGFMT" == "qcow2" ] && ! (echo "$IMGOPTS" | grep "compat=" > /dev/null); then
634
- IMGOPTS=$(_optstr_add "$IMGOPTS" "compat=1.1")
635
-fi
636
-if [ "$IMGFMT" == "luks" ] && ! (echo "$IMGOPTS" | grep "iter-time=" > /dev/null); then
637
- IMGOPTS=$(_optstr_add "$IMGOPTS" "iter-time=10")
638
-fi
639
-if [ "$IMGFMT" == "vmdk" ] && ! (echo "$IMGOPTS" | grep "zeroed_grain=" > /dev/null); then
640
- IMGOPTS=$(_optstr_add "$IMGOPTS" "zeroed_grain=on")
641
-fi
642
-
643
-if [ -z "$SAMPLE_IMG_DIR" ]; then
644
- SAMPLE_IMG_DIR="$source_iotests/sample_images"
645
-fi
646
-
647
-export TEST_DIR
648
-export SOCK_DIR
649
-export SAMPLE_IMG_DIR
650
-
651
-if [ -s $tmp.list ]
652
-then
653
- # found some valid test numbers ... this is good
654
- :
655
-else
656
- if $have_test_arg
657
- then
658
- # had test numbers, but none in group file ... do nothing
659
- touch $tmp.list
660
- else
661
- # no test numbers, do everything from group file
662
- sed -n -e '/^[0-9][0-9][0-9]*/s/^\([0-9]*\).*/\1/p' <"$source_iotests/group" >$tmp.list
663
- fi
664
-fi
665
-
666
-# should be sort -n, but this did not work for Linux when this
667
-# was ported from IRIX
668
-#
669
-list=$(sort $tmp.list)
670
-rm -f $tmp.list $tmp.tmp $tmp.sed
671
-
672
-if [ -z "$QEMU_PROG" ]
673
-then
674
- if [ -x "$build_iotests/qemu" ]; then
675
- export QEMU_PROG="$build_iotests/qemu"
676
- elif [ -x "$build_root/qemu-system-${qemu_arch}" ]; then
677
- export QEMU_PROG="$build_root/qemu-system-${qemu_arch}"
678
- else
679
- pushd "$build_root" > /dev/null
680
- for binary in qemu-system-*
681
- do
682
- if [ -x "$binary" ]
683
- then
684
- export QEMU_PROG="$build_root/$binary"
685
- break
686
- fi
687
- done
688
- popd > /dev/null
689
- [ "$QEMU_PROG" = "" ] && _init_error "qemu not found"
690
- fi
691
-fi
692
-export QEMU_PROG="$(type -p "$QEMU_PROG")"
693
-
694
-export QEMU_OPTIONS="-nodefaults -display none -accel qtest"
695
-case "$QEMU_PROG" in
696
- *qemu-system-arm|*qemu-system-aarch64)
697
- export QEMU_OPTIONS="$QEMU_OPTIONS -machine virt"
698
- ;;
699
- *qemu-system-avr)
700
- export QEMU_OPTIONS="$QEMU_OPTIONS -machine mega2560"
701
- ;;
702
- *qemu-system-rx)
703
- export QEMU_OPTIONS="$QEMU_OPTIONS -machine gdbsim-r5f562n8"
704
- ;;
705
- *qemu-system-tricore)
706
- export QEMU_OPTIONS="-$QEMU_OPTIONS -machine tricore_testboard"
707
- ;;
708
-esac
709
-
710
-if [ -z "$QEMU_IMG_PROG" ]; then
711
- if [ -x "$build_iotests/qemu-img" ]; then
712
- export QEMU_IMG_PROG="$build_iotests/qemu-img"
713
- elif [ -x "$build_root/qemu-img" ]; then
714
- export QEMU_IMG_PROG="$build_root/qemu-img"
715
- else
716
- _init_error "qemu-img not found"
717
- fi
718
-fi
719
-export QEMU_IMG_PROG="$(type -p "$QEMU_IMG_PROG")"
720
-
721
-if [ -z "$QEMU_IO_PROG" ]; then
722
- if [ -x "$build_iotests/qemu-io" ]; then
723
- export QEMU_IO_PROG="$build_iotests/qemu-io"
724
- elif [ -x "$build_root/qemu-io" ]; then
725
- export QEMU_IO_PROG="$build_root/qemu-io"
726
- else
727
- _init_error "qemu-io not found"
728
- fi
729
-fi
730
-export QEMU_IO_PROG="$(type -p "$QEMU_IO_PROG")"
731
-
732
-if [ -z $QEMU_NBD_PROG ]; then
733
- if [ -x "$build_iotests/qemu-nbd" ]; then
734
- export QEMU_NBD_PROG="$build_iotests/qemu-nbd"
735
- elif [ -x "$build_root/qemu-nbd" ]; then
736
- export QEMU_NBD_PROG="$build_root/qemu-nbd"
737
- else
738
- _init_error "qemu-nbd not found"
739
- fi
740
-fi
741
-export QEMU_NBD_PROG="$(type -p "$QEMU_NBD_PROG")"
742
-
743
-if [ -z "$QSD_PROG" ]; then
744
- if [ -x "$build_iotests/qemu-storage-daemon" ]; then
745
- export QSD_PROG="$build_iotests/qemu-storage-daemon"
746
- elif [ -x "$build_root/storage-daemon/qemu-storage-daemon" ]; then
747
- export QSD_PROG="$build_root/storage-daemon/qemu-storage-daemon"
748
- else
749
- _init_error "qemu-storage-daemon not found"
750
- fi
751
-fi
752
-export QSD_PROG="$(type -p "$QSD_PROG")"
753
-
754
-if [ -x "$build_iotests/socket_scm_helper" ]
755
-then
756
- export SOCKET_SCM_HELPER="$build_iotests/socket_scm_helper"
757
-fi
758
-
759
-python_usable=false
760
-if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)'
761
-then
762
- # Our python framework also requires virtio-blk
763
- if "$QEMU_PROG" -M none -device help | grep -q virtio-blk >/dev/null 2>&1
764
- then
765
- python_usable=true
766
- else
767
- python_unusable_because="Missing virtio-blk in QEMU binary"
768
- fi
769
-else
770
- python_unusable_because="Unsupported Python version"
771
-fi
772
-
773
-default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p')
774
-default_alias_machine=$($QEMU_PROG -machine help | \
775
- sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }")
776
-if [[ "$default_alias_machine" ]]; then
777
- default_machine="$default_alias_machine"
778
-fi
779
-
780
-export QEMU_DEFAULT_MACHINE="$default_machine"
781
-
782
-TIMESTAMP_FILE=check.time-$IMGPROTO-$IMGFMT
783
-
784
-_wallclock()
785
-{
786
- date "+%H %M %S" | awk '{ print $1*3600 + $2*60 + $3 }'
787
-}
788
-
789
-_wrapup()
790
-{
791
- if $showme
792
- then
793
- :
794
- elif $needwrap
795
- then
796
- if [ -f $TIMESTAMP_FILE -a -f $tmp.time ]
797
- then
798
- cat $TIMESTAMP_FILE $tmp.time \
799
- | awk '
800
- { t[$1] = $2 }
801
-END { if (NR > 0) {
802
- for (i in t) print i " " t[i]
803
- }
804
- }' \
805
- | sort -n >$tmp.out
806
- mv $tmp.out $TIMESTAMP_FILE
807
- fi
808
-
809
- if [ -f $tmp.expunged ]
810
- then
811
- notrun=$(wc -l <$tmp.expunged | sed -e 's/ *//g')
812
- try=$(expr $try - $notrun)
813
- list=$(echo "$list" | sed -f $tmp.expunged)
814
- fi
815
-
816
- echo "" >>check.log
817
- date >>check.log
818
- echo $list | fmt | sed -e 's/^/ /' >>check.log
819
- $interrupt && echo "Interrupted!" >>check.log
820
-
821
- if [ ! -z "$notrun" ]
822
- then
823
- echo "Not run:$notrun"
824
- echo "Not run:$notrun" >>check.log
825
- fi
826
- if [ ! -z "$casenotrun" ]
827
- then
828
- echo "Some cases not run in:$casenotrun"
829
- echo "Some cases not run in:$casenotrun" >>check.log
830
- fi
831
- if [ ! -z "$n_bad" -a $n_bad != 0 ]
832
- then
833
- echo "Failures:$bad"
834
- echo "Failed $n_bad of $try iotests"
835
- echo "Failures:$bad" | fmt >>check.log
836
- echo "Failed $n_bad of $try iotests" >>check.log
837
- else
838
- echo "Passed all $try iotests"
839
- echo "Passed all $try iotests" >>check.log
840
- fi
841
- needwrap=false
842
- fi
843
-
844
- if test -n "$STTY_RESTORE"; then
845
- stty $STTY_RESTORE
846
- fi
847
- rm -f "${TEST_DIR}"/*.out "${TEST_DIR}"/*.err "${TEST_DIR}"/*.time
848
- rm -f "${TEST_DIR}"/check.pid "${TEST_DIR}"/check.sts
849
- rm -f $tmp.*
850
-
851
- if $tmp_sock_dir
852
- then
853
- rm -rf "$SOCK_DIR"
854
- fi
855
-}
856
-
857
-trap "_wrapup; exit \$status" 0 1 2 3 15
858
-
859
-# Report the test start and results. For makecheck we want to pretty
860
-# print the whole report at the end of the execution.
861
-# args: $seq, $starttime, $lasttime
862
-_report_test_start()
863
-{
864
- if ! $makecheck; then
865
- if [ -n "$3" ]; then
866
- local lasttime=" (last: $3s)"
867
- fi
868
- printf "%-8s %-10s [%s] %4s%-14s\r" "$1" "..." "$2" "..." "$lasttime"
869
- fi
870
-}
871
-# args:$seq $status $starttime $lasttime $thistime $details
872
-_report_test_result()
873
-{
874
- local status lasttime thistime
875
- if $makecheck; then
876
- if [ -n "$2" ] && [ "$2" != "pass" ]; then
877
- status=" [$2]"
878
- fi
879
- printf " TEST iotest-$IMGFMT: %s%s\n" "$1" "$status"
880
- return
881
- fi
882
-
883
- if [ -n "$4" ]; then
884
- lasttime=" (last: $4s)"
885
- fi
886
- if [ -n "$5" ]; then
887
- thistime=" $5s"
888
- fi
889
- case "$2" in
890
- "pass") status=$(printf "\e[32m%-10s\e[0m" "$2") ;;
891
- "fail") status=$(printf "\e[1m\e[31m%-10s\e[0m" "$2") ;;
892
- "not run") status=$(printf "\e[33m%-10s\e[0m" "$2") ;;
893
- *) status=$(printf "%-10s" "$2") ;;
894
- esac
895
-
896
- printf "%-8s %s [%s] [%s] %4s%-14s %s\n" "$1" "$status" "$3" "$(date '+%T')" "$thistime" "$lasttime" "$6"
897
-}
898
-
899
-[ -f $TIMESTAMP_FILE ] || touch $TIMESTAMP_FILE
900
-
901
-FULL_IMGFMT_DETAILS=$(_full_imgfmt_details)
902
-FULL_HOST_DETAILS=$(_full_platform_details)
903
-
904
-if ! $makecheck; then
905
- _full_env_details
906
-fi
907
-
908
-seq="check"
909
-
910
-[ -n "$TESTS_REMAINING_LOG" ] && echo $list > $TESTS_REMAINING_LOG
911
-
912
-for seq in $list
913
-do
914
- err=false # error flag
915
- printdiff=false # show diff to reference output?
916
- status="" # test result summary
917
- results="" # test result details
918
- thistime="" # time the test took
919
-
920
- if [ -n "$TESTS_REMAINING_LOG" ] ; then
921
- sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp
922
- mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG
923
- sync
924
- fi
925
-
926
- lasttime=$(sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE)
927
- starttime=$(date "+%T")
928
- _report_test_start $seq $starttime $lasttime
929
-
930
- if $showme
931
- then
932
- status="not run"
933
- elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null
934
- then
935
- status="not run"
936
- results="expunged"
937
- rm -f $seq.out.bad
938
- echo "/^$seq\$/d" >>$tmp.expunged
939
- elif [ ! -f "$source_iotests/$seq" ]
940
- then
941
- status="not run"
942
- results="no such test?"
943
- echo "/^$seq\$/d" >>$tmp.expunged
944
- else
945
- # really going to try and run this one
946
- #
947
- rm -f $seq.out.bad
948
- rm -f core $seq.notrun
949
- rm -f $seq.casenotrun
950
-
951
- start=$(_wallclock)
952
-
953
- if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python3" ]; then
954
- if $python_usable; then
955
- run_command="$PYTHON $seq"
956
- else
957
- run_command="false"
958
- echo "$python_unusable_because" > $seq.notrun
959
- fi
960
- else
961
- run_command="./$seq"
962
- fi
963
- export OUTPUT_DIR=$PWD
964
- if $debug; then
965
- (cd "$source_iotests";
966
- MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \
967
- $run_command -d 2>&1 | tee $tmp.out)
968
- else
969
- (cd "$source_iotests";
970
- MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \
971
- $run_command >$tmp.out 2>&1)
972
- fi
973
- sts=$?
974
- stop=$(_wallclock)
975
-
976
- if [ -f core ]
977
- then
978
- mv core $seq.core
979
- status="fail"
980
- results="[dumped core] $seq.core"
981
- err=true
982
- fi
983
-
984
- if [ -f $seq.notrun ]
985
- then
986
- # overwrites timestamp output
987
- status="not run"
988
- results="$(cat $seq.notrun)"
989
- else
990
- if [ $sts -ne 0 ]
991
- then
992
- status="fail"
993
- results=$(printf %s "[failed, exit status $sts]")
994
- err=true
995
- fi
996
-
997
- reference="$source_iotests/$seq.out"
998
- reference_machine="$source_iotests/$seq.$QEMU_DEFAULT_MACHINE.out"
999
- if [ -f "$reference_machine" ]; then
1000
- reference="$reference_machine"
1001
- fi
1002
-
1003
- reference_format="$source_iotests/$seq.out.$IMGFMT"
1004
- if [ -f "$reference_format" ]; then
1005
- reference="$reference_format"
1006
- fi
1007
-
1008
- if [ "$CACHEMODE" = "none" ]; then
1009
- [ -f "$source_iotests/$seq.out.nocache" ] && reference="$source_iotests/$seq.out.nocache"
1010
- fi
1011
-
1012
- if [ ! -f "$reference" ]
1013
- then
1014
- status="fail"
1015
- results="no qualified output"
1016
- err=true
1017
- else
1018
- if diff -w "$reference" $tmp.out >/dev/null 2>&1
1019
- then
1020
- if ! $err; then
1021
- status="pass"
1022
- thistime=$(expr $stop - $start)
1023
- echo "$seq $thistime" >>$tmp.time
1024
- fi
1025
- else
1026
- mv $tmp.out $seq.out.bad
1027
- status="fail"
1028
- results="output mismatch (see $seq.out.bad)"
1029
- printdiff=true
1030
- err=true
1031
- fi
1032
- fi
1033
- fi
1034
- if [ -f $seq.casenotrun ]
1035
- then
1036
- cat $seq.casenotrun
1037
- casenotrun="$casenotrun $seq"
1038
- fi
1039
- fi
1040
-
1041
- # come here for each test, except when $showme is true
1042
- #
1043
- _report_test_result $seq "$status" "$starttime" "$lasttime" "$thistime" "$results"
1044
- case "$status" in
1045
- "pass")
1046
- try=$(expr $try + 1)
1047
- ;;
1048
- "fail")
1049
- try=$(expr $try + 1)
1050
- if $makecheck; then
1051
- _full_env_details
1052
- fi
1053
- if $printdiff; then
1054
- $diff -w "$reference" "$PWD"/$seq.out.bad
1055
- fi
1056
- bad="$bad $seq"
1057
- n_bad=$(expr $n_bad + 1)
1058
- quick=false
1059
- ;;
1060
- "not run")
1061
- notrun="$notrun $seq"
1062
- ;;
1063
- esac
1064
-
1065
- seq="after_$seq"
1066
-done
1067
1068
-interrupt=false
1069
-status=$(expr $n_bad)
1070
-exit
1071
+import os
1072
+import sys
1073
+import argparse
1074
+from findtests import TestFinder
1075
+from testenv import TestEnv
1076
+from testrunner import TestRunner
1077
+
38
+
39
+ while (!s->should_complete) {
40
+ block_job_sleep_ns(&s->common, 100000);
41
+ }
1078
+
42
+
1079
+def make_argparser() -> argparse.ArgumentParser:
43
+ block_job_defer_to_main_loop(&s->common, test_job_completed, NULL);
1080
+ p = argparse.ArgumentParser(description="Test run options")
44
+}
1081
+
45
+
1082
+ p.add_argument('-n', '--dry-run', action='store_true',
46
+static void test_job_complete(BlockJob *job, Error **errp)
1083
+ help='show me, do not run tests')
47
+{
1084
+ p.add_argument('-makecheck', action='store_true',
48
+ TestBlockJob *s = container_of(job, TestBlockJob, common);
1085
+ help='pretty print output for make check')
49
+ s->should_complete = true;
50
+}
1086
+
51
+
1087
+ p.add_argument('-d', dest='debug', action='store_true', help='debug')
52
+BlockJobDriver test_job_driver = {
1088
+ p.add_argument('-misalign', action='store_true',
53
+ .instance_size = sizeof(TestBlockJob),
1089
+ help='misalign memory allocations')
54
+ .start = test_job_start,
1090
+ p.add_argument('--color', choices=['on', 'off', 'auto'],
55
+ .complete = test_job_complete,
1091
+ default='auto', help="use terminal colors. The default "
56
+};
1092
+ "'auto' value means use colors if terminal stdout detected")
1093
+
57
+
1094
+ g_env = p.add_argument_group('test environment options')
58
+static void test_blockjob_common(enum drain_type drain_type)
1095
+ mg = g_env.add_mutually_exclusive_group()
59
+{
1096
+ # We don't set default for cachemode, as we need to distinguish default
60
+ BlockBackend *blk_src, *blk_target;
1097
+ # from user input later.
61
+ BlockDriverState *src, *target;
1098
+ mg.add_argument('-nocache', dest='cachemode', action='store_const',
62
+ BlockJob *job;
1099
+ const='none', help='set cache mode "none" (O_DIRECT), '
63
+ int ret;
1100
+ 'sets CACHEMODE environment variable')
1101
+ mg.add_argument('-c', dest='cachemode',
1102
+ help='sets CACHEMODE environment variable')
1103
+
64
+
1104
+ g_env.add_argument('-i', dest='aiomode', default='threads',
65
+ src = bdrv_new_open_driver(&bdrv_test, "source", BDRV_O_RDWR,
1105
+ help='sets AIOMODE environment variable')
66
+ &error_abort);
67
+ blk_src = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
68
+ blk_insert_bs(blk_src, src, &error_abort);
1106
+
69
+
1107
+ p.set_defaults(imgfmt='raw', imgproto='file')
70
+ target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR,
71
+ &error_abort);
72
+ blk_target = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
73
+ blk_insert_bs(blk_target, target, &error_abort);
1108
+
74
+
1109
+ format_list = ['raw', 'bochs', 'cloop', 'parallels', 'qcow', 'qcow2',
75
+ job = block_job_create("job0", &test_job_driver, src, 0, BLK_PERM_ALL, 0,
1110
+ 'qed', 'vdi', 'vpc', 'vhdx', 'vmdk', 'luks', 'dmg']
76
+ 0, NULL, NULL, &error_abort);
1111
+ g_fmt = p.add_argument_group(
77
+ block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort);
1112
+ ' image format options',
78
+ block_job_start(job);
1113
+ 'The following options set the IMGFMT environment variable. '
1114
+ 'At most one choice is allowed, default is "raw"')
1115
+ mg = g_fmt.add_mutually_exclusive_group()
1116
+ for fmt in format_list:
1117
+ mg.add_argument('-' + fmt, dest='imgfmt', action='store_const',
1118
+ const=fmt, help=f'test {fmt}')
1119
+
79
+
1120
+ protocol_list = ['file', 'rbd', 'sheepdog', 'nbd', 'ssh', 'nfs',
80
+ g_assert_cmpint(job->pause_count, ==, 0);
1121
+ 'fuse']
81
+ g_assert_false(job->paused);
1122
+ g_prt = p.add_argument_group(
82
+ g_assert_false(job->busy); /* We're in block_job_sleep_ns() */
1123
+ ' image protocol options',
1124
+ 'The following options set the IMGPROTO environment variable. '
1125
+ 'At most one choice is allowed, default is "file"')
1126
+ mg = g_prt.add_mutually_exclusive_group()
1127
+ for prt in protocol_list:
1128
+ mg.add_argument('-' + prt, dest='imgproto', action='store_const',
1129
+ const=prt, help=f'test {prt}')
1130
+
83
+
1131
+ g_bash = p.add_argument_group('bash tests options',
84
+ do_drain_begin(drain_type, src);
1132
+ 'The following options are ignored by '
1133
+ 'python tests.')
1134
+ # TODO: make support for the following options in iotests.py
1135
+ g_bash.add_argument('-o', dest='imgopts',
1136
+ help='options to pass to qemu-img create/convert, '
1137
+ 'sets IMGOPTS environment variable')
1138
+ g_bash.add_argument('-valgrind', action='store_true',
1139
+ help='use valgrind, sets VALGRIND_QEMU environment '
1140
+ 'variable')
1141
+
85
+
1142
+ g_sel = p.add_argument_group('test selecting options',
86
+ if (drain_type == BDRV_DRAIN_ALL) {
1143
+ 'The following options specify test set '
87
+ /* bdrv_drain_all() drains both src and target, and involves an
1144
+ 'to run.')
88
+ * additional block_job_pause_all() */
1145
+ g_sel.add_argument('-g', '--groups', metavar='group1,...',
89
+ g_assert_cmpint(job->pause_count, ==, 3);
1146
+ help='include tests from these groups')
90
+ } else {
1147
+ g_sel.add_argument('-x', '--exclude-groups', metavar='group1,...',
91
+ g_assert_cmpint(job->pause_count, ==, 1);
1148
+ help='exclude tests from these groups')
92
+ }
1149
+ g_sel.add_argument('--start-from', metavar='TEST',
93
+ /* XXX We don't wait until the job is actually paused. Is this okay? */
1150
+ help='Start from specified test: make sorted sequence '
94
+ /* g_assert_true(job->paused); */
1151
+ 'of tests as usual and then drop tests from the first '
95
+ g_assert_false(job->busy); /* The job is paused */
1152
+ 'one to TEST (not inclusive). This may be used to '
1153
+ 'rerun failed ./check command, starting from the '
1154
+ 'middle of the process.')
1155
+ g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*',
1156
+ help='tests to run')
1157
+
96
+
1158
+ return p
97
+ do_drain_end(drain_type, src);
1159
+
98
+
99
+ g_assert_cmpint(job->pause_count, ==, 0);
100
+ g_assert_false(job->paused);
101
+ g_assert_false(job->busy); /* We're in block_job_sleep_ns() */
1160
+
102
+
1161
+if __name__ == '__main__':
103
+ do_drain_begin(drain_type, target);
1162
+ args = make_argparser().parse_args()
1163
+
104
+
1164
+ env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
105
+ if (drain_type == BDRV_DRAIN_ALL) {
1165
+ aiomode=args.aiomode, cachemode=args.cachemode,
106
+ /* bdrv_drain_all() drains both src and target, and involves an
1166
+ imgopts=args.imgopts, misalign=args.misalign,
107
+ * additional block_job_pause_all() */
1167
+ debug=args.debug, valgrind=args.valgrind)
108
+ g_assert_cmpint(job->pause_count, ==, 3);
109
+ } else {
110
+ g_assert_cmpint(job->pause_count, ==, 1);
111
+ }
112
+ /* XXX We don't wait until the job is actually paused. Is this okay? */
113
+ /* g_assert_true(job->paused); */
114
+ g_assert_false(job->busy); /* The job is paused */
1168
+
115
+
1169
+ testfinder = TestFinder(test_dir=env.source_iotests)
116
+ do_drain_end(drain_type, target);
1170
+
117
+
1171
+ groups = args.groups.split(',') if args.groups else None
118
+ g_assert_cmpint(job->pause_count, ==, 0);
1172
+ x_groups = args.exclude_groups.split(',') if args.exclude_groups else None
119
+ g_assert_false(job->paused);
120
+ g_assert_false(job->busy); /* We're in block_job_sleep_ns() */
1173
+
121
+
1174
+ group_local = os.path.join(env.source_iotests, 'group.local')
122
+ ret = block_job_complete_sync(job, &error_abort);
1175
+ if os.path.isfile(group_local):
123
+ g_assert_cmpint(ret, ==, 0);
1176
+ try:
1177
+ testfinder.add_group_file(group_local)
1178
+ except ValueError as e:
1179
+ sys.exit(f"Failed to parse group file '{group_local}': {e}")
1180
+
124
+
1181
+ try:
125
+ blk_unref(blk_src);
1182
+ tests = testfinder.find_tests(groups=groups, exclude_groups=x_groups,
126
+ blk_unref(blk_target);
1183
+ tests=args.tests,
127
+ bdrv_unref(src);
1184
+ start_from=args.start_from)
128
+ bdrv_unref(target);
1185
+ if not tests:
129
+}
1186
+ raise ValueError('No tests selected')
1187
+ except ValueError as e:
1188
+ sys.exit(e)
1189
+
130
+
1190
+ if args.dry_run:
131
+static void test_blockjob_drain_all(void)
1191
+ print('\n'.join(tests))
132
+{
1192
+ else:
133
+ test_blockjob_common(BDRV_DRAIN_ALL);
1193
+ with TestRunner(env, makecheck=args.makecheck,
134
+}
1194
+ color=args.color) as tr:
135
+
1195
+ tr.run_tests([os.path.join(env.source_iotests, t) for t in tests])
136
+static void test_blockjob_drain(void)
1196
diff --git a/tests/qemu-iotests/common.env.in b/tests/qemu-iotests/common.env.in
137
+{
1197
deleted file mode 100644
138
+ test_blockjob_common(BDRV_DRAIN);
1198
index XXXXXXX..XXXXXXX
139
+}
1199
--- a/tests/qemu-iotests/common.env.in
140
+
1200
+++ /dev/null
141
int main(int argc, char **argv)
1201
@@ -XXX,XX +XXX,XX @@
142
{
1202
-# Automatically generated by configure - do not modify
143
bdrv_init();
1203
-
144
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
1204
-export PYTHON='@PYTHON@'
145
g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
1205
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
146
g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
1206
deleted file mode 100644
147
1207
index XXXXXXX..XXXXXXX
148
+ g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
1208
--- a/tests/qemu-iotests/group
149
+ g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
1209
+++ /dev/null
150
+
1210
@@ -XXX,XX +XXX,XX @@
151
return g_test_run();
1211
-#
152
}
1212
-# QA groups control file
1213
-# Defines test groups
1214
-#
1215
-# Some notes about the groups:
1216
-#
1217
-# - do not start group names with a digit
1218
-#
1219
-# - quick : Tests in this group should finish within some few seconds.
1220
-#
1221
-# - img : Tests in this group can be used to excercise the qemu-img tool.
1222
-#
1223
-# - auto : Tests in this group are used during "make check" and should be
1224
-# runnable in any case. That means they should run with every QEMU binary
1225
-# (also non-x86), with every QEMU configuration (i.e. must not fail if
1226
-# an optional feature is not compiled in - but reporting a "skip" is ok),
1227
-# work at least with the qcow2 file format, work with all kind of host
1228
-# filesystems and users (e.g. "nobody" or "root") and must not take too
1229
-# much memory and disk space (since CI pipelines tend to fail otherwise).
1230
-#
1231
-
1232
-#
1233
-# test-group association ... one line per test
1234
-#
1235
-001 rw auto quick
1236
-002 rw auto quick
1237
-003 rw auto
1238
-004 rw auto quick
1239
-005 img auto quick
1240
-# 006 was removed, do not reuse
1241
-007 snapshot auto
1242
-008 rw auto quick
1243
-009 rw auto quick
1244
-010 rw auto quick
1245
-011 rw auto quick
1246
-012 auto quick
1247
-013 rw auto
1248
-014 rw
1249
-015 rw snapshot
1250
-# 016 was removed, do not reuse
1251
-017 rw backing auto quick
1252
-018 rw backing auto quick
1253
-019 rw backing auto quick
1254
-020 rw backing auto quick
1255
-021 io auto quick
1256
-022 rw snapshot auto
1257
-023 rw
1258
-024 rw backing auto quick
1259
-025 rw auto quick
1260
-026 rw blkdbg
1261
-027 rw auto quick
1262
-028 rw backing quick
1263
-029 rw auto quick
1264
-030 rw auto backing
1265
-031 rw auto quick
1266
-032 rw auto quick
1267
-033 rw auto quick
1268
-034 rw auto backing quick
1269
-035 rw auto quick
1270
-036 rw auto quick
1271
-037 rw auto backing quick
1272
-038 rw auto backing quick
1273
-039 rw auto quick
1274
-040 rw auto
1275
-041 rw auto backing
1276
-042 rw auto quick
1277
-043 rw auto backing
1278
-044 rw
1279
-045 rw quick
1280
-046 rw auto aio quick
1281
-047 rw auto quick
1282
-048 img auto quick
1283
-049 rw auto
1284
-050 rw auto backing quick
1285
-051 rw
1286
-052 rw auto backing quick
1287
-053 rw auto quick
1288
-054 rw auto quick
1289
-055 rw
1290
-056 rw backing
1291
-057 rw
1292
-058 rw quick
1293
-059 rw quick
1294
-060 rw auto quick
1295
-061 rw auto
1296
-062 rw auto quick
1297
-063 rw auto quick
1298
-064 rw quick
1299
-065 rw quick
1300
-066 rw auto quick
1301
-# 067 was removed, do not reuse
1302
-068 rw quick
1303
-069 rw auto quick
1304
-070 rw quick
1305
-071 rw auto quick
1306
-072 rw auto quick
1307
-073 rw auto quick
1308
-074 rw auto quick
1309
-075 rw quick
1310
-076 io
1311
-077 rw quick
1312
-078 rw quick
1313
-079 rw auto
1314
-080 rw auto
1315
-081 rw quick
1316
-082 rw quick
1317
-083 rw
1318
-084 img quick
1319
-085 rw
1320
-086 rw auto quick
1321
-087 rw quick
1322
-088 rw quick
1323
-089 rw auto quick
1324
-090 rw auto quick
1325
-091 rw migration quick
1326
-092 rw quick
1327
-093 throttle
1328
-094 rw quick
1329
-095 rw quick
1330
-096 rw quick
1331
-097 rw auto backing
1332
-098 rw auto backing quick
1333
-099 rw auto quick
1334
-# 100 was removed, do not reuse
1335
-101 rw quick
1336
-102 rw quick
1337
-103 rw auto quick
1338
-104 rw auto
1339
-105 rw auto quick
1340
-106 rw quick
1341
-107 rw auto quick
1342
-108 rw auto quick
1343
-109 rw
1344
-110 rw auto backing quick
1345
-111 rw auto quick
1346
-112 rw
1347
-113 rw quick
1348
-114 rw auto quick
1349
-115 rw
1350
-116 rw quick
1351
-117 rw auto
1352
-118 rw
1353
-119 rw quick
1354
-120 rw auto quick
1355
-121 rw
1356
-122 rw
1357
-123 rw quick
1358
-124 rw backing
1359
-125 rw
1360
-126 rw auto backing
1361
-127 rw auto backing quick
1362
-128 rw quick
1363
-129 rw quick
1364
-130 rw quick
1365
-131 rw quick
1366
-132 rw quick
1367
-133 auto quick
1368
-134 rw auto quick
1369
-135 rw
1370
-136 rw
1371
-137 rw auto
1372
-138 rw auto quick
1373
-139 rw quick
1374
-140 rw auto quick
1375
-141 rw auto quick
1376
-142
1377
-143 auto quick
1378
-144 rw quick
1379
-145 quick
1380
-146 quick
1381
-147 img
1382
-148 rw quick
1383
-149 rw sudo
1384
-150 rw auto quick
1385
-151 rw
1386
-152 rw quick
1387
-153 rw quick
1388
-154 rw auto backing quick
1389
-155 rw
1390
-156 rw auto quick
1391
-157 quick
1392
-158 rw auto quick
1393
-159 rw auto quick
1394
-160 rw quick
1395
-161 rw auto quick
1396
-162 quick
1397
-163 rw
1398
-165 rw quick
1399
-169 rw migration
1400
-170 rw auto quick
1401
-171 rw quick
1402
-172 auto
1403
-173 rw
1404
-174 auto
1405
-175 quick
1406
-176 rw auto backing
1407
-177 rw auto quick
1408
-178 img
1409
-179 rw auto quick
1410
-181 rw auto migration quick
1411
-182 rw quick
1412
-183 rw migration quick
1413
-184 rw auto quick
1414
-185 rw
1415
-186 rw auto
1416
-187 rw auto
1417
-188 rw quick
1418
-189 rw
1419
-190 rw auto quick
1420
-191 rw auto
1421
-192 rw auto quick
1422
-194 rw migration quick
1423
-195 rw auto quick
1424
-196 rw quick migration
1425
-197 rw quick
1426
-198 rw
1427
-199 rw migration
1428
-200 rw
1429
-201 rw migration quick
1430
-202 rw quick
1431
-203 rw auto migration quick
1432
-204 rw quick
1433
-205 rw quick
1434
-206 rw
1435
-207 rw
1436
-208 rw quick
1437
-209 rw quick
1438
-210 rw
1439
-211 rw quick
1440
-212 rw quick
1441
-213 rw quick
1442
-214 rw auto
1443
-215 rw quick
1444
-216 rw quick
1445
-217 rw auto quick
1446
-218 rw quick
1447
-219 rw
1448
-220 rw auto
1449
-221 rw quick
1450
-222 rw quick
1451
-223 rw quick
1452
-224 rw quick
1453
-225 rw quick
1454
-226 auto quick
1455
-227 quick
1456
-228 rw quick
1457
-229 auto quick
1458
-231 quick
1459
-232 quick
1460
-233 quick
1461
-234 quick migration
1462
-235 quick
1463
-236 quick
1464
-237 rw quick
1465
-238 quick
1466
-239 rw quick
1467
-240 quick
1468
-241 rw quick
1469
-242 rw quick
1470
-243 rw quick
1471
-244 rw auto quick
1472
-245 rw
1473
-246 rw quick
1474
-247 rw quick
1475
-248 rw quick
1476
-249 rw auto quick
1477
-250 rw quick
1478
-251 rw auto quick
1479
-252 rw auto backing quick
1480
-253 rw quick
1481
-254 rw backing quick
1482
-255 rw quick
1483
-256 rw auto quick
1484
-257 rw
1485
-258 rw quick
1486
-259 rw auto quick
1487
-260 rw quick
1488
-261 rw
1489
-262 rw quick migration
1490
-263 rw quick
1491
-264 rw
1492
-265 rw auto quick
1493
-266 rw quick
1494
-267 rw auto quick snapshot
1495
-268 rw auto quick
1496
-270 rw backing quick
1497
-271 rw auto
1498
-272 rw
1499
-273 backing quick
1500
-274 rw backing
1501
-277 rw quick
1502
-279 rw backing quick
1503
-280 rw migration quick
1504
-281 rw quick
1505
-282 rw img quick
1506
-283 auto quick
1507
-284 rw
1508
-286 rw quick
1509
-287 auto quick
1510
-288 quick
1511
-289 rw quick
1512
-290 rw auto quick
1513
-291 rw quick
1514
-292 rw auto quick
1515
-293 rw
1516
-294 rw quick
1517
-295 rw
1518
-296 rw
1519
-297 meta
1520
-298
1521
-299 auto quick
1522
-300 migration
1523
-301 backing quick
1524
-302 quick
1525
-303 rw quick
1526
-304 rw quick
1527
-305 rw quick
1528
-307 rw quick export
1529
-308 rw
1530
-309 rw auto quick
1531
-310 rw quick
1532
-312 rw quick
1533
-313 rw auto quick
1534
diff --git a/tests/qemu-iotests/meson.build b/tests/qemu-iotests/meson.build
1535
index XXXXXXX..XXXXXXX 100644
1536
--- a/tests/qemu-iotests/meson.build
1537
+++ b/tests/qemu-iotests/meson.build
1538
@@ -XXX,XX +XXX,XX @@ if 'CONFIG_LINUX' in config_host
1539
else
1540
socket_scm_helper = []
1541
endif
1542
-configure_file(output: 'common.env',
1543
- input: files('common.env.in'),
1544
- configuration: {'PYTHON': python.full_path()})
1545
--
153
--
1546
2.29.2
154
2.13.6
1547
155
1548
156
diff view generated by jsdifflib
New patch
1
Block jobs are already paused using the BdrvChildRole drain callbacks,
2
so we don't need an additional block_job_pause_all() call.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
block/io.c | 4 ----
7
tests/test-bdrv-drain.c | 10 ++++------
8
2 files changed, 4 insertions(+), 10 deletions(-)
9
10
diff --git a/block/io.c b/block/io.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/io.c
13
+++ b/block/io.c
14
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
15
* context. */
16
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
17
18
- block_job_pause_all();
19
-
20
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
21
AioContext *aio_context = bdrv_get_aio_context(bs);
22
23
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
24
aio_enable_external(aio_context);
25
aio_context_release(aio_context);
26
}
27
-
28
- block_job_resume_all();
29
}
30
31
void bdrv_drain_all(void)
32
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/tests/test-bdrv-drain.c
35
+++ b/tests/test-bdrv-drain.c
36
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common(enum drain_type drain_type)
37
do_drain_begin(drain_type, src);
38
39
if (drain_type == BDRV_DRAIN_ALL) {
40
- /* bdrv_drain_all() drains both src and target, and involves an
41
- * additional block_job_pause_all() */
42
- g_assert_cmpint(job->pause_count, ==, 3);
43
+ /* bdrv_drain_all() drains both src and target */
44
+ g_assert_cmpint(job->pause_count, ==, 2);
45
} else {
46
g_assert_cmpint(job->pause_count, ==, 1);
47
}
48
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common(enum drain_type drain_type)
49
do_drain_begin(drain_type, target);
50
51
if (drain_type == BDRV_DRAIN_ALL) {
52
- /* bdrv_drain_all() drains both src and target, and involves an
53
- * additional block_job_pause_all() */
54
- g_assert_cmpint(job->pause_count, ==, 3);
55
+ /* bdrv_drain_all() drains both src and target */
56
+ g_assert_cmpint(job->pause_count, ==, 2);
57
} else {
58
g_assert_cmpint(job->pause_count, ==, 1);
59
}
60
--
61
2.13.6
62
63
diff view generated by jsdifflib
New patch
1
bdrv_do_drained_begin() restricts the call of parent callbacks and
2
aio_disable_external() to the outermost drain section, but the block
3
driver callbacks are always called. bdrv_do_drained_end() must match
4
this behaviour, otherwise nodes stay drained even if begin/end calls
5
were balanced.
1
6
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/io.c | 12 +++++++-----
10
1 file changed, 7 insertions(+), 5 deletions(-)
11
12
diff --git a/block/io.c b/block/io.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/io.c
15
+++ b/block/io.c
16
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs)
17
18
void bdrv_drained_end(BlockDriverState *bs)
19
{
20
+ int old_quiesce_counter;
21
+
22
if (qemu_in_coroutine()) {
23
bdrv_co_yield_to_drain(bs, false);
24
return;
25
}
26
assert(bs->quiesce_counter > 0);
27
- if (atomic_fetch_dec(&bs->quiesce_counter) > 1) {
28
- return;
29
- }
30
+ old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
31
32
/* Re-enable things in child-to-parent order */
33
bdrv_drain_invoke(bs, false, false);
34
- bdrv_parent_drained_end(bs);
35
- aio_enable_external(bdrv_get_aio_context(bs));
36
+ if (old_quiesce_counter == 1) {
37
+ bdrv_parent_drained_end(bs);
38
+ aio_enable_external(bdrv_get_aio_context(bs));
39
+ }
40
}
41
42
/*
43
--
44
2.13.6
45
46
diff view generated by jsdifflib
New patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
---
3
tests/test-bdrv-drain.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
4
1 file changed, 57 insertions(+)
1
5
6
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
7
index XXXXXXX..XXXXXXX 100644
8
--- a/tests/test-bdrv-drain.c
9
+++ b/tests/test-bdrv-drain.c
10
@@ -XXX,XX +XXX,XX @@ static void aio_ret_cb(void *opaque, int ret)
11
enum drain_type {
12
BDRV_DRAIN_ALL,
13
BDRV_DRAIN,
14
+ DRAIN_TYPE_MAX,
15
};
16
17
static void do_drain_begin(enum drain_type drain_type, BlockDriverState *bs)
18
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_drain(void)
19
test_quiesce_common(BDRV_DRAIN, false);
20
}
21
22
+static void test_nested(void)
23
+{
24
+ BlockBackend *blk;
25
+ BlockDriverState *bs, *backing;
26
+ BDRVTestState *s, *backing_s;
27
+ enum drain_type outer, inner;
28
+
29
+ blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
30
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
31
+ &error_abort);
32
+ s = bs->opaque;
33
+ blk_insert_bs(blk, bs, &error_abort);
34
+
35
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
36
+ backing_s = backing->opaque;
37
+ bdrv_set_backing_hd(bs, backing, &error_abort);
38
+
39
+ for (outer = 0; outer < DRAIN_TYPE_MAX; outer++) {
40
+ for (inner = 0; inner < DRAIN_TYPE_MAX; inner++) {
41
+ /* XXX bdrv_drain_all() doesn't increase the quiesce_counter */
42
+ int bs_quiesce = (outer != BDRV_DRAIN_ALL) +
43
+ (inner != BDRV_DRAIN_ALL);
44
+ int backing_quiesce = 0;
45
+ int backing_cb_cnt = (outer != BDRV_DRAIN) +
46
+ (inner != BDRV_DRAIN);
47
+
48
+ g_assert_cmpint(bs->quiesce_counter, ==, 0);
49
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
50
+ g_assert_cmpint(s->drain_count, ==, 0);
51
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
52
+
53
+ do_drain_begin(outer, bs);
54
+ do_drain_begin(inner, bs);
55
+
56
+ g_assert_cmpint(bs->quiesce_counter, ==, bs_quiesce);
57
+ g_assert_cmpint(backing->quiesce_counter, ==, backing_quiesce);
58
+ g_assert_cmpint(s->drain_count, ==, 2);
59
+ g_assert_cmpint(backing_s->drain_count, ==, backing_cb_cnt);
60
+
61
+ do_drain_end(inner, bs);
62
+ do_drain_end(outer, bs);
63
+
64
+ g_assert_cmpint(bs->quiesce_counter, ==, 0);
65
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
66
+ g_assert_cmpint(s->drain_count, ==, 0);
67
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
68
+ }
69
+ }
70
+
71
+ bdrv_unref(backing);
72
+ bdrv_unref(bs);
73
+ blk_unref(blk);
74
+}
75
+
76
77
typedef struct TestBlockJob {
78
BlockJob common;
79
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
80
g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
81
g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
82
83
+ g_test_add_func("/bdrv-drain/nested", test_nested);
84
+
85
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
86
g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
87
88
--
89
2.13.6
90
91
diff view generated by jsdifflib
New patch
1
1
This is in preparation for subtree drains, i.e. drained sections that
2
affect not only a single node, but recursively all child nodes, too.
3
4
Calling the parent callbacks for drain is pointless when we just came
5
from that parent node recursively and leads to multiple increases of
6
bs->quiesce_counter in a single drain call. Don't do it.
7
8
In order for this to work correctly, the parent callback must be called
9
for every bdrv_drain_begin/end() call, not only for the outermost one:
10
11
If we have a node N with two parents A and B, recursive draining of A
12
should cause the quiesce_counter of B to increase because its child N is
13
drained independently of B. If now B is recursively drained, too, A must
14
increase its quiesce_counter because N is drained independently of A
15
only now, even if N is going from quiesce_counter 1 to 2.
16
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
include/block/block.h | 4 ++--
20
block.c | 13 +++++++++----
21
block/io.c | 47 ++++++++++++++++++++++++++++++++++-------------
22
3 files changed, 45 insertions(+), 19 deletions(-)
23
24
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
27
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ void bdrv_io_unplug(BlockDriverState *bs);
29
* Begin a quiesced section of all users of @bs. This is part of
30
* bdrv_drained_begin.
31
*/
32
-void bdrv_parent_drained_begin(BlockDriverState *bs);
33
+void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore);
34
35
/**
36
* bdrv_parent_drained_end:
37
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin(BlockDriverState *bs);
38
* End a quiesced section of all users of @bs. This is part of
39
* bdrv_drained_end.
40
*/
41
-void bdrv_parent_drained_end(BlockDriverState *bs);
42
+void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore);
43
44
/**
45
* bdrv_drained_begin:
46
diff --git a/block.c b/block.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block.c
49
+++ b/block.c
50
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
51
BlockDriverState *new_bs)
52
{
53
BlockDriverState *old_bs = child->bs;
54
+ int i;
55
56
if (old_bs && new_bs) {
57
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
58
}
59
if (old_bs) {
60
if (old_bs->quiesce_counter && child->role->drained_end) {
61
- child->role->drained_end(child);
62
+ for (i = 0; i < old_bs->quiesce_counter; i++) {
63
+ child->role->drained_end(child);
64
+ }
65
}
66
if (child->role->detach) {
67
child->role->detach(child);
68
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
69
if (new_bs) {
70
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
71
if (new_bs->quiesce_counter && child->role->drained_begin) {
72
- child->role->drained_begin(child);
73
+ for (i = 0; i < new_bs->quiesce_counter; i++) {
74
+ child->role->drained_begin(child);
75
+ }
76
}
77
78
if (child->role->attach) {
79
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
80
AioContext *ctx = bdrv_get_aio_context(bs);
81
82
aio_disable_external(ctx);
83
- bdrv_parent_drained_begin(bs);
84
+ bdrv_parent_drained_begin(bs, NULL);
85
bdrv_drain(bs); /* ensure there are no in-flight requests */
86
87
while (aio_poll(ctx, false)) {
88
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
89
*/
90
aio_context_acquire(new_context);
91
bdrv_attach_aio_context(bs, new_context);
92
- bdrv_parent_drained_end(bs);
93
+ bdrv_parent_drained_end(bs, NULL);
94
aio_enable_external(ctx);
95
aio_context_release(new_context);
96
}
97
diff --git a/block/io.c b/block/io.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/block/io.c
100
+++ b/block/io.c
101
@@ -XXX,XX +XXX,XX @@
102
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
103
int64_t offset, int bytes, BdrvRequestFlags flags);
104
105
-void bdrv_parent_drained_begin(BlockDriverState *bs)
106
+void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
107
{
108
BdrvChild *c, *next;
109
110
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
111
+ if (c == ignore) {
112
+ continue;
113
+ }
114
if (c->role->drained_begin) {
115
c->role->drained_begin(c);
116
}
117
}
118
}
119
120
-void bdrv_parent_drained_end(BlockDriverState *bs)
121
+void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
122
{
123
BdrvChild *c, *next;
124
125
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
126
+ if (c == ignore) {
127
+ continue;
128
+ }
129
if (c->role->drained_end) {
130
c->role->drained_end(c);
131
}
132
@@ -XXX,XX +XXX,XX @@ typedef struct {
133
BlockDriverState *bs;
134
bool done;
135
bool begin;
136
+ BdrvChild *parent;
137
} BdrvCoDrainData;
138
139
static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
140
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_recurse(BlockDriverState *bs)
141
return waited;
142
}
143
144
+static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent);
145
+static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent);
146
+
147
static void bdrv_co_drain_bh_cb(void *opaque)
148
{
149
BdrvCoDrainData *data = opaque;
150
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_drain_bh_cb(void *opaque)
151
152
bdrv_dec_in_flight(bs);
153
if (data->begin) {
154
- bdrv_drained_begin(bs);
155
+ bdrv_do_drained_begin(bs, data->parent);
156
} else {
157
- bdrv_drained_end(bs);
158
+ bdrv_do_drained_end(bs, data->parent);
159
}
160
161
data->done = true;
162
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_drain_bh_cb(void *opaque)
163
}
164
165
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
166
- bool begin)
167
+ bool begin, BdrvChild *parent)
168
{
169
BdrvCoDrainData data;
170
171
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
172
.bs = bs,
173
.done = false,
174
.begin = begin,
175
+ .parent = parent,
176
};
177
bdrv_inc_in_flight(bs);
178
aio_bh_schedule_oneshot(bdrv_get_aio_context(bs),
179
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
180
assert(data.done);
181
}
182
183
-void bdrv_drained_begin(BlockDriverState *bs)
184
+static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent)
185
{
186
if (qemu_in_coroutine()) {
187
- bdrv_co_yield_to_drain(bs, true);
188
+ bdrv_co_yield_to_drain(bs, true, parent);
189
return;
190
}
191
192
/* Stop things in parent-to-child order */
193
if (atomic_fetch_inc(&bs->quiesce_counter) == 0) {
194
aio_disable_external(bdrv_get_aio_context(bs));
195
- bdrv_parent_drained_begin(bs);
196
}
197
198
+ bdrv_parent_drained_begin(bs, parent);
199
bdrv_drain_invoke(bs, true, false);
200
bdrv_drain_recurse(bs);
201
}
202
203
-void bdrv_drained_end(BlockDriverState *bs)
204
+void bdrv_drained_begin(BlockDriverState *bs)
205
+{
206
+ bdrv_do_drained_begin(bs, NULL);
207
+}
208
+
209
+static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
210
{
211
int old_quiesce_counter;
212
213
if (qemu_in_coroutine()) {
214
- bdrv_co_yield_to_drain(bs, false);
215
+ bdrv_co_yield_to_drain(bs, false, parent);
216
return;
217
}
218
assert(bs->quiesce_counter > 0);
219
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_end(BlockDriverState *bs)
220
221
/* Re-enable things in child-to-parent order */
222
bdrv_drain_invoke(bs, false, false);
223
+ bdrv_parent_drained_end(bs, parent);
224
if (old_quiesce_counter == 1) {
225
- bdrv_parent_drained_end(bs);
226
aio_enable_external(bdrv_get_aio_context(bs));
227
}
228
}
229
230
+void bdrv_drained_end(BlockDriverState *bs)
231
+{
232
+ bdrv_do_drained_end(bs, NULL);
233
+}
234
+
235
/*
236
* Wait for pending requests to complete on a single BlockDriverState subtree,
237
* and suspend block driver's internal I/O until next request arrives.
238
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
239
/* Stop things in parent-to-child order */
240
aio_context_acquire(aio_context);
241
aio_disable_external(aio_context);
242
- bdrv_parent_drained_begin(bs);
243
+ bdrv_parent_drained_begin(bs, NULL);
244
bdrv_drain_invoke(bs, true, true);
245
aio_context_release(aio_context);
246
247
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
248
/* Re-enable things in child-to-parent order */
249
aio_context_acquire(aio_context);
250
bdrv_drain_invoke(bs, false, true);
251
- bdrv_parent_drained_end(bs);
252
+ bdrv_parent_drained_end(bs, NULL);
253
aio_enable_external(aio_context);
254
aio_context_release(aio_context);
255
}
256
--
257
2.13.6
258
259
diff view generated by jsdifflib
1
Currently, blk_is_read_only() tells whether a given BlockBackend can
1
bdrv_drained_begin() waits for the completion of requests in the whole
2
only be used in read-only mode because its root node is read-only. Some
2
subtree, but it only actually keeps its immediate bs parameter quiesced
3
callers actually try to answer a slightly different question: Is the
3
until bdrv_drained_end().
4
BlockBackend configured to be writable, by taking write permissions on
5
the root node?
6
4
7
This can differ, for example, for CD-ROM devices which don't take write
5
Add a version that keeps the whole subtree drained. As of this commit,
8
permissions, but may be backed by a writable image file. scsi-cd allows
6
graph changes cannot be allowed during a subtree drained section, but
9
write requests to the drive if blk_is_read_only() returns false.
7
this will be fixed soon.
10
However, the write request will immediately run into an assertion
11
failure because the write permission is missing.
12
8
13
This patch introduces separate functions for both questions.
14
blk_supports_write_perm() answers the question whether the block
15
node/image file can support writable devices, whereas blk_is_writable()
16
tells whether the BlockBackend is currently configured to be writable.
17
18
All calls of blk_is_read_only() are converted to one of the two new
19
functions.
20
21
Fixes: https://bugs.launchpad.net/bugs/1906693
22
Cc: qemu-stable@nongnu.org
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Message-Id: <20210118123448.307825-2-kwolf@redhat.com>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26
Reviewed-by: Max Reitz <mreitz@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
---
10
---
29
include/sysemu/block-backend.h | 3 ++-
11
include/block/block.h | 13 +++++++++++++
30
block/block-backend.c | 19 ++++++++++++++++---
12
block/io.c | 54 ++++++++++++++++++++++++++++++++++++++++-----------
31
hw/block/dataplane/xen-block.c | 2 +-
13
2 files changed, 56 insertions(+), 11 deletions(-)
32
hw/block/fdc.c | 9 +++++----
33
hw/block/m25p80.c | 6 +++---
34
hw/block/nand.c | 2 +-
35
hw/block/nvme-ns.c | 7 ++++---
36
hw/block/onenand.c | 2 +-
37
hw/block/pflash_cfi01.c | 2 +-
38
hw/block/pflash_cfi02.c | 2 +-
39
hw/block/swim.c | 6 +++---
40
hw/block/virtio-blk.c | 6 +++---
41
hw/block/xen-block.c | 2 +-
42
hw/ide/core.c | 2 +-
43
hw/misc/sifive_u_otp.c | 2 +-
44
hw/ppc/pnv_pnor.c | 2 +-
45
hw/scsi/scsi-disk.c | 10 +++++-----
46
hw/scsi/scsi-generic.c | 4 ++--
47
hw/sd/sd.c | 6 +++---
48
hw/usb/dev-storage.c | 4 ++--
49
20 files changed, 57 insertions(+), 41 deletions(-)
50
14
51
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
15
diff --git a/include/block/block.h b/include/block/block.h
52
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
53
--- a/include/sysemu/block-backend.h
17
--- a/include/block/block.h
54
+++ b/include/sysemu/block-backend.h
18
+++ b/include/block/block.h
55
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
19
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore);
56
int error);
20
void bdrv_drained_begin(BlockDriverState *bs);
57
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
21
58
bool is_read, int error);
22
/**
59
-bool blk_is_read_only(BlockBackend *blk);
23
+ * Like bdrv_drained_begin, but recursively begins a quiesced section for
60
+bool blk_supports_write_perm(BlockBackend *blk);
24
+ * exclusive access to all child nodes as well.
61
+bool blk_is_writable(BlockBackend *blk);
25
+ *
62
bool blk_is_sg(BlockBackend *blk);
26
+ * Graph changes are not allowed during a subtree drain section.
63
bool blk_enable_write_cache(BlockBackend *blk);
27
+ */
64
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
28
+void bdrv_subtree_drained_begin(BlockDriverState *bs);
65
diff --git a/block/block-backend.c b/block/block-backend.c
29
+
30
+/**
31
* bdrv_drained_end:
32
*
33
* End a quiescent section started by bdrv_drained_begin().
34
*/
35
void bdrv_drained_end(BlockDriverState *bs);
36
37
+/**
38
+ * End a quiescent section started by bdrv_subtree_drained_begin().
39
+ */
40
+void bdrv_subtree_drained_end(BlockDriverState *bs);
41
+
42
void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child,
43
Error **errp);
44
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
45
diff --git a/block/io.c b/block/io.c
66
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
67
--- a/block/block-backend.c
47
--- a/block/io.c
68
+++ b/block/block-backend.c
48
+++ b/block/io.c
69
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
49
@@ -XXX,XX +XXX,XX @@ typedef struct {
50
BlockDriverState *bs;
51
bool done;
52
bool begin;
53
+ bool recursive;
54
BdrvChild *parent;
55
} BdrvCoDrainData;
56
57
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_recurse(BlockDriverState *bs)
58
return waited;
59
}
60
61
-static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent);
62
-static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent);
63
+static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
64
+ BdrvChild *parent);
65
+static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
66
+ BdrvChild *parent);
67
68
static void bdrv_co_drain_bh_cb(void *opaque)
69
{
70
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_drain_bh_cb(void *opaque)
71
72
bdrv_dec_in_flight(bs);
73
if (data->begin) {
74
- bdrv_do_drained_begin(bs, data->parent);
75
+ bdrv_do_drained_begin(bs, data->recursive, data->parent);
76
} else {
77
- bdrv_do_drained_end(bs, data->parent);
78
+ bdrv_do_drained_end(bs, data->recursive, data->parent);
70
}
79
}
80
81
data->done = true;
82
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_drain_bh_cb(void *opaque)
71
}
83
}
72
84
73
-bool blk_is_read_only(BlockBackend *blk)
85
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
74
+/*
86
- bool begin, BdrvChild *parent)
75
+ * Returns true if the BlockBackend can support taking write permissions
87
+ bool begin, bool recursive,
76
+ * (because its root node is not read-only).
88
+ BdrvChild *parent)
77
+ */
78
+bool blk_supports_write_perm(BlockBackend *blk)
79
{
89
{
80
BlockDriverState *bs = blk_bs(blk);
90
BdrvCoDrainData data;
81
91
82
if (bs) {
92
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
83
- return bdrv_is_read_only(bs);
93
.bs = bs,
84
+ return !bdrv_is_read_only(bs);
94
.done = false,
85
} else {
95
.begin = begin,
86
- return blk->root_state.read_only;
96
+ .recursive = recursive,
87
+ return !blk->root_state.read_only;
97
.parent = parent,
98
};
99
bdrv_inc_in_flight(bs);
100
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
101
assert(data.done);
102
}
103
104
-static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent)
105
+static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
106
+ BdrvChild *parent)
107
{
108
+ BdrvChild *child, *next;
109
+
110
if (qemu_in_coroutine()) {
111
- bdrv_co_yield_to_drain(bs, true, parent);
112
+ bdrv_co_yield_to_drain(bs, true, recursive, parent);
113
return;
88
}
114
}
115
116
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent)
117
bdrv_parent_drained_begin(bs, parent);
118
bdrv_drain_invoke(bs, true, false);
119
bdrv_drain_recurse(bs);
120
+
121
+ if (recursive) {
122
+ QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
123
+ bdrv_do_drained_begin(child->bs, true, child);
124
+ }
125
+ }
89
}
126
}
90
127
91
+/*
128
void bdrv_drained_begin(BlockDriverState *bs)
92
+ * Returns true if the BlockBackend can be written to in its current
129
{
93
+ * configuration (i.e. if write permission have been requested)
130
- bdrv_do_drained_begin(bs, NULL);
94
+ */
131
+ bdrv_do_drained_begin(bs, false, NULL);
95
+bool blk_is_writable(BlockBackend *blk)
96
+{
97
+ return blk->perm & BLK_PERM_WRITE;
98
+}
132
+}
99
+
133
+
100
bool blk_is_sg(BlockBackend *blk)
134
+void bdrv_subtree_drained_begin(BlockDriverState *bs)
135
+{
136
+ bdrv_do_drained_begin(bs, true, NULL);
137
}
138
139
-static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
140
+static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
141
+ BdrvChild *parent)
101
{
142
{
102
BlockDriverState *bs = blk_bs(blk);
143
+ BdrvChild *child, *next;
103
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
144
int old_quiesce_counter;
104
index XXXXXXX..XXXXXXX 100644
145
105
--- a/hw/block/dataplane/xen-block.c
146
if (qemu_in_coroutine()) {
106
+++ b/hw/block/dataplane/xen-block.c
147
- bdrv_co_yield_to_drain(bs, false, parent);
107
@@ -XXX,XX +XXX,XX @@ static int xen_block_parse_request(XenBlockRequest *request)
148
+ bdrv_co_yield_to_drain(bs, false, recursive, parent);
108
};
109
110
if (request->req.operation != BLKIF_OP_READ &&
111
- blk_is_read_only(dataplane->blk)) {
112
+ !blk_is_writable(dataplane->blk)) {
113
error_report("error: write req for ro device");
114
goto err;
115
}
116
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/block/fdc.c
119
+++ b/hw/block/fdc.c
120
@@ -XXX,XX +XXX,XX @@ static void fd_revalidate(FDrive *drv)
121
122
FLOPPY_DPRINTF("revalidate\n");
123
if (drv->blk != NULL) {
124
- drv->ro = blk_is_read_only(drv->blk);
125
+ drv->ro = !blk_is_writable(drv->blk);
126
if (!blk_is_inserted(drv->blk)) {
127
FLOPPY_DPRINTF("No disk in drive\n");
128
drv->disk = FLOPPY_DRIVE_TYPE_NONE;
129
@@ -XXX,XX +XXX,XX @@ static void fd_change_cb(void *opaque, bool load, Error **errp)
130
blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
131
} else {
132
if (!blkconf_apply_backend_options(drive->conf,
133
- blk_is_read_only(drive->blk), false,
134
- errp)) {
135
+ !blk_supports_write_perm(drive->blk),
136
+ false, errp)) {
137
return;
138
}
139
}
140
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
141
* read-only node later */
142
read_only = true;
143
} else {
144
- read_only = !blk_bs(dev->conf.blk) || blk_is_read_only(dev->conf.blk);
145
+ read_only = !blk_bs(dev->conf.blk) ||
146
+ !blk_supports_write_perm(dev->conf.blk);
147
}
148
149
if (!blkconf_blocksizes(&dev->conf, errp)) {
150
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/hw/block/m25p80.c
153
+++ b/hw/block/m25p80.c
154
@@ -XXX,XX +XXX,XX @@ static void flash_sync_page(Flash *s, int page)
155
{
156
QEMUIOVector *iov;
157
158
- if (!s->blk || blk_is_read_only(s->blk)) {
159
+ if (!s->blk || !blk_is_writable(s->blk)) {
160
return;
149
return;
161
}
150
}
162
151
assert(bs->quiesce_counter > 0);
163
@@ -XXX,XX +XXX,XX @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
152
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
153
if (old_quiesce_counter == 1) {
154
aio_enable_external(bdrv_get_aio_context(bs));
155
}
156
+
157
+ if (recursive) {
158
+ QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
159
+ bdrv_do_drained_end(child->bs, true, child);
160
+ }
161
+ }
162
}
163
164
void bdrv_drained_end(BlockDriverState *bs)
164
{
165
{
165
QEMUIOVector *iov;
166
- bdrv_do_drained_end(bs, NULL);
166
167
+ bdrv_do_drained_end(bs, false, NULL);
167
- if (!s->blk || blk_is_read_only(s->blk)) {
168
+}
168
+ if (!s->blk || !blk_is_writable(s->blk)) {
169
return;
170
}
171
172
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSIPeripheral *ss, Error **errp)
173
174
if (s->blk) {
175
uint64_t perm = BLK_PERM_CONSISTENT_READ |
176
- (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
177
+ (blk_supports_write_perm(s->blk) ? BLK_PERM_WRITE : 0);
178
ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
179
if (ret < 0) {
180
return;
181
diff --git a/hw/block/nand.c b/hw/block/nand.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/hw/block/nand.c
184
+++ b/hw/block/nand.c
185
@@ -XXX,XX +XXX,XX @@ static void nand_realize(DeviceState *dev, Error **errp)
186
pagesize = 1 << s->oob_shift;
187
s->mem_oob = 1;
188
if (s->blk) {
189
- if (blk_is_read_only(s->blk)) {
190
+ if (!blk_supports_write_perm(s->blk)) {
191
error_setg(errp, "Can't use a read-only drive");
192
return;
193
}
194
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/hw/block/nvme-ns.c
197
+++ b/hw/block/nvme-ns.c
198
@@ -XXX,XX +XXX,XX @@ static void nvme_ns_init(NvmeNamespace *ns)
199
200
static int nvme_ns_init_blk(NvmeCtrl *n, NvmeNamespace *ns, Error **errp)
201
{
202
+ bool read_only;
203
+
169
+
204
if (!blkconf_blocksizes(&ns->blkconf, errp)) {
170
+void bdrv_subtree_drained_end(BlockDriverState *bs)
205
return -1;
171
+{
206
}
172
+ bdrv_do_drained_end(bs, true, NULL);
207
208
- if (!blkconf_apply_backend_options(&ns->blkconf,
209
- blk_is_read_only(ns->blkconf.blk),
210
- false, errp)) {
211
+ read_only = !blk_supports_write_perm(ns->blkconf.blk);
212
+ if (!blkconf_apply_backend_options(&ns->blkconf, read_only, false, errp)) {
213
return -1;
214
}
215
216
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
217
index XXXXXXX..XXXXXXX 100644
218
--- a/hw/block/onenand.c
219
+++ b/hw/block/onenand.c
220
@@ -XXX,XX +XXX,XX @@ static void onenand_realize(DeviceState *dev, Error **errp)
221
s->image = memset(g_malloc(size + (size >> 5)),
222
0xff, size + (size >> 5));
223
} else {
224
- if (blk_is_read_only(s->blk)) {
225
+ if (!blk_supports_write_perm(s->blk)) {
226
error_setg(errp, "Can't use a read-only drive");
227
return;
228
}
229
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/hw/block/pflash_cfi01.c
232
+++ b/hw/block/pflash_cfi01.c
233
@@ -XXX,XX +XXX,XX @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
234
235
if (pfl->blk) {
236
uint64_t perm;
237
- pfl->ro = blk_is_read_only(pfl->blk);
238
+ pfl->ro = !blk_supports_write_perm(pfl->blk);
239
perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
240
ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
241
if (ret < 0) {
242
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/hw/block/pflash_cfi02.c
245
+++ b/hw/block/pflash_cfi02.c
246
@@ -XXX,XX +XXX,XX @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
247
248
if (pfl->blk) {
249
uint64_t perm;
250
- pfl->ro = blk_is_read_only(pfl->blk);
251
+ pfl->ro = !blk_supports_write_perm(pfl->blk);
252
perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
253
ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
254
if (ret < 0) {
255
diff --git a/hw/block/swim.c b/hw/block/swim.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/hw/block/swim.c
258
+++ b/hw/block/swim.c
259
@@ -XXX,XX +XXX,XX @@ static void swim_change_cb(void *opaque, bool load, Error **errp)
260
blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
261
} else {
262
if (!blkconf_apply_backend_options(drive->conf,
263
- blk_is_read_only(drive->blk), false,
264
- errp)) {
265
+ !blk_supports_write_perm(drive->blk),
266
+ false, errp)) {
267
return;
268
}
269
}
270
@@ -XXX,XX +XXX,XX @@ static void swim_drive_realize(DeviceState *qdev, Error **errp)
271
dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO;
272
273
if (!blkconf_apply_backend_options(&dev->conf,
274
- blk_is_read_only(dev->conf.blk),
275
+ !blk_supports_write_perm(dev->conf.blk),
276
false, errp)) {
277
return;
278
}
279
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/hw/block/virtio-blk.c
282
+++ b/hw/block/virtio-blk.c
283
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
284
virtio_has_feature(features, VIRTIO_BLK_F_CONFIG_WCE))) {
285
virtio_add_feature(&features, VIRTIO_BLK_F_WCE);
286
}
287
- if (blk_is_read_only(s->blk)) {
288
+ if (!blk_is_writable(s->blk)) {
289
virtio_add_feature(&features, VIRTIO_BLK_F_RO);
290
}
291
if (s->conf.num_queues > 1) {
292
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
293
}
294
295
if (!blkconf_apply_backend_options(&conf->conf,
296
- blk_is_read_only(conf->conf.blk), true,
297
- errp)) {
298
+ !blk_supports_write_perm(conf->conf.blk),
299
+ true, errp)) {
300
return;
301
}
302
s->original_wce = blk_enable_write_cache(conf->conf.blk);
303
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/hw/block/xen-block.c
306
+++ b/hw/block/xen-block.c
307
@@ -XXX,XX +XXX,XX @@ static void xen_disk_realize(XenBlockDevice *blockdev, Error **errp)
308
return;
309
}
310
311
- blockdev->info = blk_is_read_only(conf->blk) ? VDISK_READONLY : 0;
312
+ blockdev->info = blk_supports_write_perm(conf->blk) ? 0 : VDISK_READONLY;
313
}
173
}
314
174
315
static void xen_disk_class_init(ObjectClass *class, void *data)
175
/*
316
diff --git a/hw/ide/core.c b/hw/ide/core.c
317
index XXXXXXX..XXXXXXX 100644
318
--- a/hw/ide/core.c
319
+++ b/hw/ide/core.c
320
@@ -XXX,XX +XXX,XX @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
321
error_setg(errp, "Device needs media, but drive is empty");
322
return -1;
323
}
324
- if (blk_is_read_only(blk)) {
325
+ if (!blk_is_writable(blk)) {
326
error_setg(errp, "Can't use a read-only drive");
327
return -1;
328
}
329
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
330
index XXXXXXX..XXXXXXX 100644
331
--- a/hw/misc/sifive_u_otp.c
332
+++ b/hw/misc/sifive_u_otp.c
333
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
334
335
if (s->blk) {
336
perm = BLK_PERM_CONSISTENT_READ |
337
- (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
338
+ (blk_supports_write_perm(s->blk) ? BLK_PERM_WRITE : 0);
339
ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
340
if (ret < 0) {
341
return;
342
diff --git a/hw/ppc/pnv_pnor.c b/hw/ppc/pnv_pnor.c
343
index XXXXXXX..XXXXXXX 100644
344
--- a/hw/ppc/pnv_pnor.c
345
+++ b/hw/ppc/pnv_pnor.c
346
@@ -XXX,XX +XXX,XX @@ static void pnv_pnor_realize(DeviceState *dev, Error **errp)
347
348
if (s->blk) {
349
uint64_t perm = BLK_PERM_CONSISTENT_READ |
350
- (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
351
+ (blk_supports_write_perm(s->blk) ? BLK_PERM_WRITE : 0);
352
ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
353
if (ret < 0) {
354
return;
355
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
356
index XXXXXXX..XXXXXXX 100644
357
--- a/hw/scsi/scsi-disk.c
358
+++ b/hw/scsi/scsi-disk.c
359
@@ -XXX,XX +XXX,XX @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
360
361
if (s->qdev.type == TYPE_DISK) {
362
dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;
363
- if (blk_is_read_only(s->qdev.conf.blk)) {
364
+ if (!blk_is_writable(s->qdev.conf.blk)) {
365
dev_specific_param |= 0x80; /* Readonly. */
366
}
367
} else {
368
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
369
goto invalid_param_len;
370
}
371
372
- if (blk_is_read_only(s->qdev.conf.blk)) {
373
+ if (!blk_is_writable(s->qdev.conf.blk)) {
374
block_acct_invalid(blk_get_stats(s->qdev.conf.blk), BLOCK_ACCT_UNMAP);
375
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
376
return;
377
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
378
return;
379
}
380
381
- if (blk_is_read_only(s->qdev.conf.blk)) {
382
+ if (!blk_is_writable(s->qdev.conf.blk)) {
383
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
384
return;
385
}
386
@@ -XXX,XX +XXX,XX @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
387
case WRITE_VERIFY_10:
388
case WRITE_VERIFY_12:
389
case WRITE_VERIFY_16:
390
- if (blk_is_read_only(s->qdev.conf.blk)) {
391
+ if (!blk_is_writable(s->qdev.conf.blk)) {
392
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
393
return 0;
394
}
395
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
396
}
397
}
398
399
- read_only = blk_is_read_only(s->qdev.conf.blk);
400
+ read_only = !blk_supports_write_perm(s->qdev.conf.blk);
401
if (dev->type == TYPE_ROM) {
402
read_only = true;
403
}
404
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
405
index XXXXXXX..XXXXXXX 100644
406
--- a/hw/scsi/scsi-generic.c
407
+++ b/hw/scsi/scsi-generic.c
408
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
409
* readonly.
410
*/
411
if ((s->type == TYPE_DISK || s->type == TYPE_TAPE || s->type == TYPE_ZBC) &&
412
- blk_is_read_only(s->conf.blk) &&
413
+ !blk_is_writable(s->conf.blk) &&
414
(r->req.cmd.buf[0] == MODE_SENSE ||
415
r->req.cmd.buf[0] == MODE_SENSE_10) &&
416
(r->req.cmd.buf[1] & 0x8) == 0) {
417
@@ -XXX,XX +XXX,XX @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
418
return;
419
}
420
if (!blkconf_apply_backend_options(&s->conf,
421
- blk_is_read_only(s->conf.blk),
422
+ !blk_supports_write_perm(s->conf.blk),
423
true, errp)) {
424
return;
425
}
426
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
427
index XXXXXXX..XXXXXXX 100644
428
--- a/hw/sd/sd.c
429
+++ b/hw/sd/sd.c
430
@@ -XXX,XX +XXX,XX @@ static void sd_reset(DeviceState *dev)
431
sd_set_sdstatus(sd);
432
433
g_free(sd->wp_groups);
434
- sd->wp_switch = sd->blk ? blk_is_read_only(sd->blk) : false;
435
+ sd->wp_switch = sd->blk ? !blk_is_writable(sd->blk) : false;
436
sd->wpgrps_size = sect;
437
sd->wp_groups = bitmap_new(sd->wpgrps_size);
438
memset(sd->function_group, 0, sizeof(sd->function_group));
439
@@ -XXX,XX +XXX,XX @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
440
{
441
sd->readonly_cb = readonly;
442
sd->inserted_cb = insert;
443
- qemu_set_irq(readonly, sd->blk ? blk_is_read_only(sd->blk) : 0);
444
+ qemu_set_irq(readonly, sd->blk ? !blk_is_writable(sd->blk) : 0);
445
qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0);
446
}
447
448
@@ -XXX,XX +XXX,XX @@ static void sd_realize(DeviceState *dev, Error **errp)
449
if (sd->blk) {
450
int64_t blk_size;
451
452
- if (blk_is_read_only(sd->blk)) {
453
+ if (!blk_supports_write_perm(sd->blk)) {
454
error_setg(errp, "Cannot use read-only drive as SD card");
455
return;
456
}
457
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
458
index XXXXXXX..XXXXXXX 100644
459
--- a/hw/usb/dev-storage.c
460
+++ b/hw/usb/dev-storage.c
461
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
462
return;
463
}
464
465
- if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
466
- errp)) {
467
+ if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk),
468
+ true, errp)) {
469
return;
470
}
471
472
--
176
--
473
2.29.2
177
2.13.6
474
178
475
179
diff view generated by jsdifflib
1
This tests that trying to write to a (read-only) scsi-cd device backed
1
Add a subtree drain version to the existing test cases.
2
by a read-write image file doesn't crash and results in the correct
3
error.
4
5
This is a regression test for https://bugs.launchpad.net/bugs/1906693.
6
2
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20210118123448.307825-3-kwolf@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
4
---
13
tests/qtest/virtio-scsi-test.c | 39 ++++++++++++++++++++++++++++++++++
5
tests/test-bdrv-drain.c | 27 ++++++++++++++++++++++++++-
14
1 file changed, 39 insertions(+)
6
1 file changed, 26 insertions(+), 1 deletion(-)
15
7
16
diff --git a/tests/qtest/virtio-scsi-test.c b/tests/qtest/virtio-scsi-test.c
8
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
17
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qtest/virtio-scsi-test.c
10
--- a/tests/test-bdrv-drain.c
19
+++ b/tests/qtest/virtio-scsi-test.c
11
+++ b/tests/test-bdrv-drain.c
20
@@ -XXX,XX +XXX,XX @@ static void test_unaligned_write_same(void *obj, void *data,
12
@@ -XXX,XX +XXX,XX @@ static void aio_ret_cb(void *opaque, int ret)
21
qvirtio_scsi_pci_free(vs);
13
enum drain_type {
14
BDRV_DRAIN_ALL,
15
BDRV_DRAIN,
16
+ BDRV_SUBTREE_DRAIN,
17
DRAIN_TYPE_MAX,
18
};
19
20
@@ -XXX,XX +XXX,XX @@ static void do_drain_begin(enum drain_type drain_type, BlockDriverState *bs)
21
switch (drain_type) {
22
case BDRV_DRAIN_ALL: bdrv_drain_all_begin(); break;
23
case BDRV_DRAIN: bdrv_drained_begin(bs); break;
24
+ case BDRV_SUBTREE_DRAIN: bdrv_subtree_drained_begin(bs); break;
25
default: g_assert_not_reached();
26
}
22
}
27
}
23
28
@@ -XXX,XX +XXX,XX @@ static void do_drain_end(enum drain_type drain_type, BlockDriverState *bs)
24
+static void test_write_to_cdrom(void *obj, void *data,
29
switch (drain_type) {
25
+ QGuestAllocator *t_alloc)
30
case BDRV_DRAIN_ALL: bdrv_drain_all_end(); break;
31
case BDRV_DRAIN: bdrv_drained_end(bs); break;
32
+ case BDRV_SUBTREE_DRAIN: bdrv_subtree_drained_end(bs); break;
33
default: g_assert_not_reached();
34
}
35
}
36
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_drain(void)
37
test_drv_cb_common(BDRV_DRAIN, false);
38
}
39
40
+static void test_drv_cb_drain_subtree(void)
26
+{
41
+{
27
+ QVirtioSCSI *scsi = obj;
42
+ test_drv_cb_common(BDRV_SUBTREE_DRAIN, true);
28
+ QVirtioSCSIQueues *vs;
29
+ uint8_t buf[2048] = { 0 };
30
+ const uint8_t write_cdb[VIRTIO_SCSI_CDB_SIZE] = {
31
+ /* WRITE(10) to LBA 0, transfer length 1 */
32
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
33
+ };
34
+ struct virtio_scsi_cmd_resp resp;
35
+
36
+ alloc = t_alloc;
37
+ vs = qvirtio_scsi_init(scsi->vdev);
38
+
39
+ virtio_scsi_do_command(vs, write_cdb, NULL, 0, buf, 2048, &resp);
40
+ g_assert_cmphex(resp.response, ==, 0);
41
+ g_assert_cmphex(resp.status, ==, CHECK_CONDITION);
42
+ g_assert_cmphex(resp.sense[0], ==, 0x70);
43
+ g_assert_cmphex(resp.sense[2], ==, DATA_PROTECT);
44
+ g_assert_cmphex(resp.sense[12], ==, 0x27); /* WRITE PROTECTED */
45
+ g_assert_cmphex(resp.sense[13], ==, 0x00); /* WRITE PROTECTED */
46
+
47
+ qvirtio_scsi_pci_free(vs);
48
+}
43
+}
49
+
44
+
50
static void test_iothread_attach_node(void *obj, void *data,
45
static void test_quiesce_common(enum drain_type drain_type, bool recursive)
51
QGuestAllocator *t_alloc)
52
{
46
{
53
@@ -XXX,XX +XXX,XX @@ static void *virtio_scsi_setup(GString *cmd_line, void *arg)
47
BlockBackend *blk;
54
return arg;
48
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_drain(void)
49
test_quiesce_common(BDRV_DRAIN, false);
55
}
50
}
56
51
57
+static void *virtio_scsi_setup_cd(GString *cmd_line, void *arg)
52
+static void test_quiesce_drain_subtree(void)
58
+{
53
+{
59
+ g_string_append(cmd_line,
54
+ test_quiesce_common(BDRV_SUBTREE_DRAIN, true);
60
+ " -drive file=null-co://,"
61
+ "file.read-zeroes=on,"
62
+ "if=none,id=dr1,format=raw "
63
+ "-device scsi-cd,drive=dr1,lun=0,scsi-id=1");
64
+ return arg;
65
+}
55
+}
66
+
56
+
67
static void *virtio_scsi_setup_iothread(GString *cmd_line, void *arg)
57
static void test_nested(void)
68
{
58
{
69
g_string_append(cmd_line,
59
BlockBackend *blk;
70
@@ -XXX,XX +XXX,XX @@ static void register_virtio_scsi_test(void)
60
@@ -XXX,XX +XXX,XX @@ static void test_nested(void)
71
qos_add_test("unaligned-write-same", "virtio-scsi",
61
/* XXX bdrv_drain_all() doesn't increase the quiesce_counter */
72
test_unaligned_write_same, &opts);
62
int bs_quiesce = (outer != BDRV_DRAIN_ALL) +
73
63
(inner != BDRV_DRAIN_ALL);
74
+ opts.before = virtio_scsi_setup_cd;
64
- int backing_quiesce = 0;
75
+ qos_add_test("write-to-cdrom", "virtio-scsi", test_write_to_cdrom, &opts);
65
+ int backing_quiesce = (outer == BDRV_SUBTREE_DRAIN) +
66
+ (inner == BDRV_SUBTREE_DRAIN);
67
int backing_cb_cnt = (outer != BDRV_DRAIN) +
68
(inner != BDRV_DRAIN);
69
70
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_drain(void)
71
test_blockjob_common(BDRV_DRAIN);
72
}
73
74
+static void test_blockjob_drain_subtree(void)
75
+{
76
+ test_blockjob_common(BDRV_SUBTREE_DRAIN);
77
+}
76
+
78
+
77
opts.before = virtio_scsi_setup_iothread;
79
int main(int argc, char **argv)
78
opts.edge = (QOSGraphEdgeOptions) {
80
{
79
.extra_device_opts = "iothread=thread0",
81
bdrv_init();
82
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
83
84
g_test_add_func("/bdrv-drain/driver-cb/drain_all", test_drv_cb_drain_all);
85
g_test_add_func("/bdrv-drain/driver-cb/drain", test_drv_cb_drain);
86
+ g_test_add_func("/bdrv-drain/driver-cb/drain_subtree",
87
+ test_drv_cb_drain_subtree);
88
89
g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
90
g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
91
+ g_test_add_func("/bdrv-drain/quiesce/drain_subtree",
92
+ test_quiesce_drain_subtree);
93
94
g_test_add_func("/bdrv-drain/nested", test_nested);
95
96
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
97
g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
98
+ g_test_add_func("/bdrv-drain/blockjob/drain_subtree",
99
+ test_blockjob_drain_subtree);
100
101
return g_test_run();
102
}
80
--
103
--
81
2.29.2
104
2.13.6
82
105
83
106
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
If bdrv_do_drained_begin/end() are called in coroutine context, they
2
first use a BH to get out of the coroutine context. Call some existing
3
tests again from a coroutine to cover this code path.
2
4
3
Add TestRunner class, which will run tests in a new python iotests
4
running framework.
5
6
There are some differences with current ./check behavior, most
7
significant are:
8
- Consider all tests self-executable, just run them, don't run python
9
by hand.
10
- Elapsed time is cached in json file
11
- Elapsed time precision increased a bit
12
- Instead of using "diff -w" which ignores all whitespace differences,
13
manually strip whitespace at line end then use python difflib, which
14
no longer ignores spacing mid-line
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <20210125185056.129513-5-vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
6
---
20
tests/qemu-iotests/testrunner.py | 367 +++++++++++++++++++++++++++++++
7
tests/test-bdrv-drain.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
21
1 file changed, 367 insertions(+)
8
1 file changed, 59 insertions(+)
22
create mode 100644 tests/qemu-iotests/testrunner.py
23
9
24
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
10
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
25
new file mode 100644
11
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX
12
--- a/tests/test-bdrv-drain.c
27
--- /dev/null
13
+++ b/tests/test-bdrv-drain.c
28
+++ b/tests/qemu-iotests/testrunner.py
14
@@ -XXX,XX +XXX,XX @@ static void aio_ret_cb(void *opaque, int ret)
29
@@ -XXX,XX +XXX,XX @@
15
*aio_ret = ret;
30
+# Class for actually running tests.
16
}
31
+#
17
32
+# Copyright (c) 2020-2021 Virtuozzo International GmbH
18
+typedef struct CallInCoroutineData {
33
+#
19
+ void (*entry)(void);
34
+# This program is free software; you can redistribute it and/or modify
20
+ bool done;
35
+# it under the terms of the GNU General Public License as published by
21
+} CallInCoroutineData;
36
+# the Free Software Foundation; either version 2 of the License, or
37
+# (at your option) any later version.
38
+#
39
+# This program is distributed in the hope that it will be useful,
40
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
41
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42
+# GNU General Public License for more details.
43
+#
44
+# You should have received a copy of the GNU General Public License
45
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
46
+#
47
+
22
+
48
+import os
23
+static coroutine_fn void call_in_coroutine_entry(void *opaque)
49
+from pathlib import Path
24
+{
50
+import datetime
25
+ CallInCoroutineData *data = opaque;
51
+import time
52
+import difflib
53
+import subprocess
54
+import contextlib
55
+import json
56
+import termios
57
+import sys
58
+from contextlib import contextmanager
59
+from typing import List, Optional, Iterator, Any, Sequence, Dict, \
60
+ ContextManager
61
+
26
+
62
+from testenv import TestEnv
27
+ data->entry();
28
+ data->done = true;
29
+}
30
+
31
+static void call_in_coroutine(void (*entry)(void))
32
+{
33
+ Coroutine *co;
34
+ CallInCoroutineData data = {
35
+ .entry = entry,
36
+ .done = false,
37
+ };
38
+
39
+ co = qemu_coroutine_create(call_in_coroutine_entry, &data);
40
+ qemu_coroutine_enter(co);
41
+ while (!data.done) {
42
+ aio_poll(qemu_get_aio_context(), true);
43
+ }
44
+}
45
+
46
enum drain_type {
47
BDRV_DRAIN_ALL,
48
BDRV_DRAIN,
49
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_drain_subtree(void)
50
test_drv_cb_common(BDRV_SUBTREE_DRAIN, true);
51
}
52
53
+static void test_drv_cb_co_drain(void)
54
+{
55
+ call_in_coroutine(test_drv_cb_drain);
56
+}
57
+
58
+static void test_drv_cb_co_drain_subtree(void)
59
+{
60
+ call_in_coroutine(test_drv_cb_drain_subtree);
61
+}
62
+
63
static void test_quiesce_common(enum drain_type drain_type, bool recursive)
64
{
65
BlockBackend *blk;
66
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_drain_subtree(void)
67
test_quiesce_common(BDRV_SUBTREE_DRAIN, true);
68
}
69
70
+static void test_quiesce_co_drain(void)
71
+{
72
+ call_in_coroutine(test_quiesce_drain);
73
+}
74
+
75
+static void test_quiesce_co_drain_subtree(void)
76
+{
77
+ call_in_coroutine(test_quiesce_drain_subtree);
78
+}
79
+
80
static void test_nested(void)
81
{
82
BlockBackend *blk;
83
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
84
g_test_add_func("/bdrv-drain/driver-cb/drain_subtree",
85
test_drv_cb_drain_subtree);
86
87
+ // XXX bdrv_drain_all() doesn't work in coroutine context
88
+ g_test_add_func("/bdrv-drain/driver-cb/co/drain", test_drv_cb_co_drain);
89
+ g_test_add_func("/bdrv-drain/driver-cb/co/drain_subtree",
90
+ test_drv_cb_co_drain_subtree);
63
+
91
+
64
+
92
+
65
+def silent_unlink(path: Path) -> None:
93
g_test_add_func("/bdrv-drain/quiesce/drain_all", test_quiesce_drain_all);
66
+ try:
94
g_test_add_func("/bdrv-drain/quiesce/drain", test_quiesce_drain);
67
+ path.unlink()
95
g_test_add_func("/bdrv-drain/quiesce/drain_subtree",
68
+ except OSError:
96
test_quiesce_drain_subtree);
69
+ pass
97
98
+ // XXX bdrv_drain_all() doesn't work in coroutine context
99
+ g_test_add_func("/bdrv-drain/quiesce/co/drain", test_quiesce_co_drain);
100
+ g_test_add_func("/bdrv-drain/quiesce/co/drain_subtree",
101
+ test_quiesce_co_drain_subtree);
70
+
102
+
71
+
103
g_test_add_func("/bdrv-drain/nested", test_nested);
72
+def file_diff(file1: str, file2: str) -> List[str]:
104
73
+ with open(file1, encoding="utf-8") as f1, \
105
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
74
+ open(file2, encoding="utf-8") as f2:
75
+ # We want to ignore spaces at line ends. There are a lot of mess about
76
+ # it in iotests.
77
+ # TODO: fix all tests to not produce extra spaces, fix all .out files
78
+ # and use strict diff here!
79
+ seq1 = [line.rstrip() for line in f1]
80
+ seq2 = [line.rstrip() for line in f2]
81
+ res = [line.rstrip()
82
+ for line in difflib.unified_diff(seq1, seq2, file1, file2)]
83
+ return res
84
+
85
+
86
+# We want to save current tty settings during test run,
87
+# since an aborting qemu call may leave things screwed up.
88
+@contextmanager
89
+def savetty() -> Iterator[None]:
90
+ isterm = sys.stdin.isatty()
91
+ if isterm:
92
+ fd = sys.stdin.fileno()
93
+ attr = termios.tcgetattr(fd)
94
+
95
+ try:
96
+ yield
97
+ finally:
98
+ if isterm:
99
+ termios.tcsetattr(fd, termios.TCSADRAIN, attr)
100
+
101
+
102
+class LastElapsedTime(ContextManager['LastElapsedTime']):
103
+ """ Cache for elapsed time for tests, to show it during new test run
104
+
105
+ It is safe to use get() at any time. To use update(), you must either
106
+ use it inside with-block or use save() after update().
107
+ """
108
+ def __init__(self, cache_file: str, env: TestEnv) -> None:
109
+ self.env = env
110
+ self.cache_file = cache_file
111
+ self.cache: Dict[str, Dict[str, Dict[str, float]]]
112
+
113
+ try:
114
+ with open(cache_file, encoding="utf-8") as f:
115
+ self.cache = json.load(f)
116
+ except (OSError, ValueError):
117
+ self.cache = {}
118
+
119
+ def get(self, test: str,
120
+ default: Optional[float] = None) -> Optional[float]:
121
+ if test not in self.cache:
122
+ return default
123
+
124
+ if self.env.imgproto not in self.cache[test]:
125
+ return default
126
+
127
+ return self.cache[test][self.env.imgproto].get(self.env.imgfmt,
128
+ default)
129
+
130
+ def update(self, test: str, elapsed: float) -> None:
131
+ d = self.cache.setdefault(test, {})
132
+ d.setdefault(self.env.imgproto, {})[self.env.imgfmt] = elapsed
133
+
134
+ def save(self) -> None:
135
+ with open(self.cache_file, 'w', encoding="utf-8") as f:
136
+ json.dump(self.cache, f)
137
+
138
+ def __enter__(self) -> 'LastElapsedTime':
139
+ return self
140
+
141
+ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
142
+ self.save()
143
+
144
+
145
+class TestResult:
146
+ def __init__(self, status: str, description: str = '',
147
+ elapsed: Optional[float] = None, diff: Sequence[str] = (),
148
+ casenotrun: str = '', interrupted: bool = False) -> None:
149
+ self.status = status
150
+ self.description = description
151
+ self.elapsed = elapsed
152
+ self.diff = diff
153
+ self.casenotrun = casenotrun
154
+ self.interrupted = interrupted
155
+
156
+
157
+class TestRunner(ContextManager['TestRunner']):
158
+ def __init__(self, env: TestEnv, makecheck: bool = False,
159
+ color: str = 'auto') -> None:
160
+ self.env = env
161
+ self.test_run_env = self.env.get_env()
162
+ self.makecheck = makecheck
163
+ self.last_elapsed = LastElapsedTime('.last-elapsed-cache', env)
164
+
165
+ assert color in ('auto', 'on', 'off')
166
+ self.color = (color == 'on') or (color == 'auto' and
167
+ sys.stdout.isatty())
168
+
169
+ self._stack: contextlib.ExitStack
170
+
171
+ def __enter__(self) -> 'TestRunner':
172
+ self._stack = contextlib.ExitStack()
173
+ self._stack.enter_context(self.env)
174
+ self._stack.enter_context(self.last_elapsed)
175
+ self._stack.enter_context(savetty())
176
+ return self
177
+
178
+ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
179
+ self._stack.close()
180
+
181
+ def test_print_one_line(self, test: str, starttime: str,
182
+ endtime: Optional[str] = None, status: str = '...',
183
+ lasttime: Optional[float] = None,
184
+ thistime: Optional[float] = None,
185
+ description: str = '',
186
+ test_field_width: Optional[int] = None,
187
+ end: str = '\n') -> None:
188
+ """ Print short test info before/after test run """
189
+ test = os.path.basename(test)
190
+
191
+ if test_field_width is None:
192
+ test_field_width = 8
193
+
194
+ if self.makecheck and status != '...':
195
+ if status and status != 'pass':
196
+ status = f' [{status}]'
197
+ else:
198
+ status = ''
199
+
200
+ print(f' TEST iotest-{self.env.imgfmt}: {test}{status}')
201
+ return
202
+
203
+ if lasttime:
204
+ lasttime_s = f' (last: {lasttime:.1f}s)'
205
+ else:
206
+ lasttime_s = ''
207
+ if thistime:
208
+ thistime_s = f'{thistime:.1f}s'
209
+ else:
210
+ thistime_s = '...'
211
+
212
+ if endtime:
213
+ endtime = f'[{endtime}]'
214
+ else:
215
+ endtime = ''
216
+
217
+ if self.color:
218
+ if status == 'pass':
219
+ col = '\033[32m'
220
+ elif status == 'fail':
221
+ col = '\033[1m\033[31m'
222
+ elif status == 'not run':
223
+ col = '\033[33m'
224
+ else:
225
+ col = ''
226
+
227
+ col_end = '\033[0m'
228
+ else:
229
+ col = ''
230
+ col_end = ''
231
+
232
+ print(f'{test:{test_field_width}} {col}{status:10}{col_end} '
233
+ f'[{starttime}] {endtime:13}{thistime_s:5} {lasttime_s:14} '
234
+ f'{description}', end=end)
235
+
236
+ def find_reference(self, test: str) -> str:
237
+ if self.env.cachemode == 'none':
238
+ ref = f'{test}.out.nocache'
239
+ if os.path.isfile(ref):
240
+ return ref
241
+
242
+ ref = f'{test}.out.{self.env.imgfmt}'
243
+ if os.path.isfile(ref):
244
+ return ref
245
+
246
+ ref = f'{test}.{self.env.qemu_default_machine}.out'
247
+ if os.path.isfile(ref):
248
+ return ref
249
+
250
+ return f'{test}.out'
251
+
252
+ def do_run_test(self, test: str) -> TestResult:
253
+ f_test = Path(test)
254
+ f_bad = Path(f_test.name + '.out.bad')
255
+ f_notrun = Path(f_test.name + '.notrun')
256
+ f_casenotrun = Path(f_test.name + '.casenotrun')
257
+ f_reference = Path(self.find_reference(test))
258
+
259
+ if not f_test.exists():
260
+ return TestResult(status='fail',
261
+ description=f'No such test file: {f_test}')
262
+
263
+ if not os.access(str(f_test), os.X_OK):
264
+ sys.exit(f'Not executable: {f_test}')
265
+
266
+ if not f_reference.exists():
267
+ return TestResult(status='not run',
268
+ description='No qualified output '
269
+ f'(expected {f_reference})')
270
+
271
+ for p in (f_bad, f_notrun, f_casenotrun):
272
+ silent_unlink(p)
273
+
274
+ args = [str(f_test.resolve())]
275
+ if self.env.debug:
276
+ args.append('-d')
277
+
278
+ with f_test.open(encoding="utf-8") as f:
279
+ try:
280
+ if f.readline() == '#!/usr/bin/env python3':
281
+ args.insert(0, self.env.python)
282
+ except UnicodeDecodeError: # binary test? for future.
283
+ pass
284
+
285
+ env = os.environ.copy()
286
+ env.update(self.test_run_env)
287
+
288
+ t0 = time.time()
289
+ with f_bad.open('w', encoding="utf-8") as f:
290
+ proc = subprocess.Popen(args, cwd=str(f_test.parent), env=env,
291
+ stdout=f, stderr=subprocess.STDOUT)
292
+ try:
293
+ proc.wait()
294
+ except KeyboardInterrupt:
295
+ proc.terminate()
296
+ proc.wait()
297
+ return TestResult(status='not run',
298
+ description='Interrupted by user',
299
+ interrupted=True)
300
+ ret = proc.returncode
301
+
302
+ elapsed = round(time.time() - t0, 1)
303
+
304
+ if ret != 0:
305
+ return TestResult(status='fail', elapsed=elapsed,
306
+ description=f'failed, exit status {ret}',
307
+ diff=file_diff(str(f_reference), str(f_bad)))
308
+
309
+ if f_notrun.exists():
310
+ return TestResult(status='not run',
311
+ description=f_notrun.read_text().strip())
312
+
313
+ casenotrun = ''
314
+ if f_casenotrun.exists():
315
+ casenotrun = f_casenotrun.read_text()
316
+
317
+ diff = file_diff(str(f_reference), str(f_bad))
318
+ if diff:
319
+ return TestResult(status='fail', elapsed=elapsed,
320
+ description=f'output mismatch (see {f_bad})',
321
+ diff=diff, casenotrun=casenotrun)
322
+ else:
323
+ f_bad.unlink()
324
+ self.last_elapsed.update(test, elapsed)
325
+ return TestResult(status='pass', elapsed=elapsed,
326
+ casenotrun=casenotrun)
327
+
328
+ def run_test(self, test: str,
329
+ test_field_width: Optional[int] = None) -> TestResult:
330
+ last_el = self.last_elapsed.get(test)
331
+ start = datetime.datetime.now().strftime('%H:%M:%S')
332
+
333
+ self.test_print_one_line(test=test, starttime=start, lasttime=last_el,
334
+ end='\r', test_field_width=test_field_width)
335
+
336
+ res = self.do_run_test(test)
337
+
338
+ end = datetime.datetime.now().strftime('%H:%M:%S')
339
+ self.test_print_one_line(test=test, status=res.status,
340
+ starttime=start, endtime=end,
341
+ lasttime=last_el, thistime=res.elapsed,
342
+ description=res.description,
343
+ test_field_width=test_field_width)
344
+
345
+ if res.casenotrun:
346
+ print(res.casenotrun)
347
+
348
+ return res
349
+
350
+ def run_tests(self, tests: List[str]) -> None:
351
+ n_run = 0
352
+ failed = []
353
+ notrun = []
354
+ casenotrun = []
355
+
356
+ if not self.makecheck:
357
+ self.env.print_env()
358
+ print()
359
+
360
+ test_field_width = max(len(os.path.basename(t)) for t in tests) + 2
361
+
362
+ for t in tests:
363
+ name = os.path.basename(t)
364
+ res = self.run_test(t, test_field_width=test_field_width)
365
+
366
+ assert res.status in ('pass', 'fail', 'not run')
367
+
368
+ if res.casenotrun:
369
+ casenotrun.append(t)
370
+
371
+ if res.status != 'not run':
372
+ n_run += 1
373
+
374
+ if res.status == 'fail':
375
+ failed.append(name)
376
+ if self.makecheck:
377
+ self.env.print_env()
378
+ if res.diff:
379
+ print('\n'.join(res.diff))
380
+ elif res.status == 'not run':
381
+ notrun.append(name)
382
+
383
+ if res.interrupted:
384
+ break
385
+
386
+ if notrun:
387
+ print('Not run:', ' '.join(notrun))
388
+
389
+ if casenotrun:
390
+ print('Some cases not run in:', ' '.join(casenotrun))
391
+
392
+ if failed:
393
+ print('Failures:', ' '.join(failed))
394
+ print(f'Failed {len(failed)} of {n_run} iotests')
395
+ else:
396
+ print(f'Passed all {n_run} iotests')
397
--
106
--
398
2.29.2
107
2.13.6
399
108
400
109
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Test that drain sections are correctly propagated through the graph.
2
2
3
Rename bitmaps migration tests and move them to tests subdirectory to
4
demonstrate new human-friendly test naming.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20210125185056.129513-7-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
4
---
10
tests/qemu-iotests/{199 => tests/migrate-bitmaps-postcopy-test} | 0
5
tests/test-bdrv-drain.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
11
.../{199.out => tests/migrate-bitmaps-postcopy-test.out} | 0
6
1 file changed, 74 insertions(+)
12
tests/qemu-iotests/{169 => tests/migrate-bitmaps-test} | 0
13
tests/qemu-iotests/{169.out => tests/migrate-bitmaps-test.out} | 0
14
4 files changed, 0 insertions(+), 0 deletions(-)
15
rename tests/qemu-iotests/{199 => tests/migrate-bitmaps-postcopy-test} (100%)
16
rename tests/qemu-iotests/{199.out => tests/migrate-bitmaps-postcopy-test.out} (100%)
17
rename tests/qemu-iotests/{169 => tests/migrate-bitmaps-test} (100%)
18
rename tests/qemu-iotests/{169.out => tests/migrate-bitmaps-test.out} (100%)
19
7
20
diff --git a/tests/qemu-iotests/199 b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test
8
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
21
similarity index 100%
9
index XXXXXXX..XXXXXXX 100644
22
rename from tests/qemu-iotests/199
10
--- a/tests/test-bdrv-drain.c
23
rename to tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test
11
+++ b/tests/test-bdrv-drain.c
24
diff --git a/tests/qemu-iotests/199.out b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test.out
12
@@ -XXX,XX +XXX,XX @@ static void test_nested(void)
25
similarity index 100%
13
blk_unref(blk);
26
rename from tests/qemu-iotests/199.out
14
}
27
rename to tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test.out
15
28
diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/tests/migrate-bitmaps-test
16
+static void test_multiparent(void)
29
similarity index 100%
17
+{
30
rename from tests/qemu-iotests/169
18
+ BlockBackend *blk_a, *blk_b;
31
rename to tests/qemu-iotests/tests/migrate-bitmaps-test
19
+ BlockDriverState *bs_a, *bs_b, *backing;
32
diff --git a/tests/qemu-iotests/169.out b/tests/qemu-iotests/tests/migrate-bitmaps-test.out
20
+ BDRVTestState *a_s, *b_s, *backing_s;
33
similarity index 100%
21
+
34
rename from tests/qemu-iotests/169.out
22
+ blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
35
rename to tests/qemu-iotests/tests/migrate-bitmaps-test.out
23
+ bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
24
+ &error_abort);
25
+ a_s = bs_a->opaque;
26
+ blk_insert_bs(blk_a, bs_a, &error_abort);
27
+
28
+ blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
29
+ bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
30
+ &error_abort);
31
+ b_s = bs_b->opaque;
32
+ blk_insert_bs(blk_b, bs_b, &error_abort);
33
+
34
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
35
+ backing_s = backing->opaque;
36
+ bdrv_set_backing_hd(bs_a, backing, &error_abort);
37
+ bdrv_set_backing_hd(bs_b, backing, &error_abort);
38
+
39
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
40
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
41
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
42
+ g_assert_cmpint(a_s->drain_count, ==, 0);
43
+ g_assert_cmpint(b_s->drain_count, ==, 0);
44
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
45
+
46
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
47
+
48
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 1);
49
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 1);
50
+ g_assert_cmpint(backing->quiesce_counter, ==, 1);
51
+ g_assert_cmpint(a_s->drain_count, ==, 1);
52
+ g_assert_cmpint(b_s->drain_count, ==, 1);
53
+ g_assert_cmpint(backing_s->drain_count, ==, 1);
54
+
55
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
56
+
57
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 2);
58
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 2);
59
+ g_assert_cmpint(backing->quiesce_counter, ==, 2);
60
+ g_assert_cmpint(a_s->drain_count, ==, 2);
61
+ g_assert_cmpint(b_s->drain_count, ==, 2);
62
+ g_assert_cmpint(backing_s->drain_count, ==, 2);
63
+
64
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
65
+
66
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 1);
67
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 1);
68
+ g_assert_cmpint(backing->quiesce_counter, ==, 1);
69
+ g_assert_cmpint(a_s->drain_count, ==, 1);
70
+ g_assert_cmpint(b_s->drain_count, ==, 1);
71
+ g_assert_cmpint(backing_s->drain_count, ==, 1);
72
+
73
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
74
+
75
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
76
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
77
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
78
+ g_assert_cmpint(a_s->drain_count, ==, 0);
79
+ g_assert_cmpint(b_s->drain_count, ==, 0);
80
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
81
+
82
+ bdrv_unref(backing);
83
+ bdrv_unref(bs_a);
84
+ bdrv_unref(bs_b);
85
+ blk_unref(blk_a);
86
+ blk_unref(blk_b);
87
+}
88
+
89
90
typedef struct TestBlockJob {
91
BlockJob common;
92
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
93
test_quiesce_co_drain_subtree);
94
95
g_test_add_func("/bdrv-drain/nested", test_nested);
96
+ g_test_add_func("/bdrv-drain/multiparent", test_multiparent);
97
98
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
99
g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
36
--
100
--
37
2.29.2
101
2.13.6
38
102
39
103
diff view generated by jsdifflib
New patch
1
1
We need to remember how many of the drain sections in which a node is
2
were recursive (i.e. subtree drain rather than node drain), so that they
3
can be correctly applied when children are added or removed during the
4
drained section.
5
6
With this change, it is safe to modify the graph even inside a
7
bdrv_subtree_drained_begin/end() section.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block.h | 2 --
12
include/block/block_int.h | 5 +++++
13
block.c | 32 +++++++++++++++++++++++++++++---
14
block/io.c | 28 ++++++++++++++++++++++++----
15
4 files changed, 58 insertions(+), 9 deletions(-)
16
17
diff --git a/include/block/block.h b/include/block/block.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block.h
20
+++ b/include/block/block.h
21
@@ -XXX,XX +XXX,XX @@ void bdrv_drained_begin(BlockDriverState *bs);
22
/**
23
* Like bdrv_drained_begin, but recursively begins a quiesced section for
24
* exclusive access to all child nodes as well.
25
- *
26
- * Graph changes are not allowed during a subtree drain section.
27
*/
28
void bdrv_subtree_drained_begin(BlockDriverState *bs);
29
30
diff --git a/include/block/block_int.h b/include/block/block_int.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block_int.h
33
+++ b/include/block/block_int.h
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
35
36
/* Accessed with atomic ops. */
37
int quiesce_counter;
38
+ int recursive_quiesce_counter;
39
+
40
unsigned int write_gen; /* Current data generation */
41
42
/* Protected by reqs_lock. */
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
44
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
45
BdrvRequestFlags flags);
46
47
+void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
48
+void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
49
+
50
int get_tmp_filename(char *filename, int size);
51
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
52
const char *filename);
53
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
56
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child)
58
bdrv_drained_end(bs);
59
}
60
61
+static void bdrv_child_cb_attach(BdrvChild *child)
62
+{
63
+ BlockDriverState *bs = child->opaque;
64
+ bdrv_apply_subtree_drain(child, bs);
65
+}
66
+
67
+static void bdrv_child_cb_detach(BdrvChild *child)
68
+{
69
+ BlockDriverState *bs = child->opaque;
70
+ bdrv_unapply_subtree_drain(child, bs);
71
+}
72
+
73
static int bdrv_child_cb_inactivate(BdrvChild *child)
74
{
75
BlockDriverState *bs = child->opaque;
76
@@ -XXX,XX +XXX,XX @@ const BdrvChildRole child_file = {
77
.inherit_options = bdrv_inherited_options,
78
.drained_begin = bdrv_child_cb_drained_begin,
79
.drained_end = bdrv_child_cb_drained_end,
80
+ .attach = bdrv_child_cb_attach,
81
+ .detach = bdrv_child_cb_detach,
82
.inactivate = bdrv_child_cb_inactivate,
83
};
84
85
@@ -XXX,XX +XXX,XX @@ const BdrvChildRole child_format = {
86
.inherit_options = bdrv_inherited_fmt_options,
87
.drained_begin = bdrv_child_cb_drained_begin,
88
.drained_end = bdrv_child_cb_drained_end,
89
+ .attach = bdrv_child_cb_attach,
90
+ .detach = bdrv_child_cb_detach,
91
.inactivate = bdrv_child_cb_inactivate,
92
};
93
94
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
95
parent->backing_blocker);
96
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
97
parent->backing_blocker);
98
+
99
+ bdrv_child_cb_attach(c);
100
}
101
102
static void bdrv_backing_detach(BdrvChild *c)
103
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
104
bdrv_op_unblock_all(c->bs, parent->backing_blocker);
105
error_free(parent->backing_blocker);
106
parent->backing_blocker = NULL;
107
+
108
+ bdrv_child_cb_detach(c);
109
}
110
111
/*
112
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
113
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
114
}
115
if (old_bs) {
116
+ /* Detach first so that the recursive drain sections coming from @child
117
+ * are already gone and we only end the drain sections that came from
118
+ * elsewhere. */
119
+ if (child->role->detach) {
120
+ child->role->detach(child);
121
+ }
122
if (old_bs->quiesce_counter && child->role->drained_end) {
123
for (i = 0; i < old_bs->quiesce_counter; i++) {
124
child->role->drained_end(child);
125
}
126
}
127
- if (child->role->detach) {
128
- child->role->detach(child);
129
- }
130
QLIST_REMOVE(child, next_parent);
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
134
}
135
}
136
137
+ /* Attach only after starting new drained sections, so that recursive
138
+ * drain sections coming from @child don't get an extra .drained_begin
139
+ * callback. */
140
if (child->role->attach) {
141
child->role->attach(child);
142
}
143
diff --git a/block/io.c b/block/io.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/block/io.c
146
+++ b/block/io.c
147
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
148
assert(data.done);
149
}
150
151
-static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
152
- BdrvChild *parent)
153
+void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
154
+ BdrvChild *parent)
155
{
156
BdrvChild *child, *next;
157
158
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
159
bdrv_drain_recurse(bs);
160
161
if (recursive) {
162
+ bs->recursive_quiesce_counter++;
163
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
164
bdrv_do_drained_begin(child->bs, true, child);
165
}
166
@@ -XXX,XX +XXX,XX @@ void bdrv_subtree_drained_begin(BlockDriverState *bs)
167
bdrv_do_drained_begin(bs, true, NULL);
168
}
169
170
-static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
171
- BdrvChild *parent)
172
+void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
173
+ BdrvChild *parent)
174
{
175
BdrvChild *child, *next;
176
int old_quiesce_counter;
177
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
178
}
179
180
if (recursive) {
181
+ bs->recursive_quiesce_counter--;
182
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
183
bdrv_do_drained_end(child->bs, true, child);
184
}
185
@@ -XXX,XX +XXX,XX @@ void bdrv_subtree_drained_end(BlockDriverState *bs)
186
bdrv_do_drained_end(bs, true, NULL);
187
}
188
189
+void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
190
+{
191
+ int i;
192
+
193
+ for (i = 0; i < new_parent->recursive_quiesce_counter; i++) {
194
+ bdrv_do_drained_begin(child->bs, true, child);
195
+ }
196
+}
197
+
198
+void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
199
+{
200
+ int i;
201
+
202
+ for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
203
+ bdrv_do_drained_end(child->bs, true, child);
204
+ }
205
+}
206
+
207
/*
208
* Wait for pending requests to complete on a single BlockDriverState subtree,
209
* and suspend block driver's internal I/O until next request arrives.
210
--
211
2.13.6
212
213
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Add python script with new logic of searching for tests:
4
5
Current ./check behavior:
6
- tests are named [0-9][0-9][0-9]
7
- tests must be registered in group file (even if test doesn't belong
8
to any group, like 142)
9
10
Behavior of findtests.py:
11
- group file is dropped
12
- tests are all files in tests/ subdirectory (except for .out files),
13
so it's not needed more to "register the test", just create it with
14
appropriate name in tests/ subdirectory. Old names like
15
[0-9][0-9][0-9] (in root iotests directory) are supported too, but
16
not recommended for new tests
17
- groups are parsed from '# group: ' line inside test files
18
- optional file group.local may be used to define some additional
19
groups for downstreams
20
- 'disabled' group is used to temporary disable tests. So instead of
21
commenting tests in old 'group' file you now can add them to
22
disabled group with help of 'group.local' file
23
- selecting test ranges like 5-15 are not supported more
24
(to support restarting failed ./check command from the middle of the
25
process, new argument is added: --start-from)
26
27
Benefits:
28
- no rebase conflicts in group file on patch porting from branch to
29
branch
30
- no conflicts in upstream, when different series want to occupy same
31
test number
32
- meaningful names for test files
33
For example, with digital number, when some person wants to add some
34
test about block-stream, he most probably will just create a new
35
test. But if there would be test-block-stream test already, he will
36
at first look at it and may be just add a test-case into it.
37
And anyway meaningful names are better.
38
39
This commit doesn't update check behavior (which will be done in
40
further commit), still, the documentation changed like new behavior is
41
already here. Let's live with this small inconsistency for the
42
following few commits, until final change.
43
44
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
45
Reviewed-by: Eric Blake <eblake@redhat.com>
46
Message-Id: <20210125185056.129513-3-vsementsov@virtuozzo.com>
47
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
48
---
2
---
49
docs/devel/testing.rst | 50 +++++++++-
3
tests/test-bdrv-drain.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
50
tests/qemu-iotests/findtests.py | 159 ++++++++++++++++++++++++++++++++
4
1 file changed, 80 insertions(+)
51
2 files changed, 208 insertions(+), 1 deletion(-)
52
create mode 100644 tests/qemu-iotests/findtests.py
53
5
54
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
6
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
55
index XXXXXXX..XXXXXXX 100644
7
index XXXXXXX..XXXXXXX 100644
56
--- a/docs/devel/testing.rst
8
--- a/tests/test-bdrv-drain.c
57
+++ b/docs/devel/testing.rst
9
+++ b/tests/test-bdrv-drain.c
58
@@ -XXX,XX +XXX,XX @@ check-block
10
@@ -XXX,XX +XXX,XX @@ static void test_multiparent(void)
59
-----------
11
blk_unref(blk_b);
60
12
}
61
``make check-block`` runs a subset of the block layer iotests (the tests that
13
62
-are in the "auto" group in ``tests/qemu-iotests/group``).
14
+static void test_graph_change(void)
63
+are in the "auto" group).
15
+{
64
See the "QEMU iotests" section below for more information.
16
+ BlockBackend *blk_a, *blk_b;
65
17
+ BlockDriverState *bs_a, *bs_b, *backing;
66
GCC gcov support
18
+ BDRVTestState *a_s, *b_s, *backing_s;
67
@@ -XXX,XX +XXX,XX @@ another application on the host may have locked the file, possibly leading to a
68
test failure. If using such devices are explicitly desired, consider adding
69
``locking=off`` option to disable image locking.
70
71
+Test case groups
72
+----------------
73
+
19
+
74
+"Tests may belong to one or more test groups, which are defined in the form
20
+ blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
75
+of a comment in the test source file. By convention, test groups are listed
21
+ bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
76
+in the second line of the test file, after the "#!/..." line, like this:
22
+ &error_abort);
23
+ a_s = bs_a->opaque;
24
+ blk_insert_bs(blk_a, bs_a, &error_abort);
77
+
25
+
78
+.. code::
26
+ blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
27
+ bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
28
+ &error_abort);
29
+ b_s = bs_b->opaque;
30
+ blk_insert_bs(blk_b, bs_b, &error_abort);
79
+
31
+
80
+ #!/usr/bin/env python3
32
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
81
+ # group: auto quick
33
+ backing_s = backing->opaque;
82
+ #
34
+ bdrv_set_backing_hd(bs_a, backing, &error_abort);
83
+ ...
84
+
35
+
85
+Another way of defining groups is creating the tests/qemu-iotests/group.local
36
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
86
+file. This should be used only for downstream (this file should never appear
37
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
87
+in upstream). This file may be used for defining some downstream test groups
38
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
88
+or for temporarily disabling tests, like this:
39
+ g_assert_cmpint(a_s->drain_count, ==, 0);
40
+ g_assert_cmpint(b_s->drain_count, ==, 0);
41
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
89
+
42
+
90
+.. code::
43
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
44
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
45
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_a);
46
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
47
+ do_drain_begin(BDRV_SUBTREE_DRAIN, bs_b);
91
+
48
+
92
+ # groups for some company downstream process
49
+ bdrv_set_backing_hd(bs_b, backing, &error_abort);
93
+ #
50
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 5);
94
+ # ci - tests to run on build
51
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 5);
95
+ # down - our downstream tests, not for upstream
52
+ g_assert_cmpint(backing->quiesce_counter, ==, 5);
96
+ #
53
+ g_assert_cmpint(a_s->drain_count, ==, 5);
97
+ # Format of each line is:
54
+ g_assert_cmpint(b_s->drain_count, ==, 5);
98
+ # TEST_NAME TEST_GROUP [TEST_GROUP ]...
55
+ g_assert_cmpint(backing_s->drain_count, ==, 5);
99
+
56
+
100
+ 013 ci
57
+ bdrv_set_backing_hd(bs_b, NULL, &error_abort);
101
+ 210 disabled
58
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 3);
102
+ 215 disabled
59
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 2);
103
+ our-ugly-workaround-test down ci
60
+ g_assert_cmpint(backing->quiesce_counter, ==, 3);
61
+ g_assert_cmpint(a_s->drain_count, ==, 3);
62
+ g_assert_cmpint(b_s->drain_count, ==, 2);
63
+ g_assert_cmpint(backing_s->drain_count, ==, 3);
104
+
64
+
105
+Note that the following group names have a special meaning:
65
+ bdrv_set_backing_hd(bs_b, backing, &error_abort);
66
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 5);
67
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 5);
68
+ g_assert_cmpint(backing->quiesce_counter, ==, 5);
69
+ g_assert_cmpint(a_s->drain_count, ==, 5);
70
+ g_assert_cmpint(b_s->drain_count, ==, 5);
71
+ g_assert_cmpint(backing_s->drain_count, ==, 5);
106
+
72
+
107
+- quick: Tests in this group should finish within a few seconds.
73
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
74
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_b);
75
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
76
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
77
+ do_drain_end(BDRV_SUBTREE_DRAIN, bs_a);
108
+
78
+
109
+- auto: Tests in this group are used during "make check" and should be
79
+ g_assert_cmpint(bs_a->quiesce_counter, ==, 0);
110
+ runnable in any case. That means they should run with every QEMU binary
80
+ g_assert_cmpint(bs_b->quiesce_counter, ==, 0);
111
+ (also non-x86), with every QEMU configuration (i.e. must not fail if
81
+ g_assert_cmpint(backing->quiesce_counter, ==, 0);
112
+ an optional feature is not compiled in - but reporting a "skip" is ok),
82
+ g_assert_cmpint(a_s->drain_count, ==, 0);
113
+ work at least with the qcow2 file format, work with all kind of host
83
+ g_assert_cmpint(b_s->drain_count, ==, 0);
114
+ filesystems and users (e.g. "nobody" or "root") and must not take too
84
+ g_assert_cmpint(backing_s->drain_count, ==, 0);
115
+ much memory and disk space (since CI pipelines tend to fail otherwise).
116
+
85
+
117
+- disabled: Tests in this group are disabled and ignored by check.
86
+ bdrv_unref(backing);
87
+ bdrv_unref(bs_a);
88
+ bdrv_unref(bs_b);
89
+ blk_unref(blk_a);
90
+ blk_unref(blk_b);
91
+}
118
+
92
+
119
.. _docker-ref:
93
120
94
typedef struct TestBlockJob {
121
Docker based tests
95
BlockJob common;
122
diff --git a/tests/qemu-iotests/findtests.py b/tests/qemu-iotests/findtests.py
96
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
123
new file mode 100644
97
124
index XXXXXXX..XXXXXXX
98
g_test_add_func("/bdrv-drain/nested", test_nested);
125
--- /dev/null
99
g_test_add_func("/bdrv-drain/multiparent", test_multiparent);
126
+++ b/tests/qemu-iotests/findtests.py
100
+ g_test_add_func("/bdrv-drain/graph-change", test_graph_change);
127
@@ -XXX,XX +XXX,XX @@
101
128
+# TestFinder class, define set of tests to run.
102
g_test_add_func("/bdrv-drain/blockjob/drain_all", test_blockjob_drain_all);
129
+#
103
g_test_add_func("/bdrv-drain/blockjob/drain", test_blockjob_drain);
130
+# Copyright (c) 2020-2021 Virtuozzo International GmbH
131
+#
132
+# This program is free software; you can redistribute it and/or modify
133
+# it under the terms of the GNU General Public License as published by
134
+# the Free Software Foundation; either version 2 of the License, or
135
+# (at your option) any later version.
136
+#
137
+# This program is distributed in the hope that it will be useful,
138
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
139
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
140
+# GNU General Public License for more details.
141
+#
142
+# You should have received a copy of the GNU General Public License
143
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
144
+#
145
+
146
+import os
147
+import glob
148
+import re
149
+from collections import defaultdict
150
+from contextlib import contextmanager
151
+from typing import Optional, List, Iterator, Set
152
+
153
+
154
+@contextmanager
155
+def chdir(path: Optional[str] = None) -> Iterator[None]:
156
+ if path is None:
157
+ yield
158
+ return
159
+
160
+ saved_dir = os.getcwd()
161
+ os.chdir(path)
162
+ try:
163
+ yield
164
+ finally:
165
+ os.chdir(saved_dir)
166
+
167
+
168
+class TestFinder:
169
+ def __init__(self, test_dir: Optional[str] = None) -> None:
170
+ self.groups = defaultdict(set)
171
+
172
+ with chdir(test_dir):
173
+ self.all_tests = glob.glob('[0-9][0-9][0-9]')
174
+ self.all_tests += [f for f in glob.iglob('tests/*')
175
+ if not f.endswith('.out') and
176
+ os.path.isfile(f + '.out')]
177
+
178
+ for t in self.all_tests:
179
+ with open(t, encoding="utf-8") as f:
180
+ for line in f:
181
+ if line.startswith('# group: '):
182
+ for g in line.split()[2:]:
183
+ self.groups[g].add(t)
184
+ break
185
+
186
+ def add_group_file(self, fname: str) -> None:
187
+ with open(fname, encoding="utf-8") as f:
188
+ for line in f:
189
+ line = line.strip()
190
+
191
+ if (not line) or line[0] == '#':
192
+ continue
193
+
194
+ words = line.split()
195
+ test_file = self.parse_test_name(words[0])
196
+ groups = words[1:]
197
+
198
+ for g in groups:
199
+ self.groups[g].add(test_file)
200
+
201
+ def parse_test_name(self, name: str) -> str:
202
+ if '/' in name:
203
+ raise ValueError('Paths are unsupported for test selection, '
204
+ f'requiring "{name}" is wrong')
205
+
206
+ if re.fullmatch(r'\d+', name):
207
+ # Numbered tests are old naming convention. We should convert them
208
+ # to three-digit-length, like 1 --> 001.
209
+ name = f'{int(name):03}'
210
+ else:
211
+ # Named tests all should be in tests/ subdirectory
212
+ name = os.path.join('tests', name)
213
+
214
+ if name not in self.all_tests:
215
+ raise ValueError(f'Test "{name}" is not found')
216
+
217
+ return name
218
+
219
+ def find_tests(self, groups: Optional[List[str]] = None,
220
+ exclude_groups: Optional[List[str]] = None,
221
+ tests: Optional[List[str]] = None,
222
+ start_from: Optional[str] = None) -> List[str]:
223
+ """Find tests
224
+
225
+ Algorithm:
226
+
227
+ 1. a. if some @groups specified
228
+ a.1 Take all tests from @groups
229
+ a.2 Drop tests, which are in at least one of @exclude_groups or in
230
+ 'disabled' group (if 'disabled' is not listed in @groups)
231
+ a.3 Add tests from @tests (don't exclude anything from them)
232
+
233
+ b. else, if some @tests specified:
234
+ b.1 exclude_groups must be not specified, so just take @tests
235
+
236
+ c. else (only @exclude_groups list is non-empty):
237
+ c.1 Take all tests
238
+ c.2 Drop tests, which are in at least one of @exclude_groups or in
239
+ 'disabled' group
240
+
241
+ 2. sort
242
+
243
+ 3. If start_from specified, drop tests from first one to @start_from
244
+ (not inclusive)
245
+ """
246
+ if groups is None:
247
+ groups = []
248
+ if exclude_groups is None:
249
+ exclude_groups = []
250
+ if tests is None:
251
+ tests = []
252
+
253
+ res: Set[str] = set()
254
+ if groups:
255
+ # Some groups specified. exclude_groups supported, additionally
256
+ # selecting some individual tests supported as well.
257
+ res.update(*(self.groups[g] for g in groups))
258
+ elif tests:
259
+ # Some individual tests specified, but no groups. In this case
260
+ # we don't support exclude_groups.
261
+ if exclude_groups:
262
+ raise ValueError("Can't exclude from individually specified "
263
+ "tests.")
264
+ else:
265
+ # No tests no groups: start from all tests, exclude_groups
266
+ # supported.
267
+ res.update(self.all_tests)
268
+
269
+ if 'disabled' not in groups and 'disabled' not in exclude_groups:
270
+ # Don't want to modify function argument, so create new list.
271
+ exclude_groups = exclude_groups + ['disabled']
272
+
273
+ res = res.difference(*(self.groups[g] for g in exclude_groups))
274
+
275
+ # We want to add @tests. But for compatibility with old test names,
276
+ # we should convert any number < 100 to number padded by
277
+ # leading zeroes, like 1 -> 001 and 23 -> 023.
278
+ for t in tests:
279
+ res.add(self.parse_test_name(t))
280
+
281
+ sequence = sorted(res)
282
+
283
+ if start_from is not None:
284
+ del sequence[:sequence.index(self.parse_test_name(start_from))]
285
+
286
+ return sequence
287
--
104
--
288
2.29.2
105
2.13.6
289
106
290
107
diff view generated by jsdifflib
New patch
1
Since commit bde70715, base is the only node that is reopened in
2
commit_start(). This means that the code, which still involves an
3
explicit BlockReopenQueue, can now be simplified by using bdrv_reopen().
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Fam Zheng <famz@redhat.com>
7
---
8
block/commit.c | 8 +-------
9
1 file changed, 1 insertion(+), 7 deletions(-)
10
11
diff --git a/block/commit.c b/block/commit.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/commit.c
14
+++ b/block/commit.c
15
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
16
const char *filter_node_name, Error **errp)
17
{
18
CommitBlockJob *s;
19
- BlockReopenQueue *reopen_queue = NULL;
20
int orig_base_flags;
21
BlockDriverState *iter;
22
BlockDriverState *commit_top_bs = NULL;
23
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
24
/* convert base to r/w, if necessary */
25
orig_base_flags = bdrv_get_flags(base);
26
if (!(orig_base_flags & BDRV_O_RDWR)) {
27
- reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
28
- orig_base_flags | BDRV_O_RDWR);
29
- }
30
-
31
- if (reopen_queue) {
32
- bdrv_reopen_multiple(bdrv_get_aio_context(bs), reopen_queue, &local_err);
33
+ bdrv_reopen(base, orig_base_flags | BDRV_O_RDWR, &local_err);
34
if (local_err != NULL) {
35
error_propagate(errp, local_err);
36
goto fail;
37
--
38
2.13.6
39
40
diff view generated by jsdifflib
New patch
1
The bdrv_reopen*() implementation doesn't like it if the graph is
2
changed between queuing nodes for reopen and actually reopening them
3
(one of the reasons is that queuing can be recursive).
1
4
5
So instead of draining the device only in bdrv_reopen_multiple(),
6
require that callers already drained all affected nodes, and assert this
7
in bdrv_reopen_queue().
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
---
12
block.c | 23 ++++++++++++++++-------
13
block/replication.c | 6 ++++++
14
qemu-io-cmds.c | 3 +++
15
3 files changed, 25 insertions(+), 7 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
22
* returns a pointer to bs_queue, which is either the newly allocated
23
* bs_queue, or the existing bs_queue being used.
24
*
25
+ * bs must be drained between bdrv_reopen_queue() and bdrv_reopen_multiple().
26
*/
27
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
28
BlockDriverState *bs,
29
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
30
BdrvChild *child;
31
QDict *old_options, *explicit_options;
32
33
+ /* Make sure that the caller remembered to use a drained section. This is
34
+ * important to avoid graph changes between the recursive queuing here and
35
+ * bdrv_reopen_multiple(). */
36
+ assert(bs->quiesce_counter > 0);
37
+
38
if (bs_queue == NULL) {
39
bs_queue = g_new0(BlockReopenQueue, 1);
40
QSIMPLEQ_INIT(bs_queue);
41
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
42
* If all devices prepare successfully, then the changes are committed
43
* to all devices.
44
*
45
+ * All affected nodes must be drained between bdrv_reopen_queue() and
46
+ * bdrv_reopen_multiple().
47
*/
48
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp)
49
{
50
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
51
52
assert(bs_queue != NULL);
53
54
- aio_context_release(ctx);
55
- bdrv_drain_all_begin();
56
- aio_context_acquire(ctx);
57
-
58
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
59
+ assert(bs_entry->state.bs->quiesce_counter > 0);
60
if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) {
61
error_propagate(errp, local_err);
62
goto cleanup;
63
@@ -XXX,XX +XXX,XX @@ cleanup:
64
}
65
g_free(bs_queue);
66
67
- bdrv_drain_all_end();
68
-
69
return ret;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
73
{
74
int ret = -1;
75
Error *local_err = NULL;
76
- BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
77
+ BlockReopenQueue *queue;
78
79
+ bdrv_subtree_drained_begin(bs);
80
+
81
+ queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
82
ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
83
if (local_err != NULL) {
84
error_propagate(errp, local_err);
85
}
86
+
87
+ bdrv_subtree_drained_end(bs);
88
+
89
return ret;
90
}
91
92
diff --git a/block/replication.c b/block/replication.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/block/replication.c
95
+++ b/block/replication.c
96
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
97
new_secondary_flags = s->orig_secondary_flags;
98
}
99
100
+ bdrv_subtree_drained_begin(s->hidden_disk->bs);
101
+ bdrv_subtree_drained_begin(s->secondary_disk->bs);
102
+
103
if (orig_hidden_flags != new_hidden_flags) {
104
reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
105
new_hidden_flags);
106
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
107
reopen_queue, &local_err);
108
error_propagate(errp, local_err);
109
}
110
+
111
+ bdrv_subtree_drained_end(s->hidden_disk->bs);
112
+ bdrv_subtree_drained_end(s->secondary_disk->bs);
113
}
114
115
static void backup_job_cleanup(BlockDriverState *bs)
116
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/qemu-io-cmds.c
119
+++ b/qemu-io-cmds.c
120
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
121
opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
122
qemu_opts_reset(&reopen_opts);
123
124
+ bdrv_subtree_drained_begin(bs);
125
brq = bdrv_reopen_queue(NULL, bs, opts, flags);
126
bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
127
+ bdrv_subtree_drained_end(bs);
128
+
129
if (local_err) {
130
error_report_err(local_err);
131
} else {
132
--
133
2.13.6
134
135
diff view generated by jsdifflib