1
The following changes since commit 75ee62ac606bfc9eb59310b9446df3434bf6e8c2:
1
The following changes since commit ca61fa4b803e5d0abaf6f1ceb690f23bb78a4def:
2
2
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2020-12-17 18:53:36 +0000)
3
Merge remote-tracking branch 'remotes/quic/tags/pull-hex-20211006' into staging (2021-10-06 12:11:14 -0700)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-12-18
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 0e72078128229bf9efb542e396ab44bf91b91340:
9
for you to fetch changes up to 1cc7eada97914f090125e588497986f6f7900514:
10
10
11
iotests: Fix _send_qemu_cmd with bash 5.1 (2020-12-18 12:47:38 +0100)
11
iothread: use IOThreadParamInfo in iothread_[set|get]_param() (2021-10-07 15:29:50 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- New block filter: preallocate (which, on writes beyond an image file's
16
end, allocates big chunks of data so that such post-EOF writes will
17
occur less frequently)
18
- write-zeroes and block-status support for Quorum
19
- Implementation of truncate for the nvme block driver similarly to the
20
existing implementations for host block devices and iscsi devices
21
- Block layer refactoring: Drop the tighten_restrictions concept in the
22
block permission functions
23
- iotest fixes
24
15
25
----------------------------------------------------------------
16
----------------------------------------------------------------
26
Alberto Garcia (2):
27
quorum: Implement bdrv_co_block_status()
28
quorum: Implement bdrv_co_pwrite_zeroes()
29
17
30
Max Reitz (2):
18
Stefano Garzarella (2):
31
iotests/102: Pass $QEMU_HANDLE to _send_qemu_cmd
19
iothread: rename PollParamInfo to IOThreadParamInfo
32
iotests: Fix _send_qemu_cmd with bash 5.1
20
iothread: use IOThreadParamInfo in iothread_[set|get]_param()
33
21
34
Philippe Mathieu-Daudé (1):
22
iothread.c | 28 +++++++++++++++-------------
35
block/nvme: Implement fake truncate() coroutine
23
1 file changed, 15 insertions(+), 13 deletions(-)
36
37
Vladimir Sementsov-Ogievskiy (25):
38
block: add bdrv_refresh_perms() helper
39
block: bdrv_set_perm() drop redundant parameters.
40
block: bdrv_child_set_perm() drop redundant parameters.
41
block: drop tighten_restrictions
42
block: simplify comment to BDRV_REQ_SERIALISING
43
block/io.c: drop assertion on double waiting for request serialisation
44
block/io: split out bdrv_find_conflicting_request
45
block/io: bdrv_wait_serialising_requests_locked: drop extra bs arg
46
block: bdrv_mark_request_serialising: split non-waiting function
47
block: introduce BDRV_REQ_NO_WAIT flag
48
block: bdrv_check_perm(): process children anyway
49
block: introduce preallocate filter
50
qemu-io: add preallocate mode parameter for truncate command
51
iotests: qemu_io_silent: support --image-opts
52
iotests.py: execute_setup_common(): add required_fmts argument
53
iotests: add 298 to test new preallocate filter driver
54
scripts/simplebench: fix grammar: s/successed/succeeded/
55
scripts/simplebench: support iops
56
scripts/simplebench: use standard deviation for +- error
57
simplebench: rename ascii() to results_to_text()
58
simplebench: move results_to_text() into separate file
59
simplebench/results_to_text: improve view of the table
60
simplebench/results_to_text: add difference line to the table
61
simplebench/results_to_text: make executable
62
scripts/simplebench: add bench_prealloc.py
63
64
docs/system/qemu-block-drivers.rst.inc | 26 ++
65
qapi/block-core.json | 20 +-
66
include/block/block.h | 20 +-
67
include/block/block_int.h | 3 +-
68
block.c | 185 +++-----
69
block/file-posix.c | 2 +-
70
block/io.c | 130 +++---
71
block/nvme.c | 24 ++
72
block/preallocate.c | 559 +++++++++++++++++++++++++
73
block/quorum.c | 88 +++-
74
qemu-io-cmds.c | 46 +-
75
block/meson.build | 1 +
76
scripts/simplebench/bench-example.py | 3 +-
77
scripts/simplebench/bench_prealloc.py | 132 ++++++
78
scripts/simplebench/bench_write_req.py | 3 +-
79
scripts/simplebench/results_to_text.py | 126 ++++++
80
scripts/simplebench/simplebench.py | 66 ++-
81
tests/qemu-iotests/085.out | 167 ++++++--
82
tests/qemu-iotests/094.out | 10 +-
83
tests/qemu-iotests/095.out | 4 +-
84
tests/qemu-iotests/102 | 2 +-
85
tests/qemu-iotests/102.out | 2 +-
86
tests/qemu-iotests/109.out | 88 +++-
87
tests/qemu-iotests/117.out | 13 +-
88
tests/qemu-iotests/127.out | 12 +-
89
tests/qemu-iotests/140.out | 10 +-
90
tests/qemu-iotests/141.out | 128 ++++--
91
tests/qemu-iotests/143.out | 4 +-
92
tests/qemu-iotests/144.out | 28 +-
93
tests/qemu-iotests/153.out | 18 +-
94
tests/qemu-iotests/156.out | 39 +-
95
tests/qemu-iotests/161.out | 18 +-
96
tests/qemu-iotests/173.out | 25 +-
97
tests/qemu-iotests/182.out | 42 +-
98
tests/qemu-iotests/183.out | 19 +-
99
tests/qemu-iotests/185.out | 45 +-
100
tests/qemu-iotests/191.out | 12 +-
101
tests/qemu-iotests/223.out | 92 ++--
102
tests/qemu-iotests/229.out | 13 +-
103
tests/qemu-iotests/249.out | 16 +-
104
tests/qemu-iotests/298 | 186 ++++++++
105
tests/qemu-iotests/298.out | 5 +
106
tests/qemu-iotests/308.out | 103 ++++-
107
tests/qemu-iotests/312 | 159 +++++++
108
tests/qemu-iotests/312.out | 81 ++++
109
tests/qemu-iotests/common.qemu | 11 +-
110
tests/qemu-iotests/group | 2 +
111
tests/qemu-iotests/iotests.py | 16 +-
112
48 files changed, 2357 insertions(+), 447 deletions(-)
113
create mode 100644 block/preallocate.c
114
create mode 100755 scripts/simplebench/bench_prealloc.py
115
create mode 100755 scripts/simplebench/results_to_text.py
116
create mode 100644 tests/qemu-iotests/298
117
create mode 100644 tests/qemu-iotests/298.out
118
create mode 100755 tests/qemu-iotests/312
119
create mode 100644 tests/qemu-iotests/312.out
120
24
121
--
25
--
122
2.29.2
26
2.31.1
123
27
124
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Make separate function for common pattern.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20201106124241.16950-5-vsementsov@virtuozzo.com>
7
[mreitz: Squashed in
8
https://lists.nongnu.org/archive/html/qemu-block/2020-11/msg00299.html]
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block.c | 61 +++++++++++++++++++++++++++++----------------------------
12
1 file changed, 31 insertions(+), 30 deletions(-)
13
14
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
17
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_abort_perm_update(BdrvChild *c)
19
bdrv_abort_perm_update(c->bs);
20
}
21
22
+static int bdrv_refresh_perms(BlockDriverState *bs, bool *tighten_restrictions,
23
+ Error **errp)
24
+{
25
+ int ret;
26
+ uint64_t perm, shared_perm;
27
+
28
+ bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
29
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
30
+ tighten_restrictions, errp);
31
+ if (ret < 0) {
32
+ bdrv_abort_perm_update(bs);
33
+ return ret;
34
+ }
35
+ bdrv_set_perm(bs, perm, shared_perm);
36
+
37
+ return 0;
38
+}
39
+
40
int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
41
Error **errp)
42
{
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
44
}
45
46
if (old_bs) {
47
- /* Update permissions for old node. This is guaranteed to succeed
48
- * because we're just taking a parent away, so we're loosening
49
- * restrictions. */
50
bool tighten_restrictions;
51
- int ret;
52
53
- bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
54
- ret = bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL,
55
- &tighten_restrictions, NULL);
56
+ /*
57
+ * Update permissions for old node. We're just taking a parent away, so
58
+ * we're loosening restrictions. Errors of permission update are not
59
+ * fatal in this case, ignore them.
60
+ */
61
+ bdrv_refresh_perms(old_bs, &tighten_restrictions, NULL);
62
assert(tighten_restrictions == false);
63
- if (ret < 0) {
64
- /* We only tried to loosen restrictions, so errors are not fatal */
65
- bdrv_abort_perm_update(old_bs);
66
- } else {
67
- bdrv_set_perm(old_bs, perm, shared_perm);
68
- }
69
70
/* When the parent requiring a non-default AioContext is removed, the
71
* node moves back to the main AioContext */
72
@@ -XXX,XX +XXX,XX @@ void bdrv_init_with_whitelist(void)
73
int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
74
{
75
BdrvChild *child, *parent;
76
- uint64_t perm, shared_perm;
77
Error *local_err = NULL;
78
int ret;
79
BdrvDirtyBitmap *bm;
80
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
81
*/
82
if (bs->open_flags & BDRV_O_INACTIVE) {
83
bs->open_flags &= ~BDRV_O_INACTIVE;
84
- bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
85
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, errp);
86
+ ret = bdrv_refresh_perms(bs, NULL, errp);
87
if (ret < 0) {
88
- bdrv_abort_perm_update(bs);
89
bs->open_flags |= BDRV_O_INACTIVE;
90
return ret;
91
}
92
- bdrv_set_perm(bs, perm, shared_perm);
93
94
if (bs->drv->bdrv_co_invalidate_cache) {
95
bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
96
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
97
{
98
BdrvChild *child, *parent;
99
bool tighten_restrictions;
100
- uint64_t perm, shared_perm;
101
int ret;
102
103
if (!bs->drv) {
104
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
105
106
bs->open_flags |= BDRV_O_INACTIVE;
107
108
- /* Update permissions, they may differ for inactive nodes */
109
- bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
110
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
111
- &tighten_restrictions, NULL);
112
+ /*
113
+ * Update permissions, they may differ for inactive nodes.
114
+ * We only tried to loosen restrictions, so errors are not fatal, ignore
115
+ * them.
116
+ */
117
+ bdrv_refresh_perms(bs, &tighten_restrictions, NULL);
118
assert(tighten_restrictions == false);
119
- if (ret < 0) {
120
- /* We only tried to loosen restrictions, so errors are not fatal */
121
- bdrv_abort_perm_update(bs);
122
- } else {
123
- bdrv_set_perm(bs, perm, shared_perm);
124
- }
125
-
126
127
/* Recursively inactivate children */
128
QLIST_FOREACH(child, &bs->children, next) {
129
--
130
2.29.2
131
132
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
To be reused in separate.
3
Commit 1793ad0247 ("iothread: add aio-max-batch parameter") added
4
a new parameter (aio-max-batch) to IOThread and used PollParamInfo
5
structure to handle it.
4
6
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Since it is not a parameter of the polling mechanism, we rename the
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
structure to a more generic IOThreadParamInfo.
7
Message-Id: <20201021145859.11201-4-vsementsov@virtuozzo.com>
9
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Suggested-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20210727145936.147032-2-sgarzare@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
15
---
10
block/io.c | 71 +++++++++++++++++++++++++++++++-----------------------
16
iothread.c | 14 +++++++-------
11
1 file changed, 41 insertions(+), 30 deletions(-)
17
1 file changed, 7 insertions(+), 7 deletions(-)
12
18
13
diff --git a/block/io.c b/block/io.c
19
diff --git a/iothread.c b/iothread.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
21
--- a/iothread.c
16
+++ b/block/io.c
22
+++ b/iothread.c
17
@@ -XXX,XX +XXX,XX @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
23
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
18
return true;
24
typedef struct {
19
}
25
const char *name;
20
26
ptrdiff_t offset; /* field's byte offset in IOThread struct */
21
+/* Called with self->bs->reqs_lock held */
27
-} PollParamInfo;
22
+static BdrvTrackedRequest *
28
+} IOThreadParamInfo;
23
+bdrv_find_conflicting_request(BdrvTrackedRequest *self)
29
24
+{
30
-static PollParamInfo poll_max_ns_info = {
25
+ BdrvTrackedRequest *req;
31
+static IOThreadParamInfo poll_max_ns_info = {
26
+
32
"poll-max-ns", offsetof(IOThread, poll_max_ns),
27
+ QLIST_FOREACH(req, &self->bs->tracked_requests, list) {
33
};
28
+ if (req == self || (!req->serialising && !self->serialising)) {
34
-static PollParamInfo poll_grow_info = {
29
+ continue;
35
+static IOThreadParamInfo poll_grow_info = {
30
+ }
36
"poll-grow", offsetof(IOThread, poll_grow),
31
+ if (tracked_request_overlaps(req, self->overlap_offset,
37
};
32
+ self->overlap_bytes))
38
-static PollParamInfo poll_shrink_info = {
33
+ {
39
+static IOThreadParamInfo poll_shrink_info = {
34
+ /*
40
"poll-shrink", offsetof(IOThread, poll_shrink),
35
+ * Hitting this means there was a reentrant request, for
41
};
36
+ * example, a block driver issuing nested requests. This must
42
-static PollParamInfo aio_max_batch_info = {
37
+ * never happen since it means deadlock.
43
+static IOThreadParamInfo aio_max_batch_info = {
38
+ */
44
"aio-max-batch", offsetof(IOThread, aio_max_batch),
39
+ assert(qemu_coroutine_self() != req->co);
45
};
40
+
46
41
+ /*
47
@@ -XXX,XX +XXX,XX @@ static void iothread_get_param(Object *obj, Visitor *v,
42
+ * If the request is already (indirectly) waiting for us, or
48
const char *name, void *opaque, Error **errp)
43
+ * will wait for us as soon as it wakes up, then just go on
44
+ * (instead of producing a deadlock in the former case).
45
+ */
46
+ if (!req->waiting_for) {
47
+ return req;
48
+ }
49
+ }
50
+ }
51
+
52
+ return NULL;
53
+}
54
+
55
static bool coroutine_fn
56
bdrv_wait_serialising_requests_locked(BlockDriverState *bs,
57
BdrvTrackedRequest *self)
58
{
49
{
59
BdrvTrackedRequest *req;
50
IOThread *iothread = IOTHREAD(obj);
60
- bool retry;
51
- PollParamInfo *info = opaque;
61
bool waited = false;
52
+ IOThreadParamInfo *info = opaque;
62
53
int64_t *field = (void *)iothread + info->offset;
63
- do {
54
64
- retry = false;
55
visit_type_int64(v, name, field, errp);
65
- QLIST_FOREACH(req, &bs->tracked_requests, list) {
56
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
66
- if (req == self || (!req->serialising && !self->serialising)) {
57
const char *name, void *opaque, Error **errp)
67
- continue;
58
{
68
- }
59
IOThread *iothread = IOTHREAD(obj);
69
- if (tracked_request_overlaps(req, self->overlap_offset,
60
- PollParamInfo *info = opaque;
70
- self->overlap_bytes))
61
+ IOThreadParamInfo *info = opaque;
71
- {
62
int64_t *field = (void *)iothread + info->offset;
72
- /* Hitting this means there was a reentrant request, for
63
int64_t value;
73
- * example, a block driver issuing nested requests. This must
74
- * never happen since it means deadlock.
75
- */
76
- assert(qemu_coroutine_self() != req->co);
77
-
78
- /* If the request is already (indirectly) waiting for us, or
79
- * will wait for us as soon as it wakes up, then just go on
80
- * (instead of producing a deadlock in the former case). */
81
- if (!req->waiting_for) {
82
- self->waiting_for = req;
83
- qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock);
84
- self->waiting_for = NULL;
85
- retry = true;
86
- waited = true;
87
- break;
88
- }
89
- }
90
- }
91
- } while (retry);
92
+ while ((req = bdrv_find_conflicting_request(self))) {
93
+ self->waiting_for = req;
94
+ qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock);
95
+ self->waiting_for = NULL;
96
+ waited = true;
97
+ }
98
+
99
return waited;
100
}
101
64
102
--
65
--
103
2.29.2
66
2.31.1
104
67
105
68
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
We should never set permissions other than cumulative permissions of
3
Commit 0445409d74 ("iothread: generalize
4
parents. During bdrv_reopen_multiple() we _check_ for synthetic
4
iothread_set_param/iothread_get_param") moved common code to set and
5
permissions but when we do _set_ the graph is already updated.
5
get IOThread parameters in two new functions.
6
Add an assertion to bdrv_reopen_multiple(), other cases are more
7
obvious.
8
6
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
These functions are called inside callbacks, so we don't need to use an
10
Message-Id: <20201106124241.16950-6-vsementsov@virtuozzo.com>
8
opaque pointer. Let's replace `void *opaque` parameter with
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
`IOThreadParamInfo *info`.
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20210727145936.147032-3-sgarzare@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
16
---
14
block.c | 29 +++++++++++++++--------------
17
iothread.c | 18 ++++++++++--------
15
1 file changed, 15 insertions(+), 14 deletions(-)
18
1 file changed, 10 insertions(+), 8 deletions(-)
16
19
17
diff --git a/block.c b/block.c
20
diff --git a/iothread.c b/iothread.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
22
--- a/iothread.c
20
+++ b/block.c
23
+++ b/iothread.c
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_abort_perm_update(BlockDriverState *bs)
24
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo aio_max_batch_info = {
22
}
25
};
26
27
static void iothread_get_param(Object *obj, Visitor *v,
28
- const char *name, void *opaque, Error **errp)
29
+ const char *name, IOThreadParamInfo *info, Error **errp)
30
{
31
IOThread *iothread = IOTHREAD(obj);
32
- IOThreadParamInfo *info = opaque;
33
int64_t *field = (void *)iothread + info->offset;
34
35
visit_type_int64(v, name, field, errp);
23
}
36
}
24
37
25
-static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
38
static bool iothread_set_param(Object *obj, Visitor *v,
26
- uint64_t cumulative_shared_perms)
39
- const char *name, void *opaque, Error **errp)
27
+static void bdrv_set_perm(BlockDriverState *bs)
40
+ const char *name, IOThreadParamInfo *info, Error **errp)
28
{
41
{
29
+ uint64_t cumulative_perms, cumulative_shared_perms;
42
IOThread *iothread = IOTHREAD(obj);
30
BlockDriver *drv = bs->drv;
43
- IOThreadParamInfo *info = opaque;
31
BdrvChild *c;
44
int64_t *field = (void *)iothread + info->offset;
32
45
int64_t value;
33
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
46
47
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
48
static void iothread_get_poll_param(Object *obj, Visitor *v,
49
const char *name, void *opaque, Error **errp)
50
{
51
+ IOThreadParamInfo *info = opaque;
52
53
- iothread_get_param(obj, v, name, opaque, errp);
54
+ iothread_get_param(obj, v, name, info, errp);
55
}
56
57
static void iothread_set_poll_param(Object *obj, Visitor *v,
58
const char *name, void *opaque, Error **errp)
59
{
60
IOThread *iothread = IOTHREAD(obj);
61
+ IOThreadParamInfo *info = opaque;
62
63
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
64
+ if (!iothread_set_param(obj, v, name, info, errp)) {
34
return;
65
return;
35
}
66
}
36
67
37
+ bdrv_get_cumulative_perm(bs, &cumulative_perms, &cumulative_shared_perms);
68
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
38
+
69
static void iothread_get_aio_param(Object *obj, Visitor *v,
39
/* Update this node */
70
const char *name, void *opaque, Error **errp)
40
if (drv->bdrv_set_perm) {
41
drv->bdrv_set_perm(bs, cumulative_perms, cumulative_shared_perms);
42
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
43
44
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
45
{
71
{
46
- uint64_t cumulative_perms, cumulative_shared_perms;
72
+ IOThreadParamInfo *info = opaque;
47
-
73
48
c->has_backup_perm = false;
74
- iothread_get_param(obj, v, name, opaque, errp);
49
75
+ iothread_get_param(obj, v, name, info, errp);
50
c->perm = perm;
51
c->shared_perm = shared;
52
53
- bdrv_get_cumulative_perm(c->bs, &cumulative_perms,
54
- &cumulative_shared_perms);
55
- bdrv_set_perm(c->bs, cumulative_perms, cumulative_shared_perms);
56
+ bdrv_set_perm(c->bs);
57
}
76
}
58
77
59
static void bdrv_child_abort_perm_update(BdrvChild *c)
78
static void iothread_set_aio_param(Object *obj, Visitor *v,
60
@@ -XXX,XX +XXX,XX @@ static int bdrv_refresh_perms(BlockDriverState *bs, bool *tighten_restrictions,
79
const char *name, void *opaque, Error **errp)
61
bdrv_abort_perm_update(bs);
80
{
62
return ret;
81
IOThread *iothread = IOTHREAD(obj);
82
+ IOThreadParamInfo *info = opaque;
83
84
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
85
+ if (!iothread_set_param(obj, v, name, info, errp)) {
86
return;
63
}
87
}
64
- bdrv_set_perm(bs, perm, shared_perm);
88
65
+ bdrv_set_perm(bs);
66
67
return 0;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
70
static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
71
{
72
BlockDriverState *old_bs = child->bs;
73
- uint64_t perm, shared_perm;
74
75
/* Asserts that child->frozen == false */
76
bdrv_replace_child_noperm(child, new_bs);
77
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
78
* restrictions.
79
*/
80
if (new_bs) {
81
- bdrv_get_cumulative_perm(new_bs, &perm, &shared_perm);
82
- bdrv_set_perm(new_bs, perm, shared_perm);
83
+ bdrv_set_perm(new_bs);
84
}
85
86
if (old_bs) {
87
@@ -XXX,XX +XXX,XX @@ cleanup_perm:
88
}
89
90
if (ret == 0) {
91
- bdrv_set_perm(state->bs, state->perm, state->shared_perm);
92
+ uint64_t perm, shared;
93
+
94
+ bdrv_get_cumulative_perm(state->bs, &perm, &shared);
95
+ assert(perm == state->perm);
96
+ assert(shared == state->shared_perm);
97
+
98
+ bdrv_set_perm(state->bs);
99
} else {
100
bdrv_abort_perm_update(state->bs);
101
if (state->replace_backing_bs && state->new_backing_bs) {
102
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_node_common(BlockDriverState *from,
103
bdrv_unref(from);
104
}
105
106
- bdrv_get_cumulative_perm(to, &perm, &shared);
107
- bdrv_set_perm(to, perm, shared);
108
+ bdrv_set_perm(to);
109
110
out:
111
g_slist_free(list);
112
--
89
--
113
2.29.2
90
2.31.1
114
91
115
92
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We must set the permission used for _check_. Assert that we have
4
backup and drop extra arguments.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201106124241.16950-7-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block.c | 15 ++++-----------
12
1 file changed, 4 insertions(+), 11 deletions(-)
13
14
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
17
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
19
GSList *ignore_children,
20
bool *tighten_restrictions, Error **errp);
21
static void bdrv_child_abort_perm_update(BdrvChild *c);
22
-static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
23
+static void bdrv_child_set_perm(BdrvChild *c);
24
25
typedef struct BlockReopenQueueEntry {
26
bool prepared;
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs)
28
29
/* Update all children */
30
QLIST_FOREACH(c, &bs->children, next) {
31
- uint64_t cur_perm, cur_shared;
32
- bdrv_child_perm(bs, c->bs, c, c->role, NULL,
33
- cumulative_perms, cumulative_shared_perms,
34
- &cur_perm, &cur_shared);
35
- bdrv_child_set_perm(c, cur_perm, cur_shared);
36
+ bdrv_child_set_perm(c);
37
}
38
}
39
40
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
41
return 0;
42
}
43
44
-static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
45
+static void bdrv_child_set_perm(BdrvChild *c)
46
{
47
c->has_backup_perm = false;
48
49
- c->perm = perm;
50
- c->shared_perm = shared;
51
-
52
bdrv_set_perm(c->bs);
53
}
54
55
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
56
return ret;
57
}
58
59
- bdrv_child_set_perm(c, perm, shared);
60
+ bdrv_child_set_perm(c);
61
62
return 0;
63
}
64
--
65
2.29.2
66
67
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
The only users of this thing are:
4
1. bdrv_child_try_set_perm, to ignore failures on loosen restrictions
5
2. assertion in bdrv_replace_child
6
3. assertion in bdrv_inactivate_recurse
7
8
Assertions are not enough reason for overcomplication the permission
9
update system. So, look at bdrv_child_try_set_perm.
10
11
We are interested in tighten_restrictions only on failure. But on
12
failure this field is not reliable: we may fail in the middle of
13
permission update, some nodes are not touched and we don't know should
14
their permissions be tighten or not. So, we rely on the fact that if we
15
loose restrictions on some node (or BdrvChild), we'll not tighten
16
restriction in the whole subtree as part of this update (assertions 2
17
and 3 rely on this fact as well). And, if we rely on this fact anyway,
18
we can just check it on top, and don't pass additional pointer through
19
the whole recursive infrastructure.
20
21
Note also, that further patches will fix real bugs in permission update
22
system, so now is good time to simplify it, as a help for further
23
refactorings.
24
25
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Message-Id: <20201106124241.16950-8-vsementsov@virtuozzo.com>
27
[mreitz: Fixed rebase conflict]
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
29
---
30
block.c | 89 +++++++++++----------------------------------------------
31
1 file changed, 17 insertions(+), 72 deletions(-)
32
33
diff --git a/block.c b/block.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block.c
36
+++ b/block.c
37
@@ -XXX,XX +XXX,XX @@ static int bdrv_fill_options(QDict **options, const char *filename,
38
39
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
40
uint64_t perm, uint64_t shared,
41
- GSList *ignore_children,
42
- bool *tighten_restrictions, Error **errp);
43
+ GSList *ignore_children, Error **errp);
44
static void bdrv_child_abort_perm_update(BdrvChild *c);
45
static void bdrv_child_set_perm(BdrvChild *c);
46
47
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
48
* permissions of all its parents. This involves checking whether all necessary
49
* permission changes to child nodes can be performed.
50
*
51
- * Will set *tighten_restrictions to true if and only if new permissions have to
52
- * be taken or currently shared permissions are to be unshared. Otherwise,
53
- * errors are not fatal as long as the caller accepts that the restrictions
54
- * remain tighter than they need to be. The caller still has to abort the
55
- * transaction.
56
- * @tighten_restrictions cannot be used together with @q: When reopening, we may
57
- * encounter fatal errors even though no restrictions are to be tightened. For
58
- * example, changing a node from RW to RO will fail if the WRITE permission is
59
- * to be kept.
60
- *
61
* A call to this function must always be followed by a call to bdrv_set_perm()
62
* or bdrv_abort_perm_update().
63
*/
64
static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
65
uint64_t cumulative_perms,
66
uint64_t cumulative_shared_perms,
67
- GSList *ignore_children,
68
- bool *tighten_restrictions, Error **errp)
69
+ GSList *ignore_children, Error **errp)
70
{
71
BlockDriver *drv = bs->drv;
72
BdrvChild *c;
73
int ret;
74
75
- assert(!q || !tighten_restrictions);
76
-
77
- if (tighten_restrictions) {
78
- uint64_t current_perms, current_shared;
79
- uint64_t added_perms, removed_shared_perms;
80
-
81
- bdrv_get_cumulative_perm(bs, &current_perms, &current_shared);
82
-
83
- added_perms = cumulative_perms & ~current_perms;
84
- removed_shared_perms = current_shared & ~cumulative_shared_perms;
85
-
86
- *tighten_restrictions = added_perms || removed_shared_perms;
87
- }
88
-
89
/* Write permissions never work with read-only images */
90
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
91
!bdrv_is_writable_after_reopen(bs, q))
92
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
93
/* Check all children */
94
QLIST_FOREACH(c, &bs->children, next) {
95
uint64_t cur_perm, cur_shared;
96
- bool child_tighten_restr;
97
98
bdrv_child_perm(bs, c->bs, c, c->role, q,
99
cumulative_perms, cumulative_shared_perms,
100
&cur_perm, &cur_shared);
101
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
102
- tighten_restrictions ? &child_tighten_restr
103
- : NULL,
104
errp);
105
- if (tighten_restrictions) {
106
- *tighten_restrictions |= child_tighten_restr;
107
- }
108
if (ret < 0) {
109
return ret;
110
}
111
@@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm)
112
* set, the BdrvChild objects in this list are ignored in the calculations;
113
* this allows checking permission updates for an existing reference.
114
*
115
- * See bdrv_check_perm() for the semantics of @tighten_restrictions.
116
- *
117
* Needs to be followed by a call to either bdrv_set_perm() or
118
* bdrv_abort_perm_update(). */
119
static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
120
uint64_t new_used_perm,
121
uint64_t new_shared_perm,
122
GSList *ignore_children,
123
- bool *tighten_restrictions,
124
Error **errp)
125
{
126
BdrvChild *c;
127
uint64_t cumulative_perms = new_used_perm;
128
uint64_t cumulative_shared_perms = new_shared_perm;
129
130
- assert(!q || !tighten_restrictions);
131
132
/* There is no reason why anyone couldn't tolerate write_unchanged */
133
assert(new_shared_perm & BLK_PERM_WRITE_UNCHANGED);
134
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
135
char *user = bdrv_child_user_desc(c);
136
char *perm_names = bdrv_perm_names(new_used_perm & ~c->shared_perm);
137
138
- if (tighten_restrictions) {
139
- *tighten_restrictions = true;
140
- }
141
-
142
error_setg(errp, "Conflicts with use by %s as '%s', which does not "
143
"allow '%s' on %s",
144
user, c->name, perm_names, bdrv_get_node_name(c->bs));
145
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
146
char *user = bdrv_child_user_desc(c);
147
char *perm_names = bdrv_perm_names(c->perm & ~new_shared_perm);
148
149
- if (tighten_restrictions) {
150
- *tighten_restrictions = true;
151
- }
152
-
153
error_setg(errp, "Conflicts with use by %s as '%s', which uses "
154
"'%s' on %s",
155
user, c->name, perm_names, bdrv_get_node_name(c->bs));
156
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
157
}
158
159
return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms,
160
- ignore_children, tighten_restrictions, errp);
161
+ ignore_children, errp);
162
}
163
164
/* Needs to be followed by a call to either bdrv_child_set_perm() or
165
* bdrv_child_abort_perm_update(). */
166
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
167
uint64_t perm, uint64_t shared,
168
- GSList *ignore_children,
169
- bool *tighten_restrictions, Error **errp)
170
+ GSList *ignore_children, Error **errp)
171
{
172
int ret;
173
174
ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c);
175
- ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children,
176
- tighten_restrictions, errp);
177
+ ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
178
g_slist_free(ignore_children);
179
180
if (ret < 0) {
181
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_abort_perm_update(BdrvChild *c)
182
bdrv_abort_perm_update(c->bs);
183
}
184
185
-static int bdrv_refresh_perms(BlockDriverState *bs, bool *tighten_restrictions,
186
- Error **errp)
187
+static int bdrv_refresh_perms(BlockDriverState *bs, Error **errp)
188
{
189
int ret;
190
uint64_t perm, shared_perm;
191
192
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
193
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
194
- tighten_restrictions, errp);
195
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, errp);
196
if (ret < 0) {
197
bdrv_abort_perm_update(bs);
198
return ret;
199
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
200
{
201
Error *local_err = NULL;
202
int ret;
203
- bool tighten_restrictions;
204
205
- ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL,
206
- &tighten_restrictions, &local_err);
207
+ ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, &local_err);
208
if (ret < 0) {
209
bdrv_child_abort_perm_update(c);
210
- if (tighten_restrictions) {
211
+ if ((perm & ~c->perm) || (c->shared_perm & ~shared)) {
212
+ /* tighten permissions */
213
error_propagate(errp, local_err);
214
} else {
215
/*
216
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
217
}
218
219
if (old_bs) {
220
- bool tighten_restrictions;
221
-
222
/*
223
* Update permissions for old node. We're just taking a parent away, so
224
* we're loosening restrictions. Errors of permission update are not
225
* fatal in this case, ignore them.
226
*/
227
- bdrv_refresh_perms(old_bs, &tighten_restrictions, NULL);
228
- assert(tighten_restrictions == false);
229
+ bdrv_refresh_perms(old_bs, NULL);
230
231
/* When the parent requiring a non-default AioContext is removed, the
232
* node moves back to the main AioContext */
233
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
234
Error *local_err = NULL;
235
int ret;
236
237
- ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, NULL,
238
- errp);
239
+ ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
240
if (ret < 0) {
241
bdrv_abort_perm_update(child_bs);
242
bdrv_unref(child_bs);
243
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
244
QTAILQ_FOREACH(bs_entry, bs_queue, entry) {
245
BDRVReopenState *state = &bs_entry->state;
246
ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
247
- state->shared_perm, NULL, NULL, errp);
248
+ state->shared_perm, NULL, errp);
249
if (ret < 0) {
250
goto cleanup_perm;
251
}
252
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
253
bs_queue, state->perm, state->shared_perm,
254
&nperm, &nshared);
255
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
256
- nperm, nshared, NULL, NULL, errp);
257
+ nperm, nshared, NULL, errp);
258
if (ret < 0) {
259
goto cleanup_perm;
260
}
261
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_node_common(BlockDriverState *from,
262
263
/* Check whether the required permissions can be granted on @to, ignoring
264
* all BdrvChild in @list so that they can't block themselves. */
265
- ret = bdrv_check_update_perm(to, NULL, perm, shared, list, NULL, errp);
266
+ ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp);
267
if (ret < 0) {
268
bdrv_abort_perm_update(to);
269
goto out;
270
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
271
*/
272
if (bs->open_flags & BDRV_O_INACTIVE) {
273
bs->open_flags &= ~BDRV_O_INACTIVE;
274
- ret = bdrv_refresh_perms(bs, NULL, errp);
275
+ ret = bdrv_refresh_perms(bs, errp);
276
if (ret < 0) {
277
bs->open_flags |= BDRV_O_INACTIVE;
278
return ret;
279
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
280
static int bdrv_inactivate_recurse(BlockDriverState *bs)
281
{
282
BdrvChild *child, *parent;
283
- bool tighten_restrictions;
284
int ret;
285
286
if (!bs->drv) {
287
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
288
* We only tried to loosen restrictions, so errors are not fatal, ignore
289
* them.
290
*/
291
- bdrv_refresh_perms(bs, &tighten_restrictions, NULL);
292
- assert(tighten_restrictions == false);
293
+ bdrv_refresh_perms(bs, NULL);
294
295
/* Recursively inactivate children */
296
QLIST_FOREACH(child, &bs->children, next) {
297
--
298
2.29.2
299
300
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
1. BDRV_REQ_NO_SERIALISING doesn't exist already, don't mention it.
4
5
2. We are going to add one more user of BDRV_REQ_SERIALISING, so
6
comment about backup becomes a bit confusing here. The use case in
7
backup is documented in block/backup.c, so let's just drop
8
duplication here.
9
10
3. The fact that BDRV_REQ_SERIALISING is only for write requests is
11
omitted. Add a note.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Message-Id: <20201021145859.11201-2-vsementsov@virtuozzo.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
include/block/block.h | 11 +----------
20
1 file changed, 1 insertion(+), 10 deletions(-)
21
22
diff --git a/include/block/block.h b/include/block/block.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/block.h
25
+++ b/include/block/block.h
26
@@ -XXX,XX +XXX,XX @@ typedef enum {
27
* content. */
28
BDRV_REQ_WRITE_UNCHANGED = 0x40,
29
30
- /*
31
- * BDRV_REQ_SERIALISING forces request serialisation for writes.
32
- * It is used to ensure that writes to the backing file of a backup process
33
- * target cannot race with a read of the backup target that defers to the
34
- * backing file.
35
- *
36
- * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to
37
- * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter might be
38
- * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long.
39
- */
40
+ /* Forces request serialisation. Use only with write requests. */
41
BDRV_REQ_SERIALISING = 0x80,
42
43
/* Execute the request only if the operation can be offloaded or otherwise
44
--
45
2.29.2
46
47
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
The comments states, that on misaligned request we should have already
4
been waiting. But for bdrv_padding_rmw_read, we called
5
bdrv_mark_request_serialising with align = request_alignment, and now
6
we serialise with align = cluster_size. So we may have to wait again
7
with larger alignment.
8
9
Note, that the only user of BDRV_REQ_SERIALISING is backup which issues
10
cluster-aligned requests, so seems the assertion should not fire for
11
now. But it's wrong anyway.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20201021145859.11201-3-vsementsov@virtuozzo.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/io.c | 11 +----------
19
1 file changed, 1 insertion(+), 10 deletions(-)
20
21
diff --git a/block/io.c b/block/io.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/io.c
24
+++ b/block/io.c
25
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
26
BdrvTrackedRequest *req, int flags)
27
{
28
BlockDriverState *bs = child->bs;
29
- bool waited;
30
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
31
32
if (bs->read_only) {
33
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
34
assert(!(flags & ~BDRV_REQ_MASK));
35
36
if (flags & BDRV_REQ_SERIALISING) {
37
- waited = bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
38
- /*
39
- * For a misaligned request we should have already waited earlier,
40
- * because we come after bdrv_padding_rmw_read which must be called
41
- * with the request already marked as serialising.
42
- */
43
- assert(!waited ||
44
- (req->offset == req->overlap_offset &&
45
- req->bytes == req->overlap_bytes));
46
+ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
47
} else {
48
bdrv_wait_serialising_requests(req);
49
}
50
--
51
2.29.2
52
53
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
bs is linked in req, so no needs to pass it separately. Most of
4
tracked-requests API doesn't have bs argument. Actually, after this
5
patch only tracked_request_begin has it, but it's for purpose.
6
7
While being here, also add a comment about what "_locked" is.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20201021145859.11201-5-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/io.c | 10 +++++-----
15
1 file changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/block/io.c b/block/io.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/io.c
20
+++ b/block/io.c
21
@@ -XXX,XX +XXX,XX @@ bdrv_find_conflicting_request(BdrvTrackedRequest *self)
22
return NULL;
23
}
24
25
+/* Called with self->bs->reqs_lock held */
26
static bool coroutine_fn
27
-bdrv_wait_serialising_requests_locked(BlockDriverState *bs,
28
- BdrvTrackedRequest *self)
29
+bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self)
30
{
31
BdrvTrackedRequest *req;
32
bool waited = false;
33
34
while ((req = bdrv_find_conflicting_request(self))) {
35
self->waiting_for = req;
36
- qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock);
37
+ qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock);
38
self->waiting_for = NULL;
39
waited = true;
40
}
41
@@ -XXX,XX +XXX,XX @@ bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
42
43
req->overlap_offset = MIN(req->overlap_offset, overlap_offset);
44
req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
45
- waited = bdrv_wait_serialising_requests_locked(bs, req);
46
+ waited = bdrv_wait_serialising_requests_locked(req);
47
qemu_co_mutex_unlock(&bs->reqs_lock);
48
return waited;
49
}
50
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self
51
}
52
53
qemu_co_mutex_lock(&bs->reqs_lock);
54
- waited = bdrv_wait_serialising_requests_locked(bs, self);
55
+ waited = bdrv_wait_serialising_requests_locked(self);
56
qemu_co_mutex_unlock(&bs->reqs_lock);
57
58
return waited;
59
--
60
2.29.2
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We'll need a separate function, which will only "mark" request
4
serialising with specified align but not wait for conflicting
5
requests. So, it will be like old bdrv_mark_request_serialising(),
6
before merging bdrv_wait_serialising_requests_locked() into it.
7
8
To reduce the possible mess, let's do the following:
9
10
Public function that does both marking and waiting will be called
11
bdrv_make_request_serialising, and private function which will only
12
"mark" will be called tracked_request_set_serialising().
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Message-Id: <20201021145859.11201-6-vsementsov@virtuozzo.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
include/block/block_int.h | 3 ++-
20
block/file-posix.c | 2 +-
21
block/io.c | 35 +++++++++++++++++++++++------------
22
3 files changed, 26 insertions(+), 14 deletions(-)
23
24
diff --git a/include/block/block_int.h b/include/block/block_int.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block_int.h
27
+++ b/include/block/block_int.h
28
@@ -XXX,XX +XXX,XX @@ extern unsigned int bdrv_drain_all_count;
29
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
30
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
31
32
-bool coroutine_fn bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
33
+bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
34
+ uint64_t align);
35
BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs);
36
37
int get_tmp_filename(char *filename, int size);
38
diff --git a/block/file-posix.c b/block/file-posix.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/file-posix.c
41
+++ b/block/file-posix.c
42
@@ -XXX,XX +XXX,XX @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
43
44
assert(bdrv_check_request(req->offset, req->bytes) == 0);
45
46
- bdrv_mark_request_serialising(req, bs->bl.request_alignment);
47
+ bdrv_make_request_serialising(req, bs->bl.request_alignment);
48
}
49
#endif
50
51
diff --git a/block/io.c b/block/io.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/io.c
54
+++ b/block/io.c
55
@@ -XXX,XX +XXX,XX @@ bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self)
56
return waited;
57
}
58
59
-bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
60
+/* Called with req->bs->reqs_lock held */
61
+static void tracked_request_set_serialising(BdrvTrackedRequest *req,
62
+ uint64_t align)
63
{
64
- BlockDriverState *bs = req->bs;
65
int64_t overlap_offset = req->offset & ~(align - 1);
66
uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
67
- overlap_offset;
68
- bool waited;
69
70
- qemu_co_mutex_lock(&bs->reqs_lock);
71
if (!req->serialising) {
72
qatomic_inc(&req->bs->serialising_in_flight);
73
req->serialising = true;
74
@@ -XXX,XX +XXX,XX @@ bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
75
76
req->overlap_offset = MIN(req->overlap_offset, overlap_offset);
77
req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
78
- waited = bdrv_wait_serialising_requests_locked(req);
79
- qemu_co_mutex_unlock(&bs->reqs_lock);
80
- return waited;
81
}
82
83
/**
84
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self
85
return waited;
86
}
87
88
+bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
89
+ uint64_t align)
90
+{
91
+ bool waited;
92
+
93
+ qemu_co_mutex_lock(&req->bs->reqs_lock);
94
+
95
+ tracked_request_set_serialising(req, align);
96
+ waited = bdrv_wait_serialising_requests_locked(req);
97
+
98
+ qemu_co_mutex_unlock(&req->bs->reqs_lock);
99
+
100
+ return waited;
101
+}
102
+
103
int bdrv_check_request(int64_t offset, int64_t bytes)
104
{
105
if (offset < 0 || bytes < 0) {
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
107
* with each other for the same cluster. For example, in copy-on-read
108
* it ensures that the CoR read and write operations are atomic and
109
* guest writes cannot interleave between them. */
110
- bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
111
+ bdrv_make_request_serialising(req, bdrv_get_cluster_size(bs));
112
} else {
113
bdrv_wait_serialising_requests(req);
114
}
115
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
116
assert(!(flags & ~BDRV_REQ_MASK));
117
118
if (flags & BDRV_REQ_SERIALISING) {
119
- bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
120
+ bdrv_make_request_serialising(req, bdrv_get_cluster_size(bs));
121
} else {
122
bdrv_wait_serialising_requests(req);
123
}
124
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
125
126
padding = bdrv_init_padding(bs, offset, bytes, &pad);
127
if (padding) {
128
- bdrv_mark_request_serialising(req, align);
129
+ bdrv_make_request_serialising(req, align);
130
131
bdrv_padding_rmw_read(child, req, &pad, true);
132
133
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
134
}
135
136
if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) {
137
- bdrv_mark_request_serialising(&req, align);
138
+ bdrv_make_request_serialising(&req, align);
139
bdrv_padding_rmw_read(child, &req, &pad, false);
140
}
141
142
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
143
* new area, we need to make sure that no write requests are made to it
144
* concurrently or they might be overwritten by preallocation. */
145
if (new_bytes) {
146
- bdrv_mark_request_serialising(&req, 1);
147
+ bdrv_make_request_serialising(&req, 1);
148
}
149
if (bs->read_only) {
150
error_setg(errp, "Image is read-only");
151
--
152
2.29.2
153
154
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add flag to make serialising request no wait: if there are conflicting
4
requests, just return error immediately. It's will be used in upcoming
5
preallocate filter.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20201021145859.11201-7-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
include/block/block.h | 9 ++++++++-
13
block/io.c | 11 ++++++++++-
14
2 files changed, 18 insertions(+), 2 deletions(-)
15
16
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
19
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
21
* written to qiov parameter which may be NULL.
22
*/
23
BDRV_REQ_PREFETCH = 0x200,
24
+
25
+ /*
26
+ * If we need to wait for other requests, just fail immediately. Used
27
+ * only together with BDRV_REQ_SERIALISING.
28
+ */
29
+ BDRV_REQ_NO_WAIT = 0x400,
30
+
31
/* Mask of valid flags */
32
- BDRV_REQ_MASK = 0x3ff,
33
+ BDRV_REQ_MASK = 0x7ff,
34
} BdrvRequestFlags;
35
36
typedef struct BlockSizes {
37
diff --git a/block/io.c b/block/io.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/io.c
40
+++ b/block/io.c
41
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
42
assert(!(bs->open_flags & BDRV_O_INACTIVE));
43
assert((bs->open_flags & BDRV_O_NO_IO) == 0);
44
assert(!(flags & ~BDRV_REQ_MASK));
45
+ assert(!((flags & BDRV_REQ_NO_WAIT) && !(flags & BDRV_REQ_SERIALISING)));
46
47
if (flags & BDRV_REQ_SERIALISING) {
48
- bdrv_make_request_serialising(req, bdrv_get_cluster_size(bs));
49
+ QEMU_LOCK_GUARD(&bs->reqs_lock);
50
+
51
+ tracked_request_set_serialising(req, bdrv_get_cluster_size(bs));
52
+
53
+ if ((flags & BDRV_REQ_NO_WAIT) && bdrv_find_conflicting_request(req)) {
54
+ return -EBUSY;
55
+ }
56
+
57
+ bdrv_wait_serialising_requests_locked(req);
58
} else {
59
bdrv_wait_serialising_requests(req);
60
}
61
--
62
2.29.2
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Do generic processing even for drivers which define .bdrv_check_perm
4
handler. It's needed for further preallocate filter: it will need to do
5
additional action on bdrv_check_perm, but don't want to reimplement
6
generic logic.
7
8
The patch doesn't change existing behaviour: the only driver that
9
implements bdrv_check_perm is file-posix, but it never has any
10
children.
11
12
Also, bdrv_set_perm() don't stop processing if driver has
13
.bdrv_set_perm handler as well.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-Id: <20201021145859.11201-8-vsementsov@virtuozzo.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block.c | 7 +++++--
21
1 file changed, 5 insertions(+), 2 deletions(-)
22
23
diff --git a/block.c b/block.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
26
+++ b/block.c
27
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
28
}
29
30
if (drv->bdrv_check_perm) {
31
- return drv->bdrv_check_perm(bs, cumulative_perms,
32
- cumulative_shared_perms, errp);
33
+ ret = drv->bdrv_check_perm(bs, cumulative_perms,
34
+ cumulative_shared_perms, errp);
35
+ if (ret < 0) {
36
+ return ret;
37
+ }
38
}
39
40
/* Drivers that never have children can omit .bdrv_child_perm() */
41
--
42
2.29.2
43
44
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
It's intended to be inserted between format and protocol nodes to
4
preallocate additional space (expanding protocol file) on writes
5
crossing EOF. It improves performance for file-systems with slow
6
allocation.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-Id: <20201021145859.11201-9-vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
[mreitz: Two comment fixes, and bumped the version from 5.2 to 6.0]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
docs/system/qemu-block-drivers.rst.inc | 26 ++
15
qapi/block-core.json | 20 +-
16
block/preallocate.c | 559 +++++++++++++++++++++++++
17
block/meson.build | 1 +
18
4 files changed, 605 insertions(+), 1 deletion(-)
19
create mode 100644 block/preallocate.c
20
21
diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/system/qemu-block-drivers.rst.inc
24
+++ b/docs/system/qemu-block-drivers.rst.inc
25
@@ -XXX,XX +XXX,XX @@ on host and see if there are locks held by the QEMU process on the image file.
26
More than one byte could be locked by the QEMU instance, each byte of which
27
reflects a particular permission that is acquired or protected by the running
28
block driver.
29
+
30
+Filter drivers
31
+~~~~~~~~~~~~~~
32
+
33
+QEMU supports several filter drivers, which don't store any data, but perform
34
+some additional tasks, hooking io requests.
35
+
36
+.. program:: filter-drivers
37
+.. option:: preallocate
38
+
39
+ The preallocate filter driver is intended to be inserted between format
40
+ and protocol nodes and preallocates some additional space
41
+ (expanding the protocol file) when writing past the file’s end. This can be
42
+ useful for file-systems with slow allocation.
43
+
44
+ Supported options:
45
+
46
+ .. program:: preallocate
47
+ .. option:: prealloc-align
48
+
49
+ On preallocation, align the file length to this value (in bytes), default 1M.
50
+
51
+ .. program:: preallocate
52
+ .. option:: prealloc-size
53
+
54
+ How much to preallocate (in bytes), default 128M.
55
diff --git a/qapi/block-core.json b/qapi/block-core.json
56
index XXXXXXX..XXXXXXX 100644
57
--- a/qapi/block-core.json
58
+++ b/qapi/block-core.json
59
@@ -XXX,XX +XXX,XX @@
60
'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
61
'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
62
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
63
- 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
64
+ 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
65
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
66
'sheepdog',
67
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
68
@@ -XXX,XX +XXX,XX @@
69
'data': { 'aes': 'QCryptoBlockOptionsQCow',
70
'luks': 'QCryptoBlockOptionsLUKS'} }
71
72
+##
73
+# @BlockdevOptionsPreallocate:
74
+#
75
+# Filter driver intended to be inserted between format and protocol node
76
+# and do preallocation in protocol node on write.
77
+#
78
+# @prealloc-align: on preallocation, align file length to this number,
79
+# default 1048576 (1M)
80
+#
81
+# @prealloc-size: how much to preallocate, default 134217728 (128M)
82
+#
83
+# Since: 6.0
84
+##
85
+{ 'struct': 'BlockdevOptionsPreallocate',
86
+ 'base': 'BlockdevOptionsGenericFormat',
87
+ 'data': { '*prealloc-align': 'int', '*prealloc-size': 'int' } }
88
+
89
##
90
# @BlockdevOptionsQcow2:
91
#
92
@@ -XXX,XX +XXX,XX @@
93
'null-co': 'BlockdevOptionsNull',
94
'nvme': 'BlockdevOptionsNVMe',
95
'parallels': 'BlockdevOptionsGenericFormat',
96
+ 'preallocate':'BlockdevOptionsPreallocate',
97
'qcow2': 'BlockdevOptionsQcow2',
98
'qcow': 'BlockdevOptionsQcow',
99
'qed': 'BlockdevOptionsGenericCOWFormat',
100
diff --git a/block/preallocate.c b/block/preallocate.c
101
new file mode 100644
102
index XXXXXXX..XXXXXXX
103
--- /dev/null
104
+++ b/block/preallocate.c
105
@@ -XXX,XX +XXX,XX @@
106
+/*
107
+ * preallocate filter driver
108
+ *
109
+ * The driver performs preallocate operation: it is injected above
110
+ * some node, and before each write over EOF it does additional preallocating
111
+ * write-zeroes request.
112
+ *
113
+ * Copyright (c) 2020 Virtuozzo International GmbH.
114
+ *
115
+ * Author:
116
+ * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
117
+ *
118
+ * This program is free software; you can redistribute it and/or modify
119
+ * it under the terms of the GNU General Public License as published by
120
+ * the Free Software Foundation; either version 2 of the License, or
121
+ * (at your option) any later version.
122
+ *
123
+ * This program is distributed in the hope that it will be useful,
124
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
125
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
126
+ * GNU General Public License for more details.
127
+ *
128
+ * You should have received a copy of the GNU General Public License
129
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
130
+ */
131
+
132
+#include "qemu/osdep.h"
133
+
134
+#include "qapi/error.h"
135
+#include "qemu/module.h"
136
+#include "qemu/option.h"
137
+#include "qemu/units.h"
138
+#include "block/block_int.h"
139
+
140
+
141
+typedef struct PreallocateOpts {
142
+ int64_t prealloc_size;
143
+ int64_t prealloc_align;
144
+} PreallocateOpts;
145
+
146
+typedef struct BDRVPreallocateState {
147
+ PreallocateOpts opts;
148
+
149
+ /*
150
+ * Track real data end, to crop preallocation on close. If < 0 the status is
151
+ * unknown.
152
+ *
153
+ * @data_end is a maximum of file size on open (or when we get write/resize
154
+ * permissions) and all write request ends after it. So it's safe to
155
+ * truncate to data_end if it is valid.
156
+ */
157
+ int64_t data_end;
158
+
159
+ /*
160
+ * Start of trailing preallocated area which reads as zero. May be smaller
161
+ * than data_end, if user does over-EOF write zero operation. If < 0 the
162
+ * status is unknown.
163
+ *
164
+ * If both @zero_start and @file_end are valid, the region
165
+ * [@zero_start, @file_end) is known to be preallocated zeroes. If @file_end
166
+ * is not valid, @zero_start doesn't make much sense.
167
+ */
168
+ int64_t zero_start;
169
+
170
+ /*
171
+ * Real end of file. Actually the cache for bdrv_getlength(bs->file->bs),
172
+ * to avoid extra lseek() calls on each write operation. If < 0 the status
173
+ * is unknown.
174
+ */
175
+ int64_t file_end;
176
+
177
+ /*
178
+ * All three states @data_end, @zero_start and @file_end are guaranteed to
179
+ * be invalid (< 0) when we don't have both exclusive BLK_PERM_RESIZE and
180
+ * BLK_PERM_WRITE permissions on file child.
181
+ */
182
+} BDRVPreallocateState;
183
+
184
+#define PREALLOCATE_OPT_PREALLOC_ALIGN "prealloc-align"
185
+#define PREALLOCATE_OPT_PREALLOC_SIZE "prealloc-size"
186
+static QemuOptsList runtime_opts = {
187
+ .name = "preallocate",
188
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
189
+ .desc = {
190
+ {
191
+ .name = PREALLOCATE_OPT_PREALLOC_ALIGN,
192
+ .type = QEMU_OPT_SIZE,
193
+ .help = "on preallocation, align file length to this number, "
194
+ "default 1M",
195
+ },
196
+ {
197
+ .name = PREALLOCATE_OPT_PREALLOC_SIZE,
198
+ .type = QEMU_OPT_SIZE,
199
+ .help = "how much to preallocate, default 128M",
200
+ },
201
+ { /* end of list */ }
202
+ },
203
+};
204
+
205
+static bool preallocate_absorb_opts(PreallocateOpts *dest, QDict *options,
206
+ BlockDriverState *child_bs, Error **errp)
207
+{
208
+ QemuOpts *opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
209
+
210
+ if (!qemu_opts_absorb_qdict(opts, options, errp)) {
211
+ return false;
212
+ }
213
+
214
+ dest->prealloc_align =
215
+ qemu_opt_get_size(opts, PREALLOCATE_OPT_PREALLOC_ALIGN, 1 * MiB);
216
+ dest->prealloc_size =
217
+ qemu_opt_get_size(opts, PREALLOCATE_OPT_PREALLOC_SIZE, 128 * MiB);
218
+
219
+ qemu_opts_del(opts);
220
+
221
+ if (!QEMU_IS_ALIGNED(dest->prealloc_align, BDRV_SECTOR_SIZE)) {
222
+ error_setg(errp, "prealloc-align parameter of preallocate filter "
223
+ "is not aligned to %llu", BDRV_SECTOR_SIZE);
224
+ return false;
225
+ }
226
+
227
+ if (!QEMU_IS_ALIGNED(dest->prealloc_align,
228
+ child_bs->bl.request_alignment)) {
229
+ error_setg(errp, "prealloc-align parameter of preallocate filter "
230
+ "is not aligned to underlying node request alignment "
231
+ "(%" PRIi32 ")", child_bs->bl.request_alignment);
232
+ return false;
233
+ }
234
+
235
+ return true;
236
+}
237
+
238
+static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
239
+ Error **errp)
240
+{
241
+ BDRVPreallocateState *s = bs->opaque;
242
+
243
+ /*
244
+ * s->data_end and friends should be initialized on permission update.
245
+ * For this to work, mark them invalid.
246
+ */
247
+ s->file_end = s->zero_start = s->data_end = -EINVAL;
248
+
249
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
250
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
251
+ false, errp);
252
+ if (!bs->file) {
253
+ return -EINVAL;
254
+ }
255
+
256
+ if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
257
+ return -EINVAL;
258
+ }
259
+
260
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
261
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
262
+
263
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
264
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
265
+ bs->file->bs->supported_zero_flags);
266
+
267
+ return 0;
268
+}
269
+
270
+static void preallocate_close(BlockDriverState *bs)
271
+{
272
+ int ret;
273
+ BDRVPreallocateState *s = bs->opaque;
274
+
275
+ if (s->data_end < 0) {
276
+ return;
277
+ }
278
+
279
+ if (s->file_end < 0) {
280
+ s->file_end = bdrv_getlength(bs->file->bs);
281
+ if (s->file_end < 0) {
282
+ return;
283
+ }
284
+ }
285
+
286
+ if (s->data_end < s->file_end) {
287
+ ret = bdrv_truncate(bs->file, s->data_end, true, PREALLOC_MODE_OFF, 0,
288
+ NULL);
289
+ s->file_end = ret < 0 ? ret : s->data_end;
290
+ }
291
+}
292
+
293
+
294
+/*
295
+ * Handle reopen.
296
+ *
297
+ * We must implement reopen handlers, otherwise reopen just don't work. Handle
298
+ * new options and don't care about preallocation state, as it is handled in
299
+ * set/check permission handlers.
300
+ */
301
+
302
+static int preallocate_reopen_prepare(BDRVReopenState *reopen_state,
303
+ BlockReopenQueue *queue, Error **errp)
304
+{
305
+ PreallocateOpts *opts = g_new0(PreallocateOpts, 1);
306
+
307
+ if (!preallocate_absorb_opts(opts, reopen_state->options,
308
+ reopen_state->bs->file->bs, errp)) {
309
+ g_free(opts);
310
+ return -EINVAL;
311
+ }
312
+
313
+ reopen_state->opaque = opts;
314
+
315
+ return 0;
316
+}
317
+
318
+static void preallocate_reopen_commit(BDRVReopenState *state)
319
+{
320
+ BDRVPreallocateState *s = state->bs->opaque;
321
+
322
+ s->opts = *(PreallocateOpts *)state->opaque;
323
+
324
+ g_free(state->opaque);
325
+ state->opaque = NULL;
326
+}
327
+
328
+static void preallocate_reopen_abort(BDRVReopenState *state)
329
+{
330
+ g_free(state->opaque);
331
+ state->opaque = NULL;
332
+}
333
+
334
+static coroutine_fn int preallocate_co_preadv_part(
335
+ BlockDriverState *bs, uint64_t offset, uint64_t bytes,
336
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
337
+{
338
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
339
+ flags);
340
+}
341
+
342
+static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs,
343
+ int64_t offset, int bytes)
344
+{
345
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
346
+}
347
+
348
+static bool can_write_resize(uint64_t perm)
349
+{
350
+ return (perm & BLK_PERM_WRITE) && (perm & BLK_PERM_RESIZE);
351
+}
352
+
353
+static bool has_prealloc_perms(BlockDriverState *bs)
354
+{
355
+ BDRVPreallocateState *s = bs->opaque;
356
+
357
+ if (can_write_resize(bs->file->perm)) {
358
+ assert(!(bs->file->shared_perm & BLK_PERM_WRITE));
359
+ assert(!(bs->file->shared_perm & BLK_PERM_RESIZE));
360
+ return true;
361
+ }
362
+
363
+ assert(s->data_end < 0);
364
+ assert(s->zero_start < 0);
365
+ assert(s->file_end < 0);
366
+ return false;
367
+}
368
+
369
+/*
370
+ * Call on each write. Returns true if @want_merge_zero is true and the region
371
+ * [offset, offset + bytes) is zeroed (as a result of this call or earlier
372
+ * preallocation).
373
+ *
374
+ * want_merge_zero is used to merge write-zero request with preallocation in
375
+ * one bdrv_co_pwrite_zeroes() call.
376
+ */
377
+static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
378
+ int64_t bytes, bool want_merge_zero)
379
+{
380
+ BDRVPreallocateState *s = bs->opaque;
381
+ int64_t end = offset + bytes;
382
+ int64_t prealloc_start, prealloc_end;
383
+ int ret;
384
+
385
+ if (!has_prealloc_perms(bs)) {
386
+ /* We don't have state neither should try to recover it */
387
+ return false;
388
+ }
389
+
390
+ if (s->data_end < 0) {
391
+ s->data_end = bdrv_getlength(bs->file->bs);
392
+ if (s->data_end < 0) {
393
+ return false;
394
+ }
395
+
396
+ if (s->file_end < 0) {
397
+ s->file_end = s->data_end;
398
+ }
399
+ }
400
+
401
+ if (end <= s->data_end) {
402
+ return false;
403
+ }
404
+
405
+ /* We have valid s->data_end, and request writes beyond it. */
406
+
407
+ s->data_end = end;
408
+ if (s->zero_start < 0 || !want_merge_zero) {
409
+ s->zero_start = end;
410
+ }
411
+
412
+ if (s->file_end < 0) {
413
+ s->file_end = bdrv_getlength(bs->file->bs);
414
+ if (s->file_end < 0) {
415
+ return false;
416
+ }
417
+ }
418
+
419
+ /* Now s->data_end, s->zero_start and s->file_end are valid. */
420
+
421
+ if (end <= s->file_end) {
422
+ /* No preallocation needed. */
423
+ return want_merge_zero && offset >= s->zero_start;
424
+ }
425
+
426
+ /* Now we want new preallocation, as request writes beyond s->file_end. */
427
+
428
+ prealloc_start = want_merge_zero ? MIN(offset, s->file_end) : s->file_end;
429
+ prealloc_end = QEMU_ALIGN_UP(end + s->opts.prealloc_size,
430
+ s->opts.prealloc_align);
431
+
432
+ ret = bdrv_co_pwrite_zeroes(
433
+ bs->file, prealloc_start, prealloc_end - prealloc_start,
434
+ BDRV_REQ_NO_FALLBACK | BDRV_REQ_SERIALISING | BDRV_REQ_NO_WAIT);
435
+ if (ret < 0) {
436
+ s->file_end = ret;
437
+ return false;
438
+ }
439
+
440
+ s->file_end = prealloc_end;
441
+ return want_merge_zero;
442
+}
443
+
444
+static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs,
445
+ int64_t offset, int bytes, BdrvRequestFlags flags)
446
+{
447
+ bool want_merge_zero =
448
+ !(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK));
449
+ if (handle_write(bs, offset, bytes, want_merge_zero)) {
450
+ return 0;
451
+ }
452
+
453
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
454
+}
455
+
456
+static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
457
+ uint64_t offset,
458
+ uint64_t bytes,
459
+ QEMUIOVector *qiov,
460
+ size_t qiov_offset,
461
+ int flags)
462
+{
463
+ handle_write(bs, offset, bytes, false);
464
+
465
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
466
+ flags);
467
+}
468
+
469
+static int coroutine_fn
470
+preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
471
+ bool exact, PreallocMode prealloc,
472
+ BdrvRequestFlags flags, Error **errp)
473
+{
474
+ ERRP_GUARD();
475
+ BDRVPreallocateState *s = bs->opaque;
476
+ int ret;
477
+
478
+ if (s->data_end >= 0 && offset > s->data_end) {
479
+ if (s->file_end < 0) {
480
+ s->file_end = bdrv_getlength(bs->file->bs);
481
+ if (s->file_end < 0) {
482
+ error_setg(errp, "failed to get file length");
483
+ return s->file_end;
484
+ }
485
+ }
486
+
487
+ if (prealloc == PREALLOC_MODE_FALLOC) {
488
+ /*
489
+ * If offset <= s->file_end, the task is already done, just
490
+ * update s->data_end, to move part of "filter preallocation"
491
+ * to "preallocation requested by user".
492
+ * Otherwise just proceed to preallocate missing part.
493
+ */
494
+ if (offset <= s->file_end) {
495
+ s->data_end = offset;
496
+ return 0;
497
+ }
498
+ } else {
499
+ /*
500
+ * We have to drop our preallocation, to
501
+ * - avoid "Cannot use preallocation for shrinking files" in
502
+ * case of offset < file_end
503
+ * - give PREALLOC_MODE_OFF a chance to keep small disk
504
+ * usage
505
+ * - give PREALLOC_MODE_FULL a chance to actually write the
506
+ * whole region as user expects
507
+ */
508
+ if (s->file_end > s->data_end) {
509
+ ret = bdrv_co_truncate(bs->file, s->data_end, true,
510
+ PREALLOC_MODE_OFF, 0, errp);
511
+ if (ret < 0) {
512
+ s->file_end = ret;
513
+ error_prepend(errp, "preallocate-filter: failed to drop "
514
+ "write-zero preallocation: ");
515
+ return ret;
516
+ }
517
+ s->file_end = s->data_end;
518
+ }
519
+ }
520
+
521
+ s->data_end = offset;
522
+ }
523
+
524
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
525
+ if (ret < 0) {
526
+ s->file_end = s->zero_start = s->data_end = ret;
527
+ return ret;
528
+ }
529
+
530
+ if (has_prealloc_perms(bs)) {
531
+ s->file_end = s->zero_start = s->data_end = offset;
532
+ }
533
+ return 0;
534
+}
535
+
536
+static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
537
+{
538
+ return bdrv_co_flush(bs->file->bs);
539
+}
540
+
541
+static int64_t preallocate_getlength(BlockDriverState *bs)
542
+{
543
+ int64_t ret;
544
+ BDRVPreallocateState *s = bs->opaque;
545
+
546
+ if (s->data_end >= 0) {
547
+ return s->data_end;
548
+ }
549
+
550
+ ret = bdrv_getlength(bs->file->bs);
551
+
552
+ if (has_prealloc_perms(bs)) {
553
+ s->file_end = s->zero_start = s->data_end = ret;
554
+ }
555
+
556
+ return ret;
557
+}
558
+
559
+static int preallocate_check_perm(BlockDriverState *bs,
560
+ uint64_t perm, uint64_t shared, Error **errp)
561
+{
562
+ BDRVPreallocateState *s = bs->opaque;
563
+
564
+ if (s->data_end >= 0 && !can_write_resize(perm)) {
565
+ /*
566
+ * Lose permissions.
567
+ * We should truncate in check_perm, as in set_perm bs->file->perm will
568
+ * be already changed, and we should not violate it.
569
+ */
570
+ if (s->file_end < 0) {
571
+ s->file_end = bdrv_getlength(bs->file->bs);
572
+ if (s->file_end < 0) {
573
+ error_setg(errp, "Failed to get file length");
574
+ return s->file_end;
575
+ }
576
+ }
577
+
578
+ if (s->data_end < s->file_end) {
579
+ int ret = bdrv_truncate(bs->file, s->data_end, true,
580
+ PREALLOC_MODE_OFF, 0, NULL);
581
+ if (ret < 0) {
582
+ error_setg(errp, "Failed to drop preallocation");
583
+ s->file_end = ret;
584
+ return ret;
585
+ }
586
+ s->file_end = s->data_end;
587
+ }
588
+ }
589
+
590
+ return 0;
591
+}
592
+
593
+static void preallocate_set_perm(BlockDriverState *bs,
594
+ uint64_t perm, uint64_t shared)
595
+{
596
+ BDRVPreallocateState *s = bs->opaque;
597
+
598
+ if (can_write_resize(perm)) {
599
+ if (s->data_end < 0) {
600
+ s->data_end = s->file_end = s->zero_start =
601
+ bdrv_getlength(bs->file->bs);
602
+ }
603
+ } else {
604
+ /*
605
+ * We drop our permissions, as well as allow shared
606
+ * permissions (see preallocate_child_perm), anyone will be able to
607
+ * change the child, so mark all states invalid. We'll regain control if
608
+ * get good permissions back.
609
+ */
610
+ s->data_end = s->file_end = s->zero_start = -EINVAL;
611
+ }
612
+}
613
+
614
+static void preallocate_child_perm(BlockDriverState *bs, BdrvChild *c,
615
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
616
+ uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared)
617
+{
618
+ bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm, nshared);
619
+
620
+ if (can_write_resize(perm)) {
621
+ /* This should come by default, but let's enforce: */
622
+ *nperm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
623
+
624
+ /*
625
+ * Don't share, to keep our states s->file_end, s->data_end and
626
+ * s->zero_start valid.
627
+ */
628
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
629
+ }
630
+}
631
+
632
+BlockDriver bdrv_preallocate_filter = {
633
+ .format_name = "preallocate",
634
+ .instance_size = sizeof(BDRVPreallocateState),
635
+
636
+ .bdrv_getlength = preallocate_getlength,
637
+ .bdrv_open = preallocate_open,
638
+ .bdrv_close = preallocate_close,
639
+
640
+ .bdrv_reopen_prepare = preallocate_reopen_prepare,
641
+ .bdrv_reopen_commit = preallocate_reopen_commit,
642
+ .bdrv_reopen_abort = preallocate_reopen_abort,
643
+
644
+ .bdrv_co_preadv_part = preallocate_co_preadv_part,
645
+ .bdrv_co_pwritev_part = preallocate_co_pwritev_part,
646
+ .bdrv_co_pwrite_zeroes = preallocate_co_pwrite_zeroes,
647
+ .bdrv_co_pdiscard = preallocate_co_pdiscard,
648
+ .bdrv_co_flush = preallocate_co_flush,
649
+ .bdrv_co_truncate = preallocate_co_truncate,
650
+
651
+ .bdrv_check_perm = preallocate_check_perm,
652
+ .bdrv_set_perm = preallocate_set_perm,
653
+ .bdrv_child_perm = preallocate_child_perm,
654
+
655
+ .has_variable_length = true,
656
+ .is_filter = true,
657
+};
658
+
659
+static void bdrv_preallocate_init(void)
660
+{
661
+ bdrv_register(&bdrv_preallocate_filter);
662
+}
663
+
664
+block_init(bdrv_preallocate_init);
665
diff --git a/block/meson.build b/block/meson.build
666
index XXXXXXX..XXXXXXX 100644
667
--- a/block/meson.build
668
+++ b/block/meson.build
669
@@ -XXX,XX +XXX,XX @@ block_ss.add(files(
670
'block-copy.c',
671
'commit.c',
672
'copy-on-read.c',
673
+ 'preallocate.c',
674
'create.c',
675
'crypto.c',
676
'dirty-bitmap.c',
677
--
678
2.29.2
679
680
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This will be used in further test.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20201021145859.11201-10-vsementsov@virtuozzo.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
qemu-io-cmds.c | 46 ++++++++++++++++++++++++++++++++--------------
11
1 file changed, 32 insertions(+), 14 deletions(-)
12
13
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/qemu-io-cmds.c
16
+++ b/qemu-io-cmds.c
17
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t flush_cmd = {
18
.oneline = "flush all in-core file state to disk",
19
};
20
21
+static int truncate_f(BlockBackend *blk, int argc, char **argv);
22
+static const cmdinfo_t truncate_cmd = {
23
+ .name = "truncate",
24
+ .altname = "t",
25
+ .cfunc = truncate_f,
26
+ .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
27
+ .argmin = 1,
28
+ .argmax = 3,
29
+ .args = "[-m prealloc_mode] off",
30
+ .oneline = "truncates the current file at the given offset",
31
+};
32
+
33
static int truncate_f(BlockBackend *blk, int argc, char **argv)
34
{
35
Error *local_err = NULL;
36
int64_t offset;
37
- int ret;
38
+ int c, ret;
39
+ PreallocMode prealloc = PREALLOC_MODE_OFF;
40
41
- offset = cvtnum(argv[1]);
42
+ while ((c = getopt(argc, argv, "m:")) != -1) {
43
+ switch (c) {
44
+ case 'm':
45
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
46
+ PREALLOC_MODE__MAX, NULL);
47
+ if (prealloc == PREALLOC_MODE__MAX) {
48
+ error_report("Invalid preallocation mode '%s'", optarg);
49
+ return -EINVAL;
50
+ }
51
+ break;
52
+ default:
53
+ qemuio_command_usage(&truncate_cmd);
54
+ return -EINVAL;
55
+ }
56
+ }
57
+
58
+ offset = cvtnum(argv[optind]);
59
if (offset < 0) {
60
print_cvtnum_err(offset, argv[1]);
61
return offset;
62
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
63
* exact=true. It is better to err on the "emit more errors" side
64
* than to be overly permissive.
65
*/
66
- ret = blk_truncate(blk, offset, false, PREALLOC_MODE_OFF, 0, &local_err);
67
+ ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
68
if (ret < 0) {
69
error_report_err(local_err);
70
return ret;
71
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
72
return 0;
73
}
74
75
-static const cmdinfo_t truncate_cmd = {
76
- .name = "truncate",
77
- .altname = "t",
78
- .cfunc = truncate_f,
79
- .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
80
- .argmin = 1,
81
- .argmax = 1,
82
- .args = "off",
83
- .oneline = "truncates the current file at the given offset",
84
-};
85
-
86
static int length_f(BlockBackend *blk, int argc, char **argv)
87
{
88
int64_t size;
89
--
90
2.29.2
91
92
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Message-Id: <20201021145859.11201-11-vsementsov@virtuozzo.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/iotests.py | 7 ++++++-
9
1 file changed, 6 insertions(+), 1 deletion(-)
10
11
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/iotests.py
14
+++ b/tests/qemu-iotests/iotests.py
15
@@ -XXX,XX +XXX,XX @@ def qemu_io_log(*args):
16
17
def qemu_io_silent(*args):
18
'''Run qemu-io and return the exit code, suppressing stdout'''
19
- args = qemu_io_args + list(args)
20
+ if '-f' in args or '--image-opts' in args:
21
+ default_args = qemu_io_args_no_fmt
22
+ else:
23
+ default_args = qemu_io_args
24
+
25
+ args = default_args + list(args)
26
exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
27
if exitcode < 0:
28
sys.stderr.write('qemu-io received signal %i: %s\n' %
29
--
30
2.29.2
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add a parameter to skip test if some needed additional formats are not
4
supported (for example filter drivers).
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-12-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/iotests.py | 9 ++++++++-
12
1 file changed, 8 insertions(+), 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/iotests.py
17
+++ b/tests/qemu-iotests/iotests.py
18
@@ -XXX,XX +XXX,XX @@ def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
19
if supported_aio_modes and (aiomode not in supported_aio_modes):
20
notrun('not suitable for this aio mode: %s' % aiomode)
21
22
+def _verify_formats(required_formats: Sequence[str] = ()) -> None:
23
+ usf_list = list(set(required_formats) - set(supported_formats()))
24
+ if usf_list:
25
+ notrun(f'formats {usf_list} are not whitelisted')
26
+
27
def supports_quorum():
28
return 'quorum' in qemu_img_pipe('--help')
29
30
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
31
supported_aio_modes: Sequence[str] = (),
32
unsupported_fmts: Sequence[str] = (),
33
supported_protocols: Sequence[str] = (),
34
- unsupported_protocols: Sequence[str] = ()) -> bool:
35
+ unsupported_protocols: Sequence[str] = (),
36
+ required_fmts: Sequence[str] = ()) -> bool:
37
"""
38
Perform necessary setup for either script-style or unittest-style tests.
39
40
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
41
_verify_platform(supported=supported_platforms)
42
_verify_cache_mode(supported_cache_modes)
43
_verify_aio_mode(supported_aio_modes)
44
+ _verify_formats(required_fmts)
45
46
return debug
47
48
--
49
2.29.2
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Message-Id: <20201021145859.11201-13-vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/298 | 186 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/298.out | 5 +
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 192 insertions(+)
12
create mode 100644 tests/qemu-iotests/298
13
create mode 100644 tests/qemu-iotests/298.out
14
15
diff --git a/tests/qemu-iotests/298 b/tests/qemu-iotests/298
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/qemu-iotests/298
20
@@ -XXX,XX +XXX,XX @@
21
+#!/usr/bin/env python3
22
+#
23
+# Test for preallocate filter
24
+#
25
+# Copyright (c) 2020 Virtuozzo International GmbH.
26
+#
27
+# This program is free software; you can redistribute it and/or modify
28
+# it under the terms of the GNU General Public License as published by
29
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
31
+#
32
+# This program is distributed in the hope that it will be useful,
33
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+# GNU General Public License for more details.
36
+#
37
+# You should have received a copy of the GNU General Public License
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
40
+
41
+import os
42
+import iotests
43
+
44
+MiB = 1024 * 1024
45
+disk = os.path.join(iotests.test_dir, 'disk')
46
+overlay = os.path.join(iotests.test_dir, 'overlay')
47
+refdisk = os.path.join(iotests.test_dir, 'refdisk')
48
+drive_opts = f'node-name=disk,driver={iotests.imgfmt},' \
49
+ f'file.node-name=filter,file.driver=preallocate,' \
50
+ f'file.file.node-name=file,file.file.filename={disk}'
51
+
52
+
53
+class TestPreallocateBase(iotests.QMPTestCase):
54
+ def setUp(self):
55
+ iotests.qemu_img_create('-f', iotests.imgfmt, disk, str(10 * MiB))
56
+
57
+ def tearDown(self):
58
+ try:
59
+ self.check_small()
60
+ check = iotests.qemu_img_check(disk)
61
+ self.assertFalse('leaks' in check)
62
+ self.assertFalse('corruptions' in check)
63
+ self.assertEqual(check['check-errors'], 0)
64
+ finally:
65
+ os.remove(disk)
66
+
67
+ def check_big(self):
68
+ self.assertTrue(os.path.getsize(disk) > 100 * MiB)
69
+
70
+ def check_small(self):
71
+ self.assertTrue(os.path.getsize(disk) < 10 * MiB)
72
+
73
+
74
+class TestQemuImg(TestPreallocateBase):
75
+ def test_qemu_img(self):
76
+ p = iotests.QemuIoInteractive('--image-opts', drive_opts)
77
+
78
+ p.cmd('write 0 1M')
79
+ p.cmd('flush')
80
+
81
+ self.check_big()
82
+
83
+ p.close()
84
+
85
+
86
+class TestPreallocateFilter(TestPreallocateBase):
87
+ def setUp(self):
88
+ super().setUp()
89
+ self.vm = iotests.VM().add_drive(path=None, opts=drive_opts)
90
+ self.vm.launch()
91
+
92
+ def tearDown(self):
93
+ self.vm.shutdown()
94
+ super().tearDown()
95
+
96
+ def test_prealloc(self):
97
+ self.vm.hmp_qemu_io('drive0', 'write 0 1M')
98
+ self.check_big()
99
+
100
+ def test_external_snapshot(self):
101
+ self.test_prealloc()
102
+
103
+ result = self.vm.qmp('blockdev-snapshot-sync', node_name='disk',
104
+ snapshot_file=overlay,
105
+ snapshot_node_name='overlay')
106
+ self.assert_qmp(result, 'return', {})
107
+
108
+ # on reopen to r-o base preallocation should be dropped
109
+ self.check_small()
110
+
111
+ self.vm.hmp_qemu_io('drive0', 'write 1M 1M')
112
+
113
+ result = self.vm.qmp('block-commit', device='overlay')
114
+ self.assert_qmp(result, 'return', {})
115
+ self.complete_and_wait()
116
+
117
+ # commit of new megabyte should trigger preallocation
118
+ self.check_big()
119
+
120
+ def test_reopen_opts(self):
121
+ result = self.vm.qmp('x-blockdev-reopen', **{
122
+ 'node-name': 'disk',
123
+ 'driver': iotests.imgfmt,
124
+ 'file': {
125
+ 'node-name': 'filter',
126
+ 'driver': 'preallocate',
127
+ 'prealloc-size': 20 * MiB,
128
+ 'prealloc-align': 5 * MiB,
129
+ 'file': {
130
+ 'node-name': 'file',
131
+ 'driver': 'file',
132
+ 'filename': disk
133
+ }
134
+ }
135
+ })
136
+ self.assert_qmp(result, 'return', {})
137
+
138
+ self.vm.hmp_qemu_io('drive0', 'write 0 1M')
139
+ self.assertTrue(os.path.getsize(disk) == 25 * MiB)
140
+
141
+
142
+class TestTruncate(iotests.QMPTestCase):
143
+ def setUp(self):
144
+ iotests.qemu_img_create('-f', iotests.imgfmt, disk, str(10 * MiB))
145
+ iotests.qemu_img_create('-f', iotests.imgfmt, refdisk, str(10 * MiB))
146
+
147
+ def tearDown(self):
148
+ os.remove(disk)
149
+ os.remove(refdisk)
150
+
151
+ def do_test(self, prealloc_mode, new_size):
152
+ ret = iotests.qemu_io_silent('--image-opts', '-c', 'write 0 10M', '-c',
153
+ f'truncate -m {prealloc_mode} {new_size}',
154
+ drive_opts)
155
+ self.assertEqual(ret, 0)
156
+
157
+ ret = iotests.qemu_io_silent('-f', iotests.imgfmt, '-c', 'write 0 10M',
158
+ '-c',
159
+ f'truncate -m {prealloc_mode} {new_size}',
160
+ refdisk)
161
+ self.assertEqual(ret, 0)
162
+
163
+ stat = os.stat(disk)
164
+ refstat = os.stat(refdisk)
165
+
166
+ # Probably we'll want preallocate filter to keep align to cluster when
167
+ # shrink preallocation, so, ignore small differece
168
+ self.assertLess(abs(stat.st_size - refstat.st_size), 64 * 1024)
169
+
170
+ # Preallocate filter may leak some internal clusters (for example, if
171
+ # guest write far over EOF, skipping some clusters - they will remain
172
+ # fallocated, preallocate filter don't care about such leaks, it drops
173
+ # only trailing preallocation.
174
+ self.assertLess(abs(stat.st_blocks - refstat.st_blocks) * 512,
175
+ 1024 * 1024)
176
+
177
+ def test_real_shrink(self):
178
+ self.do_test('off', '5M')
179
+
180
+ def test_truncate_inside_preallocated_area__falloc(self):
181
+ self.do_test('falloc', '50M')
182
+
183
+ def test_truncate_inside_preallocated_area__metadata(self):
184
+ self.do_test('metadata', '50M')
185
+
186
+ def test_truncate_inside_preallocated_area__full(self):
187
+ self.do_test('full', '50M')
188
+
189
+ def test_truncate_inside_preallocated_area__off(self):
190
+ self.do_test('off', '50M')
191
+
192
+ def test_truncate_over_preallocated_area__falloc(self):
193
+ self.do_test('falloc', '150M')
194
+
195
+ def test_truncate_over_preallocated_area__metadata(self):
196
+ self.do_test('metadata', '150M')
197
+
198
+ def test_truncate_over_preallocated_area__full(self):
199
+ self.do_test('full', '150M')
200
+
201
+ def test_truncate_over_preallocated_area__off(self):
202
+ self.do_test('off', '150M')
203
+
204
+
205
+if __name__ == '__main__':
206
+ iotests.main(supported_fmts=['qcow2'], required_fmts=['preallocate'])
207
diff --git a/tests/qemu-iotests/298.out b/tests/qemu-iotests/298.out
208
new file mode 100644
209
index XXXXXXX..XXXXXXX
210
--- /dev/null
211
+++ b/tests/qemu-iotests/298.out
212
@@ -XXX,XX +XXX,XX @@
213
+.............
214
+----------------------------------------------------------------------
215
+Ran 13 tests
216
+
217
+OK
218
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
219
index XXXXXXX..XXXXXXX 100644
220
--- a/tests/qemu-iotests/group
221
+++ b/tests/qemu-iotests/group
222
@@ -XXX,XX +XXX,XX @@
223
295 rw
224
296 rw
225
297 meta
226
+298
227
299 auto quick
228
300 migration
229
301 backing quick
230
--
231
2.29.2
232
233
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Message-Id: <20201021145859.11201-14-vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
scripts/simplebench/simplebench.py | 12 ++++++------
9
1 file changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
12
index XXXXXXX..XXXXXXX 100644
13
--- a/scripts/simplebench/simplebench.py
14
+++ b/scripts/simplebench/simplebench.py
15
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
16
17
result = {'runs': runs}
18
19
- successed = [r for r in runs if ('seconds' in r)]
20
- if successed:
21
- avg = sum(r['seconds'] for r in successed) / len(successed)
22
+ succeeded = [r for r in runs if ('seconds' in r)]
23
+ if succeeded:
24
+ avg = sum(r['seconds'] for r in succeeded) / len(succeeded)
25
result['average'] = avg
26
- result['delta'] = max(abs(r['seconds'] - avg) for r in successed)
27
+ result['delta'] = max(abs(r['seconds'] - avg) for r in succeeded)
28
29
- if len(successed) < count:
30
- result['n-failed'] = count - len(successed)
31
+ if len(succeeded) < count:
32
+ result['n-failed'] = count - len(succeeded)
33
34
return result
35
36
--
37
2.29.2
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Support benchmarks returning not seconds but iops. We'll use it for
4
further new test.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-15-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/simplebench/simplebench.py | 38 ++++++++++++++++++++++--------
12
1 file changed, 28 insertions(+), 10 deletions(-)
13
14
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/scripts/simplebench/simplebench.py
17
+++ b/scripts/simplebench/simplebench.py
18
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
19
20
test_func -- benchmarking function with prototype
21
test_func(env, case), which takes test_env and test_case
22
- arguments and returns {'seconds': int} (which is benchmark
23
- result) on success and {'error': str} on error. Returned
24
- dict may contain any other additional fields.
25
+ arguments and on success returns dict with 'seconds' or
26
+ 'iops' (or both) fields, specifying the benchmark result.
27
+ If both 'iops' and 'seconds' provided, the 'iops' is
28
+ considered the main, and 'seconds' is just an additional
29
+ info. On failure test_func should return {'error': str}.
30
+ Returned dict may contain any other additional fields.
31
test_env -- test environment - opaque first argument for test_func
32
test_case -- test case - opaque second argument for test_func
33
count -- how many times to call test_func, to calculate average
34
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
35
36
Returns dict with the following fields:
37
'runs': list of test_func results
38
- 'average': average seconds per run (exists only if at least one run
39
- succeeded)
40
+ 'dimension': dimension of results, may be 'seconds' or 'iops'
41
+ 'average': average value (iops or seconds) per run (exists only if at
42
+ least one run succeeded)
43
'delta': maximum delta between test_func result and the average
44
(exists only if at least one run succeeded)
45
'n-failed': number of failed runs (exists only if at least one run
46
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
47
48
result = {'runs': runs}
49
50
- succeeded = [r for r in runs if ('seconds' in r)]
51
+ succeeded = [r for r in runs if ('seconds' in r or 'iops' in r)]
52
if succeeded:
53
- avg = sum(r['seconds'] for r in succeeded) / len(succeeded)
54
+ if 'iops' in succeeded[0]:
55
+ assert all('iops' in r for r in succeeded)
56
+ dim = 'iops'
57
+ else:
58
+ assert all('seconds' in r for r in succeeded)
59
+ assert all('iops' not in r for r in succeeded)
60
+ dim = 'seconds'
61
+ avg = sum(r[dim] for r in succeeded) / len(succeeded)
62
+ result['dimension'] = dim
63
result['average'] = avg
64
- result['delta'] = max(abs(r['seconds'] - avg) for r in succeeded)
65
+ result['delta'] = max(abs(r[dim] - avg) for r in succeeded)
66
67
if len(succeeded) < count:
68
result['n-failed'] = count - len(succeeded)
69
@@ -XXX,XX +XXX,XX @@ def ascii(results):
70
"""Return ASCII representation of bench() returned dict."""
71
from tabulate import tabulate
72
73
+ dim = None
74
tab = [[""] + [c['id'] for c in results['envs']]]
75
for case in results['cases']:
76
row = [case['id']]
77
for env in results['envs']:
78
- row.append(ascii_one(results['tab'][case['id']][env['id']]))
79
+ res = results['tab'][case['id']][env['id']]
80
+ if dim is None:
81
+ dim = res['dimension']
82
+ else:
83
+ assert dim == res['dimension']
84
+ row.append(ascii_one(res))
85
tab.append(row)
86
87
- return tabulate(tab)
88
+ return f'All results are in {dim}\n\n' + tabulate(tab)
89
--
90
2.29.2
91
92
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Standard deviation is more usual to see after +- than current maximum
4
of deviations.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-16-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/simplebench/simplebench.py | 11 ++++++-----
12
1 file changed, 6 insertions(+), 5 deletions(-)
13
14
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/scripts/simplebench/simplebench.py
17
+++ b/scripts/simplebench/simplebench.py
18
@@ -XXX,XX +XXX,XX @@
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#
21
22
+import statistics
23
+
24
25
def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
26
"""Benchmark one test-case
27
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
28
'dimension': dimension of results, may be 'seconds' or 'iops'
29
'average': average value (iops or seconds) per run (exists only if at
30
least one run succeeded)
31
- 'delta': maximum delta between test_func result and the average
32
+ 'stdev': standard deviation of results
33
(exists only if at least one run succeeded)
34
'n-failed': number of failed runs (exists only if at least one run
35
failed)
36
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
37
assert all('seconds' in r for r in succeeded)
38
assert all('iops' not in r for r in succeeded)
39
dim = 'seconds'
40
- avg = sum(r[dim] for r in succeeded) / len(succeeded)
41
result['dimension'] = dim
42
- result['average'] = avg
43
- result['delta'] = max(abs(r[dim] - avg) for r in succeeded)
44
+ result['average'] = statistics.mean(r[dim] for r in succeeded)
45
+ result['stdev'] = statistics.stdev(r[dim] for r in succeeded)
46
47
if len(succeeded) < count:
48
result['n-failed'] = count - len(succeeded)
49
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
50
def ascii_one(result):
51
"""Return ASCII representation of bench_one() returned dict."""
52
if 'average' in result:
53
- s = '{:.2f} +- {:.2f}'.format(result['average'], result['delta'])
54
+ s = '{:.2f} +- {:.2f}'.format(result['average'], result['stdev'])
55
if 'n-failed' in result:
56
s += '\n({} failed)'.format(result['n-failed'])
57
return s
58
--
59
2.29.2
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Next patch will use utf8 plus-minus symbol, let's use more generic (and
4
more readable) name.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-17-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/simplebench/bench-example.py | 2 +-
12
scripts/simplebench/bench_write_req.py | 2 +-
13
scripts/simplebench/simplebench.py | 10 +++++-----
14
3 files changed, 7 insertions(+), 7 deletions(-)
15
16
diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/scripts/simplebench/bench-example.py
19
+++ b/scripts/simplebench/bench-example.py
20
@@ -XXX,XX +XXX,XX @@ test_envs = [
21
]
22
23
result = simplebench.bench(bench_func, test_envs, test_cases, count=3)
24
-print(simplebench.ascii(result))
25
+print(simplebench.results_to_text(result))
26
diff --git a/scripts/simplebench/bench_write_req.py b/scripts/simplebench/bench_write_req.py
27
index XXXXXXX..XXXXXXX 100755
28
--- a/scripts/simplebench/bench_write_req.py
29
+++ b/scripts/simplebench/bench_write_req.py
30
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
31
32
result = simplebench.bench(bench_func, test_envs, test_cases, count=3,
33
initial_run=False)
34
- print(simplebench.ascii(result))
35
+ print(simplebench.results_to_text(result))
36
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
37
index XXXXXXX..XXXXXXX 100644
38
--- a/scripts/simplebench/simplebench.py
39
+++ b/scripts/simplebench/simplebench.py
40
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
41
return result
42
43
44
-def ascii_one(result):
45
- """Return ASCII representation of bench_one() returned dict."""
46
+def result_to_text(result):
47
+ """Return text representation of bench_one() returned dict."""
48
if 'average' in result:
49
s = '{:.2f} +- {:.2f}'.format(result['average'], result['stdev'])
50
if 'n-failed' in result:
51
@@ -XXX,XX +XXX,XX @@ def bench(test_func, test_envs, test_cases, *args, **vargs):
52
return results
53
54
55
-def ascii(results):
56
- """Return ASCII representation of bench() returned dict."""
57
+def results_to_text(results):
58
+ """Return text representation of bench() returned dict."""
59
from tabulate import tabulate
60
61
dim = None
62
@@ -XXX,XX +XXX,XX @@ def ascii(results):
63
dim = res['dimension']
64
else:
65
assert dim == res['dimension']
66
- row.append(ascii_one(res))
67
+ row.append(result_to_text(res))
68
tab.append(row)
69
70
return f'All results are in {dim}\n\n' + tabulate(tab)
71
--
72
2.29.2
73
74
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Let's keep view part in separate: this way it's better to improve it in
4
the following commits.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-18-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/simplebench/bench-example.py | 3 +-
12
scripts/simplebench/bench_write_req.py | 3 +-
13
scripts/simplebench/results_to_text.py | 48 ++++++++++++++++++++++++++
14
scripts/simplebench/simplebench.py | 31 -----------------
15
4 files changed, 52 insertions(+), 33 deletions(-)
16
create mode 100644 scripts/simplebench/results_to_text.py
17
18
diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py
19
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/simplebench/bench-example.py
21
+++ b/scripts/simplebench/bench-example.py
22
@@ -XXX,XX +XXX,XX @@
23
#
24
25
import simplebench
26
+from results_to_text import results_to_text
27
from bench_block_job import bench_block_copy, drv_file, drv_nbd
28
29
30
@@ -XXX,XX +XXX,XX @@ test_envs = [
31
]
32
33
result = simplebench.bench(bench_func, test_envs, test_cases, count=3)
34
-print(simplebench.results_to_text(result))
35
+print(results_to_text(result))
36
diff --git a/scripts/simplebench/bench_write_req.py b/scripts/simplebench/bench_write_req.py
37
index XXXXXXX..XXXXXXX 100755
38
--- a/scripts/simplebench/bench_write_req.py
39
+++ b/scripts/simplebench/bench_write_req.py
40
@@ -XXX,XX +XXX,XX @@ import sys
41
import os
42
import subprocess
43
import simplebench
44
+from results_to_text import results_to_text
45
46
47
def bench_func(env, case):
48
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
49
50
result = simplebench.bench(bench_func, test_envs, test_cases, count=3,
51
initial_run=False)
52
- print(simplebench.results_to_text(result))
53
+ print(results_to_text(result))
54
diff --git a/scripts/simplebench/results_to_text.py b/scripts/simplebench/results_to_text.py
55
new file mode 100644
56
index XXXXXXX..XXXXXXX
57
--- /dev/null
58
+++ b/scripts/simplebench/results_to_text.py
59
@@ -XXX,XX +XXX,XX @@
60
+# Simple benchmarking framework
61
+#
62
+# Copyright (c) 2019 Virtuozzo International GmbH.
63
+#
64
+# This program is free software; you can redistribute it and/or modify
65
+# it under the terms of the GNU General Public License as published by
66
+# the Free Software Foundation; either version 2 of the License, or
67
+# (at your option) any later version.
68
+#
69
+# This program is distributed in the hope that it will be useful,
70
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
71
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72
+# GNU General Public License for more details.
73
+#
74
+# You should have received a copy of the GNU General Public License
75
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
76
+#
77
+
78
+
79
+def result_to_text(result):
80
+ """Return text representation of bench_one() returned dict."""
81
+ if 'average' in result:
82
+ s = '{:.2f} +- {:.2f}'.format(result['average'], result['stdev'])
83
+ if 'n-failed' in result:
84
+ s += '\n({} failed)'.format(result['n-failed'])
85
+ return s
86
+ else:
87
+ return 'FAILED'
88
+
89
+
90
+def results_to_text(results):
91
+ """Return text representation of bench() returned dict."""
92
+ from tabulate import tabulate
93
+
94
+ dim = None
95
+ tab = [[""] + [c['id'] for c in results['envs']]]
96
+ for case in results['cases']:
97
+ row = [case['id']]
98
+ for env in results['envs']:
99
+ res = results['tab'][case['id']][env['id']]
100
+ if dim is None:
101
+ dim = res['dimension']
102
+ else:
103
+ assert dim == res['dimension']
104
+ row.append(result_to_text(res))
105
+ tab.append(row)
106
+
107
+ return f'All results are in {dim}\n\n' + tabulate(tab)
108
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
109
index XXXXXXX..XXXXXXX 100644
110
--- a/scripts/simplebench/simplebench.py
111
+++ b/scripts/simplebench/simplebench.py
112
@@ -XXX,XX +XXX,XX @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
113
return result
114
115
116
-def result_to_text(result):
117
- """Return text representation of bench_one() returned dict."""
118
- if 'average' in result:
119
- s = '{:.2f} +- {:.2f}'.format(result['average'], result['stdev'])
120
- if 'n-failed' in result:
121
- s += '\n({} failed)'.format(result['n-failed'])
122
- return s
123
- else:
124
- return 'FAILED'
125
-
126
-
127
def bench(test_func, test_envs, test_cases, *args, **vargs):
128
"""Fill benchmark table
129
130
@@ -XXX,XX +XXX,XX @@ def bench(test_func, test_envs, test_cases, *args, **vargs):
131
132
print('Done')
133
return results
134
-
135
-
136
-def results_to_text(results):
137
- """Return text representation of bench() returned dict."""
138
- from tabulate import tabulate
139
-
140
- dim = None
141
- tab = [[""] + [c['id'] for c in results['envs']]]
142
- for case in results['cases']:
143
- row = [case['id']]
144
- for env in results['envs']:
145
- res = results['tab'][case['id']][env['id']]
146
- if dim is None:
147
- dim = res['dimension']
148
- else:
149
- assert dim == res['dimension']
150
- row.append(result_to_text(res))
151
- tab.append(row)
152
-
153
- return f'All results are in {dim}\n\n' + tabulate(tab)
154
--
155
2.29.2
156
157
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Move to generic format for floats and percentage for error.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20201021145859.11201-19-vsementsov@virtuozzo.com>
7
Acked-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
scripts/simplebench/results_to_text.py | 13 ++++++++++++-
11
1 file changed, 12 insertions(+), 1 deletion(-)
12
13
diff --git a/scripts/simplebench/results_to_text.py b/scripts/simplebench/results_to_text.py
14
index XXXXXXX..XXXXXXX 100644
15
--- a/scripts/simplebench/results_to_text.py
16
+++ b/scripts/simplebench/results_to_text.py
17
@@ -XXX,XX +XXX,XX @@
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#
20
21
+import math
22
+
23
+
24
+def format_value(x, stdev):
25
+ stdev_pr = stdev / x * 100
26
+ if stdev_pr < 1.5:
27
+ # don't care too much
28
+ return f'{x:.2g}'
29
+ else:
30
+ return f'{x:.2g} ± {math.ceil(stdev_pr)}%'
31
+
32
33
def result_to_text(result):
34
"""Return text representation of bench_one() returned dict."""
35
if 'average' in result:
36
- s = '{:.2f} +- {:.2f}'.format(result['average'], result['stdev'])
37
+ s = format_value(result['average'], result['stdev'])
38
if 'n-failed' in result:
39
s += '\n({} failed)'.format(result['n-failed'])
40
return s
41
--
42
2.29.2
43
44
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Performance improvements / degradations are usually discussed in
4
percentage. Let's make the script calculate it for us.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20201021145859.11201-20-vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
[mreitz: 'seconds' instead of 'secs']
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
scripts/simplebench/results_to_text.py | 67 +++++++++++++++++++++++---
13
1 file changed, 60 insertions(+), 7 deletions(-)
14
15
diff --git a/scripts/simplebench/results_to_text.py b/scripts/simplebench/results_to_text.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/scripts/simplebench/results_to_text.py
18
+++ b/scripts/simplebench/results_to_text.py
19
@@ -XXX,XX +XXX,XX @@
20
#
21
22
import math
23
+import tabulate
24
+
25
+# We want leading whitespace for difference row cells (see below)
26
+tabulate.PRESERVE_WHITESPACE = True
27
28
29
def format_value(x, stdev):
30
@@ -XXX,XX +XXX,XX @@ def result_to_text(result):
31
return 'FAILED'
32
33
34
-def results_to_text(results):
35
- """Return text representation of bench() returned dict."""
36
- from tabulate import tabulate
37
-
38
+def results_dimension(results):
39
dim = None
40
- tab = [[""] + [c['id'] for c in results['envs']]]
41
for case in results['cases']:
42
- row = [case['id']]
43
for env in results['envs']:
44
res = results['tab'][case['id']][env['id']]
45
if dim is None:
46
dim = res['dimension']
47
else:
48
assert dim == res['dimension']
49
+
50
+ assert dim in ('iops', 'seconds')
51
+
52
+ return dim
53
+
54
+
55
+def results_to_text(results):
56
+ """Return text representation of bench() returned dict."""
57
+ n_columns = len(results['envs'])
58
+ named_columns = n_columns > 2
59
+ dim = results_dimension(results)
60
+ tab = []
61
+
62
+ if named_columns:
63
+ # Environment columns are named A, B, ...
64
+ tab.append([''] + [chr(ord('A') + i) for i in range(n_columns)])
65
+
66
+ tab.append([''] + [c['id'] for c in results['envs']])
67
+
68
+ for case in results['cases']:
69
+ row = [case['id']]
70
+ case_results = results['tab'][case['id']]
71
+ for env in results['envs']:
72
+ res = case_results[env['id']]
73
row.append(result_to_text(res))
74
tab.append(row)
75
76
- return f'All results are in {dim}\n\n' + tabulate(tab)
77
+ # Add row of difference between columns. For each column starting from
78
+ # B we calculate difference with all previous columns.
79
+ row = ['', ''] # case name and first column
80
+ for i in range(1, n_columns):
81
+ cell = ''
82
+ env = results['envs'][i]
83
+ res = case_results[env['id']]
84
+
85
+ if 'average' not in res:
86
+ # Failed result
87
+ row.append(cell)
88
+ continue
89
+
90
+ for j in range(0, i):
91
+ env_j = results['envs'][j]
92
+ res_j = case_results[env_j['id']]
93
+ cell += ' '
94
+
95
+ if 'average' not in res_j:
96
+ # Failed result
97
+ cell += '--'
98
+ continue
99
+
100
+ col_j = tab[0][j + 1] if named_columns else ''
101
+ diff_pr = round((res['average'] - res_j['average']) /
102
+ res_j['average'] * 100)
103
+ cell += f' {col_j}{diff_pr:+}%'
104
+ row.append(cell)
105
+ tab.append(row)
106
+
107
+ return f'All results are in {dim}\n\n' + tabulate.tabulate(tab)
108
--
109
2.29.2
110
111
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Make results_to_text a tool to dump results saved in JSON file.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20201021145859.11201-21-vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
scripts/simplebench/results_to_text.py | 14 ++++++++++++++
11
1 file changed, 14 insertions(+)
12
mode change 100644 => 100755 scripts/simplebench/results_to_text.py
13
14
diff --git a/scripts/simplebench/results_to_text.py b/scripts/simplebench/results_to_text.py
15
old mode 100644
16
new mode 100755
17
index XXXXXXX..XXXXXXX
18
--- a/scripts/simplebench/results_to_text.py
19
+++ b/scripts/simplebench/results_to_text.py
20
@@ -XXX,XX +XXX,XX @@
21
+#!/usr/bin/env python3
22
+#
23
# Simple benchmarking framework
24
#
25
# Copyright (c) 2019 Virtuozzo International GmbH.
26
@@ -XXX,XX +XXX,XX @@ def results_to_text(results):
27
tab.append(row)
28
29
return f'All results are in {dim}\n\n' + tabulate.tabulate(tab)
30
+
31
+
32
+if __name__ == '__main__':
33
+ import sys
34
+ import json
35
+
36
+ if len(sys.argv) < 2:
37
+ print(f'USAGE: {sys.argv[0]} results.json')
38
+ exit(1)
39
+
40
+ with open(sys.argv[1]) as f:
41
+ print(results_to_text(json.load(f)))
42
--
43
2.29.2
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Benchmark for new preallocate filter.
4
5
Example usage:
6
./bench_prealloc.py ../../build/qemu-img \
7
ssd-ext4:/path/to/mount/point \
8
ssd-xfs:/path2 hdd-ext4:/path3 hdd-xfs:/path4
9
10
The benchmark shows performance improvement (or degradation) when use
11
new preallocate filter with qcow2 image.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-Id: <20201021145859.11201-22-vsementsov@virtuozzo.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
scripts/simplebench/bench_prealloc.py | 132 ++++++++++++++++++++++++++
19
1 file changed, 132 insertions(+)
20
create mode 100755 scripts/simplebench/bench_prealloc.py
21
22
diff --git a/scripts/simplebench/bench_prealloc.py b/scripts/simplebench/bench_prealloc.py
23
new file mode 100755
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/scripts/simplebench/bench_prealloc.py
27
@@ -XXX,XX +XXX,XX @@
28
+#!/usr/bin/env python3
29
+#
30
+# Benchmark preallocate filter
31
+#
32
+# Copyright (c) 2020 Virtuozzo International GmbH.
33
+#
34
+# This program is free software; you can redistribute it and/or modify
35
+# it under the terms of the GNU General Public License as published by
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
+
48
+
49
+import sys
50
+import os
51
+import subprocess
52
+import re
53
+import json
54
+
55
+import simplebench
56
+from results_to_text import results_to_text
57
+
58
+
59
+def qemu_img_bench(args):
60
+ p = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
61
+ universal_newlines=True)
62
+
63
+ if p.returncode == 0:
64
+ try:
65
+ m = re.search(r'Run completed in (\d+.\d+) seconds.', p.stdout)
66
+ return {'seconds': float(m.group(1))}
67
+ except Exception:
68
+ return {'error': f'failed to parse qemu-img output: {p.stdout}'}
69
+ else:
70
+ return {'error': f'qemu-img failed: {p.returncode}: {p.stdout}'}
71
+
72
+
73
+def bench_func(env, case):
74
+ fname = f"{case['dir']}/prealloc-test.qcow2"
75
+ try:
76
+ os.remove(fname)
77
+ except OSError:
78
+ pass
79
+
80
+ subprocess.run([env['qemu-img-binary'], 'create', '-f', 'qcow2', fname,
81
+ '16G'], stdout=subprocess.DEVNULL,
82
+ stderr=subprocess.DEVNULL, check=True)
83
+
84
+ args = [env['qemu-img-binary'], 'bench', '-c', str(case['count']),
85
+ '-d', '64', '-s', case['block-size'], '-t', 'none', '-n', '-w']
86
+ if env['prealloc']:
87
+ args += ['--image-opts',
88
+ 'driver=qcow2,file.driver=preallocate,file.file.driver=file,'
89
+ f'file.file.filename={fname}']
90
+ else:
91
+ args += ['-f', 'qcow2', fname]
92
+
93
+ return qemu_img_bench(args)
94
+
95
+
96
+def auto_count_bench_func(env, case):
97
+ case['count'] = 100
98
+ while True:
99
+ res = bench_func(env, case)
100
+ if 'error' in res:
101
+ return res
102
+
103
+ if res['seconds'] >= 1:
104
+ break
105
+
106
+ case['count'] *= 10
107
+
108
+ if res['seconds'] < 5:
109
+ case['count'] = round(case['count'] * 5 / res['seconds'])
110
+ res = bench_func(env, case)
111
+ if 'error' in res:
112
+ return res
113
+
114
+ res['iops'] = case['count'] / res['seconds']
115
+ return res
116
+
117
+
118
+if __name__ == '__main__':
119
+ if len(sys.argv) < 2:
120
+ print(f'USAGE: {sys.argv[0]} <qemu-img binary> '
121
+ 'DISK_NAME:DIR_PATH ...')
122
+ exit(1)
123
+
124
+ qemu_img = sys.argv[1]
125
+
126
+ envs = [
127
+ {
128
+ 'id': 'no-prealloc',
129
+ 'qemu-img-binary': qemu_img,
130
+ 'prealloc': False
131
+ },
132
+ {
133
+ 'id': 'prealloc',
134
+ 'qemu-img-binary': qemu_img,
135
+ 'prealloc': True
136
+ }
137
+ ]
138
+
139
+ aligned_cases = []
140
+ unaligned_cases = []
141
+
142
+ for disk in sys.argv[2:]:
143
+ name, path = disk.split(':')
144
+ aligned_cases.append({
145
+ 'id': f'{name}, aligned sequential 16k',
146
+ 'block-size': '16k',
147
+ 'dir': path
148
+ })
149
+ unaligned_cases.append({
150
+ 'id': f'{name}, unaligned sequential 64k',
151
+ 'block-size': '16k',
152
+ 'dir': path
153
+ })
154
+
155
+ result = simplebench.bench(auto_count_bench_func, envs,
156
+ aligned_cases + unaligned_cases, count=5)
157
+ print(results_to_text(result))
158
+ with open('results.json', 'w') as f:
159
+ json.dump(result, f, indent=4)
160
--
161
2.29.2
162
163
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The quorum driver does not implement bdrv_co_block_status() and
4
because of that it always reports to contain data even if all its
5
children are known to be empty.
6
7
One consequence of this is that if we for example create a quorum with
8
a size of 10GB and we mirror it to a new image the operation will
9
write 10GB of actual zeroes to the destination image wasting a lot of
10
time and disk space.
11
12
Since a quorum has an arbitrary number of children of potentially
13
different formats there is no way to report all possible allocation
14
status flags in a way that makes sense, so this implementation only
15
reports when a given region is known to contain zeroes
16
(BDRV_BLOCK_ZERO) or not (BDRV_BLOCK_DATA).
17
18
If all children agree that a region contains zeroes then we can return
19
BDRV_BLOCK_ZERO using the smallest size reported by the children
20
(because all agree that a region of at least that size contains
21
zeroes).
22
23
If at least one child disagrees we have to return BDRV_BLOCK_DATA.
24
In this case we use the largest of the sizes reported by the children
25
that didn't return BDRV_BLOCK_ZERO (because we know that there won't
26
be an agreement for at least that size).
27
28
Signed-off-by: Alberto Garcia <berto@igalia.com>
29
Tested-by: Tao Xu <tao3.xu@intel.com>
30
Reviewed-by: Max Reitz <mreitz@redhat.com>
31
Message-Id: <db83149afcf0f793effc8878089d29af4c46ffe1.1605286097.git.berto@igalia.com>
32
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
---
34
block/quorum.c | 52 +++++++++++++
35
tests/qemu-iotests/312 | 148 +++++++++++++++++++++++++++++++++++++
36
tests/qemu-iotests/312.out | 67 +++++++++++++++++
37
tests/qemu-iotests/group | 1 +
38
4 files changed, 268 insertions(+)
39
create mode 100755 tests/qemu-iotests/312
40
create mode 100644 tests/qemu-iotests/312.out
41
42
diff --git a/block/quorum.c b/block/quorum.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/quorum.c
45
+++ b/block/quorum.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qemu/module.h"
48
#include "qemu/option.h"
49
#include "block/block_int.h"
50
+#include "block/coroutines.h"
51
#include "block/qdict.h"
52
#include "qapi/error.h"
53
#include "qapi/qapi-events-block.h"
54
@@ -XXX,XX +XXX,XX @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
55
| DEFAULT_PERM_UNCHANGED;
56
}
57
58
+/*
59
+ * Each one of the children can report different status flags even
60
+ * when they contain the same data, so what this function does is
61
+ * return BDRV_BLOCK_ZERO if *all* children agree that a certain
62
+ * region contains zeroes, and BDRV_BLOCK_DATA otherwise.
63
+ */
64
+static int coroutine_fn quorum_co_block_status(BlockDriverState *bs,
65
+ bool want_zero,
66
+ int64_t offset, int64_t count,
67
+ int64_t *pnum, int64_t *map,
68
+ BlockDriverState **file)
69
+{
70
+ BDRVQuorumState *s = bs->opaque;
71
+ int i, ret;
72
+ int64_t pnum_zero = count;
73
+ int64_t pnum_data = 0;
74
+
75
+ for (i = 0; i < s->num_children; i++) {
76
+ int64_t bytes;
77
+ ret = bdrv_co_common_block_status_above(s->children[i]->bs, NULL, false,
78
+ want_zero, offset, count,
79
+ &bytes, NULL, NULL, NULL);
80
+ if (ret < 0) {
81
+ quorum_report_bad(QUORUM_OP_TYPE_READ, offset, count,
82
+ s->children[i]->bs->node_name, ret);
83
+ pnum_data = count;
84
+ break;
85
+ }
86
+ /*
87
+ * Even if all children agree about whether there are zeroes
88
+ * or not at @offset they might disagree on the size, so use
89
+ * the smallest when reporting BDRV_BLOCK_ZERO and the largest
90
+ * when reporting BDRV_BLOCK_DATA.
91
+ */
92
+ if (ret & BDRV_BLOCK_ZERO) {
93
+ pnum_zero = MIN(pnum_zero, bytes);
94
+ } else {
95
+ pnum_data = MAX(pnum_data, bytes);
96
+ }
97
+ }
98
+
99
+ if (pnum_data) {
100
+ *pnum = pnum_data;
101
+ return BDRV_BLOCK_DATA;
102
+ } else {
103
+ *pnum = pnum_zero;
104
+ return BDRV_BLOCK_ZERO;
105
+ }
106
+}
107
+
108
static const char *const quorum_strong_runtime_opts[] = {
109
QUORUM_OPT_VOTE_THRESHOLD,
110
QUORUM_OPT_BLKVERIFY,
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
112
.bdrv_close = quorum_close,
113
.bdrv_gather_child_options = quorum_gather_child_options,
114
.bdrv_dirname = quorum_dirname,
115
+ .bdrv_co_block_status = quorum_co_block_status,
116
117
.bdrv_co_flush_to_disk = quorum_co_flush,
118
119
diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312
120
new file mode 100755
121
index XXXXXXX..XXXXXXX
122
--- /dev/null
123
+++ b/tests/qemu-iotests/312
124
@@ -XXX,XX +XXX,XX @@
125
+#!/usr/bin/env bash
126
+#
127
+# Test drive-mirror with quorum
128
+#
129
+# The goal of this test is to check how the quorum driver reports
130
+# regions that are known to read as zeroes (BDRV_BLOCK_ZERO). The idea
131
+# is that drive-mirror will try the efficient representation of zeroes
132
+# in the destination image instead of writing actual zeroes.
133
+#
134
+# Copyright (C) 2020 Igalia, S.L.
135
+# Author: Alberto Garcia <berto@igalia.com>
136
+#
137
+# This program is free software; you can redistribute it and/or modify
138
+# it under the terms of the GNU General Public License as published by
139
+# the Free Software Foundation; either version 2 of the License, or
140
+# (at your option) any later version.
141
+#
142
+# This program is distributed in the hope that it will be useful,
143
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
144
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
145
+# GNU General Public License for more details.
146
+#
147
+# You should have received a copy of the GNU General Public License
148
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
149
+#
150
+
151
+# creator
152
+owner=berto@igalia.com
153
+
154
+seq=`basename $0`
155
+echo "QA output created by $seq"
156
+
157
+status=1    # failure is the default!
158
+
159
+_cleanup()
160
+{
161
+ _rm_test_img "$TEST_IMG.0"
162
+ _rm_test_img "$TEST_IMG.1"
163
+ _rm_test_img "$TEST_IMG.2"
164
+ _rm_test_img "$TEST_IMG.3"
165
+ _cleanup_qemu
166
+}
167
+trap "_cleanup; exit \$status" 0 1 2 3 15
168
+
169
+# get standard environment, filters and checks
170
+. ./common.rc
171
+. ./common.filter
172
+. ./common.qemu
173
+
174
+_supported_fmt qcow2
175
+_supported_proto file
176
+_supported_os Linux
177
+_unsupported_imgopts cluster_size data_file
178
+
179
+echo
180
+echo '### Create all images' # three source (quorum), one destination
181
+echo
182
+TEST_IMG="$TEST_IMG.0" _make_test_img -o cluster_size=64k 10M
183
+TEST_IMG="$TEST_IMG.1" _make_test_img -o cluster_size=64k 10M
184
+TEST_IMG="$TEST_IMG.2" _make_test_img -o cluster_size=64k 10M
185
+TEST_IMG="$TEST_IMG.3" _make_test_img -o cluster_size=64k 10M
186
+
187
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2"
188
+quorum="$quorum,file.children.0.file.filename=$TEST_IMG.0"
189
+quorum="$quorum,file.children.1.file.filename=$TEST_IMG.1"
190
+quorum="$quorum,file.children.2.file.filename=$TEST_IMG.2"
191
+quorum="$quorum,file.children.0.driver=$IMGFMT"
192
+quorum="$quorum,file.children.1.driver=$IMGFMT"
193
+quorum="$quorum,file.children.2.driver=$IMGFMT"
194
+
195
+echo
196
+echo '### Output of qemu-img map (empty quorum)'
197
+echo
198
+$QEMU_IMG map --image-opts $quorum | _filter_qemu_img_map
199
+
200
+# Now we write data to the quorum. All three images will read as
201
+# zeroes in all cases, but with different ways to represent them
202
+# (unallocated clusters, zero clusters, data clusters with zeroes)
203
+# that will have an effect on how the data will be mirrored and the
204
+# output of qemu-img map on the resulting image.
205
+echo
206
+echo '### Write data to the quorum'
207
+echo
208
+# Test 1: data regions surrounded by unallocated clusters.
209
+# Three data regions, the largest one (0x30000) will be picked, end result:
210
+# offset 0x10000, length 0x30000 -> data
211
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
212
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
213
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
214
+
215
+# Test 2: zero regions surrounded by data clusters.
216
+# First we allocate the data clusters.
217
+$QEMU_IO -c "open -o $quorum" -c "write -P 0 $((0x100000)) $((0x40000))" | _filter_qemu_io
218
+
219
+# Three zero regions, the smallest one (0x10000) will be picked, end result:
220
+# offset 0x100000, length 0x10000 -> data
221
+# offset 0x110000, length 0x10000 -> zeroes
222
+# offset 0x120000, length 0x20000 -> data
223
+$QEMU_IO -c "write -z $((0x110000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
224
+$QEMU_IO -c "write -z $((0x110000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
225
+$QEMU_IO -c "write -z $((0x110000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
226
+
227
+# Test 3: zero clusters surrounded by unallocated clusters.
228
+# Everything reads as zeroes, no effect on the end result.
229
+$QEMU_IO -c "write -z $((0x150000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
230
+$QEMU_IO -c "write -z $((0x150000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
231
+$QEMU_IO -c "write -z $((0x150000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
232
+
233
+# Test 4: mix of data and zero clusters.
234
+# The zero region will be ignored in favor of the largest data region
235
+# (0x20000), end result:
236
+# offset 0x200000, length 0x20000 -> data
237
+$QEMU_IO -c "write -P 0 $((0x200000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
238
+$QEMU_IO -c "write -z $((0x200000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
239
+$QEMU_IO -c "write -P 0 $((0x200000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
240
+
241
+echo
242
+echo '### Launch the drive-mirror job'
243
+echo
244
+qemu_comm_method="qmp" _launch_qemu -drive if=virtio,"$quorum"
245
+h=$QEMU_HANDLE
246
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
247
+
248
+_send_qemu_cmd $h \
249
+ "{'execute': 'drive-mirror',
250
+ 'arguments': {'device': 'virtio0',
251
+ 'format': '$IMGFMT',
252
+ 'target': '$TEST_IMG.3',
253
+ 'sync': 'full',
254
+ 'mode': 'existing' }}" \
255
+ "BLOCK_JOB_READY.*virtio0"
256
+
257
+_send_qemu_cmd $h \
258
+ "{ 'execute': 'block-job-complete',
259
+ 'arguments': { 'device': 'virtio0' } }" \
260
+ 'BLOCK_JOB_COMPLETED'
261
+
262
+_send_qemu_cmd $h "{ 'execute': 'quit' }" ''
263
+
264
+echo
265
+echo '### Output of qemu-img map (destination image)'
266
+echo
267
+$QEMU_IMG map "$TEST_IMG.3" | _filter_qemu_img_map
268
+
269
+# success, all done
270
+echo "*** done"
271
+rm -f $seq.full
272
+status=0
273
diff --git a/tests/qemu-iotests/312.out b/tests/qemu-iotests/312.out
274
new file mode 100644
275
index XXXXXXX..XXXXXXX
276
--- /dev/null
277
+++ b/tests/qemu-iotests/312.out
278
@@ -XXX,XX +XXX,XX @@
279
+QA output created by 312
280
+
281
+### Create all images
282
+
283
+Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=10485760
284
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=10485760
285
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=10485760
286
+Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=10485760
287
+
288
+### Output of qemu-img map (empty quorum)
289
+
290
+Offset Length File
291
+
292
+### Write data to the quorum
293
+
294
+wrote 65536/65536 bytes at offset 65536
295
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
296
+wrote 196608/196608 bytes at offset 65536
297
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
298
+wrote 131072/131072 bytes at offset 65536
299
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
300
+wrote 262144/262144 bytes at offset 1048576
301
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
302
+wrote 65536/65536 bytes at offset 1114112
303
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
304
+wrote 196608/196608 bytes at offset 1114112
305
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
306
+wrote 131072/131072 bytes at offset 1114112
307
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+wrote 65536/65536 bytes at offset 1376256
309
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
310
+wrote 196608/196608 bytes at offset 1376256
311
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
312
+wrote 131072/131072 bytes at offset 1376256
313
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
314
+wrote 65536/65536 bytes at offset 2097152
315
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
316
+wrote 196608/196608 bytes at offset 2097152
317
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
318
+wrote 131072/131072 bytes at offset 2097152
319
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
320
+
321
+### Launch the drive-mirror job
322
+
323
+{ 'execute': 'qmp_capabilities' }
324
+{"return": {}}
325
+{'execute': 'drive-mirror', 'arguments': {'device': 'virtio0', 'format': 'IMGFMT', 'target': 'TEST_DIR/t.IMGFMT.3', 'sync': 'full', 'mode': 'existing' }}
326
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
327
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
328
+{"return": {}}
329
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
330
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 10485760, "offset": 10485760, "speed": 0, "type": "mirror"}}
331
+{ 'execute': 'block-job-complete', 'arguments': { 'device': 'virtio0' } }
332
+{"return": {}}
333
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
334
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
335
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 10485760, "offset": 10485760, "speed": 0, "type": "mirror"}}
336
+{ 'execute': 'quit' }
337
+
338
+### Output of qemu-img map (destination image)
339
+
340
+Offset Length File
341
+0x10000 0x30000 TEST_DIR/t.IMGFMT.3
342
+0x100000 0x10000 TEST_DIR/t.IMGFMT.3
343
+0x120000 0x20000 TEST_DIR/t.IMGFMT.3
344
+0x200000 0x20000 TEST_DIR/t.IMGFMT.3
345
+*** done
346
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
347
index XXXXXXX..XXXXXXX 100644
348
--- a/tests/qemu-iotests/group
349
+++ b/tests/qemu-iotests/group
350
@@ -XXX,XX +XXX,XX @@
351
307 rw quick export
352
308 rw
353
309 rw auto quick
354
+312 rw auto quick
355
--
356
2.29.2
357
358
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This simply calls bdrv_co_pwrite_zeroes() in all children.
4
5
bs->supported_zero_flags is also set to the flags that are supported
6
by all children.
7
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <2f09c842781fe336b4c2e40036bba577b7430190.1605286097.git.berto@igalia.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/quorum.c | 36 ++++++++++++++++++++++++++++++++++--
14
tests/qemu-iotests/312 | 11 +++++++++++
15
tests/qemu-iotests/312.out | 8 ++++++++
16
3 files changed, 53 insertions(+), 2 deletions(-)
17
18
diff --git a/block/quorum.c b/block/quorum.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/quorum.c
21
+++ b/block/quorum.c
22
@@ -XXX,XX +XXX,XX @@ static void write_quorum_entry(void *opaque)
23
QuorumChildRequest *sacb = &acb->qcrs[i];
24
25
sacb->bs = s->children[i]->bs;
26
- sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
27
- acb->qiov, acb->flags);
28
+ if (acb->flags & BDRV_REQ_ZERO_WRITE) {
29
+ sacb->ret = bdrv_co_pwrite_zeroes(s->children[i], acb->offset,
30
+ acb->bytes, acb->flags);
31
+ } else {
32
+ sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
33
+ acb->qiov, acb->flags);
34
+ }
35
if (sacb->ret == 0) {
36
acb->success_count++;
37
} else {
38
@@ -XXX,XX +XXX,XX @@ static int quorum_co_pwritev(BlockDriverState *bs, uint64_t offset,
39
return ret;
40
}
41
42
+static int quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
43
+ int bytes, BdrvRequestFlags flags)
44
+
45
+{
46
+ return quorum_co_pwritev(bs, offset, bytes, NULL,
47
+ flags | BDRV_REQ_ZERO_WRITE);
48
+}
49
+
50
static int64_t quorum_getlength(BlockDriverState *bs)
51
{
52
BDRVQuorumState *s = bs->opaque;
53
@@ -XXX,XX +XXX,XX @@ static QemuOptsList quorum_runtime_opts = {
54
},
55
};
56
57
+static void quorum_refresh_flags(BlockDriverState *bs)
58
+{
59
+ BDRVQuorumState *s = bs->opaque;
60
+ int i;
61
+
62
+ bs->supported_zero_flags =
63
+ BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
64
+
65
+ for (i = 0; i < s->num_children; i++) {
66
+ bs->supported_zero_flags &= s->children[i]->bs->supported_zero_flags;
67
+ }
68
+
69
+ bs->supported_zero_flags |= BDRV_REQ_WRITE_UNCHANGED;
70
+}
71
+
72
static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
73
Error **errp)
74
{
75
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
76
s->next_child_index = s->num_children;
77
78
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
79
+ quorum_refresh_flags(bs);
80
81
g_free(opened);
82
goto exit;
83
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
84
}
85
s->children = g_renew(BdrvChild *, s->children, s->num_children + 1);
86
s->children[s->num_children++] = child;
87
+ quorum_refresh_flags(bs);
88
89
out:
90
bdrv_drained_end(bs);
91
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
92
s->children = g_renew(BdrvChild *, s->children, --s->num_children);
93
bdrv_unref_child(bs, child);
94
95
+ quorum_refresh_flags(bs);
96
bdrv_drained_end(bs);
97
}
98
99
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
100
101
.bdrv_co_preadv = quorum_co_preadv,
102
.bdrv_co_pwritev = quorum_co_pwritev,
103
+ .bdrv_co_pwrite_zeroes = quorum_co_pwrite_zeroes,
104
105
.bdrv_add_child = quorum_add_child,
106
.bdrv_del_child = quorum_del_child,
107
diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312
108
index XXXXXXX..XXXXXXX 100755
109
--- a/tests/qemu-iotests/312
110
+++ b/tests/qemu-iotests/312
111
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write -P 0 $((0x200000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu
112
$QEMU_IO -c "write -z $((0x200000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
113
$QEMU_IO -c "write -P 0 $((0x200000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
114
115
+# Test 5: write data to a region and then zeroize it, doing it
116
+# directly on the quorum device instead of the individual images.
117
+# This has no effect on the end result but proves that the quorum driver
118
+# supports 'write -z'.
119
+$QEMU_IO -c "open -o $quorum" -c "write -P 1 $((0x250000)) $((0x10000))" | _filter_qemu_io
120
+# Verify the data that we just wrote
121
+$QEMU_IO -c "open -o $quorum" -c "read -P 1 $((0x250000)) $((0x10000))" | _filter_qemu_io
122
+$QEMU_IO -c "open -o $quorum" -c "write -z $((0x250000)) $((0x10000))" | _filter_qemu_io
123
+# Now it should read back as zeroes
124
+$QEMU_IO -c "open -o $quorum" -c "read -P 0 $((0x250000)) $((0x10000))" | _filter_qemu_io
125
+
126
echo
127
echo '### Launch the drive-mirror job'
128
echo
129
diff --git a/tests/qemu-iotests/312.out b/tests/qemu-iotests/312.out
130
index XXXXXXX..XXXXXXX 100644
131
--- a/tests/qemu-iotests/312.out
132
+++ b/tests/qemu-iotests/312.out
133
@@ -XXX,XX +XXX,XX @@ wrote 196608/196608 bytes at offset 2097152
134
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
135
wrote 131072/131072 bytes at offset 2097152
136
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
137
+wrote 65536/65536 bytes at offset 2424832
138
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
139
+read 65536/65536 bytes at offset 2424832
140
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
141
+wrote 65536/65536 bytes at offset 2424832
142
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
143
+read 65536/65536 bytes at offset 2424832
144
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
145
146
### Launch the drive-mirror job
147
148
--
149
2.29.2
150
151
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
NVMe drive cannot be shrunk.
4
5
Since commit c80d8b06cfa we can use the @exact parameter (set
6
to false) to return success if the block device is larger than
7
the requested offset (even if we can not be shrunk).
8
9
Use this parameter to implement the NVMe truncate() coroutine,
10
similarly how it is done for the iscsi and file-posix drivers
11
(see commit 82325ae5f2f "Evaluate @exact in protocol drivers").
12
13
Reported-by: Xueqiang Wei <xuwei@redhat.com>
14
Suggested-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Message-Id: <20201210125202.858656-1-philmd@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/nvme.c | 24 ++++++++++++++++++++++++
20
1 file changed, 24 insertions(+)
21
22
diff --git a/block/nvme.c b/block/nvme.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/nvme.c
25
+++ b/block/nvme.c
26
@@ -XXX,XX +XXX,XX @@ out:
27
28
}
29
30
+static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset,
31
+ bool exact, PreallocMode prealloc,
32
+ BdrvRequestFlags flags, Error **errp)
33
+{
34
+ int64_t cur_length;
35
+
36
+ if (prealloc != PREALLOC_MODE_OFF) {
37
+ error_setg(errp, "Unsupported preallocation mode '%s'",
38
+ PreallocMode_str(prealloc));
39
+ return -ENOTSUP;
40
+ }
41
+
42
+ cur_length = nvme_getlength(bs);
43
+ if (offset != cur_length && exact) {
44
+ error_setg(errp, "Cannot resize NVMe devices");
45
+ return -ENOTSUP;
46
+ } else if (offset > cur_length) {
47
+ error_setg(errp, "Cannot grow NVMe devices");
48
+ return -EINVAL;
49
+ }
50
+
51
+ return 0;
52
+}
53
54
static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
55
BlockReopenQueue *queue, Error **errp)
56
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
57
.bdrv_close = nvme_close,
58
.bdrv_getlength = nvme_getlength,
59
.bdrv_probe_blocksizes = nvme_probe_blocksizes,
60
+ .bdrv_co_truncate = nvme_co_truncate,
61
62
.bdrv_co_preadv = nvme_co_preadv,
63
.bdrv_co_pwritev = nvme_co_pwritev,
64
--
65
2.29.2
66
67
diff view generated by jsdifflib
Deleted patch
1
The first parameter passed to _send_qemu_cmd is supposed to be the
2
$QEMU_HANDLE. 102 does not do so here, fix it.
3
1
4
As a result, the output changes: Now we see the prompt this command is
5
supposedly waiting for before the resize message - as it should be.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20201217153803.101231-2-mreitz@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/qemu-iotests/102 | 2 +-
12
tests/qemu-iotests/102.out | 2 +-
13
2 files changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/102
18
+++ b/tests/qemu-iotests/102
19
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
20
qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0
21
22
# Wait for a prompt to appear (so we know qemu has opened the image)
23
-_send_qemu_cmd '' '(qemu)'
24
+_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
25
26
$QEMU_IMG resize --shrink --image-opts \
27
"driver=raw,file.driver=file,file.filename=$TEST_IMG,file.locking=off" \
28
diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qemu-iotests/102.out
31
+++ b/tests/qemu-iotests/102.out
32
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
33
wrote 65536/65536 bytes at offset 0
34
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
35
QEMU X.Y.Z monitor - type 'help' for more information
36
-Image resized.
37
(qemu)
38
+Image resized.
39
(qemu) qemu-io drv0 map
40
64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
41
*** done
42
--
43
2.29.2
44
45
diff view generated by jsdifflib
Deleted patch
1
With bash 5.1, the output of the following script changes:
2
1
3
a=("double space")
4
a=${a[@]:0:1}
5
echo "$a"
6
7
from "double space" to "double space", i.e. all white space is
8
preserved as-is. This is probably what we actually want here (judging
9
from the "...to accommodate pathnames with spaces" comment), but before
10
5.1, we would have to quote the ${} slice to get the same behavior.
11
12
In any case, without quoting, the reference output of many iotests is
13
different between bash 5.1 and pre-5.1, which is not very good. The
14
output of 5.1 is what we want, so whatever we do to get pre-5.1 to the
15
same result, it means we have to fix the reference output of basically
16
all tests that invoke _send_qemu_cmd (except the ones that only use
17
single spaces in the commands they invoke).
18
19
Instead of quoting the ${} slice (cmd="${$@: 1:...}"), we can also just
20
not use array slicing and replace the whole thing with a simple "cmd=$1;
21
shift", which works because all callers quote the whole $cmd argument
22
anyway.
23
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
Message-Id: <20201217153803.101231-3-mreitz@redhat.com>
26
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
27
---
28
tests/qemu-iotests/085.out | 167 ++++++++++++++++++++++++++++-----
29
tests/qemu-iotests/094.out | 10 +-
30
tests/qemu-iotests/095.out | 4 +-
31
tests/qemu-iotests/109.out | 88 ++++++++++++-----
32
tests/qemu-iotests/117.out | 13 ++-
33
tests/qemu-iotests/127.out | 12 ++-
34
tests/qemu-iotests/140.out | 10 +-
35
tests/qemu-iotests/141.out | 128 +++++++++++++++++++------
36
tests/qemu-iotests/143.out | 4 +-
37
tests/qemu-iotests/144.out | 28 +++++-
38
tests/qemu-iotests/153.out | 18 ++--
39
tests/qemu-iotests/156.out | 39 ++++++--
40
tests/qemu-iotests/161.out | 18 +++-
41
tests/qemu-iotests/173.out | 25 ++++-
42
tests/qemu-iotests/182.out | 42 +++++++--
43
tests/qemu-iotests/183.out | 19 +++-
44
tests/qemu-iotests/185.out | 45 +++++++--
45
tests/qemu-iotests/191.out | 12 ++-
46
tests/qemu-iotests/223.out | 92 ++++++++++++------
47
tests/qemu-iotests/229.out | 13 ++-
48
tests/qemu-iotests/249.out | 16 +++-
49
tests/qemu-iotests/308.out | 103 +++++++++++++++++---
50
tests/qemu-iotests/312.out | 10 +-
51
tests/qemu-iotests/common.qemu | 11 +--
52
24 files changed, 728 insertions(+), 199 deletions(-)
53
54
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
55
index XXXXXXX..XXXXXXX 100644
56
--- a/tests/qemu-iotests/085.out
57
+++ b/tests/qemu-iotests/085.out
58
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
59
60
=== Create a single snapshot on virtio0 ===
61
62
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
63
+{ 'execute': 'blockdev-snapshot-sync',
64
+ 'arguments': { 'device': 'virtio0',
65
+ 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT',
66
+ 'format': 'IMGFMT' } }
67
Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
68
{"return": {}}
69
70
=== Invalid command - missing device and nodename ===
71
72
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
73
+{ 'execute': 'blockdev-snapshot-sync',
74
+ 'arguments': { 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT',
75
+ 'format': 'IMGFMT' } }
76
{"error": {"class": "GenericError", "desc": "Cannot find device= nor node_name="}}
77
78
=== Invalid command - missing snapshot-file ===
79
80
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'format': 'IMGFMT' } }
81
+{ 'execute': 'blockdev-snapshot-sync',
82
+ 'arguments': { 'device': 'virtio0',
83
+ 'format': 'IMGFMT' } }
84
{"error": {"class": "GenericError", "desc": "Parameter 'snapshot-file' is missing"}}
85
86
87
=== Create several transactional group snapshots ===
88
89
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
90
+{ 'execute': 'transaction', 'arguments':
91
+ {'actions': [
92
+ { 'type': 'blockdev-snapshot-sync', 'data' :
93
+ { 'device': 'virtio0',
94
+ 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } },
95
+ { 'type': 'blockdev-snapshot-sync', 'data' :
96
+ { 'device': 'virtio1',
97
+ 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ]
98
+ } }
99
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
100
Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
101
{"return": {}}
102
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
103
+{ 'execute': 'transaction', 'arguments':
104
+ {'actions': [
105
+ { 'type': 'blockdev-snapshot-sync', 'data' :
106
+ { 'device': 'virtio0',
107
+ 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } },
108
+ { 'type': 'blockdev-snapshot-sync', 'data' :
109
+ { 'device': 'virtio1',
110
+ 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ]
111
+ } }
112
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
113
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
114
{"return": {}}
115
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
116
+{ 'execute': 'transaction', 'arguments':
117
+ {'actions': [
118
+ { 'type': 'blockdev-snapshot-sync', 'data' :
119
+ { 'device': 'virtio0',
120
+ 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } },
121
+ { 'type': 'blockdev-snapshot-sync', 'data' :
122
+ { 'device': 'virtio1',
123
+ 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ]
124
+ } }
125
Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
126
Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
127
{"return": {}}
128
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
129
+{ 'execute': 'transaction', 'arguments':
130
+ {'actions': [
131
+ { 'type': 'blockdev-snapshot-sync', 'data' :
132
+ { 'device': 'virtio0',
133
+ 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } },
134
+ { 'type': 'blockdev-snapshot-sync', 'data' :
135
+ { 'device': 'virtio1',
136
+ 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ]
137
+ } }
138
Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
139
Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
140
{"return": {}}
141
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
142
+{ 'execute': 'transaction', 'arguments':
143
+ {'actions': [
144
+ { 'type': 'blockdev-snapshot-sync', 'data' :
145
+ { 'device': 'virtio0',
146
+ 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } },
147
+ { 'type': 'blockdev-snapshot-sync', 'data' :
148
+ { 'device': 'virtio1',
149
+ 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ]
150
+ } }
151
Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
152
Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
153
{"return": {}}
154
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
155
+{ 'execute': 'transaction', 'arguments':
156
+ {'actions': [
157
+ { 'type': 'blockdev-snapshot-sync', 'data' :
158
+ { 'device': 'virtio0',
159
+ 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } },
160
+ { 'type': 'blockdev-snapshot-sync', 'data' :
161
+ { 'device': 'virtio1',
162
+ 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ]
163
+ } }
164
Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
165
Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
166
{"return": {}}
167
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
168
+{ 'execute': 'transaction', 'arguments':
169
+ {'actions': [
170
+ { 'type': 'blockdev-snapshot-sync', 'data' :
171
+ { 'device': 'virtio0',
172
+ 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } },
173
+ { 'type': 'blockdev-snapshot-sync', 'data' :
174
+ { 'device': 'virtio1',
175
+ 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ]
176
+ } }
177
Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
178
Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
179
{"return": {}}
180
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
181
+{ 'execute': 'transaction', 'arguments':
182
+ {'actions': [
183
+ { 'type': 'blockdev-snapshot-sync', 'data' :
184
+ { 'device': 'virtio0',
185
+ 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } },
186
+ { 'type': 'blockdev-snapshot-sync', 'data' :
187
+ { 'device': 'virtio1',
188
+ 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ]
189
+ } }
190
Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
191
Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
192
{"return": {}}
193
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
194
+{ 'execute': 'transaction', 'arguments':
195
+ {'actions': [
196
+ { 'type': 'blockdev-snapshot-sync', 'data' :
197
+ { 'device': 'virtio0',
198
+ 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } },
199
+ { 'type': 'blockdev-snapshot-sync', 'data' :
200
+ { 'device': 'virtio1',
201
+ 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ]
202
+ } }
203
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
204
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
205
{"return": {}}
206
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extende
207
=== Create a couple of snapshots using blockdev-snapshot ===
208
209
Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT backing_fmt=IMGFMT
210
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } }
211
+{ 'execute': 'blockdev-add', 'arguments':
212
+ { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null,
213
+ 'file':
214
+ { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT',
215
+ 'node-name': 'file_11' } } }
216
{"return": {}}
217
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
218
+{ 'execute': 'blockdev-snapshot',
219
+ 'arguments': { 'node': 'virtio0',
220
+ 'overlay':'snap_11' } }
221
{"return": {}}
222
Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT backing_fmt=IMGFMT
223
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } }
224
+{ 'execute': 'blockdev-add', 'arguments':
225
+ { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null,
226
+ 'file':
227
+ { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT',
228
+ 'node-name': 'file_12' } } }
229
{"return": {}}
230
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
231
+{ 'execute': 'blockdev-snapshot',
232
+ 'arguments': { 'node': 'virtio0',
233
+ 'overlay':'snap_12' } }
234
{"return": {}}
235
236
=== Invalid command - cannot create a snapshot using a file BDS ===
237
238
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } }
239
+{ 'execute': 'blockdev-snapshot',
240
+ 'arguments': { 'node':'virtio0',
241
+ 'overlay':'file_12' }
242
+ }
243
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
244
245
=== Invalid command - snapshot node used as active layer ===
246
247
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
248
+{ 'execute': 'blockdev-snapshot',
249
+ 'arguments': { 'node': 'virtio0',
250
+ 'overlay':'snap_12' } }
251
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
252
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'virtio0' } }
253
+{ 'execute': 'blockdev-snapshot',
254
+ 'arguments': { 'node':'virtio0',
255
+ 'overlay':'virtio0' }
256
+ }
257
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
258
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'virtio1' } }
259
+{ 'execute': 'blockdev-snapshot',
260
+ 'arguments': { 'node':'virtio0',
261
+ 'overlay':'virtio1' }
262
+ }
263
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
264
265
=== Invalid command - snapshot node used as backing hd ===
266
267
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
268
+{ 'execute': 'blockdev-snapshot',
269
+ 'arguments': { 'node': 'virtio0',
270
+ 'overlay':'snap_11' } }
271
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
272
273
=== Invalid command - snapshot node has a backing image ===
274
275
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
276
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
277
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_13', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'node-name': 'file_13' } } }
278
-{"return": {}}
279
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_13' } }
280
+{ 'execute': 'blockdev-add', 'arguments':
281
+ { 'driver': 'IMGFMT', 'node-name': 'snap_13',
282
+ 'file':
283
+ { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT',
284
+ 'node-name': 'file_13' } } }
285
+{"return": {}}
286
+{ 'execute': 'blockdev-snapshot',
287
+ 'arguments': { 'node': 'virtio0',
288
+ 'overlay':'snap_13' } }
289
{"error": {"class": "GenericError", "desc": "The overlay already has a backing image"}}
290
291
=== Invalid command - The node does not exist ===
292
293
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_14' } }
294
+{ 'execute': 'blockdev-snapshot',
295
+ 'arguments': { 'node': 'virtio0',
296
+ 'overlay':'snap_14' } }
297
{"error": {"class": "GenericError", "desc": "Cannot find device=snap_14 nor node_name=snap_14"}}
298
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'nodevice', 'overlay':'snap_13' } }
299
+{ 'execute': 'blockdev-snapshot',
300
+ 'arguments': { 'node':'nodevice',
301
+ 'overlay':'snap_13' }
302
+ }
303
{"error": {"class": "GenericError", "desc": "Cannot find device=nodevice nor node_name=nodevice"}}
304
*** done
305
diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
306
index XXXXXXX..XXXXXXX 100644
307
--- a/tests/qemu-iotests/094.out
308
+++ b/tests/qemu-iotests/094.out
309
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
310
Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
311
{'execute': 'qmp_capabilities'}
312
{"return": {}}
313
-{'execute': 'drive-mirror', 'arguments': {'device': 'src', 'target': 'nbd+unix:///?socket=SOCK_DIR/nbd', 'format': 'nbd', 'sync':'full', 'mode':'existing'}}
314
+{'execute': 'drive-mirror',
315
+ 'arguments': {'device': 'src',
316
+ 'target': 'nbd+unix:///?socket=SOCK_DIR/nbd',
317
+ 'format': 'nbd',
318
+ 'sync':'full',
319
+ 'mode':'existing'}}
320
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
321
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
322
{"return": {}}
323
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
324
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
325
-{'execute': 'block-job-complete', 'arguments': {'device': 'src'}}
326
+{'execute': 'block-job-complete',
327
+ 'arguments': {'device': 'src'}}
328
{"return": {}}
329
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
330
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
331
diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out
332
index XXXXXXX..XXXXXXX 100644
333
--- a/tests/qemu-iotests/095.out
334
+++ b/tests/qemu-iotests/095.out
335
@@ -XXX,XX +XXX,XX @@ virtual size: 5 MiB (5242880 bytes)
336
337
{ 'execute': 'qmp_capabilities' }
338
{"return": {}}
339
-{ 'execute': 'block-commit', 'arguments': { 'device': 'test', 'top': 'TEST_DIR/t.IMGFMT.snp1' } }
340
+{ 'execute': 'block-commit',
341
+ 'arguments': { 'device': 'test',
342
+ 'top': 'TEST_DIR/t.IMGFMT.snp1' } }
343
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "test"}}
344
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "test"}}
345
{"return": {}}
346
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
347
index XXXXXXX..XXXXXXX 100644
348
--- a/tests/qemu-iotests/109.out
349
+++ b/tests/qemu-iotests/109.out
350
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
351
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
352
{ 'execute': 'qmp_capabilities' }
353
{"return": {}}
354
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
355
+{'execute':'drive-mirror', 'arguments':{
356
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
357
+ 'mode': 'existing', 'sync': 'full'}}
358
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
359
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
360
Specify the 'raw' format explicitly to remove the restrictions.
361
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
362
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
363
{ 'execute': 'qmp_capabilities' }
364
{"return": {}}
365
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
366
+{'execute':'drive-mirror', 'arguments':{
367
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
368
+ 'mode': 'existing', 'sync': 'full'}}
369
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
370
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
371
{"return": {}}
372
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
373
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
374
{ 'execute': 'qmp_capabilities' }
375
{"return": {}}
376
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
377
+{'execute':'drive-mirror', 'arguments':{
378
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
379
+ 'mode': 'existing', 'sync': 'full'}}
380
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
381
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
382
Specify the 'raw' format explicitly to remove the restrictions.
383
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
384
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
385
{ 'execute': 'qmp_capabilities' }
386
{"return": {}}
387
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
388
+{'execute':'drive-mirror', 'arguments':{
389
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
390
+ 'mode': 'existing', 'sync': 'full'}}
391
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
392
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
393
{"return": {}}
394
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
395
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
396
{ 'execute': 'qmp_capabilities' }
397
{"return": {}}
398
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
399
+{'execute':'drive-mirror', 'arguments':{
400
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
401
+ 'mode': 'existing', 'sync': 'full'}}
402
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
403
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
404
Specify the 'raw' format explicitly to remove the restrictions.
405
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
406
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
407
{ 'execute': 'qmp_capabilities' }
408
{"return": {}}
409
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
410
+{'execute':'drive-mirror', 'arguments':{
411
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
412
+ 'mode': 'existing', 'sync': 'full'}}
413
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
414
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
415
{"return": {}}
416
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
417
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
418
{ 'execute': 'qmp_capabilities' }
419
{"return": {}}
420
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
421
+{'execute':'drive-mirror', 'arguments':{
422
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
423
+ 'mode': 'existing', 'sync': 'full'}}
424
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
425
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
426
Specify the 'raw' format explicitly to remove the restrictions.
427
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
428
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
429
{ 'execute': 'qmp_capabilities' }
430
{"return": {}}
431
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
432
+{'execute':'drive-mirror', 'arguments':{
433
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
434
+ 'mode': 'existing', 'sync': 'full'}}
435
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
436
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
437
{"return": {}}
438
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
439
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
440
{ 'execute': 'qmp_capabilities' }
441
{"return": {}}
442
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
443
+{'execute':'drive-mirror', 'arguments':{
444
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
445
+ 'mode': 'existing', 'sync': 'full'}}
446
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
447
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
448
Specify the 'raw' format explicitly to remove the restrictions.
449
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
450
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
451
{ 'execute': 'qmp_capabilities' }
452
{"return": {}}
453
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
454
+{'execute':'drive-mirror', 'arguments':{
455
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
456
+ 'mode': 'existing', 'sync': 'full'}}
457
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
458
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
459
{"return": {}}
460
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
461
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
462
{ 'execute': 'qmp_capabilities' }
463
{"return": {}}
464
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
465
+{'execute':'drive-mirror', 'arguments':{
466
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
467
+ 'mode': 'existing', 'sync': 'full'}}
468
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
469
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
470
Specify the 'raw' format explicitly to remove the restrictions.
471
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
472
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
473
{ 'execute': 'qmp_capabilities' }
474
{"return": {}}
475
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
476
+{'execute':'drive-mirror', 'arguments':{
477
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
478
+ 'mode': 'existing', 'sync': 'full'}}
479
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
480
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
481
{"return": {}}
482
@@ -XXX,XX +XXX,XX @@ Images are identical.
483
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
484
{ 'execute': 'qmp_capabilities' }
485
{"return": {}}
486
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
487
+{'execute':'drive-mirror', 'arguments':{
488
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
489
+ 'mode': 'existing', 'sync': 'full'}}
490
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
491
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
492
Specify the 'raw' format explicitly to remove the restrictions.
493
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
494
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
495
{ 'execute': 'qmp_capabilities' }
496
{"return": {}}
497
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
498
+{'execute':'drive-mirror', 'arguments':{
499
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
500
+ 'mode': 'existing', 'sync': 'full'}}
501
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
502
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
503
{"return": {}}
504
@@ -XXX,XX +XXX,XX @@ Images are identical.
505
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
506
{ 'execute': 'qmp_capabilities' }
507
{"return": {}}
508
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
509
+{'execute':'drive-mirror', 'arguments':{
510
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
511
+ 'mode': 'existing', 'sync': 'full'}}
512
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
513
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
514
Specify the 'raw' format explicitly to remove the restrictions.
515
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
516
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
517
{ 'execute': 'qmp_capabilities' }
518
{"return": {}}
519
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
520
+{'execute':'drive-mirror', 'arguments':{
521
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
522
+ 'mode': 'existing', 'sync': 'full'}}
523
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
524
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
525
{"return": {}}
526
@@ -XXX,XX +XXX,XX @@ Images are identical.
527
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
528
{ 'execute': 'qmp_capabilities' }
529
{"return": {}}
530
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
531
+{'execute':'drive-mirror', 'arguments':{
532
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
533
+ 'mode': 'existing', 'sync': 'full'}}
534
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
535
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
536
Specify the 'raw' format explicitly to remove the restrictions.
537
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
538
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
539
{ 'execute': 'qmp_capabilities' }
540
{"return": {}}
541
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
542
+{'execute':'drive-mirror', 'arguments':{
543
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
544
+ 'mode': 'existing', 'sync': 'full'}}
545
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
546
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
547
{"return": {}}
548
@@ -XXX,XX +XXX,XX @@ Images are identical.
549
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
550
{ 'execute': 'qmp_capabilities' }
551
{"return": {}}
552
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
553
+{'execute':'drive-mirror', 'arguments':{
554
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
555
+ 'mode': 'existing', 'sync': 'full'}}
556
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
557
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
558
Specify the 'raw' format explicitly to remove the restrictions.
559
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
560
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
561
{ 'execute': 'qmp_capabilities' }
562
{"return": {}}
563
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
564
+{'execute':'drive-mirror', 'arguments':{
565
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
566
+ 'mode': 'existing', 'sync': 'full'}}
567
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
568
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
569
{"return": {}}
570
@@ -XXX,XX +XXX,XX @@ Images are identical.
571
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
572
{ 'execute': 'qmp_capabilities' }
573
{"return": {}}
574
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
575
+{'execute':'drive-mirror', 'arguments':{
576
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
577
+ 'mode': 'existing', 'sync': 'full'}}
578
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
579
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
580
Specify the 'raw' format explicitly to remove the restrictions.
581
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
582
Images are identical.
583
{ 'execute': 'qmp_capabilities' }
584
{"return": {}}
585
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
586
+{'execute':'drive-mirror', 'arguments':{
587
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
588
+ 'mode': 'existing', 'sync': 'full'}}
589
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
590
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
591
{"return": {}}
592
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
593
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qemu-iotests/117.out
595
+++ b/tests/qemu-iotests/117.out
596
@@ -XXX,XX +XXX,XX @@ QA output created by 117
597
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
598
{ 'execute': 'qmp_capabilities' }
599
{"return": {}}
600
-{ 'execute': 'blockdev-add', 'arguments': { 'node-name': 'protocol', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' } }
601
+{ 'execute': 'blockdev-add',
602
+ 'arguments': { 'node-name': 'protocol',
603
+ 'driver': 'file',
604
+ 'filename': 'TEST_DIR/t.IMGFMT' } }
605
{"return": {}}
606
-{ 'execute': 'blockdev-add', 'arguments': { 'node-name': 'format', 'driver': 'IMGFMT', 'file': 'protocol' } }
607
+{ 'execute': 'blockdev-add',
608
+ 'arguments': { 'node-name': 'format',
609
+ 'driver': 'IMGFMT',
610
+ 'file': 'protocol' } }
611
{"return": {}}
612
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io format "write -P 42 0 64k"' } }
613
+{ 'execute': 'human-monitor-command',
614
+ 'arguments': { 'command-line': 'qemu-io format "write -P 42 0 64k"' } }
615
wrote 65536/65536 bytes at offset 0
616
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
617
{"return": ""}
618
diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out
619
index XXXXXXX..XXXXXXX 100644
620
--- a/tests/qemu-iotests/127.out
621
+++ b/tests/qemu-iotests/127.out
622
@@ -XXX,XX +XXX,XX @@ wrote 42/42 bytes at offset 0
623
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
624
{ 'execute': 'qmp_capabilities' }
625
{"return": {}}
626
-{ 'execute': 'drive-mirror', 'arguments': { 'job-id': 'mirror', 'device': 'source', 'target': 'TEST_DIR/t.IMGFMT.overlay1', 'mode': 'existing', 'sync': 'top' } }
627
+{ 'execute': 'drive-mirror',
628
+ 'arguments': {
629
+ 'job-id': 'mirror',
630
+ 'device': 'source',
631
+ 'target': 'TEST_DIR/t.IMGFMT.overlay1',
632
+ 'mode': 'existing',
633
+ 'sync': 'top'
634
+ } }
635
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "mirror"}}
636
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "mirror"}}
637
{"return": {}}
638
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "mirror"}}
639
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
640
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'mirror' } }
641
+{ 'execute': 'block-job-complete',
642
+ 'arguments': { 'device': 'mirror' } }
643
{"return": {}}
644
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "mirror"}}
645
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "mirror"}}
646
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
647
index XXXXXXX..XXXXXXX 100644
648
--- a/tests/qemu-iotests/140.out
649
+++ b/tests/qemu-iotests/140.out
650
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 0
651
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
652
{ 'execute': 'qmp_capabilities' }
653
{"return": {}}
654
-{ 'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd' }}}}
655
+{ 'execute': 'nbd-server-start',
656
+ 'arguments': { 'addr': { 'type': 'unix',
657
+ 'data': { 'path': 'SOCK_DIR/nbd' }}}}
658
{"return": {}}
659
-{ 'execute': 'nbd-server-add', 'arguments': { 'device': 'drv' }}
660
+{ 'execute': 'nbd-server-add',
661
+ 'arguments': { 'device': 'drv' }}
662
{"return": {}}
663
read 65536/65536 bytes at offset 0
664
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
665
-{ 'execute': 'eject', 'arguments': { 'device': 'drv' }}
666
+{ 'execute': 'eject',
667
+ 'arguments': { 'device': 'drv' }}
668
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "drv"}}
669
qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available
670
server reported: export 'drv' not present
671
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
672
index XXXXXXX..XXXXXXX 100644
673
--- a/tests/qemu-iotests/141.out
674
+++ b/tests/qemu-iotests/141.out
675
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
676
677
=== Testing drive-backup ===
678
679
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
680
-{"return": {}}
681
-{'execute': 'drive-backup', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'target': 'TEST_DIR/o.IMGFMT', 'format': 'IMGFMT', 'sync': 'none'}}
682
+{'execute': 'blockdev-add',
683
+ 'arguments': {
684
+ 'node-name': 'drv0',
685
+ 'driver': 'IMGFMT',
686
+ 'file': {
687
+ 'driver': 'file',
688
+ 'filename': 'TEST_DIR/t.IMGFMT'
689
+ }}}
690
+{"return": {}}
691
+{'execute': 'drive-backup',
692
+'arguments': {'job-id': 'job0',
693
+'device': 'drv0',
694
+'target': 'TEST_DIR/o.IMGFMT',
695
+'format': 'IMGFMT',
696
+'sync': 'none'}}
697
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
698
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
699
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
700
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
701
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
702
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
703
+{'execute': 'blockdev-del',
704
+ 'arguments': {'node-name': 'drv0'}}
705
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
706
-{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
707
+{'execute': 'block-job-cancel',
708
+ 'arguments': {'device': 'job0'}}
709
{"return": {}}
710
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
711
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
712
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
713
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
714
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
715
+{'execute': 'blockdev-del',
716
+ 'arguments': {'node-name': 'drv0'}}
717
{"return": {}}
718
719
=== Testing drive-mirror ===
720
721
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
722
-{"return": {}}
723
-{'execute': 'drive-mirror', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'target': 'TEST_DIR/o.IMGFMT', 'format': 'IMGFMT', 'sync': 'none'}}
724
+{'execute': 'blockdev-add',
725
+ 'arguments': {
726
+ 'node-name': 'drv0',
727
+ 'driver': 'IMGFMT',
728
+ 'file': {
729
+ 'driver': 'file',
730
+ 'filename': 'TEST_DIR/t.IMGFMT'
731
+ }}}
732
+{"return": {}}
733
+{'execute': 'drive-mirror',
734
+'arguments': {'job-id': 'job0',
735
+'device': 'drv0',
736
+'target': 'TEST_DIR/o.IMGFMT',
737
+'format': 'IMGFMT',
738
+'sync': 'none'}}
739
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
740
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
741
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
742
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
743
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
744
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
745
+{'execute': 'blockdev-del',
746
+ 'arguments': {'node-name': 'drv0'}}
747
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
748
-{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
749
+{'execute': 'block-job-cancel',
750
+ 'arguments': {'device': 'job0'}}
751
{"return": {}}
752
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
753
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
754
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
755
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
756
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
757
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
758
+{'execute': 'blockdev-del',
759
+ 'arguments': {'node-name': 'drv0'}}
760
{"return": {}}
761
762
=== Testing active block-commit ===
763
764
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
765
-{"return": {}}
766
-{'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'drv0'}}
767
+{'execute': 'blockdev-add',
768
+ 'arguments': {
769
+ 'node-name': 'drv0',
770
+ 'driver': 'IMGFMT',
771
+ 'file': {
772
+ 'driver': 'file',
773
+ 'filename': 'TEST_DIR/t.IMGFMT'
774
+ }}}
775
+{"return": {}}
776
+{'execute': 'block-commit',
777
+'arguments': {'job-id': 'job0', 'device': 'drv0'}}
778
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
779
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
780
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
781
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
782
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
783
+{'execute': 'blockdev-del',
784
+ 'arguments': {'node-name': 'drv0'}}
785
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
786
-{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
787
+{'execute': 'block-job-cancel',
788
+ 'arguments': {'device': 'job0'}}
789
{"return": {}}
790
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
791
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
792
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
793
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
794
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
795
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
796
+{'execute': 'blockdev-del',
797
+ 'arguments': {'node-name': 'drv0'}}
798
{"return": {}}
799
800
=== Testing non-active block-commit ===
801
802
wrote 1048576/1048576 bytes at offset 0
803
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
804
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
805
-{"return": {}}
806
-{'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'top': 'TEST_DIR/m.IMGFMT', 'speed': 1}}
807
+{'execute': 'blockdev-add',
808
+ 'arguments': {
809
+ 'node-name': 'drv0',
810
+ 'driver': 'IMGFMT',
811
+ 'file': {
812
+ 'driver': 'file',
813
+ 'filename': 'TEST_DIR/t.IMGFMT'
814
+ }}}
815
+{"return": {}}
816
+{'execute': 'block-commit',
817
+'arguments': {'job-id': 'job0',
818
+'device': 'drv0',
819
+'top': 'TEST_DIR/m.IMGFMT',
820
+'speed': 1}}
821
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
822
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
823
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
824
+{'execute': 'blockdev-del',
825
+ 'arguments': {'node-name': 'drv0'}}
826
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
827
-{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
828
+{'execute': 'block-job-cancel',
829
+ 'arguments': {'device': 'job0'}}
830
{"return": {}}
831
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
832
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
833
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
834
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
835
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
836
+{'execute': 'blockdev-del',
837
+ 'arguments': {'node-name': 'drv0'}}
838
{"return": {}}
839
840
=== Testing block-stream ===
841
842
wrote 1048576/1048576 bytes at offset 0
843
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
844
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
845
-{"return": {}}
846
-{'execute': 'block-stream', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'speed': 1}}
847
+{'execute': 'blockdev-add',
848
+ 'arguments': {
849
+ 'node-name': 'drv0',
850
+ 'driver': 'IMGFMT',
851
+ 'file': {
852
+ 'driver': 'file',
853
+ 'filename': 'TEST_DIR/t.IMGFMT'
854
+ }}}
855
+{"return": {}}
856
+{'execute': 'block-stream',
857
+'arguments': {'job-id': 'job0',
858
+'device': 'drv0',
859
+'speed': 1}}
860
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
861
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
862
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
863
+{'execute': 'blockdev-del',
864
+ 'arguments': {'node-name': 'drv0'}}
865
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
866
-{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
867
+{'execute': 'block-job-cancel',
868
+ 'arguments': {'device': 'job0'}}
869
{"return": {}}
870
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
871
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
872
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
873
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
874
-{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
875
+{'execute': 'blockdev-del',
876
+ 'arguments': {'node-name': 'drv0'}}
877
{"return": {}}
878
*** done
879
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
880
index XXXXXXX..XXXXXXX 100644
881
--- a/tests/qemu-iotests/143.out
882
+++ b/tests/qemu-iotests/143.out
883
@@ -XXX,XX +XXX,XX @@
884
QA output created by 143
885
{ 'execute': 'qmp_capabilities' }
886
{"return": {}}
887
-{ 'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd' }}}}
888
+{ 'execute': 'nbd-server-start',
889
+ 'arguments': { 'addr': { 'type': 'unix',
890
+ 'data': { 'path': 'SOCK_DIR/nbd' }}}}
891
{"return": {}}
892
qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available
893
server reported: export 'no_such_export' not present
894
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
895
index XXXXXXX..XXXXXXX 100644
896
--- a/tests/qemu-iotests/144.out
897
+++ b/tests/qemu-iotests/144.out
898
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
899
900
{ 'execute': 'qmp_capabilities' }
901
{"return": {}}
902
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
903
+{ 'execute': 'blockdev-snapshot-sync',
904
+ 'arguments': {
905
+ 'device': 'virtio0',
906
+ 'snapshot-file':'TEST_DIR/tmp.IMGFMT',
907
+ 'format': 'IMGFMT'
908
+ }
909
+ }
910
Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
911
{"return": {}}
912
913
=== Performing block-commit on active layer ===
914
915
-{ 'execute': 'block-commit', 'arguments': { 'device': 'virtio0' } }
916
+{ 'execute': 'block-commit',
917
+ 'arguments': {
918
+ 'device': 'virtio0'
919
+ }
920
+ }
921
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
922
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
923
{"return": {}}
924
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
925
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
926
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'virtio0' } }
927
+{ 'execute': 'block-job-complete',
928
+ 'arguments': {
929
+ 'device': 'virtio0'
930
+ }
931
+ }
932
{"return": {}}
933
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
934
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
935
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off co
936
937
=== Performing Live Snapshot 2 ===
938
939
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
940
+{ 'execute': 'blockdev-snapshot-sync',
941
+ 'arguments': {
942
+ 'device': 'virtio0',
943
+ 'snapshot-file':'TEST_DIR/tmp2.IMGFMT',
944
+ 'format': 'IMGFMT'
945
+ }
946
+ }
947
Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
948
{"return": {}}
949
*** done
950
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
951
index XXXXXXX..XXXXXXX 100644
952
--- a/tests/qemu-iotests/153.out
953
+++ b/tests/qemu-iotests/153.out
954
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
955
{ 'execute': 'qmp_capabilities' }
956
{"return": {}}
957
Adding drive
958
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT' } }
959
+{ 'execute': 'human-monitor-command',
960
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT' } }
961
{"return": "OKrn"}
962
963
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
964
@@ -XXX,XX +XXX,XX @@ Creating overlay with qemu-img when the guest is running should be allowed
965
966
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 -F qcow2 TEST_DIR/t.qcow2.overlay
967
== Closing an image should unlock it ==
968
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d0' } }
969
+{ 'execute': 'human-monitor-command',
970
+ 'arguments': { 'command-line': 'drive_del d0' } }
971
{"return": ""}
972
973
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
974
Adding two and closing one
975
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT,readonly=on' } }
976
+{ 'execute': 'human-monitor-command',
977
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT,readonly=on' } }
978
{"return": "OKrn"}
979
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d1,file=TEST_DIR/t.IMGFMT,readonly=on' } }
980
+{ 'execute': 'human-monitor-command',
981
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d1,file=TEST_DIR/t.IMGFMT,readonly=on' } }
982
{"return": "OKrn"}
983
984
_qemu_img_wrapper info TEST_DIR/t.qcow2
985
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d0' } }
986
+{ 'execute': 'human-monitor-command',
987
+ 'arguments': { 'command-line': 'drive_del d0' } }
988
{"return": ""}
989
990
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
991
qemu-io: can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
992
Is another process using the image [TEST_DIR/t.qcow2]?
993
Closing the other
994
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d1' } }
995
+{ 'execute': 'human-monitor-command',
996
+ 'arguments': { 'command-line': 'drive_del d1' } }
997
{"return": ""}
998
999
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
1000
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
1001
index XXXXXXX..XXXXXXX 100644
1002
--- a/tests/qemu-iotests/156.out
1003
+++ b/tests/qemu-iotests/156.out
1004
@@ -XXX,XX +XXX,XX @@ wrote 196608/196608 bytes at offset 65536
1005
{ 'execute': 'qmp_capabilities' }
1006
{"return": {}}
1007
Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
1008
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'source', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'format': 'IMGFMT', 'mode': 'existing' } }
1009
+{ 'execute': 'blockdev-snapshot-sync',
1010
+ 'arguments': { 'device': 'source',
1011
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay',
1012
+ 'format': 'IMGFMT',
1013
+ 'mode': 'existing' } }
1014
{"return": {}}
1015
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "write -P 3 128k 128k"' } }
1016
+{ 'execute': 'human-monitor-command',
1017
+ 'arguments': { 'command-line':
1018
+ 'qemu-io source "write -P 3 128k 128k"' } }
1019
wrote 131072/131072 bytes at offset 131072
1020
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1021
{"return": ""}
1022
Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target backing_fmt=IMGFMT
1023
-{ 'execute': 'drive-mirror', 'arguments': { 'device': 'source', 'target': 'TEST_DIR/t.IMGFMT.target.overlay', 'mode': 'existing', 'sync': 'top' } }
1024
+{ 'execute': 'drive-mirror',
1025
+ 'arguments': { 'device': 'source',
1026
+ 'target': 'TEST_DIR/t.IMGFMT.target.overlay',
1027
+ 'mode': 'existing',
1028
+ 'sync': 'top' } }
1029
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "source"}}
1030
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "source"}}
1031
{"return": {}}
1032
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "source"}}
1033
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "source", "len": 131072, "offset": 131072, "speed": 0, "type": "mirror"}}
1034
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "write -P 4 192k 64k"' } }
1035
+{ 'execute': 'human-monitor-command',
1036
+ 'arguments': { 'command-line':
1037
+ 'qemu-io source "write -P 4 192k 64k"' } }
1038
wrote 65536/65536 bytes at offset 196608
1039
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1040
{"return": ""}
1041
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'source' } }
1042
+{ 'execute': 'block-job-complete',
1043
+ 'arguments': { 'device': 'source' } }
1044
{"return": {}}
1045
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "source"}}
1046
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "source"}}
1047
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 196608
1048
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "source"}}
1049
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "source"}}
1050
1051
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 1 0k 64k"' } }
1052
+{ 'execute': 'human-monitor-command',
1053
+ 'arguments': { 'command-line':
1054
+ 'qemu-io source "read -P 1 0k 64k"' } }
1055
read 65536/65536 bytes at offset 0
1056
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1057
{"return": ""}
1058
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 2 64k 64k"' } }
1059
+{ 'execute': 'human-monitor-command',
1060
+ 'arguments': { 'command-line':
1061
+ 'qemu-io source "read -P 2 64k 64k"' } }
1062
read 65536/65536 bytes at offset 65536
1063
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1064
{"return": ""}
1065
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 3 128k 64k"' } }
1066
+{ 'execute': 'human-monitor-command',
1067
+ 'arguments': { 'command-line':
1068
+ 'qemu-io source "read -P 3 128k 64k"' } }
1069
read 65536/65536 bytes at offset 131072
1070
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1071
{"return": ""}
1072
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 4 192k 64k"' } }
1073
+{ 'execute': 'human-monitor-command',
1074
+ 'arguments': { 'command-line':
1075
+ 'qemu-io source "read -P 4 192k 64k"' } }
1076
read 65536/65536 bytes at offset 196608
1077
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1078
{"return": ""}
1079
diff --git a/tests/qemu-iotests/161.out b/tests/qemu-iotests/161.out
1080
index XXXXXXX..XXXXXXX 100644
1081
--- a/tests/qemu-iotests/161.out
1082
+++ b/tests/qemu-iotests/161.out
1083
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
1084
1085
{ 'execute': 'qmp_capabilities' }
1086
{"return": {}}
1087
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1088
+{ 'execute': 'human-monitor-command',
1089
+ 'arguments': { 'command-line':
1090
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1091
{"return": ""}
1092
1093
*** Stream and then change an option on the backing file
1094
1095
{ 'execute': 'qmp_capabilities' }
1096
{"return": {}}
1097
-{ 'execute': 'block-stream', 'arguments': { 'device': 'none0', 'base': 'TEST_DIR/t.IMGFMT.base' } }
1098
+{ 'execute': 'block-stream', 'arguments': { 'device': 'none0',
1099
+ 'base': 'TEST_DIR/t.IMGFMT.base' } }
1100
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
1101
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
1102
{"return": {}}
1103
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1104
+{ 'execute': 'human-monitor-command',
1105
+ 'arguments': { 'command-line':
1106
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1107
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
1108
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
1109
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "stream"}}
1110
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DI
1111
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int backing_fmt=IMGFMT
1112
{ 'execute': 'qmp_capabilities' }
1113
{"return": {}}
1114
-{ 'execute': 'block-commit', 'arguments': { 'device': 'none0', 'top': 'TEST_DIR/t.IMGFMT.int' } }
1115
+{ 'execute': 'block-commit', 'arguments': { 'device': 'none0',
1116
+ 'top': 'TEST_DIR/t.IMGFMT.int' } }
1117
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
1118
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
1119
{"return": {}}
1120
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1121
+{ 'execute': 'human-monitor-command',
1122
+ 'arguments': { 'command-line':
1123
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
1124
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
1125
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
1126
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
1127
diff --git a/tests/qemu-iotests/173.out b/tests/qemu-iotests/173.out
1128
index XXXXXXX..XXXXXXX 100644
1129
--- a/tests/qemu-iotests/173.out
1130
+++ b/tests/qemu-iotests/173.out
1131
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/image.snp1', fmt=IMGFMT size=104857600
1132
1133
{ 'execute': 'qmp_capabilities' }
1134
{"return": {}}
1135
-{ 'arguments': { 'device': 'disk2', 'format': 'IMGFMT', 'mode': 'existing', 'snapshot-file': 'TEST_DIR/image.snp1', 'snapshot-node-name': 'snp1' }, 'execute': 'blockdev-snapshot-sync' }
1136
+{ 'arguments': {
1137
+ 'device': 'disk2',
1138
+ 'format': 'IMGFMT',
1139
+ 'mode': 'existing',
1140
+ 'snapshot-file': 'TEST_DIR/image.snp1',
1141
+ 'snapshot-node-name': 'snp1'
1142
+ },
1143
+ 'execute': 'blockdev-snapshot-sync'
1144
+ }
1145
{"return": {}}
1146
-{ 'arguments': { 'backing-file': 'image.base', 'device': 'disk2', 'image-node-name': 'snp1' }, 'execute': 'change-backing-file' }
1147
+{ 'arguments': {
1148
+ 'backing-file': 'image.base',
1149
+ 'device': 'disk2',
1150
+ 'image-node-name': 'snp1'
1151
+ },
1152
+ 'execute': 'change-backing-file'
1153
+ }
1154
{"return": {}}
1155
-{ 'arguments': { 'base': 'TEST_DIR/image.base', 'device': 'disk2' }, 'execute': 'block-stream' }
1156
+{ 'arguments': {
1157
+ 'base': 'TEST_DIR/image.base',
1158
+ 'device': 'disk2'
1159
+ },
1160
+ 'execute': 'block-stream'
1161
+ }
1162
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk2"}}
1163
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk2"}}
1164
{"return": {}}
1165
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
1166
index XXXXXXX..XXXXXXX 100644
1167
--- a/tests/qemu-iotests/182.out
1168
+++ b/tests/qemu-iotests/182.out
1169
@@ -XXX,XX +XXX,XX @@ Is another process using the image [TEST_DIR/t.qcow2]?
1170
1171
{'execute': 'qmp_capabilities'}
1172
{"return": {}}
1173
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
1174
-{"return": {}}
1175
-{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
1176
+{'execute': 'blockdev-add',
1177
+ 'arguments': {
1178
+ 'node-name': 'node0',
1179
+ 'driver': 'file',
1180
+ 'filename': 'TEST_DIR/t.IMGFMT',
1181
+ 'locking': 'on'
1182
+ } }
1183
+{"return": {}}
1184
+{'execute': 'blockdev-snapshot-sync',
1185
+ 'arguments': {
1186
+ 'node-name': 'node0',
1187
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay',
1188
+ 'snapshot-node-name': 'node1'
1189
+ } }
1190
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
1191
{"return": {}}
1192
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
1193
-{"return": {}}
1194
-{'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd.socket' } } } }
1195
-{"return": {}}
1196
-{'execute': 'nbd-server-add', 'arguments': { 'device': 'node1' } }
1197
+{'execute': 'blockdev-add',
1198
+ 'arguments': {
1199
+ 'node-name': 'node1',
1200
+ 'driver': 'file',
1201
+ 'filename': 'TEST_DIR/t.IMGFMT',
1202
+ 'locking': 'on'
1203
+ } }
1204
+{"return": {}}
1205
+{'execute': 'nbd-server-start',
1206
+ 'arguments': {
1207
+ 'addr': {
1208
+ 'type': 'unix',
1209
+ 'data': {
1210
+ 'path': 'SOCK_DIR/nbd.socket'
1211
+ } } } }
1212
+{"return": {}}
1213
+{'execute': 'nbd-server-add',
1214
+ 'arguments': {
1215
+ 'device': 'node1'
1216
+ } }
1217
{"return": {}}
1218
1219
=== Testing failure to loosen restrictions ===
1220
diff --git a/tests/qemu-iotests/183.out b/tests/qemu-iotests/183.out
1221
index XXXXXXX..XXXXXXX 100644
1222
--- a/tests/qemu-iotests/183.out
1223
+++ b/tests/qemu-iotests/183.out
1224
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.dest', fmt=IMGFMT size=67108864
1225
1226
=== Write something on the source ===
1227
1228
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write -P 0x55 0 64k"' } }
1229
+{ 'execute': 'human-monitor-command',
1230
+ 'arguments': { 'command-line':
1231
+ 'qemu-io disk "write -P 0x55 0 64k"' } }
1232
wrote 65536/65536 bytes at offset 0
1233
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1234
{"return": ""}
1235
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "read -P 0x55 0 64k"' } }
1236
+{ 'execute': 'human-monitor-command',
1237
+ 'arguments': { 'command-line':
1238
+ 'qemu-io disk "read -P 0x55 0 64k"' } }
1239
read 65536/65536 bytes at offset 0
1240
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1241
{"return": ""}
1242
1243
=== Do block migration to destination ===
1244
1245
-{ 'execute': 'migrate', 'arguments': { 'uri': 'unix:SOCK_DIR/migrate', 'blk': true } }
1246
+{ 'execute': 'migrate',
1247
+ 'arguments': { 'uri': 'unix:SOCK_DIR/migrate', 'blk': true } }
1248
{"return": {}}
1249
{ 'execute': 'query-status' }
1250
{"return": {"status": "postmigrate", "singlestep": false, "running": false}}
1251
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
1252
{ 'execute': 'query-status' }
1253
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESUME"}
1254
{"return": {"status": "running", "singlestep": false, "running": true}}
1255
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "read -P 0x55 0 64k"' } }
1256
+{ 'execute': 'human-monitor-command',
1257
+ 'arguments': { 'command-line':
1258
+ 'qemu-io disk "read -P 0x55 0 64k"' } }
1259
read 65536/65536 bytes at offset 0
1260
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1261
{"return": ""}
1262
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write -P 0x66 1M 64k"' } }
1263
+{ 'execute': 'human-monitor-command',
1264
+ 'arguments': { 'command-line':
1265
+ 'qemu-io disk "write -P 0x66 1M 64k"' } }
1266
wrote 65536/65536 bytes at offset 1048576
1267
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1268
{"return": ""}
1269
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
1270
index XXXXXXX..XXXXXXX 100644
1271
--- a/tests/qemu-iotests/185.out
1272
+++ b/tests/qemu-iotests/185.out
1273
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
1274
1275
=== Creating backing chain ===
1276
1277
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
1278
+{ 'execute': 'blockdev-snapshot-sync',
1279
+ 'arguments': { 'device': 'disk',
1280
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid',
1281
+ 'format': 'IMGFMT',
1282
+ 'mode': 'absolute-paths' } }
1283
Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1284
{"return": {}}
1285
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
1286
+{ 'execute': 'human-monitor-command',
1287
+ 'arguments': { 'command-line':
1288
+ 'qemu-io disk "write 0 4M"' } }
1289
wrote 4194304/4194304 bytes at offset 0
1290
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1291
{"return": ""}
1292
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
1293
+{ 'execute': 'blockdev-snapshot-sync',
1294
+ 'arguments': { 'device': 'disk',
1295
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT',
1296
+ 'format': 'IMGFMT',
1297
+ 'mode': 'absolute-paths' } }
1298
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1299
{"return": {}}
1300
1301
=== Start commit job and exit qemu ===
1302
1303
-{ 'execute': 'block-commit', 'arguments': { 'device': 'disk', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid', 'speed': 65536 } }
1304
+{ 'execute': 'block-commit',
1305
+ 'arguments': { 'device': 'disk',
1306
+ 'base':'TEST_DIR/t.IMGFMT.base',
1307
+ 'top': 'TEST_DIR/t.IMGFMT.mid',
1308
+ 'speed': 65536 } }
1309
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1310
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1311
{"return": {}}
1312
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
1313
1314
{ 'execute': 'qmp_capabilities' }
1315
{"return": {}}
1316
-{ 'execute': 'block-commit', 'arguments': { 'device': 'disk', 'base':'TEST_DIR/t.IMGFMT.base', 'speed': 65536 } }
1317
+{ 'execute': 'block-commit',
1318
+ 'arguments': { 'device': 'disk',
1319
+ 'base':'TEST_DIR/t.IMGFMT.base',
1320
+ 'speed': 65536 } }
1321
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1322
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1323
{"return": {}}
1324
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
1325
1326
{ 'execute': 'qmp_capabilities' }
1327
{"return": {}}
1328
-{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
1329
+{ 'execute': 'drive-mirror',
1330
+ 'arguments': { 'device': 'disk',
1331
+ 'target': 'TEST_DIR/t.IMGFMT.copy',
1332
+ 'format': 'IMGFMT',
1333
+ 'sync': 'full',
1334
+ 'speed': 65536 } }
1335
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1336
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1337
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1338
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
1339
1340
{ 'execute': 'qmp_capabilities' }
1341
{"return": {}}
1342
-{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
1343
+{ 'execute': 'drive-backup',
1344
+ 'arguments': { 'device': 'disk',
1345
+ 'target': 'TEST_DIR/t.IMGFMT.copy',
1346
+ 'format': 'IMGFMT',
1347
+ 'sync': 'full',
1348
+ 'speed': 65536 } }
1349
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1350
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1351
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1352
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
1353
1354
{ 'execute': 'qmp_capabilities' }
1355
{"return": {}}
1356
-{ 'execute': 'block-stream', 'arguments': { 'device': 'disk', 'speed': 65536 } }
1357
+{ 'execute': 'block-stream',
1358
+ 'arguments': { 'device': 'disk',
1359
+ 'speed': 65536 } }
1360
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1361
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1362
{"return": {}}
1363
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
1364
index XXXXXXX..XXXXXXX 100644
1365
--- a/tests/qemu-iotests/191.out
1366
+++ b/tests/qemu-iotests/191.out
1367
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
1368
1369
=== Perform commit job ===
1370
1371
-{ 'execute': 'block-commit', 'arguments': { 'job-id': 'commit0', 'device': 'top', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid' } }
1372
+{ 'execute': 'block-commit',
1373
+ 'arguments': { 'job-id': 'commit0',
1374
+ 'device': 'top',
1375
+ 'base':'TEST_DIR/t.IMGFMT.base',
1376
+ 'top': 'TEST_DIR/t.IMGFMT.mid' } }
1377
{
1378
"timestamp": {
1379
"seconds": TIMESTAMP,
1380
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
1381
1382
=== Perform commit job ===
1383
1384
-{ 'execute': 'block-commit', 'arguments': { 'job-id': 'commit0', 'device': 'top', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid' } }
1385
+{ 'execute': 'block-commit',
1386
+ 'arguments': { 'job-id': 'commit0',
1387
+ 'device': 'top',
1388
+ 'base':'TEST_DIR/t.IMGFMT.base',
1389
+ 'top': 'TEST_DIR/t.IMGFMT.mid' } }
1390
{
1391
"timestamp": {
1392
"seconds": TIMESTAMP,
1393
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
1394
index XXXXXXX..XXXXXXX 100644
1395
--- a/tests/qemu-iotests/223.out
1396
+++ b/tests/qemu-iotests/223.out
1397
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 2097152
1398
1399
{"execute":"qmp_capabilities"}
1400
{"return": {}}
1401
-{"execute":"blockdev-add", "arguments":{"driver":"IMGFMT", "node-name":"n", "file":{"driver":"file", "filename":"TEST_DIR/t.IMGFMT"}}}
1402
+{"execute":"blockdev-add",
1403
+ "arguments":{"driver":"IMGFMT", "node-name":"n",
1404
+ "file":{"driver":"file", "filename":"TEST_DIR/t.IMGFMT"}}}
1405
{"return": {}}
1406
-{"execute":"block-dirty-bitmap-disable", "arguments":{"node":"n", "name":"b"}}
1407
+{"execute":"block-dirty-bitmap-disable",
1408
+ "arguments":{"node":"n", "name":"b"}}
1409
{"return": {}}
1410
1411
=== Set up NBD with normal access ===
1412
1413
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
1414
+{"execute":"nbd-server-add",
1415
+ "arguments":{"device":"n"}}
1416
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
1417
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd"}}}}
1418
+{"execute":"nbd-server-start",
1419
+ "arguments":{"addr":{"type":"unix",
1420
+ "data":{"path":"SOCK_DIR/nbd"}}}}
1421
{"return": {}}
1422
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd1"}}}}
1423
+{"execute":"nbd-server-start",
1424
+ "arguments":{"addr":{"type":"unix",
1425
+ "data":{"path":"SOCK_DIR/nbd1"}}}}
1426
{"error": {"class": "GenericError", "desc": "NBD server already running"}}
1427
exports available: 0
1428
-{"execute":"nbd-server-add", "arguments":{"device":"n", "bitmap":"b"}}
1429
+{"execute":"nbd-server-add",
1430
+ "arguments":{"device":"n", "bitmap":"b"}}
1431
{"return": {}}
1432
-{"execute":"nbd-server-add", "arguments":{"device":"nosuch"}}
1433
+{"execute":"nbd-server-add",
1434
+ "arguments":{"device":"nosuch"}}
1435
{"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
1436
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
1437
+{"execute":"nbd-server-add",
1438
+ "arguments":{"device":"n"}}
1439
{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}}
1440
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}}
1441
+{"execute":"nbd-server-add",
1442
+ "arguments":{"device":"n", "name":"n2",
1443
+ "bitmap":"b2"}}
1444
{"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
1445
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}}
1446
+{"execute":"nbd-server-add",
1447
+ "arguments":{"device":"n", "name":"n2",
1448
+ "bitmap":"b3"}}
1449
{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
1450
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "writable":true, "description":"some text", "bitmap":"b2"}}
1451
+{"execute":"nbd-server-add",
1452
+ "arguments":{"device":"n", "name":"n2", "writable":true,
1453
+ "description":"some text", "bitmap":"b2"}}
1454
{"return": {}}
1455
exports available: 2
1456
export: 'n'
1457
@@ -XXX,XX +XXX,XX @@ read 2097152/2097152 bytes at offset 2097152
1458
1459
=== End qemu NBD server ===
1460
1461
-{"execute":"nbd-server-remove", "arguments":{"name":"n"}}
1462
+{"execute":"nbd-server-remove",
1463
+ "arguments":{"name":"n"}}
1464
{"return": {}}
1465
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
1466
+{"execute":"nbd-server-remove",
1467
+ "arguments":{"name":"n2"}}
1468
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
1469
{"return": {}}
1470
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
1471
+{"execute":"nbd-server-remove",
1472
+ "arguments":{"name":"n2"}}
1473
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
1474
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
1475
{"execute":"nbd-server-stop"}
1476
@@ -XXX,XX +XXX,XX @@ read 2097152/2097152 bytes at offset 2097152
1477
1478
=== Set up NBD with iothread access ===
1479
1480
-{"execute":"x-blockdev-set-iothread", "arguments":{"node-name":"n", "iothread":"io0"}}
1481
+{"execute":"x-blockdev-set-iothread",
1482
+ "arguments":{"node-name":"n", "iothread":"io0"}}
1483
{"return": {}}
1484
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
1485
+{"execute":"nbd-server-add",
1486
+ "arguments":{"device":"n"}}
1487
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
1488
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd"}}}}
1489
+{"execute":"nbd-server-start",
1490
+ "arguments":{"addr":{"type":"unix",
1491
+ "data":{"path":"SOCK_DIR/nbd"}}}}
1492
{"return": {}}
1493
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd1"}}}}
1494
+{"execute":"nbd-server-start",
1495
+ "arguments":{"addr":{"type":"unix",
1496
+ "data":{"path":"SOCK_DIR/nbd1"}}}}
1497
{"error": {"class": "GenericError", "desc": "NBD server already running"}}
1498
exports available: 0
1499
-{"execute":"nbd-server-add", "arguments":{"device":"n", "bitmap":"b"}}
1500
+{"execute":"nbd-server-add",
1501
+ "arguments":{"device":"n", "bitmap":"b"}}
1502
{"return": {}}
1503
-{"execute":"nbd-server-add", "arguments":{"device":"nosuch"}}
1504
+{"execute":"nbd-server-add",
1505
+ "arguments":{"device":"nosuch"}}
1506
{"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
1507
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
1508
+{"execute":"nbd-server-add",
1509
+ "arguments":{"device":"n"}}
1510
{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}}
1511
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}}
1512
+{"execute":"nbd-server-add",
1513
+ "arguments":{"device":"n", "name":"n2",
1514
+ "bitmap":"b2"}}
1515
{"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
1516
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}}
1517
+{"execute":"nbd-server-add",
1518
+ "arguments":{"device":"n", "name":"n2",
1519
+ "bitmap":"b3"}}
1520
{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
1521
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "writable":true, "description":"some text", "bitmap":"b2"}}
1522
+{"execute":"nbd-server-add",
1523
+ "arguments":{"device":"n", "name":"n2", "writable":true,
1524
+ "description":"some text", "bitmap":"b2"}}
1525
{"return": {}}
1526
exports available: 2
1527
export: 'n'
1528
@@ -XXX,XX +XXX,XX @@ read 2097152/2097152 bytes at offset 2097152
1529
1530
=== End qemu NBD server ===
1531
1532
-{"execute":"nbd-server-remove", "arguments":{"name":"n"}}
1533
+{"execute":"nbd-server-remove",
1534
+ "arguments":{"name":"n"}}
1535
{"return": {}}
1536
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
1537
+{"execute":"nbd-server-remove",
1538
+ "arguments":{"name":"n2"}}
1539
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
1540
{"return": {}}
1541
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
1542
+{"execute":"nbd-server-remove",
1543
+ "arguments":{"name":"n2"}}
1544
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
1545
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
1546
{"execute":"nbd-server-stop"}
1547
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
1548
index XXXXXXX..XXXXXXX 100644
1549
--- a/tests/qemu-iotests/229.out
1550
+++ b/tests/qemu-iotests/229.out
1551
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
1552
1553
=== Starting drive-mirror, causing error & stop ===
1554
1555
-{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT.dest', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
1556
+{'execute': 'drive-mirror',
1557
+ 'arguments': {'device': 'testdisk',
1558
+ 'format': 'IMGFMT',
1559
+ 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT.dest',
1560
+ 'sync': 'full',
1561
+ 'mode': 'existing',
1562
+ 'on-source-error': 'stop',
1563
+ 'on-target-error': 'stop' }}
1564
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
1565
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
1566
{"return": {}}
1567
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
1568
1569
=== Force cancel job paused in error state ===
1570
1571
-{'execute': 'block-job-cancel', 'arguments': { 'device': 'testdisk', 'force': true}}
1572
+{'execute': 'block-job-cancel',
1573
+ 'arguments': { 'device': 'testdisk',
1574
+ 'force': true}}
1575
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
1576
{"return": {}}
1577
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
1578
diff --git a/tests/qemu-iotests/249.out b/tests/qemu-iotests/249.out
1579
index XXXXXXX..XXXXXXX 100644
1580
--- a/tests/qemu-iotests/249.out
1581
+++ b/tests/qemu-iotests/249.out
1582
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
1583
1584
=== Send a write command to a drive opened in read-only mode (1)
1585
1586
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1587
+{ 'execute': 'human-monitor-command',
1588
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1589
{"return": "Block node is read-onlyrn"}
1590
1591
=== Run block-commit on base using an invalid filter node name
1592
1593
-{ 'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int', 'filter-node-name': '1234'}}
1594
+{ 'execute': 'block-commit',
1595
+ 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int',
1596
+ 'filter-node-name': '1234'}}
1597
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
1598
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
1599
{"error": {"class": "GenericError", "desc": "Invalid node name"}}
1600
1601
=== Send a write command to a drive opened in read-only mode (2)
1602
1603
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1604
+{ 'execute': 'human-monitor-command',
1605
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1606
{"return": "Block node is read-onlyrn"}
1607
1608
=== Run block-commit on base using the default filter node name
1609
1610
-{ 'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int'}}
1611
+{ 'execute': 'block-commit',
1612
+ 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int'}}
1613
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
1614
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
1615
{"return": {}}
1616
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
1617
1618
=== Send a write command to a drive opened in read-only mode (3)
1619
1620
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1621
+{ 'execute': 'human-monitor-command',
1622
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
1623
{"return": "Block node is read-onlyrn"}
1624
*** done
1625
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
1626
index XXXXXXX..XXXXXXX 100644
1627
--- a/tests/qemu-iotests/308.out
1628
+++ b/tests/qemu-iotests/308.out
1629
@@ -XXX,XX +XXX,XX @@ wrote 67108864/67108864 bytes at offset 0
1630
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1631
{'execute': 'qmp_capabilities'}
1632
{"return": {}}
1633
-{'execute': 'blockdev-add', 'arguments': { 'driver': 'file', 'node-name': 'node-protocol', 'filename': 'TEST_DIR/t.IMGFMT' } }
1634
+{'execute': 'blockdev-add',
1635
+ 'arguments': {
1636
+ 'driver': 'file',
1637
+ 'node-name': 'node-protocol',
1638
+ 'filename': 'TEST_DIR/t.IMGFMT'
1639
+ } }
1640
{"return": {}}
1641
-{'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'node-format', 'file': 'node-protocol' } }
1642
+{'execute': 'blockdev-add',
1643
+ 'arguments': {
1644
+ 'driver': 'IMGFMT',
1645
+ 'node-name': 'node-format',
1646
+ 'file': 'node-protocol'
1647
+ } }
1648
{"return": {}}
1649
1650
=== Mountpoint not present ===
1651
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
1652
+{'execute': 'block-export-add',
1653
+ 'arguments': {
1654
+ 'type': 'fuse',
1655
+ 'id': 'export-err',
1656
+ 'node-name': 'node-format',
1657
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
1658
+ } }
1659
{"error": {"class": "GenericError", "desc": "Failed to stat 'TEST_DIR/t.IMGFMT.fuse': No such file or directory"}}
1660
1661
=== Mountpoint is a directory ===
1662
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
1663
+{'execute': 'block-export-add',
1664
+ 'arguments': {
1665
+ 'type': 'fuse',
1666
+ 'id': 'export-err',
1667
+ 'node-name': 'node-format',
1668
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
1669
+ } }
1670
{"error": {"class": "GenericError", "desc": "'TEST_DIR/t.IMGFMT.fuse' is not a regular file"}}
1671
1672
=== Mountpoint is a regular file ===
1673
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
1674
+{'execute': 'block-export-add',
1675
+ 'arguments': {
1676
+ 'type': 'fuse',
1677
+ 'id': 'export-mp',
1678
+ 'node-name': 'node-format',
1679
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
1680
+ } }
1681
{"return": {}}
1682
Images are identical.
1683
1684
=== Mount over existing file ===
1685
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-img', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT' } }
1686
+{'execute': 'block-export-add',
1687
+ 'arguments': {
1688
+ 'type': 'fuse',
1689
+ 'id': 'export-img',
1690
+ 'node-name': 'node-format',
1691
+ 'mountpoint': 'TEST_DIR/t.IMGFMT'
1692
+ } }
1693
{"return": {}}
1694
Images are identical.
1695
1696
=== Double export ===
1697
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
1698
+{'execute': 'block-export-add',
1699
+ 'arguments': {
1700
+ 'type': 'fuse',
1701
+ 'id': 'export-err',
1702
+ 'node-name': 'node-format',
1703
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
1704
+ } }
1705
{"error": {"class": "GenericError", "desc": "There already is a FUSE export on 'TEST_DIR/t.IMGFMT.fuse'"}}
1706
1707
=== Remove export ===
1708
virtual size: 64 MiB (67108864 bytes)
1709
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
1710
+{'execute': 'block-export-del',
1711
+ 'arguments': {
1712
+ 'id': 'export-mp'
1713
+ } }
1714
{"return": {}}
1715
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
1716
virtual size: 0 B (0 bytes)
1717
1718
=== Writable export ===
1719
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true } }
1720
+{'execute': 'block-export-add',
1721
+ 'arguments': {
1722
+ 'type': 'fuse',
1723
+ 'id': 'export-mp',
1724
+ 'node-name': 'node-format',
1725
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
1726
+ } }
1727
{"return": {}}
1728
write failed: Permission denied
1729
wrote 65536/65536 bytes at offset 1048576
1730
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
1731
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1732
1733
=== Resizing exports ===
1734
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
1735
+{'execute': 'block-export-del',
1736
+ 'arguments': {
1737
+ 'id': 'export-mp'
1738
+ } }
1739
{"return": {}}
1740
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
1741
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-img' } }
1742
+{'execute': 'block-export-del',
1743
+ 'arguments': {
1744
+ 'id': 'export-img'
1745
+ } }
1746
{"return": {}}
1747
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-img"}}
1748
-{'execute': 'blockdev-del', 'arguments': { 'node-name': 'node-format' } }
1749
+{'execute': 'blockdev-del',
1750
+ 'arguments': {
1751
+ 'node-name': 'node-format'
1752
+ } }
1753
{"return": {}}
1754
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-protocol', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true } }
1755
+{'execute': 'block-export-add',
1756
+ 'arguments': {
1757
+ 'type': 'fuse',
1758
+ 'id': 'export-mp',
1759
+ 'node-name': 'node-protocol',
1760
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
1761
+ } }
1762
{"return": {}}
1763
1764
--- Try growing non-growable export ---
1765
@@ -XXX,XX +XXX,XX @@ OK: Post-truncate image size is as expected
1766
OK: Disk usage grew with fallocate
1767
1768
--- Try growing growable export ---
1769
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
1770
+{'execute': 'block-export-del',
1771
+ 'arguments': {
1772
+ 'id': 'export-mp'
1773
+ } }
1774
{"return": {}}
1775
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
1776
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-protocol', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true, 'growable': true } }
1777
+{'execute': 'block-export-add',
1778
+ 'arguments': {
1779
+ 'type': 'fuse',
1780
+ 'id': 'export-mp',
1781
+ 'node-name': 'node-protocol',
1782
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true, 'growable': true
1783
+ } }
1784
{"return": {}}
1785
65536+0 records in
1786
65536+0 records out
1787
diff --git a/tests/qemu-iotests/312.out b/tests/qemu-iotests/312.out
1788
index XXXXXXX..XXXXXXX 100644
1789
--- a/tests/qemu-iotests/312.out
1790
+++ b/tests/qemu-iotests/312.out
1791
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 2424832
1792
1793
{ 'execute': 'qmp_capabilities' }
1794
{"return": {}}
1795
-{'execute': 'drive-mirror', 'arguments': {'device': 'virtio0', 'format': 'IMGFMT', 'target': 'TEST_DIR/t.IMGFMT.3', 'sync': 'full', 'mode': 'existing' }}
1796
+{'execute': 'drive-mirror',
1797
+ 'arguments': {'device': 'virtio0',
1798
+ 'format': 'IMGFMT',
1799
+ 'target': 'TEST_DIR/t.IMGFMT.3',
1800
+ 'sync': 'full',
1801
+ 'mode': 'existing' }}
1802
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
1803
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
1804
{"return": {}}
1805
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
1806
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 10485760, "offset": 10485760, "speed": 0, "type": "mirror"}}
1807
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'virtio0' } }
1808
+{ 'execute': 'block-job-complete',
1809
+ 'arguments': { 'device': 'virtio0' } }
1810
{"return": {}}
1811
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
1812
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
1813
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
1814
index XXXXXXX..XXXXXXX 100644
1815
--- a/tests/qemu-iotests/common.qemu
1816
+++ b/tests/qemu-iotests/common.qemu
1817
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd()
1818
count=${qemu_cmd_repeat}
1819
use_error="no"
1820
fi
1821
- # This array element extraction is done to accommodate pathnames with spaces
1822
- if [ -z "${success_or_failure}" ]; then
1823
- cmd=${@: 1:${#@}-1}
1824
- shift $(($# - 1))
1825
- else
1826
- cmd=${@: 1:${#@}-2}
1827
- shift $(($# - 2))
1828
- fi
1829
+
1830
+ cmd=$1
1831
+ shift
1832
1833
# Display QMP being sent, but not HMP (since HMP already echoes its
1834
# input back to output); decide based on leading '{'
1835
--
1836
2.29.2
1837
1838
diff view generated by jsdifflib