* [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze
@ 2019-06-27 22:32 Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
` (4 more replies)
0 siblings, 5 replies; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
As it is, this series depends on my block branch, most importantly
Andrey’s series “block/stream: get rid of the base”.
Depends-on: <1559152576-281803-1-git-send-email-andrey.shinkevich@virtuozzo.com>
This series made the problem apparent to me, but it existed before:
Namely, the commit and mirror block jobs create filter nodes which they
just try to drop with an &error_fatal. If any of its parent links is
frozen, that will abort qemu. Patch 1 fixes this by adding a
BDS.never_freeze flag, which prevents bdrv_freeze_backing_chain() from
freezing any links to a BDS that has this flag set.
Now, after Andrey’s series, you can reproduce this problem by first
launching a commit job and then launching a stream job from the commit’s
top node. This is actually something that iotest 030 tests, but I
didn’t notice the problem because 030 has two problems of itself:
(1) It fails to do proper throttling, so usually, the commit job is
already gone by the time the stream job starts. (Fixed by patch 2.)
(2) It doesn’t check the error message, but just the error class. If it
had checked the error message, we would have seen that it just says
that the stream’s base node cannot be found, and thus would have
fixed problem #1 earlier. (Fixed by patch 3.)
If you apply patches 2 and 3 to my block branch, you’ll see that both
jobs can be created. If you remove the check that creating the stream
job should fail and replace the self.wait_until_completed() by a
self.vm.run_job('drive0'), you will see that qemu aborts.
So that appears to be a new problem introduced by Andrey’s series,
right? But it actually isn’t new. Patch 5 adds a test for a
pre-existing case:
If on master you launch a commit job and then a stream job from the
commit’s filter node, qemu will abort (if the commit job completes
before the stream job, at least). So the problem existed well before
Andrey’s series, it just moved it down one node.
(You can test that by applying patches 2 through 5 on master. You will
get a failure in test_overlapping_4, and a qemu abort in
test_overlapping_5.)
In turn, thanks to said series, this test case now fully works. (So you
can stream from a commit’s filter node.)
So either way, the problem addressed by patch 1 is visible both on
master and on my block branch. It just appears in different places,
hence the dependency.
Max Reitz (5):
block: Add BDS.never_freeze
iotests: Fix throttling in 030
iotests: Compare error messages in 030
iotests: Add @use_log to VM.run_job()
iotests: Add new case to 030
include/block/block_int.h | 3 +
block.c | 8 +++
block/commit.c | 4 ++
block/mirror.c | 4 ++
tests/qemu-iotests/030 | 121 ++++++++++++++++++++++++++--------
tests/qemu-iotests/030.out | 4 +-
tests/qemu-iotests/iotests.py | 18 +++--
7 files changed, 127 insertions(+), 35 deletions(-)
--
2.21.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
@ 2019-06-27 22:32 ` Max Reitz
2019-07-01 16:46 ` Andrey Shinkevich
` (2 more replies)
2019-06-27 22:32 ` [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030 Max Reitz
` (3 subsequent siblings)
4 siblings, 3 replies; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
The commit and the mirror block job must be able to drop their filter
node at any point. However, this will not be possible if any of the
BdrvChild links to them is frozen. Therefore, we need to prevent them
from ever becoming frozen.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
include/block/block_int.h | 3 +++
block.c | 8 ++++++++
block/commit.c | 4 ++++
block/mirror.c | 4 ++++
4 files changed, 19 insertions(+)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d6415b53c1..50902531b7 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -885,6 +885,9 @@ struct BlockDriverState {
/* Only read/written by whoever has set active_flush_req to true. */
unsigned int flushed_gen; /* Flushed write generation */
+
+ /* BdrvChild links to this node may never be frozen */
+ bool never_freeze;
};
struct BlockBackendRootState {
diff --git a/block.c b/block.c
index c139540f2b..6565192b91 100644
--- a/block.c
+++ b/block.c
@@ -4416,6 +4416,14 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
return -EPERM;
}
+ for (i = bs; i != base; i = backing_bs(i)) {
+ if (i->backing && backing_bs(i)->never_freeze) {
+ error_setg(errp, "Cannot freeze '%s' link to '%s'",
+ i->backing->name, backing_bs(i)->node_name);
+ return -EPERM;
+ }
+ }
+
for (i = bs; i != base; i = backing_bs(i)) {
if (i->backing) {
i->backing->frozen = true;
diff --git a/block/commit.c b/block/commit.c
index ca7e408b26..2c5a6d4ebc 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -298,6 +298,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
if (!filter_node_name) {
commit_top_bs->implicit = true;
}
+
+ /* So that we can always drop this node */
+ commit_top_bs->never_freeze = true;
+
commit_top_bs->total_sectors = top->total_sectors;
bdrv_append(commit_top_bs, top, &local_err);
diff --git a/block/mirror.c b/block/mirror.c
index 2fcec70e35..8cb75fb409 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1551,6 +1551,10 @@ static BlockJob *mirror_start_job(
if (!filter_node_name) {
mirror_top_bs->implicit = true;
}
+
+ /* So that we can always drop this node */
+ mirror_top_bs->never_freeze = true;
+
mirror_top_bs->total_sectors = bs->total_sectors;
mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
--
2.21.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
@ 2019-06-27 22:32 ` Max Reitz
2019-07-01 16:41 ` Andrey Shinkevich
2019-07-02 15:09 ` Alberto Garcia
2019-06-27 22:32 ` [Qemu-devel] [PATCH 3/5] iotests: Compare error messages " Max Reitz
` (2 subsequent siblings)
4 siblings, 2 replies; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
Currently, TestParallelOps in 030 creates images that are too small for
job throttling to be effective. This is reflected by the fact that it
never undoes the throttling.
Increase the image size and undo the throttling when the job should be
completed. Also, add throttling in test_overlapping_4, or the jobs may
not be so overlapping after all. In fact, the error usually emitted
here is that node2 simply does not exist, not that overlapping jobs are
not allowed -- the fact that this job ignores the exact error messages
and just checks the error class is something that should be fixed in a
follow-up patch.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/030 | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index c6311d1825..2cf8d54dc5 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -154,7 +154,7 @@ class TestSingleDrive(iotests.QMPTestCase):
class TestParallelOps(iotests.QMPTestCase):
num_ops = 4 # Number of parallel block-stream operations
num_imgs = num_ops * 2 + 1
- image_len = num_ops * 512 * 1024
+ image_len = num_ops * 4 * 1024 * 1024
imgs = []
def setUp(self):
@@ -176,11 +176,11 @@ class TestParallelOps(iotests.QMPTestCase):
# Put data into the images we are copying data from
odd_img_indexes = [x for x in reversed(range(self.num_imgs)) if x % 2 == 1]
for i in range(len(odd_img_indexes)):
- # Alternate between 256KB and 512KB.
+ # Alternate between 2MB and 4MB.
# This way jobs will not finish in the same order they were created
- num_kb = 256 + 256 * (i % 2)
+ num_mb = 2 + 2 * (i % 2)
qemu_io('-f', iotests.imgfmt,
- '-c', 'write -P 0xFF %dk %dk' % (i * 512, num_kb),
+ '-c', 'write -P 0xFF %dM %dM' % (i * 4, num_mb),
self.imgs[odd_img_indexes[i]])
# Attach the drive to the VM
@@ -213,6 +213,10 @@ class TestParallelOps(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=512*1024)
self.assert_qmp(result, 'return', {})
+ for job in pending_jobs:
+ result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
+ self.assert_qmp(result, 'return', {})
+
# Wait for all jobs to be finished.
while len(pending_jobs) > 0:
for event in self.vm.get_qmp_events(wait=True):
@@ -260,6 +264,9 @@ class TestParallelOps(iotests.QMPTestCase):
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[0], top=self.imgs[1], job_id='commit-node0')
self.assert_qmp(result, 'error/class', 'GenericError')
+ result = self.vm.qmp('block-job-set-speed', device='stream-node4', speed=0)
+ self.assert_qmp(result, 'return', {})
+
self.wait_until_completed(drive='stream-node4')
self.assert_no_active_block_jobs()
@@ -289,6 +296,9 @@ class TestParallelOps(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device='drive0', base=self.imgs[5], job_id='stream-drive0')
self.assert_qmp(result, 'error/class', 'GenericError')
+ result = self.vm.qmp('block-job-set-speed', device='commit-node3', speed=0)
+ self.assert_qmp(result, 'return', {})
+
self.wait_until_completed(drive='commit-node3')
# Similar to test_overlapping_2, but here block-commit doesn't use the 'top' parameter.
@@ -309,6 +319,9 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_qmp(event, 'data/type', 'commit')
self.assert_qmp_absent(event, 'data/error')
+ result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
+ self.assert_qmp(result, 'return', {})
+
result = self.vm.qmp('block-job-complete', device='commit-drive0')
self.assert_qmp(result, 'return', {})
@@ -321,13 +334,18 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
# Commit from node2 into node0
- result = self.vm.qmp('block-commit', device='drive0', top=self.imgs[2], base=self.imgs[0])
+ result = self.vm.qmp('block-commit', device='drive0',
+ top=self.imgs[2], base=self.imgs[0],
+ speed=1024*1024)
self.assert_qmp(result, 'return', {})
# Stream from node2 into node4
result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='node4')
self.assert_qmp(result, 'error/class', 'GenericError')
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
+ self.assert_qmp(result, 'return', {})
+
self.wait_until_completed()
self.assert_no_active_block_jobs()
@@ -378,6 +396,10 @@ class TestParallelOps(iotests.QMPTestCase):
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[5], speed=1024*1024)
self.assert_qmp(result, 'return', {})
+ for job in ['drive0', 'node4']:
+ result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
+ self.assert_qmp(result, 'return', {})
+
# Wait for all jobs to be finished.
pending_jobs = ['node4', 'drive0']
while len(pending_jobs) > 0:
--
2.21.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 3/5] iotests: Compare error messages in 030
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030 Max Reitz
@ 2019-06-27 22:32 ` Max Reitz
2019-07-01 16:42 ` Andrey Shinkevich
2019-07-02 12:37 ` Alberto Garcia
2019-06-27 22:32 ` [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job() Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030 Max Reitz
4 siblings, 2 replies; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
Currently, 030 just compares the error class, which does not say
anything.
Before HEAD^ added throttling to test_overlapping_4, that test actually
usually failed because node2 was already gone, not because it was the
commit and stream job were not allowed to overlap.
Prevent such problems in the future by comparing the error description
instead.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/030 | 66 +++++++++++++++++++++++++++---------------
1 file changed, 42 insertions(+), 24 deletions(-)
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 2cf8d54dc5..10fe1de89d 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -144,11 +144,12 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_device_not_found(self):
result = self.vm.qmp('block-stream', device='nonexistent')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ 'Cannot find device=nonexistent nor node_name=nonexistent')
def test_job_id_missing(self):
result = self.vm.qmp('block-stream', device='mid')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc', "Invalid job ID ''")
class TestParallelOps(iotests.QMPTestCase):
@@ -245,24 +246,30 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-stream', device='node5', job_id='stream-node5', base=self.imgs[2])
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node4' is busy: block device is in use by block job: stream")
result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3', base=self.imgs[2])
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node3' is busy: block device is in use by block job: stream")
result = self.vm.qmp('block-stream', device='node4', job_id='stream-node4-v2')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node4' is busy: block device is in use by block job: stream")
# block-commit should also fail if it touches nodes used by the stream job
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[4], job_id='commit-node4')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node4' is busy: block device is in use by block job: stream")
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[1], top=self.imgs[3], job_id='commit-node1')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node3' is busy: block device is in use by block job: stream")
# This fails because it needs to modify the backing string in node2, which is blocked
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[0], top=self.imgs[1], job_id='commit-node0')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node2' is busy: block device is in use by block job: stream")
result = self.vm.qmp('block-job-set-speed', device='stream-node4', speed=0)
self.assert_qmp(result, 'return', {})
@@ -281,20 +288,25 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node3' is busy: block device is in use by block job: commit")
result = self.vm.qmp('block-stream', device='node6', base=self.imgs[2], job_id='stream-node6')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node5' is busy: block device is in use by block job: commit")
result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], job_id='stream-node4')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node4' is busy: block device is in use by block job: commit")
result = self.vm.qmp('block-stream', device='node6', base=self.imgs[4], job_id='stream-node6-v2')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node5' is busy: block device is in use by block job: commit")
# This fails because block-commit currently blocks the active layer even if it's not used
result = self.vm.qmp('block-stream', device='drive0', base=self.imgs[5], job_id='stream-drive0')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'drive0' is busy: block device is in use by block job: commit")
result = self.vm.qmp('block-job-set-speed', device='commit-node3', speed=0)
self.assert_qmp(result, 'return', {})
@@ -312,7 +324,8 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-stream', device='node5', base=self.imgs[3], job_id='stream-node6')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node5' is busy: block device is in use by block job: commit")
event = self.vm.event_wait(name='BLOCK_JOB_READY')
self.assert_qmp(event, 'data/device', 'commit-drive0')
@@ -328,20 +341,21 @@ class TestParallelOps(iotests.QMPTestCase):
self.wait_until_completed(drive='commit-drive0')
# In this case the base node of the stream job is the same as the
- # top node of commit job. Since block-commit removes the top node
- # when it finishes, this is not allowed.
+ # top node of commit job. Since this results in the commit filter
+ # node being part of the stream chain, this is not allowed.
def test_overlapping_4(self):
self.assert_no_active_block_jobs()
# Commit from node2 into node0
result = self.vm.qmp('block-commit', device='drive0',
top=self.imgs[2], base=self.imgs[0],
- speed=1024*1024)
+ filter_node_name='commit-filter', speed=1024*1024)
self.assert_qmp(result, 'return', {})
# Stream from node2 into node4
result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='node4')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Cannot freeze 'backing' link to 'commit-filter'")
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
self.assert_qmp(result, 'return', {})
@@ -428,19 +442,23 @@ class TestParallelOps(iotests.QMPTestCase):
# Error: the base node does not exist
result = self.vm.qmp('block-stream', device='node4', base_node='none', job_id='stream')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ 'Cannot find device= nor node_name=none')
# Error: the base node is not a backing file of the top node
result = self.vm.qmp('block-stream', device='node4', base_node='node6', job_id='stream')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node6' is not a backing image of 'node4'")
# Error: the base node is the same as the top node
result = self.vm.qmp('block-stream', device='node4', base_node='node4', job_id='stream')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "Node 'node4' is not a backing image of 'node4'")
# Error: cannot specify 'base' and 'base-node' at the same time
result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], base_node='node2', job_id='stream')
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc',
+ "'base' and 'base-node' cannot be specified at the same time")
# Success: the base node is a backing file of the top node
result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='stream')
@@ -873,7 +891,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('block-stream', device='drive0', speed=-1)
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
self.assert_no_active_block_jobs()
@@ -882,7 +900,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
- self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
self.cancel_and_wait(resume=True)
--
2.21.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job()
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
` (2 preceding siblings ...)
2019-06-27 22:32 ` [Qemu-devel] [PATCH 3/5] iotests: Compare error messages " Max Reitz
@ 2019-06-27 22:32 ` Max Reitz
2019-07-01 22:59 ` John Snow
2019-06-27 22:32 ` [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030 Max Reitz
4 siblings, 1 reply; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
unittest-style tests generally do not use the log file, but VM.run_job()
can still be useful to them. Add a parameter to it that hides its
output from the log file.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/iotests.py | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 3ecef5bc90..ce74177ab1 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -542,7 +542,7 @@ class VM(qtest.QEMUQtestMachine):
# Returns None on success, and an error string on failure
def run_job(self, job, auto_finalize=True, auto_dismiss=False,
- pre_finalize=None, wait=60.0):
+ pre_finalize=None, use_log=True, wait=60.0):
match_device = {'data': {'device': job}}
match_id = {'data': {'id': job}}
events = [
@@ -557,7 +557,8 @@ class VM(qtest.QEMUQtestMachine):
while True:
ev = filter_qmp_event(self.events_wait(events))
if ev['event'] != 'JOB_STATUS_CHANGE':
- log(ev)
+ if use_log:
+ log(ev)
continue
status = ev['data']['status']
if status == 'aborting':
@@ -565,13 +566,20 @@ class VM(qtest.QEMUQtestMachine):
for j in result['return']:
if j['id'] == job:
error = j['error']
- log('Job failed: %s' % (j['error']))
+ if use_log:
+ log('Job failed: %s' % (j['error']))
elif status == 'pending' and not auto_finalize:
if pre_finalize:
pre_finalize()
- self.qmp_log('job-finalize', id=job)
+ if use_log:
+ self.qmp_log('job-finalize', id=job)
+ else:
+ self.qmp('job-finalize', id=job)
elif status == 'concluded' and not auto_dismiss:
- self.qmp_log('job-dismiss', id=job)
+ if use_log:
+ self.qmp_log('job-dismiss', id=job)
+ else:
+ self.qmp('job-dismiss', id=job)
elif status == 'null':
return error
--
2.21.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
` (3 preceding siblings ...)
2019-06-27 22:32 ` [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job() Max Reitz
@ 2019-06-27 22:32 ` Max Reitz
2019-07-01 16:44 ` Andrey Shinkevich
2019-07-02 14:59 ` Alberto Garcia
4 siblings, 2 replies; 20+ messages in thread
From: Max Reitz @ 2019-06-27 22:32 UTC (permalink / raw)
To: qemu-block
Cc: Kevin Wolf, Alberto Garcia, qemu-devel, Max Reitz,
Andrey Shinkevich, John Snow
We recently removed the dependency of the stream job on its base node.
That makes it OK to use a commit filter node there. Test that.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/030 | 25 +++++++++++++++++++++++++
tests/qemu-iotests/030.out | 4 ++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 10fe1de89d..a0397072bc 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -363,6 +363,31 @@ class TestParallelOps(iotests.QMPTestCase):
self.wait_until_completed()
self.assert_no_active_block_jobs()
+ # In this case the base node of the stream job is the commit job's
+ # filter node. stream does not have a real dependency on its base
+ # node, so even though commit removes it when it is done, there is
+ # no conflict.
+ def test_overlapping_5(self):
+ self.assert_no_active_block_jobs()
+
+ # Commit from node2 into node0
+ result = self.vm.qmp('block-commit', device='drive0',
+ top_node='node2', base_node='node0',
+ filter_node_name='commit-filter', speed=1024*1024)
+ self.assert_qmp(result, 'return', {})
+
+ # Stream from node2 into node4
+ result = self.vm.qmp('block-stream', device='node4',
+ base_node='commit-filter', job_id='node4')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False)
+ self.vm.run_job(job='node4', auto_dismiss=True, use_log=False)
+ self.assert_no_active_block_jobs()
+
# Test a block-stream and a block-commit job in parallel
# Here the stream job is supposed to finish quickly in order to reproduce
# the scenario that triggers the bug fixed in 3d5d319e1221 and 1a63a907507
diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
index 4fd1c2dcd2..5eb508de07 100644
--- a/tests/qemu-iotests/030.out
+++ b/tests/qemu-iotests/030.out
@@ -1,5 +1,5 @@
-.........................
+..........................
----------------------------------------------------------------------
-Ran 25 tests
+Ran 26 tests
OK
--
2.21.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030 Max Reitz
@ 2019-07-01 16:41 ` Andrey Shinkevich
2019-07-02 15:09 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Andrey Shinkevich @ 2019-07-01 16:41 UTC (permalink / raw)
To: Max Reitz, qemu-block@nongnu.org
Cc: Kevin Wolf, John Snow, Alberto Garcia, qemu-devel@nongnu.org
On 28/06/2019 01:32, Max Reitz wrote:
> Currently, TestParallelOps in 030 creates images that are too small for
> job throttling to be effective. This is reflected by the fact that it
> never undoes the throttling.
>
> Increase the image size and undo the throttling when the job should be
> completed. Also, add throttling in test_overlapping_4, or the jobs may
> not be so overlapping after all. In fact, the error usually emitted
> here is that node2 simply does not exist, not that overlapping jobs are
> not allowed -- the fact that this job ignores the exact error messages
> and just checks the error class is something that should be fixed in a
> follow-up patch.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> tests/qemu-iotests/030 | 32 +++++++++++++++++++++++++++-----
> 1 file changed, 27 insertions(+), 5 deletions(-)
>
> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
> index c6311d1825..2cf8d54dc5 100755
> --- a/tests/qemu-iotests/030
> +++ b/tests/qemu-iotests/030
> @@ -154,7 +154,7 @@ class TestSingleDrive(iotests.QMPTestCase):
> class TestParallelOps(iotests.QMPTestCase):
> num_ops = 4 # Number of parallel block-stream operations
> num_imgs = num_ops * 2 + 1
> - image_len = num_ops * 512 * 1024
> + image_len = num_ops * 4 * 1024 * 1024
> imgs = []
>
> def setUp(self):
> @@ -176,11 +176,11 @@ class TestParallelOps(iotests.QMPTestCase):
> # Put data into the images we are copying data from
> odd_img_indexes = [x for x in reversed(range(self.num_imgs)) if x % 2 == 1]
> for i in range(len(odd_img_indexes)):
> - # Alternate between 256KB and 512KB.
> + # Alternate between 2MB and 4MB.
> # This way jobs will not finish in the same order they were created
> - num_kb = 256 + 256 * (i % 2)
> + num_mb = 2 + 2 * (i % 2)
> qemu_io('-f', iotests.imgfmt,
> - '-c', 'write -P 0xFF %dk %dk' % (i * 512, num_kb),
> + '-c', 'write -P 0xFF %dM %dM' % (i * 4, num_mb),
> self.imgs[odd_img_indexes[i]])
>
> # Attach the drive to the VM
> @@ -213,6 +213,10 @@ class TestParallelOps(iotests.QMPTestCase):
> result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=512*1024)
> self.assert_qmp(result, 'return', {})
>
> + for job in pending_jobs:
> + result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> # Wait for all jobs to be finished.
> while len(pending_jobs) > 0:
> for event in self.vm.get_qmp_events(wait=True):
> @@ -260,6 +264,9 @@ class TestParallelOps(iotests.QMPTestCase):
> result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[0], top=self.imgs[1], job_id='commit-node0')
> self.assert_qmp(result, 'error/class', 'GenericError')
>
> + result = self.vm.qmp('block-job-set-speed', device='stream-node4', speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> self.wait_until_completed(drive='stream-node4')
> self.assert_no_active_block_jobs()
>
> @@ -289,6 +296,9 @@ class TestParallelOps(iotests.QMPTestCase):
> result = self.vm.qmp('block-stream', device='drive0', base=self.imgs[5], job_id='stream-drive0')
> self.assert_qmp(result, 'error/class', 'GenericError')
>
> + result = self.vm.qmp('block-job-set-speed', device='commit-node3', speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> self.wait_until_completed(drive='commit-node3')
>
> # Similar to test_overlapping_2, but here block-commit doesn't use the 'top' parameter.
> @@ -309,6 +319,9 @@ class TestParallelOps(iotests.QMPTestCase):
> self.assert_qmp(event, 'data/type', 'commit')
> self.assert_qmp_absent(event, 'data/error')
>
> + result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> result = self.vm.qmp('block-job-complete', device='commit-drive0')
> self.assert_qmp(result, 'return', {})
>
> @@ -321,13 +334,18 @@ class TestParallelOps(iotests.QMPTestCase):
> self.assert_no_active_block_jobs()
>
> # Commit from node2 into node0
> - result = self.vm.qmp('block-commit', device='drive0', top=self.imgs[2], base=self.imgs[0])
> + result = self.vm.qmp('block-commit', device='drive0',
> + top=self.imgs[2], base=self.imgs[0],
> + speed=1024*1024)
> self.assert_qmp(result, 'return', {})
>
> # Stream from node2 into node4
> result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='node4')
> self.assert_qmp(result, 'error/class', 'GenericError')
>
> + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> self.wait_until_completed()
> self.assert_no_active_block_jobs()
>
> @@ -378,6 +396,10 @@ class TestParallelOps(iotests.QMPTestCase):
> result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[5], speed=1024*1024)
> self.assert_qmp(result, 'return', {})
>
> + for job in ['drive0', 'node4']:
> + result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> # Wait for all jobs to be finished.
> pending_jobs = ['node4', 'drive0']
> while len(pending_jobs) > 0:
>
Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
--
With the best regards,
Andrey Shinkevich
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] iotests: Compare error messages in 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 3/5] iotests: Compare error messages " Max Reitz
@ 2019-07-01 16:42 ` Andrey Shinkevich
2019-07-02 12:37 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Andrey Shinkevich @ 2019-07-01 16:42 UTC (permalink / raw)
To: Max Reitz, qemu-block@nongnu.org
Cc: Kevin Wolf, John Snow, Alberto Garcia, qemu-devel@nongnu.org
On 28/06/2019 01:32, Max Reitz wrote:
> Currently, 030 just compares the error class, which does not say
> anything.
>
> Before HEAD^ added throttling to test_overlapping_4, that test actually
> usually failed because node2 was already gone, not because it was the
> commit and stream job were not allowed to overlap.
>
> Prevent such problems in the future by comparing the error description
> instead.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> tests/qemu-iotests/030 | 66 +++++++++++++++++++++++++++---------------
> 1 file changed, 42 insertions(+), 24 deletions(-)
>
> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
> index 2cf8d54dc5..10fe1de89d 100755
> --- a/tests/qemu-iotests/030
> +++ b/tests/qemu-iotests/030
> @@ -144,11 +144,12 @@ class TestSingleDrive(iotests.QMPTestCase):
>
> def test_device_not_found(self):
> result = self.vm.qmp('block-stream', device='nonexistent')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + 'Cannot find device=nonexistent nor node_name=nonexistent')
>
> def test_job_id_missing(self):
> result = self.vm.qmp('block-stream', device='mid')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc', "Invalid job ID ''")
>
>
> class TestParallelOps(iotests.QMPTestCase):
> @@ -245,24 +246,30 @@ class TestParallelOps(iotests.QMPTestCase):
> self.assert_qmp(result, 'return', {})
>
> result = self.vm.qmp('block-stream', device='node5', job_id='stream-node5', base=self.imgs[2])
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node4' is busy: block device is in use by block job: stream")
>
> result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3', base=self.imgs[2])
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node3' is busy: block device is in use by block job: stream")
>
> result = self.vm.qmp('block-stream', device='node4', job_id='stream-node4-v2')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node4' is busy: block device is in use by block job: stream")
>
> # block-commit should also fail if it touches nodes used by the stream job
> result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[4], job_id='commit-node4')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node4' is busy: block device is in use by block job: stream")
>
> result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[1], top=self.imgs[3], job_id='commit-node1')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node3' is busy: block device is in use by block job: stream")
>
> # This fails because it needs to modify the backing string in node2, which is blocked
> result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[0], top=self.imgs[1], job_id='commit-node0')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node2' is busy: block device is in use by block job: stream")
>
> result = self.vm.qmp('block-job-set-speed', device='stream-node4', speed=0)
> self.assert_qmp(result, 'return', {})
> @@ -281,20 +288,25 @@ class TestParallelOps(iotests.QMPTestCase):
> self.assert_qmp(result, 'return', {})
>
> result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node3' is busy: block device is in use by block job: commit")
>
> result = self.vm.qmp('block-stream', device='node6', base=self.imgs[2], job_id='stream-node6')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node5' is busy: block device is in use by block job: commit")
>
> result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], job_id='stream-node4')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node4' is busy: block device is in use by block job: commit")
>
> result = self.vm.qmp('block-stream', device='node6', base=self.imgs[4], job_id='stream-node6-v2')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node5' is busy: block device is in use by block job: commit")
>
> # This fails because block-commit currently blocks the active layer even if it's not used
> result = self.vm.qmp('block-stream', device='drive0', base=self.imgs[5], job_id='stream-drive0')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'drive0' is busy: block device is in use by block job: commit")
>
> result = self.vm.qmp('block-job-set-speed', device='commit-node3', speed=0)
> self.assert_qmp(result, 'return', {})
> @@ -312,7 +324,8 @@ class TestParallelOps(iotests.QMPTestCase):
> self.assert_qmp(result, 'return', {})
>
> result = self.vm.qmp('block-stream', device='node5', base=self.imgs[3], job_id='stream-node6')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node5' is busy: block device is in use by block job: commit")
>
> event = self.vm.event_wait(name='BLOCK_JOB_READY')
> self.assert_qmp(event, 'data/device', 'commit-drive0')
> @@ -328,20 +341,21 @@ class TestParallelOps(iotests.QMPTestCase):
> self.wait_until_completed(drive='commit-drive0')
>
> # In this case the base node of the stream job is the same as the
> - # top node of commit job. Since block-commit removes the top node
> - # when it finishes, this is not allowed.
> + # top node of commit job. Since this results in the commit filter
> + # node being part of the stream chain, this is not allowed.
> def test_overlapping_4(self):
> self.assert_no_active_block_jobs()
>
> # Commit from node2 into node0
> result = self.vm.qmp('block-commit', device='drive0',
> top=self.imgs[2], base=self.imgs[0],
> - speed=1024*1024)
> + filter_node_name='commit-filter', speed=1024*1024)
> self.assert_qmp(result, 'return', {})
>
> # Stream from node2 into node4
> result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='node4')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Cannot freeze 'backing' link to 'commit-filter'")
>
> result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
> self.assert_qmp(result, 'return', {})
> @@ -428,19 +442,23 @@ class TestParallelOps(iotests.QMPTestCase):
>
> # Error: the base node does not exist
> result = self.vm.qmp('block-stream', device='node4', base_node='none', job_id='stream')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + 'Cannot find device= nor node_name=none')
>
> # Error: the base node is not a backing file of the top node
> result = self.vm.qmp('block-stream', device='node4', base_node='node6', job_id='stream')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node6' is not a backing image of 'node4'")
>
> # Error: the base node is the same as the top node
> result = self.vm.qmp('block-stream', device='node4', base_node='node4', job_id='stream')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "Node 'node4' is not a backing image of 'node4'")
>
> # Error: cannot specify 'base' and 'base-node' at the same time
> result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], base_node='node2', job_id='stream')
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc',
> + "'base' and 'base-node' cannot be specified at the same time")
>
> # Success: the base node is a backing file of the top node
> result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='stream')
> @@ -873,7 +891,7 @@ class TestSetSpeed(iotests.QMPTestCase):
> self.assert_no_active_block_jobs()
>
> result = self.vm.qmp('block-stream', device='drive0', speed=-1)
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
>
> self.assert_no_active_block_jobs()
>
> @@ -882,7 +900,7 @@ class TestSetSpeed(iotests.QMPTestCase):
> self.assert_qmp(result, 'return', {})
>
> result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
> - self.assert_qmp(result, 'error/class', 'GenericError')
> + self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
>
> self.cancel_and_wait(resume=True)
>
>
Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
--
With the best regards,
Andrey Shinkevich
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030 Max Reitz
@ 2019-07-01 16:44 ` Andrey Shinkevich
2019-07-02 14:59 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Andrey Shinkevich @ 2019-07-01 16:44 UTC (permalink / raw)
To: Max Reitz, qemu-block@nongnu.org
Cc: Kevin Wolf, John Snow, Alberto Garcia, qemu-devel@nongnu.org
On 28/06/2019 01:32, Max Reitz wrote:
> We recently removed the dependency of the stream job on its base node.
> That makes it OK to use a commit filter node there. Test that.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> tests/qemu-iotests/030 | 25 +++++++++++++++++++++++++
> tests/qemu-iotests/030.out | 4 ++--
> 2 files changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
> index 10fe1de89d..a0397072bc 100755
> --- a/tests/qemu-iotests/030
> +++ b/tests/qemu-iotests/030
> @@ -363,6 +363,31 @@ class TestParallelOps(iotests.QMPTestCase):
> self.wait_until_completed()
> self.assert_no_active_block_jobs()
>
> + # In this case the base node of the stream job is the commit job's
> + # filter node. stream does not have a real dependency on its base
> + # node, so even though commit removes it when it is done, there is
> + # no conflict.
> + def test_overlapping_5(self):
> + self.assert_no_active_block_jobs()
> +
> + # Commit from node2 into node0
> + result = self.vm.qmp('block-commit', device='drive0',
> + top_node='node2', base_node='node0',
> + filter_node_name='commit-filter', speed=1024*1024)
> + self.assert_qmp(result, 'return', {})
> +
> + # Stream from node2 into node4
> + result = self.vm.qmp('block-stream', device='node4',
> + base_node='commit-filter', job_id='node4')
> + self.assert_qmp(result, 'return', {})
> +
> + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
> + self.assert_qmp(result, 'return', {})
> +
> + self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False)
> + self.vm.run_job(job='node4', auto_dismiss=True, use_log=False)
> + self.assert_no_active_block_jobs()
> +
> # Test a block-stream and a block-commit job in parallel
> # Here the stream job is supposed to finish quickly in order to reproduce
> # the scenario that triggers the bug fixed in 3d5d319e1221 and 1a63a907507
> diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
> index 4fd1c2dcd2..5eb508de07 100644
> --- a/tests/qemu-iotests/030.out
> +++ b/tests/qemu-iotests/030.out
> @@ -1,5 +1,5 @@
> -.........................
> +..........................
> ----------------------------------------------------------------------
> -Ran 25 tests
> +Ran 26 tests
>
> OK
>
Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
--
With the best regards,
Andrey Shinkevich
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
@ 2019-07-01 16:46 ` Andrey Shinkevich
2019-07-02 14:02 ` Alberto Garcia
2019-07-02 15:36 ` Alberto Garcia
2 siblings, 0 replies; 20+ messages in thread
From: Andrey Shinkevich @ 2019-07-01 16:46 UTC (permalink / raw)
To: Max Reitz, qemu-block@nongnu.org
Cc: Kevin Wolf, John Snow, Alberto Garcia, qemu-devel@nongnu.org
On 28/06/2019 01:32, Max Reitz wrote:
> The commit and the mirror block job must be able to drop their filter
> node at any point. However, this will not be possible if any of the
> BdrvChild links to them is frozen. Therefore, we need to prevent them
> from ever becoming frozen.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> ---
> include/block/block_int.h | 3 +++
> block.c | 8 ++++++++
> block/commit.c | 4 ++++
> block/mirror.c | 4 ++++
> 4 files changed, 19 insertions(+)
>
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index d6415b53c1..50902531b7 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -885,6 +885,9 @@ struct BlockDriverState {
>
> /* Only read/written by whoever has set active_flush_req to true. */
> unsigned int flushed_gen; /* Flushed write generation */
> +
> + /* BdrvChild links to this node may never be frozen */
> + bool never_freeze;
> };
>
> struct BlockBackendRootState {
> diff --git a/block.c b/block.c
> index c139540f2b..6565192b91 100644
> --- a/block.c
> +++ b/block.c
> @@ -4416,6 +4416,14 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
> return -EPERM;
> }
>
> + for (i = bs; i != base; i = backing_bs(i)) {
> + if (i->backing && backing_bs(i)->never_freeze) {
> + error_setg(errp, "Cannot freeze '%s' link to '%s'",
> + i->backing->name, backing_bs(i)->node_name);
> + return -EPERM;
> + }
> + }
> +
> for (i = bs; i != base; i = backing_bs(i)) {
> if (i->backing) {
> i->backing->frozen = true;
> diff --git a/block/commit.c b/block/commit.c
> index ca7e408b26..2c5a6d4ebc 100644
> --- a/block/commit.c
> +++ b/block/commit.c
> @@ -298,6 +298,10 @@ void commit_start(const char *job_id, BlockDriverState *bs,
> if (!filter_node_name) {
> commit_top_bs->implicit = true;
> }
> +
> + /* So that we can always drop this node */
> + commit_top_bs->never_freeze = true;
> +
> commit_top_bs->total_sectors = top->total_sectors;
>
> bdrv_append(commit_top_bs, top, &local_err);
> diff --git a/block/mirror.c b/block/mirror.c
> index 2fcec70e35..8cb75fb409 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -1551,6 +1551,10 @@ static BlockJob *mirror_start_job(
> if (!filter_node_name) {
> mirror_top_bs->implicit = true;
> }
> +
> + /* So that we can always drop this node */
> + mirror_top_bs->never_freeze = true;
> +
> mirror_top_bs->total_sectors = bs->total_sectors;
> mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
> mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
>
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
--
With the best regards,
Andrey Shinkevich
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job()
2019-06-27 22:32 ` [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job() Max Reitz
@ 2019-07-01 22:59 ` John Snow
2019-07-02 16:19 ` Max Reitz
0 siblings, 1 reply; 20+ messages in thread
From: John Snow @ 2019-07-01 22:59 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, Alberto Garcia, qemu-devel,
Cleber Rosa
On 6/27/19 6:32 PM, Max Reitz wrote:
> unittest-style tests generally do not use the log file, but VM.run_job()
> can still be useful to them. Add a parameter to it that hides its
> output from the log file.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
Wondering out loud:
can log() (and by extension qmp_log, and run_job) be made to use the
python logging module and we can configure the logging environment
instead of bespoke arguments to avoid ever engaging the log?
We could theoretically just pre-disable iotests log output for unittest
style tests, unless you run in debug mode where we allow it.
I don't have a specific proposal for how to accomplish this, I think
there are some nuances to Python logging that I don't quite understand.
Maybe Cleber Rosa can help advise?
I'd like to toy with this idea; it seems like this won't be the last
time we want to turn output on/off.
--js
> ---
> tests/qemu-iotests/iotests.py | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 3ecef5bc90..ce74177ab1 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -542,7 +542,7 @@ class VM(qtest.QEMUQtestMachine):
>
> # Returns None on success, and an error string on failure
> def run_job(self, job, auto_finalize=True, auto_dismiss=False,
> - pre_finalize=None, wait=60.0):
> + pre_finalize=None, use_log=True, wait=60.0):
> match_device = {'data': {'device': job}}
> match_id = {'data': {'id': job}}
> events = [
> @@ -557,7 +557,8 @@ class VM(qtest.QEMUQtestMachine):
> while True:
> ev = filter_qmp_event(self.events_wait(events))
> if ev['event'] != 'JOB_STATUS_CHANGE':
> - log(ev)
> + if use_log:
> + log(ev)
> continue
> status = ev['data']['status']
> if status == 'aborting':
> @@ -565,13 +566,20 @@ class VM(qtest.QEMUQtestMachine):
> for j in result['return']:
> if j['id'] == job:
> error = j['error']
> - log('Job failed: %s' % (j['error']))
> + if use_log:
> + log('Job failed: %s' % (j['error']))
> elif status == 'pending' and not auto_finalize:
> if pre_finalize:
> pre_finalize()
> - self.qmp_log('job-finalize', id=job)
> + if use_log:
> + self.qmp_log('job-finalize', id=job)
> + else:
> + self.qmp('job-finalize', id=job)
> elif status == 'concluded' and not auto_dismiss:
> - self.qmp_log('job-dismiss', id=job)
> + if use_log:
> + self.qmp_log('job-dismiss', id=job)
> + else:
> + self.qmp('job-dismiss', id=job)
> elif status == 'null':
> return error
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] iotests: Compare error messages in 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 3/5] iotests: Compare error messages " Max Reitz
2019-07-01 16:42 ` Andrey Shinkevich
@ 2019-07-02 12:37 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Alberto Garcia @ 2019-07-02 12:37 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel, Max Reitz
On Fri 28 Jun 2019 12:32:53 AM CEST, Max Reitz wrote:
> Currently, 030 just compares the error class, which does not say
> anything.
>
> Before HEAD^ added throttling to test_overlapping_4, that test actually
> usually failed because node2 was already gone, not because it was the
> commit and stream job were not allowed to overlap.
>
> Prevent such problems in the future by comparing the error description
> instead.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Berto
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
2019-07-01 16:46 ` Andrey Shinkevich
@ 2019-07-02 14:02 ` Alberto Garcia
2019-07-02 15:28 ` Max Reitz
2019-07-02 15:36 ` Alberto Garcia
2 siblings, 1 reply; 20+ messages in thread
From: Alberto Garcia @ 2019-07-02 14:02 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel, Max Reitz
On Fri 28 Jun 2019 12:32:51 AM CEST, Max Reitz wrote:
> @@ -4416,6 +4416,14 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
> return -EPERM;
> }
>
> + for (i = bs; i != base; i = backing_bs(i)) {
> + if (i->backing && backing_bs(i)->never_freeze) {
> + error_setg(errp, "Cannot freeze '%s' link to '%s'",
> + i->backing->name, backing_bs(i)->node_name);
> + return -EPERM;
> + }
> + }
How about adding this to bdrv_is_backing_chain_frozen() instead?
Berto
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030 Max Reitz
2019-07-01 16:44 ` Andrey Shinkevich
@ 2019-07-02 14:59 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Alberto Garcia @ 2019-07-02 14:59 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel, Max Reitz
On Fri 28 Jun 2019 12:32:55 AM CEST, Max Reitz wrote:
> We recently removed the dependency of the stream job on its base node.
> That makes it OK to use a commit filter node there. Test that.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Berto
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030
2019-06-27 22:32 ` [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030 Max Reitz
2019-07-01 16:41 ` Andrey Shinkevich
@ 2019-07-02 15:09 ` Alberto Garcia
1 sibling, 0 replies; 20+ messages in thread
From: Alberto Garcia @ 2019-07-02 15:09 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel, Max Reitz
On Fri 28 Jun 2019 12:32:52 AM CEST, Max Reitz wrote:
> Currently, TestParallelOps in 030 creates images that are too small for
> job throttling to be effective. This is reflected by the fact that it
> never undoes the throttling.
>
> Increase the image size and undo the throttling when the job should be
> completed. Also, add throttling in test_overlapping_4, or the jobs may
> not be so overlapping after all. In fact, the error usually emitted
> here is that node2 simply does not exist, not that overlapping jobs are
> not allowed -- the fact that this job ignores the exact error messages
> and just checks the error class is something that should be fixed in a
> follow-up patch.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Berto
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-07-02 14:02 ` Alberto Garcia
@ 2019-07-02 15:28 ` Max Reitz
0 siblings, 0 replies; 20+ messages in thread
From: Max Reitz @ 2019-07-02 15:28 UTC (permalink / raw)
To: Alberto Garcia, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 1031 bytes --]
On 02.07.19 16:02, Alberto Garcia wrote:
> On Fri 28 Jun 2019 12:32:51 AM CEST, Max Reitz wrote:
>> @@ -4416,6 +4416,14 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
>> return -EPERM;
>> }
>>
>> + for (i = bs; i != base; i = backing_bs(i)) {
>> + if (i->backing && backing_bs(i)->never_freeze) {
>> + error_setg(errp, "Cannot freeze '%s' link to '%s'",
>> + i->backing->name, backing_bs(i)->node_name);
>> + return -EPERM;
>> + }
>> + }
>
> How about adding this to bdrv_is_backing_chain_frozen() instead?
But that’s the wrong place. For example, that function is called by
bdrv_set_backing_hd() to check whether the backing BDS can be changed.
But the point of never_freeze is to ensure that links to the BDS can be
changed.
never_freeze only becomes relevant when trying to freeze the backing
chain, in that it should prevent it. So I think putting the check here
is correct.
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
2019-07-01 16:46 ` Andrey Shinkevich
2019-07-02 14:02 ` Alberto Garcia
@ 2019-07-02 15:36 ` Alberto Garcia
2019-07-02 15:38 ` Max Reitz
2 siblings, 1 reply; 20+ messages in thread
From: Alberto Garcia @ 2019-07-02 15:36 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel, Max Reitz
On Fri 28 Jun 2019 12:32:51 AM CEST, Max Reitz wrote:
> The commit and the mirror block job must be able to drop their filter
> node at any point. However, this will not be possible if any of the
> BdrvChild links to them is frozen. Therefore, we need to prevent them
> from ever becoming frozen.
>
> Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Berto
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] block: Add BDS.never_freeze
2019-07-02 15:36 ` Alberto Garcia
@ 2019-07-02 15:38 ` Max Reitz
0 siblings, 0 replies; 20+ messages in thread
From: Max Reitz @ 2019-07-02 15:38 UTC (permalink / raw)
To: Alberto Garcia, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, John Snow, qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 483 bytes --]
On 02.07.19 17:36, Alberto Garcia wrote:
> On Fri 28 Jun 2019 12:32:51 AM CEST, Max Reitz wrote:
>> The commit and the mirror block job must be able to drop their filter
>> node at any point. However, this will not be possible if any of the
>> BdrvChild links to them is frozen. Therefore, we need to prevent them
>> from ever becoming frozen.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>
> Reviewed-by: Alberto Garcia <berto@igalia.com>
Thanks! :-)
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job()
2019-07-01 22:59 ` John Snow
@ 2019-07-02 16:19 ` Max Reitz
2019-07-02 20:21 ` John Snow
0 siblings, 1 reply; 20+ messages in thread
From: Max Reitz @ 2019-07-02 16:19 UTC (permalink / raw)
To: John Snow, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, Alberto Garcia, qemu-devel,
Cleber Rosa
[-- Attachment #1.1: Type: text/plain, Size: 1216 bytes --]
On 02.07.19 00:59, John Snow wrote:
>
>
> On 6/27/19 6:32 PM, Max Reitz wrote:
>> unittest-style tests generally do not use the log file, but VM.run_job()
>> can still be useful to them. Add a parameter to it that hides its
>> output from the log file.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>
> Wondering out loud:
>
> can log() (and by extension qmp_log, and run_job) be made to use the
> python logging module and we can configure the logging environment
> instead of bespoke arguments to avoid ever engaging the log?
>
> We could theoretically just pre-disable iotests log output for unittest
> style tests, unless you run in debug mode where we allow it.
>
> I don't have a specific proposal for how to accomplish this, I think
> there are some nuances to Python logging that I don't quite understand.
> Maybe Cleber Rosa can help advise?
>
> I'd like to toy with this idea; it seems like this won't be the last
> time we want to turn output on/off.
Sounds good. But considering this is just test infrastructure, I’ll
leave that for when someone(TM) gets around to doing it. (Hopefully
when the next function is about to get a @use_log parameter.)
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job()
2019-07-02 16:19 ` Max Reitz
@ 2019-07-02 20:21 ` John Snow
0 siblings, 0 replies; 20+ messages in thread
From: John Snow @ 2019-07-02 20:21 UTC (permalink / raw)
To: Max Reitz, qemu-block
Cc: Kevin Wolf, Andrey Shinkevich, Alberto Garcia, qemu-devel,
Cleber Rosa
On 7/2/19 12:19 PM, Max Reitz wrote:
> On 02.07.19 00:59, John Snow wrote:
>>
>>
>> On 6/27/19 6:32 PM, Max Reitz wrote:
>>> unittest-style tests generally do not use the log file, but VM.run_job()
>>> can still be useful to them. Add a parameter to it that hides its
>>> output from the log file.
>>>
>>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>>
>> Wondering out loud:
>>
>> can log() (and by extension qmp_log, and run_job) be made to use the
>> python logging module and we can configure the logging environment
>> instead of bespoke arguments to avoid ever engaging the log?
>>
>> We could theoretically just pre-disable iotests log output for unittest
>> style tests, unless you run in debug mode where we allow it.
>>
>> I don't have a specific proposal for how to accomplish this, I think
>> there are some nuances to Python logging that I don't quite understand.
>> Maybe Cleber Rosa can help advise?
>>
>> I'd like to toy with this idea; it seems like this won't be the last
>> time we want to turn output on/off.
>
> Sounds good. But considering this is just test infrastructure, I’ll
> leave that for when someone(TM) gets around to doing it. (Hopefully
> when the next function is about to get a @use_log parameter.)
>
> Max
>
Yes, understood.
I just noticed that our pal run_job is getting a little long in the
arguments list, which is a good hint that we're doing something wrong.
I'll try to look into this as part of my next bitmap set.
--js
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2019-07-02 20:41 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-27 22:32 [Qemu-devel] [PATCH 0/5] block: Add BDS.never_freeze Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 1/5] " Max Reitz
2019-07-01 16:46 ` Andrey Shinkevich
2019-07-02 14:02 ` Alberto Garcia
2019-07-02 15:28 ` Max Reitz
2019-07-02 15:36 ` Alberto Garcia
2019-07-02 15:38 ` Max Reitz
2019-06-27 22:32 ` [Qemu-devel] [PATCH 2/5] iotests: Fix throttling in 030 Max Reitz
2019-07-01 16:41 ` Andrey Shinkevich
2019-07-02 15:09 ` Alberto Garcia
2019-06-27 22:32 ` [Qemu-devel] [PATCH 3/5] iotests: Compare error messages " Max Reitz
2019-07-01 16:42 ` Andrey Shinkevich
2019-07-02 12:37 ` Alberto Garcia
2019-06-27 22:32 ` [Qemu-devel] [PATCH 4/5] iotests: Add @use_log to VM.run_job() Max Reitz
2019-07-01 22:59 ` John Snow
2019-07-02 16:19 ` Max Reitz
2019-07-02 20:21 ` John Snow
2019-06-27 22:32 ` [Qemu-devel] [PATCH 5/5] iotests: Add new case to 030 Max Reitz
2019-07-01 16:44 ` Andrey Shinkevich
2019-07-02 14:59 ` Alberto Garcia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).