1
The following changes since commit 8c5f94cd4182753959c8be8de415120dc879d8f0:
1
The following changes since commit 63011373ad22c794a013da69663c03f1297a5c56:
2
2
3
Merge tag 'pull-loong-20211221-2' of https://gitlab.com/rth7680/qemu into staging (2021-12-21 13:30:35 -0800)
3
Merge tag 'pull-riscv-to-apply-20231012-1' of https://github.com/alistair23/qemu into staging (2023-10-12 10:24:44 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/hreitz/qemu.git tags/pull-block-2021-12-22
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 722f87df2545b308aec49b459b028f0802b4fd9e:
9
for you to fetch changes up to 071d6d107db2e26dde9bb15457c74956c88ec5b4:
10
10
11
iotests: check: multiprocessing support (2021-12-22 16:29:48 +0100)
11
virtio-blk: don't start dataplane during the stop of dataplane (2023-10-16 15:39:13 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Added support to the iotests for running tests in several parallel
15
16
jobs (using the new -j parameter)
16
Contains a virtio-blk IOThread fix.
17
17
18
----------------------------------------------------------------
18
----------------------------------------------------------------
19
Vladimir Sementsov-Ogievskiy (3):
20
iotests/testrunner.py: add doc string for run_test()
21
iotests/testrunner.py: move updating last_elapsed to run_tests
22
iotests: check: multiprocessing support
23
19
24
tests/qemu-iotests/check | 4 +-
20
hujian (1):
25
tests/qemu-iotests/testrunner.py | 86 ++++++++++++++++++++++++++++----
21
virtio-blk: don't start dataplane during the stop of dataplane
26
2 files changed, 80 insertions(+), 10 deletions(-)
22
23
hw/block/virtio-blk.c | 2 +-
24
1 file changed, 1 insertion(+), 1 deletion(-)
27
25
28
--
26
--
29
2.33.1
27
2.41.0
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to modify these methods and will add more documentation in
4
further commit. As a preparation add basic documentation.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20211203122223.2780098-2-vsementsov@virtuozzo.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Tested-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
tests/qemu-iotests/testrunner.py | 13 +++++++++++++
13
1 file changed, 13 insertions(+)
14
15
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/testrunner.py
18
+++ b/tests/qemu-iotests/testrunner.py
19
@@ -XXX,XX +XXX,XX @@ def find_reference(self, test: str) -> str:
20
return f'{test}.out'
21
22
def do_run_test(self, test: str) -> TestResult:
23
+ """
24
+ Run one test
25
+
26
+ :param test: test file path
27
+ """
28
+
29
f_test = Path(test)
30
f_bad = Path(f_test.name + '.out.bad')
31
f_notrun = Path(f_test.name + '.notrun')
32
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
33
34
def run_test(self, test: str,
35
test_field_width: Optional[int] = None) -> TestResult:
36
+ """
37
+ Run one test and print short status
38
+
39
+ :param test: test file path
40
+ :param test_field_width: width for first field of status format
41
+ """
42
+
43
last_el = self.last_elapsed.get(test)
44
start = datetime.datetime.now().strftime('%H:%M:%S')
45
46
--
47
2.33.1
48
49
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to use do_run_test() in multiprocessing environment, where
4
we'll not be able to change original runner object.
5
6
Happily, the only thing we change is that last_elapsed and it's simple
7
to do it in run_tests() instead. All other accesses to self in
8
do_runt_test() and in run_test() are read-only.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20211203122223.2780098-3-vsementsov@virtuozzo.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Tested-by: John Snow <jsnow@redhat.com>
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
---
16
tests/qemu-iotests/testrunner.py | 4 +++-
17
1 file changed, 3 insertions(+), 1 deletion(-)
18
19
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/testrunner.py
22
+++ b/tests/qemu-iotests/testrunner.py
23
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
24
diff=diff, casenotrun=casenotrun)
25
else:
26
f_bad.unlink()
27
- self.last_elapsed.update(test, elapsed)
28
return TestResult(status='pass', elapsed=elapsed,
29
casenotrun=casenotrun)
30
31
@@ -XXX,XX +XXX,XX @@ def run_tests(self, tests: List[str]) -> bool:
32
print('\n'.join(res.diff))
33
elif res.status == 'not run':
34
notrun.append(name)
35
+ elif res.status == 'pass':
36
+ assert res.elapsed is not None
37
+ self.last_elapsed.update(t, res.elapsed)
38
39
sys.stdout.flush()
40
if res.interrupted:
41
--
42
2.33.1
43
44
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: hujian <hu.jian@zte.com.cn>
2
2
3
Add -j <JOBS> parameter, to run tests in several jobs simultaneously.
3
During the stop of dataplane for virtio-blk, virtio_bus_cleanup_host_notifier() is be
4
For realization - simply utilize multiprocessing.Pool class.
4
called to clean up notifier at the end, if polled ioeventfd, virtio_blk_handle_output()
5
is used to handle io request. But due to s->dataplane_disabled is false, it will be
6
returned directly, which drops io request.
7
Backtrace:
8
->virtio_blk_data_plane_stop
9
->virtio_bus_cleanup_host_notifier
10
->virtio_queue_host_notifier_read
11
->virtio_queue_notify_vq
12
->vq->handle_output
13
->virtio_blk_handle_output
14
->if (s->dataplane && !s->dataplane_stoped)
15
->if (!s->dataplane_disabled)
16
->return *
17
->virtio_blk_handle_output_do
18
The above problem can occur when using "virsh reset" cmdline to reset guest, while
19
guest does io.
20
To fix this problem, don't try to start dataplane if s->stopping is true, and io would
21
be handled by virtio_blk_handle_vq().
5
22
6
Notes:
23
Signed-off-by: hujian <hu.jian@zte.com.cn>
24
Message-id: 202310111414266586398@zte.com.cn
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
---
27
hw/block/virtio-blk.c | 2 +-
28
1 file changed, 1 insertion(+), 1 deletion(-)
7
29
8
1. Of course, tests can't run simultaneously in same TEST_DIR. So,
30
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
9
use subdirectories TEST_DIR/testname/ and SOCK_DIR/testname/
10
instead of simply TEST_DIR and SOCK_DIR
11
12
2. multiprocessing.Pool.starmap function doesn't support passing
13
context managers, so we can't simply pass "self". Happily, we need
14
self only for read-only access, and it just works if it is defined
15
in global space. So, add a temporary link TestRunner.shared_self
16
during run_tests().
17
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Message-Id: <20211203122223.2780098-4-vsementsov@virtuozzo.com>
20
Reviewed-by: John Snow <jsnow@redhat.com>
21
Tested-by: John Snow <jsnow@redhat.com>
22
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
23
---
24
tests/qemu-iotests/check | 4 +-
25
tests/qemu-iotests/testrunner.py | 69 ++++++++++++++++++++++++++++----
26
2 files changed, 64 insertions(+), 9 deletions(-)
27
28
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/check
31
+++ b/tests/qemu-iotests/check
32
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
33
help='show me, do not run tests')
34
p.add_argument('-makecheck', action='store_true',
35
help='pretty print output for make check')
36
+ p.add_argument('-j', dest='jobs', type=int, default=1,
37
+ help='run tests in multiple parallel jobs')
38
39
p.add_argument('-d', dest='debug', action='store_true', help='debug')
40
p.add_argument('-p', dest='print', action='store_true',
41
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
42
with TestRunner(env, makecheck=args.makecheck,
43
color=args.color) as tr:
44
paths = [os.path.join(env.source_iotests, t) for t in tests]
45
- ok = tr.run_tests(paths)
46
+ ok = tr.run_tests(paths, args.jobs)
47
if not ok:
48
sys.exit(1)
49
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
50
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
51
--- a/tests/qemu-iotests/testrunner.py
32
--- a/hw/block/virtio-blk.c
52
+++ b/tests/qemu-iotests/testrunner.py
33
+++ b/hw/block/virtio-blk.c
53
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
54
import json
35
{
55
import termios
36
VirtIOBlock *s = (VirtIOBlock *)vdev;
56
import sys
37
57
+from multiprocessing import Pool
38
- if (s->dataplane && !s->dataplane_started) {
58
from contextlib import contextmanager
39
+ if (s->dataplane && !s->dataplane_started && !s->stopping) {
59
from typing import List, Optional, Iterator, Any, Sequence, Dict, \
40
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
60
ContextManager
41
* dataplane here instead of waiting for .set_status().
61
@@ -XXX,XX +XXX,XX @@ def __init__(self, status: str, description: str = '',
42
*/
62
63
64
class TestRunner(ContextManager['TestRunner']):
65
+ shared_self = None
66
+
67
+ @staticmethod
68
+ def proc_run_test(test: str, test_field_width: int) -> TestResult:
69
+ # We are in a subprocess, we can't change the runner object!
70
+ runner = TestRunner.shared_self
71
+ assert runner is not None
72
+ return runner.run_test(test, test_field_width, mp=True)
73
+
74
+ def run_tests_pool(self, tests: List[str],
75
+ test_field_width: int, jobs: int) -> List[TestResult]:
76
+
77
+ # passing self directly to Pool.starmap() just doesn't work, because
78
+ # it's a context manager.
79
+ assert TestRunner.shared_self is None
80
+ TestRunner.shared_self = self
81
+
82
+ with Pool(jobs) as p:
83
+ results = p.starmap(self.proc_run_test,
84
+ zip(tests, [test_field_width] * len(tests)))
85
+
86
+ TestRunner.shared_self = None
87
+
88
+ return results
89
+
90
def __init__(self, env: TestEnv, makecheck: bool = False,
91
color: str = 'auto') -> None:
92
self.env = env
93
@@ -XXX,XX +XXX,XX @@ def find_reference(self, test: str) -> str:
94
95
return f'{test}.out'
96
97
- def do_run_test(self, test: str) -> TestResult:
98
+ def do_run_test(self, test: str, mp: bool) -> TestResult:
99
"""
100
Run one test
101
102
:param test: test file path
103
+ :param mp: if true, we are in a multiprocessing environment, use
104
+ personal subdirectories for test run
105
+
106
+ Note: this method may be called from subprocess, so it does not
107
+ change ``self`` object in any way!
108
"""
109
110
f_test = Path(test)
111
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
112
113
args = [str(f_test.resolve())]
114
env = self.env.prepare_subprocess(args)
115
+ if mp:
116
+ # Split test directories, so that tests running in parallel don't
117
+ # break each other.
118
+ for d in ['TEST_DIR', 'SOCK_DIR']:
119
+ env[d] = os.path.join(env[d], f_test.name)
120
+ Path(env[d]).mkdir(parents=True, exist_ok=True)
121
122
t0 = time.time()
123
with f_bad.open('w', encoding="utf-8") as f:
124
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
125
casenotrun=casenotrun)
126
127
def run_test(self, test: str,
128
- test_field_width: Optional[int] = None) -> TestResult:
129
+ test_field_width: Optional[int] = None,
130
+ mp: bool = False) -> TestResult:
131
"""
132
Run one test and print short status
133
134
:param test: test file path
135
:param test_field_width: width for first field of status format
136
+ :param mp: if true, we are in a multiprocessing environment, don't try
137
+ to rewrite things in stdout
138
+
139
+ Note: this method may be called from subprocess, so it does not
140
+ change ``self`` object in any way!
141
"""
142
143
last_el = self.last_elapsed.get(test)
144
start = datetime.datetime.now().strftime('%H:%M:%S')
145
146
if not self.makecheck:
147
- self.test_print_one_line(test=test, starttime=start,
148
- lasttime=last_el, end='\r',
149
+ self.test_print_one_line(test=test,
150
+ status = 'started' if mp else '...',
151
+ starttime=start,
152
+ lasttime=last_el,
153
+ end = '\n' if mp else '\r',
154
test_field_width=test_field_width)
155
156
- res = self.do_run_test(test)
157
+ res = self.do_run_test(test, mp)
158
159
end = datetime.datetime.now().strftime('%H:%M:%S')
160
self.test_print_one_line(test=test, status=res.status,
161
@@ -XXX,XX +XXX,XX @@ def run_test(self, test: str,
162
163
return res
164
165
- def run_tests(self, tests: List[str]) -> bool:
166
+ def run_tests(self, tests: List[str], jobs: int = 1) -> bool:
167
n_run = 0
168
failed = []
169
notrun = []
170
@@ -XXX,XX +XXX,XX @@ def run_tests(self, tests: List[str]) -> bool:
171
172
test_field_width = max(len(os.path.basename(t)) for t in tests) + 2
173
174
- for t in tests:
175
+ if jobs > 1:
176
+ results = self.run_tests_pool(tests, test_field_width, jobs)
177
+
178
+ for i, t in enumerate(tests):
179
name = os.path.basename(t)
180
- res = self.run_test(t, test_field_width=test_field_width)
181
+
182
+ if jobs > 1:
183
+ res = results[i]
184
+ else:
185
+ res = self.run_test(t, test_field_width)
186
187
assert res.status in ('pass', 'fail', 'not run')
188
189
--
43
--
190
2.33.1
44
2.41.0
191
192
diff view generated by jsdifflib