1
The following changes since commit 5375af3cd7b8adcc10c18d8083b7be63976c9645:
1
The following changes since commit 6338c30111d596d955e6bc933a82184a0b910c43:
2
2
3
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-05-04 15:51:09 +0100)
3
Merge tag 'm68k-for-7.2-pull-request' of https://github.com/vivier/qemu-m68k into staging (2022-09-21 13:12:36 -0400)
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-05-05
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 4ce5dd3e9b5ee0fac18625860eb3727399ee965e:
9
for you to fetch changes up to f16d15c9276bd8f501f861c39cbd4adc812d0c1d:
10
10
11
block/block-copy: use aio-task-pool API (2020-05-05 14:03:28 +0200)
11
virtiofsd: use g_date_time_get_microsecond to get subsecond (2022-09-22 13:13:47 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Asynchronous copying for block-copy (i.e., the backup job)
16
- Allow resizing of qcow2 images when they have internal snapshots
17
- iotests: Logging improvements for Python tests
18
- iotest 153 fix, and block comment cleanups
19
15
20
----------------------------------------------------------------
16
----------------------------------------------------------------
21
Eric Blake (4):
22
block: Add blk_new_with_bs() helper
23
qcow2: Allow resize of images with internal snapshots
24
qcow2: Tweak comment about bitmaps vs. resize
25
block: Comment cleanups
26
17
27
John Snow (14):
18
Yusuke Okada (1):
28
iotests: do a light delinting
19
virtiofsd: use g_date_time_get_microsecond to get subsecond
29
iotests: don't use 'format' for drive_add
30
iotests: ignore import warnings from pylint
31
iotests: replace mutable list default args
32
iotests: add pylintrc file
33
iotests: alphabetize standard imports
34
iotests: drop pre-Python 3.4 compatibility code
35
iotests: touch up log function signature
36
iotests: limit line length to 79 chars
37
iotests: add hmp helper with logging
38
iotests: add script_initialize
39
iotest 258: use script_main
40
iotests: Mark verify functions as private
41
iotests: use python logging for iotests.log()
42
20
43
Maxim Levitsky (1):
21
tools/virtiofsd/passthrough_ll.c | 7 +++++--
44
Fix iotest 153
22
1 file changed, 5 insertions(+), 2 deletions(-)
45
46
Vladimir Sementsov-Ogievskiy (5):
47
block/block-copy: rename in-flight requests to tasks
48
block/block-copy: alloc task on each iteration
49
block/block-copy: add state pointer to BlockCopyTask
50
block/block-copy: refactor task creation
51
block/block-copy: use aio-task-pool API
52
53
include/sysemu/block-backend.h | 2 +
54
block/block-backend.c | 23 +++
55
block/block-copy.c | 279 +++++++++++++++++--------
56
block/crypto.c | 9 +-
57
block/io.c | 3 +-
58
block/parallels.c | 8 +-
59
block/qcow.c | 8 +-
60
block/qcow2-refcount.c | 2 +-
61
block/qcow2-snapshot.c | 20 +-
62
block/qcow2.c | 45 ++--
63
block/qed.c | 8 +-
64
block/sheepdog.c | 10 +-
65
block/vdi.c | 8 +-
66
block/vhdx.c | 8 +-
67
block/vmdk.c | 9 +-
68
block/vpc.c | 8 +-
69
block/vvfat.c | 10 +-
70
blockdev.c | 8 +-
71
blockjob.c | 7 +-
72
tests/qemu-iotests/001 | 2 +-
73
tests/qemu-iotests/030 | 4 +-
74
tests/qemu-iotests/052 | 2 +-
75
tests/qemu-iotests/055 | 3 +-
76
tests/qemu-iotests/061 | 35 ++++
77
tests/qemu-iotests/061.out | 28 +++
78
tests/qemu-iotests/134 | 2 +-
79
tests/qemu-iotests/149 | 3 +-
80
tests/qemu-iotests/153 | 2 +-
81
tests/qemu-iotests/153.out | 12 +-
82
tests/qemu-iotests/155 | 2 +-
83
tests/qemu-iotests/188 | 2 +-
84
tests/qemu-iotests/194 | 4 +-
85
tests/qemu-iotests/202 | 4 +-
86
tests/qemu-iotests/203 | 4 +-
87
tests/qemu-iotests/206 | 2 +-
88
tests/qemu-iotests/207 | 6 +-
89
tests/qemu-iotests/208 | 2 +-
90
tests/qemu-iotests/209 | 2 +-
91
tests/qemu-iotests/210 | 6 +-
92
tests/qemu-iotests/211 | 6 +-
93
tests/qemu-iotests/212 | 6 +-
94
tests/qemu-iotests/213 | 6 +-
95
tests/qemu-iotests/216 | 4 +-
96
tests/qemu-iotests/218 | 2 +-
97
tests/qemu-iotests/219 | 2 +-
98
tests/qemu-iotests/222 | 7 +-
99
tests/qemu-iotests/224 | 4 +-
100
tests/qemu-iotests/228 | 6 +-
101
tests/qemu-iotests/234 | 4 +-
102
tests/qemu-iotests/235 | 4 +-
103
tests/qemu-iotests/236 | 2 +-
104
tests/qemu-iotests/237 | 2 +-
105
tests/qemu-iotests/238 | 2 +
106
tests/qemu-iotests/242 | 2 +-
107
tests/qemu-iotests/245 | 1 +
108
tests/qemu-iotests/245.out | 10 +-
109
tests/qemu-iotests/246 | 2 +-
110
tests/qemu-iotests/248 | 2 +-
111
tests/qemu-iotests/254 | 2 +-
112
tests/qemu-iotests/255 | 2 +-
113
tests/qemu-iotests/256 | 2 +-
114
tests/qemu-iotests/258 | 10 +-
115
tests/qemu-iotests/260 | 4 +-
116
tests/qemu-iotests/262 | 4 +-
117
tests/qemu-iotests/264 | 4 +-
118
tests/qemu-iotests/274 | 4 +-
119
tests/qemu-iotests/277 | 2 +
120
tests/qemu-iotests/280 | 8 +-
121
tests/qemu-iotests/283 | 4 +-
122
tests/qemu-iotests/iotests.py | 366 ++++++++++++++++++++-------------
123
tests/qemu-iotests/pylintrc | 26 +++
124
71 files changed, 728 insertions(+), 386 deletions(-)
125
create mode 100644 tests/qemu-iotests/pylintrc
126
23
127
--
24
--
128
2.26.2
25
2.37.3
129
130
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
This doesn't fix everything in here, but it does help clean up the
4
pylint report considerably.
5
6
This should be 100% style changes only; the intent is to make pylint
7
more useful by working on establishing a baseline for iotests that we
8
can gate against in the future.
9
10
Signed-off-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200331000014.11581-2-jsnow@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/iotests.py | 83 ++++++++++++++++++-----------------
18
1 file changed, 43 insertions(+), 40 deletions(-)
19
20
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/iotests.py
23
+++ b/tests/qemu-iotests/iotests.py
24
@@ -XXX,XX +XXX,XX @@
25
# along with this program. If not, see <http://www.gnu.org/licenses/>.
26
#
27
28
-import errno
29
import os
30
import re
31
import subprocess
32
-import string
33
import unittest
34
import sys
35
import struct
36
@@ -XXX,XX +XXX,XX @@ import faulthandler
37
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
38
from qemu import qtest
39
40
-assert sys.version_info >= (3,6)
41
+assert sys.version_info >= (3, 6)
42
43
faulthandler.enable()
44
45
@@ -XXX,XX +XXX,XX @@ def qemu_img_log(*args):
46
return result
47
48
def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
49
- args = [ 'info' ]
50
+ args = ['info']
51
if imgopts:
52
args.append('--image-opts')
53
else:
54
- args += [ '-f', imgfmt ]
55
+ args += ['-f', imgfmt]
56
args += extra_args
57
args.append(filename)
58
59
@@ -XXX,XX +XXX,XX @@ class QemuIoInteractive:
60
# quit command is in close(), '\n' is added automatically
61
assert '\n' not in cmd
62
cmd = cmd.strip()
63
- assert cmd != 'q' and cmd != 'quit'
64
+ assert cmd not in ('q', 'quit')
65
self._p.stdin.write(cmd + '\n')
66
self._p.stdin.flush()
67
return self._read_output()
68
@@ -XXX,XX +XXX,XX @@ def qemu_nbd_early_pipe(*args):
69
sys.stderr.write('qemu-nbd received signal %i: %s\n' %
70
(-exitcode,
71
' '.join(qemu_nbd_args + ['--fork'] + list(args))))
72
- if exitcode == 0:
73
- return exitcode, ''
74
- else:
75
- return exitcode, subp.communicate()[0]
76
+
77
+ return exitcode, subp.communicate()[0] if exitcode else ''
78
79
def qemu_nbd_popen(*args):
80
'''Run qemu-nbd in daemon mode and return the parent's exit code'''
81
@@ -XXX,XX +XXX,XX @@ def filter_qmp(qmsg, filter_fn):
82
items = qmsg.items()
83
84
for k, v in items:
85
- if isinstance(v, list) or isinstance(v, dict):
86
+ if isinstance(v, (dict, list)):
87
qmsg[k] = filter_qmp(v, filter_fn)
88
else:
89
qmsg[k] = filter_fn(k, v)
90
@@ -XXX,XX +XXX,XX @@ def filter_testfiles(msg):
91
return msg.replace(prefix, 'TEST_DIR/PID-')
92
93
def filter_qmp_testfiles(qmsg):
94
- def _filter(key, value):
95
+ def _filter(_key, value):
96
if is_str(value):
97
return filter_testfiles(value)
98
return value
99
@@ -XXX,XX +XXX,XX @@ def filter_imgfmt(msg):
100
return msg.replace(imgfmt, 'IMGFMT')
101
102
def filter_qmp_imgfmt(qmsg):
103
- def _filter(key, value):
104
+ def _filter(_key, value):
105
if is_str(value):
106
return filter_imgfmt(value)
107
return value
108
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=[], indent=None):
109
If indent is provided, JSON serializable messages are pretty-printed.'''
110
for flt in filters:
111
msg = flt(msg)
112
- if isinstance(msg, dict) or isinstance(msg, list):
113
+ if isinstance(msg, (dict, list)):
114
# Python < 3.4 needs to know not to add whitespace when pretty-printing:
115
separators = (', ', ': ') if indent is None else (',', ': ')
116
# Don't sort if it's already sorted
117
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=[], indent=None):
118
print(msg)
119
120
class Timeout:
121
- def __init__(self, seconds, errmsg = "Timeout"):
122
+ def __init__(self, seconds, errmsg="Timeout"):
123
self.seconds = seconds
124
self.errmsg = errmsg
125
def __enter__(self):
126
signal.signal(signal.SIGALRM, self.timeout)
127
signal.setitimer(signal.ITIMER_REAL, self.seconds)
128
return self
129
- def __exit__(self, type, value, traceback):
130
+ def __exit__(self, exc_type, value, traceback):
131
signal.setitimer(signal.ITIMER_REAL, 0)
132
return False
133
def timeout(self, signum, frame):
134
@@ -XXX,XX +XXX,XX @@ class Timeout:
135
def file_pattern(name):
136
return "{0}-{1}".format(os.getpid(), name)
137
138
-class FilePaths(object):
139
+class FilePaths:
140
"""
141
FilePaths is an auto-generated filename that cleans itself up.
142
143
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
144
self.pause_drive(drive, "write_aio")
145
return
146
self.qmp('human-monitor-command',
147
- command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive))
148
+ command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive))
149
150
def resume_drive(self, drive):
151
self.qmp('human-monitor-command',
152
- command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive))
153
+ command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive))
154
155
def hmp_qemu_io(self, drive, cmd):
156
'''Write to a given drive using an HMP command'''
157
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
158
if output is None:
159
output = dict()
160
if isinstance(obj, list):
161
- for i in range(len(obj)):
162
- self.flatten_qmp_object(obj[i], output, basestr + str(i) + '.')
163
+ for i, item in enumerate(obj):
164
+ self.flatten_qmp_object(item, output, basestr + str(i) + '.')
165
elif isinstance(obj, dict):
166
for key in obj:
167
self.flatten_qmp_object(obj[key], output, basestr + key + '.')
168
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
169
170
for bitmap in bitmaps[node_name]:
171
if bitmap.get('name', '') == bitmap_name:
172
- if recording is None:
173
- return bitmap
174
- elif bitmap.get('recording') == recording:
175
+ if recording is None or bitmap.get('recording') == recording:
176
return bitmap
177
return None
178
179
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
180
assert node is not None, 'Cannot follow path %s%s' % (root, path)
181
182
try:
183
- node_id = next(edge['child'] for edge in graph['edges'] \
184
- if edge['parent'] == node['id'] and
185
- edge['name'] == child_name)
186
+ node_id = next(edge['child'] for edge in graph['edges']
187
+ if (edge['parent'] == node['id'] and
188
+ edge['name'] == child_name))
189
+
190
+ node = next(node for node in graph['nodes']
191
+ if node['id'] == node_id)
192
193
- node = next(node for node in graph['nodes'] \
194
- if node['id'] == node_id)
195
except StopIteration:
196
node = None
197
198
@@ -XXX,XX +XXX,XX @@ index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
199
class QMPTestCase(unittest.TestCase):
200
'''Abstract base class for QMP test cases'''
201
202
+ def __init__(self, *args, **kwargs):
203
+ super().__init__(*args, **kwargs)
204
+ # Many users of this class set a VM property we rely on heavily
205
+ # in the methods below.
206
+ self.vm = None
207
+
208
def dictpath(self, d, path):
209
'''Traverse a path in a nested dict'''
210
for component in path.split('/'):
211
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
212
else:
213
self.assertEqual(result, value,
214
'"%s" is "%s", expected "%s"'
215
- % (path, str(result), str(value)))
216
+ % (path, str(result), str(value)))
217
218
def assert_no_active_block_jobs(self):
219
result = self.vm.qmp('query-block-jobs')
220
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
221
"""Issue a query-named-block-nodes and assert node_name and/or
222
file_name is present in the result"""
223
def check_equal_or_none(a, b):
224
- return a == None or b == None or a == b
225
+ return a is None or b is None or a == b
226
assert node_name or file_name
227
result = self.vm.qmp('query-named-block-nodes')
228
for x in result["return"]:
229
if check_equal_or_none(x.get("node-name"), node_name) and \
230
check_equal_or_none(x.get("file"), file_name):
231
return
232
- self.assertTrue(False, "Cannot find %s %s in result:\n%s" % \
233
- (node_name, file_name, result))
234
+ self.fail("Cannot find %s %s in result:\n%s" %
235
+ (node_name, file_name, result))
236
237
def assert_json_filename_equal(self, json_filename, reference):
238
'''Asserts that the given filename is a json: filename and that its
239
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
240
self.assert_qmp(event, 'data/error', error)
241
self.assert_no_active_block_jobs()
242
return event
243
- elif event['event'] == 'JOB_STATUS_CHANGE':
244
+ if event['event'] == 'JOB_STATUS_CHANGE':
245
self.assert_qmp(event, 'data/id', drive)
246
247
def wait_ready(self, drive='drive0'):
248
- '''Wait until a block job BLOCK_JOB_READY event'''
249
- f = {'data': {'type': 'mirror', 'device': drive } }
250
- event = self.vm.event_wait(name='BLOCK_JOB_READY', match=f)
251
+ """Wait until a BLOCK_JOB_READY event, and return the event."""
252
+ f = {'data': {'type': 'mirror', 'device': drive}}
253
+ return self.vm.event_wait(name='BLOCK_JOB_READY', match=f)
254
255
def wait_ready_and_cancel(self, drive='drive0'):
256
self.wait_ready(drive=drive)
257
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
258
for job in result['return']:
259
if job['device'] == job_id:
260
found = True
261
- if job['paused'] == True and job['busy'] == False:
262
+ if job['paused'] and not job['busy']:
263
return job
264
break
265
assert found
266
@@ -XXX,XX +XXX,XX @@ def qemu_pipe(*args):
267
universal_newlines=True)
268
exitcode = subp.wait()
269
if exitcode < 0:
270
- sys.stderr.write('qemu received signal %i: %s\n' % (-exitcode,
271
- ' '.join(args)))
272
+ sys.stderr.write('qemu received signal %i: %s\n' %
273
+ (-exitcode, ' '.join(args)))
274
return subp.communicate()[0]
275
276
def supported_formats(read_only=False):
277
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=[], read_only=False):
278
if usf_list:
279
test_case.case_skip('{}: formats {} are not whitelisted'.format(
280
test_case, usf_list))
281
+ return None
282
else:
283
return func(test_case, *args, **kwargs)
284
return func_wrapper
285
@@ -XXX,XX +XXX,XX @@ def skip_if_user_is_root(func):
286
def func_wrapper(*args, **kwargs):
287
if os.getuid() == 0:
288
case_notrun('{}: cannot be run as root'.format(args[0]))
289
+ return None
290
else:
291
return func(*args, **kwargs)
292
return func_wrapper
293
--
294
2.26.2
295
296
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
It shadows (with a different type) the built-in format.
4
Use something else.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200331000014.11581-3-jsnow@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/055 | 3 ++-
14
tests/qemu-iotests/iotests.py | 6 +++---
15
2 files changed, 5 insertions(+), 4 deletions(-)
16
17
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/055
20
+++ b/tests/qemu-iotests/055
21
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
22
qemu_img('create', '-f', fmt, blockdev_target_img,
23
str(TestDriveCompression.image_len), *args)
24
if attach_target:
25
- self.vm.add_drive(blockdev_target_img, format=fmt, interface="none")
26
+ self.vm.add_drive(blockdev_target_img,
27
+ img_format=fmt, interface="none")
28
29
self.vm.launch()
30
31
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/qemu-iotests/iotests.py
34
+++ b/tests/qemu-iotests/iotests.py
35
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
36
self._args.append(opts)
37
return self
38
39
- def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
40
+ def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt):
41
'''Add a virtio-blk drive to the VM'''
42
options = ['if=%s' % interface,
43
'id=drive%d' % self._num_drives]
44
45
if path is not None:
46
options.append('file=%s' % path)
47
- options.append('format=%s' % format)
48
+ options.append('format=%s' % img_format)
49
options.append('cache=%s' % cachemode)
50
options.append('aio=%s' % aiomode)
51
52
if opts:
53
options.append(opts)
54
55
- if format == 'luks' and 'key-secret' not in opts:
56
+ if img_format == 'luks' and 'key-secret' not in opts:
57
# default luks support
58
if luks_default_secret_object not in self._args:
59
self.add_object(luks_default_secret_object)
60
--
61
2.26.2
62
63
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
The right way to solve this is to come up with a virtual environment
4
infrastructure that sets all the paths correctly, and/or to create
5
installable python modules that can be imported normally.
6
7
That's hard, so just silence this error for now.
8
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: John Snow <jsnow@redhat.com>
12
Message-Id: <20200331000014.11581-4-jsnow@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/iotests.py | 1 +
17
1 file changed, 1 insertion(+)
18
19
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/iotests.py
22
+++ b/tests/qemu-iotests/iotests.py
23
@@ -XXX,XX +XXX,XX @@ import io
24
from collections import OrderedDict
25
import faulthandler
26
27
+# pylint: disable=import-error, wrong-import-position
28
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
29
from qemu import qtest
30
31
--
32
2.26.2
33
34
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
It's bad hygiene: if we modify this list, it will be modified across all
4
invocations.
5
6
(Remaining bad usages are fixed in a subsequent patch which changes the
7
function signature anyway.)
8
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200331000014.11581-5-jsnow@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/iotests.py | 24 ++++++++++++------------
17
1 file changed, 12 insertions(+), 12 deletions(-)
18
19
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/iotests.py
22
+++ b/tests/qemu-iotests/iotests.py
23
@@ -XXX,XX +XXX,XX @@ def qemu_img_log(*args):
24
log(result, filters=[filter_testfiles])
25
return result
26
27
-def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
28
+def img_info_log(filename, filter_path=None, imgopts=False, extra_args=()):
29
args = ['info']
30
if imgopts:
31
args.append('--image-opts')
32
@@ -XXX,XX +XXX,XX @@ def filter_qmp_imgfmt(qmsg):
33
return value
34
return filter_qmp(qmsg, _filter)
35
36
-def log(msg, filters=[], indent=None):
37
+def log(msg, filters=(), indent=None):
38
'''Logs either a string message or a JSON serializable message (like QMP).
39
If indent is provided, JSON serializable messages are pretty-printed.'''
40
for flt in filters:
41
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
42
result.append(filter_qmp_event(ev))
43
return result
44
45
- def qmp_log(self, cmd, filters=[], indent=None, **kwargs):
46
+ def qmp_log(self, cmd, filters=(), indent=None, **kwargs):
47
full_cmd = OrderedDict((
48
("execute", cmd),
49
("arguments", ordered_qmp(kwargs))
50
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
51
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
52
' [case not run] ' + reason + '\n')
53
54
-def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
55
+def verify_image_format(supported_fmts=(), unsupported_fmts=()):
56
assert not (supported_fmts and unsupported_fmts)
57
58
if 'generic' in supported_fmts and \
59
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
60
if not_sup or (imgfmt in unsupported_fmts):
61
notrun('not suitable for this image format: %s' % imgfmt)
62
63
-def verify_protocol(supported=[], unsupported=[]):
64
+def verify_protocol(supported=(), unsupported=()):
65
assert not (supported and unsupported)
66
67
if 'generic' in supported:
68
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=None, unsupported=None):
69
if not any((sys.platform.startswith(x) for x in supported)):
70
notrun('not suitable for this OS: %s' % sys.platform)
71
72
-def verify_cache_mode(supported_cache_modes=[]):
73
+def verify_cache_mode(supported_cache_modes=()):
74
if supported_cache_modes and (cachemode not in supported_cache_modes):
75
notrun('not suitable for this cache mode: %s' % cachemode)
76
77
-def verify_aio_mode(supported_aio_modes=[]):
78
+def verify_aio_mode(supported_aio_modes=()):
79
if supported_aio_modes and (aiomode not in supported_aio_modes):
80
notrun('not suitable for this aio mode: %s' % aiomode)
81
82
@@ -XXX,XX +XXX,XX @@ def supported_formats(read_only=False):
83
84
return supported_formats.formats[read_only]
85
86
-def skip_if_unsupported(required_formats=[], read_only=False):
87
+def skip_if_unsupported(required_formats=(), read_only=False):
88
'''Skip Test Decorator
89
Runs the test if all the required formats are whitelisted'''
90
def skip_test_decorator(func):
91
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
92
sys.stderr.write(out)
93
94
def execute_test(test_function=None,
95
- supported_fmts=[],
96
+ supported_fmts=(),
97
supported_platforms=None,
98
- supported_cache_modes=[], supported_aio_modes={},
99
- unsupported_fmts=[], supported_protocols=[],
100
- unsupported_protocols=[]):
101
+ supported_cache_modes=(), supported_aio_modes=(),
102
+ unsupported_fmts=(), supported_protocols=(),
103
+ unsupported_protocols=()):
104
"""Run either unittest or script-style tests."""
105
106
# We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
107
--
108
2.26.2
109
110
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
This allows others to get repeatable results with pylint. If you run
4
`pylint iotests.py`, you should see a 100% pass.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-6-jsnow@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/pylintrc | 22 ++++++++++++++++++++++
13
1 file changed, 22 insertions(+)
14
create mode 100644 tests/qemu-iotests/pylintrc
15
16
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/tests/qemu-iotests/pylintrc
21
@@ -XXX,XX +XXX,XX @@
22
+[MESSAGES CONTROL]
23
+
24
+# Disable the message, report, category or checker with the given id(s). You
25
+# can either give multiple identifiers separated by comma (,) or put this
26
+# option multiple times (only on the command line, not in the configuration
27
+# file where it should appear only once). You can also use "--disable=all" to
28
+# disable everything first and then reenable specific checks. For example, if
29
+# you want to run only the similarities checker, you can use "--disable=all
30
+# --enable=similarities". If you want to run only the classes checker, but have
31
+# no Warning level messages displayed, use "--disable=all --enable=classes
32
+# --disable=W".
33
+disable=invalid-name,
34
+ no-else-return,
35
+ too-few-public-methods,
36
+ too-many-arguments,
37
+ too-many-branches,
38
+ too-many-lines,
39
+ too-many-locals,
40
+ too-many-public-methods,
41
+ # These are temporary, and should be removed:
42
+ line-too-long,
43
+ missing-docstring,
44
--
45
2.26.2
46
47
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
I had to fix a merge conflict, so do this tiny harmless thing while I'm
4
here.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-7-jsnow@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 18 +++++++++---------
14
1 file changed, 9 insertions(+), 9 deletions(-)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#
23
24
+import atexit
25
+from collections import OrderedDict
26
+import faulthandler
27
+import io
28
+import json
29
+import logging
30
import os
31
import re
32
+import signal
33
+import struct
34
import subprocess
35
-import unittest
36
import sys
37
-import struct
38
-import json
39
-import signal
40
-import logging
41
-import atexit
42
-import io
43
-from collections import OrderedDict
44
-import faulthandler
45
+import unittest
46
47
# pylint: disable=import-error, wrong-import-position
48
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
49
--
50
2.26.2
51
52
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
We no longer need to accommodate <3.4, drop this code.
4
(The lines were > 79 chars and it stood out.)
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-8-jsnow@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 5 +----
13
1 file changed, 1 insertion(+), 4 deletions(-)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=(), indent=None):
20
for flt in filters:
21
msg = flt(msg)
22
if isinstance(msg, (dict, list)):
23
- # Python < 3.4 needs to know not to add whitespace when pretty-printing:
24
- separators = (', ', ': ') if indent is None else (',', ': ')
25
# Don't sort if it's already sorted
26
do_sort = not isinstance(msg, OrderedDict)
27
- print(json.dumps(msg, sort_keys=do_sort,
28
- indent=indent, separators=separators))
29
+ print(json.dumps(msg, sort_keys=do_sort, indent=indent))
30
else:
31
print(msg)
32
33
--
34
2.26.2
35
36
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Representing nested, recursive data structures in mypy is notoriously
4
difficult; the best we can reliably do right now is denote the leaf
5
types as "Any" while describing the general shape of the data.
6
7
Regardless, this fully annotates the log() function.
8
9
Typing notes:
10
11
TypeVar is a Type variable that can optionally be constrained by a
12
sequence of possible types. This variable is bound to a specific type
13
per-invocation, like a Generic.
14
15
log() behaves as log<Msg>() now, where the incoming type informs the
16
signature it expects for any filter arguments passed in. If Msg is a
17
str, then filter should take and return a str.
18
19
Signed-off-by: John Snow <jsnow@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Message-Id: <20200331000014.11581-9-jsnow@redhat.com>
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
tests/qemu-iotests/iotests.py | 14 +++++++++++---
26
1 file changed, 11 insertions(+), 3 deletions(-)
27
28
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qemu-iotests/iotests.py
31
+++ b/tests/qemu-iotests/iotests.py
32
@@ -XXX,XX +XXX,XX @@ import signal
33
import struct
34
import subprocess
35
import sys
36
+from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
37
import unittest
38
39
# pylint: disable=import-error, wrong-import-position
40
@@ -XXX,XX +XXX,XX @@ def filter_qmp_imgfmt(qmsg):
41
return value
42
return filter_qmp(qmsg, _filter)
43
44
-def log(msg, filters=(), indent=None):
45
- '''Logs either a string message or a JSON serializable message (like QMP).
46
- If indent is provided, JSON serializable messages are pretty-printed.'''
47
+
48
+Msg = TypeVar('Msg', Dict[str, Any], List[Any], str)
49
+
50
+def log(msg: Msg,
51
+ filters: Iterable[Callable[[Msg], Msg]] = (),
52
+ indent: Optional[int] = None) -> None:
53
+ """
54
+ Logs either a string message or a JSON serializable message (like QMP).
55
+ If indent is provided, JSON serializable messages are pretty-printed.
56
+ """
57
for flt in filters:
58
msg = flt(msg)
59
if isinstance(msg, (dict, list)):
60
--
61
2.26.2
62
63
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
79 is the PEP8 recommendation. This recommendation works well for
4
reading patch diffs in TUI email clients.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-10-jsnow@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 64 +++++++++++++++++++++++------------
13
tests/qemu-iotests/pylintrc | 6 +++-
14
2 files changed, 47 insertions(+), 23 deletions(-)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ luks_default_key_secret_opt = 'key-secret=keysec0'
21
def qemu_img(*args):
22
'''Run qemu-img and return the exit code'''
23
devnull = open('/dev/null', 'r+')
24
- exitcode = subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
25
+ exitcode = subprocess.call(qemu_img_args + list(args),
26
+ stdin=devnull, stdout=devnull)
27
if exitcode < 0:
28
- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
29
+ sys.stderr.write('qemu-img received signal %i: %s\n'
30
+ % (-exitcode, ' '.join(qemu_img_args + list(args))))
31
return exitcode
32
33
def ordered_qmp(qmsg, conv_keys=True):
34
@@ -XXX,XX +XXX,XX @@ def qemu_img_verbose(*args):
35
'''Run qemu-img without suppressing its output and return the exit code'''
36
exitcode = subprocess.call(qemu_img_args + list(args))
37
if exitcode < 0:
38
- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
39
+ sys.stderr.write('qemu-img received signal %i: %s\n'
40
+ % (-exitcode, ' '.join(qemu_img_args + list(args))))
41
return exitcode
42
43
def qemu_img_pipe(*args):
44
@@ -XXX,XX +XXX,XX @@ def qemu_img_pipe(*args):
45
universal_newlines=True)
46
exitcode = subp.wait()
47
if exitcode < 0:
48
- sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
49
+ sys.stderr.write('qemu-img received signal %i: %s\n'
50
+ % (-exitcode, ' '.join(qemu_img_args + list(args))))
51
return subp.communicate()[0]
52
53
def qemu_img_log(*args):
54
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args):
55
universal_newlines=True)
56
exitcode = subp.wait()
57
if exitcode < 0:
58
- sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
59
+ sys.stderr.write('qemu-io received signal %i: %s\n'
60
+ % (-exitcode, ' '.join(args)))
61
return subp.communicate()[0]
62
63
def qemu_io_log(*args):
64
@@ -XXX,XX +XXX,XX @@ win32_re = re.compile(r"\r")
65
def filter_win32(msg):
66
return win32_re.sub("", msg)
67
68
-qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* \([0-9\/.inf]* [EPTGMKiBbytes]*\/sec and [0-9\/.inf]* ops\/sec\)")
69
+qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* "
70
+ r"\([0-9\/.inf]* [EPTGMKiBbytes]*\/sec "
71
+ r"and [0-9\/.inf]* ops\/sec\)")
72
def filter_qemu_io(msg):
73
msg = filter_win32(msg)
74
- return qemu_io_re.sub("X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)", msg)
75
+ return qemu_io_re.sub("X ops; XX:XX:XX.X "
76
+ "(XXX YYY/sec and XXX ops/sec)", msg)
77
78
chown_re = re.compile(r"chown [0-9]+:[0-9]+")
79
def filter_chown(msg):
80
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
81
line = filter_testfiles(line)
82
line = line.replace(imgfmt, 'IMGFMT')
83
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
84
- line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
85
+ line = re.sub('uuid: [-a-f0-9]+',
86
+ 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
87
+ line)
88
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
89
lines.append(line)
90
return '\n'.join(lines)
91
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
92
self.pause_drive(drive, "write_aio")
93
return
94
self.qmp('human-monitor-command',
95
- command_line='qemu-io %s "break %s bp_%s"' % (drive, event, drive))
96
+ command_line='qemu-io %s "break %s bp_%s"'
97
+ % (drive, event, drive))
98
99
def resume_drive(self, drive):
100
self.qmp('human-monitor-command',
101
- command_line='qemu-io %s "remove_break bp_%s"' % (drive, drive))
102
+ command_line='qemu-io %s "remove_break bp_%s"'
103
+ % (drive, drive))
104
105
def hmp_qemu_io(self, drive, cmd):
106
'''Write to a given drive using an HMP command'''
107
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
108
idx = int(idx)
109
110
if not isinstance(d, dict) or component not in d:
111
- self.fail('failed path traversal for "%s" in "%s"' % (path, str(d)))
112
+ self.fail(f'failed path traversal for "{path}" in "{d}"')
113
d = d[component]
114
115
if m:
116
if not isinstance(d, list):
117
- self.fail('path component "%s" in "%s" is not a list in "%s"' % (component, path, str(d)))
118
+ self.fail(f'path component "{component}" in "{path}" '
119
+ f'is not a list in "{d}"')
120
try:
121
d = d[idx]
122
except IndexError:
123
- self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d)))
124
+ self.fail(f'invalid index "{idx}" in path "{path}" '
125
+ f'in "{d}"')
126
return d
127
128
def assert_qmp_absent(self, d, path):
129
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
130
'''Asserts that the given filename is a json: filename and that its
131
content is equal to the given reference object'''
132
self.assertEqual(json_filename[:5], 'json:')
133
- self.assertEqual(self.vm.flatten_qmp_object(json.loads(json_filename[5:])),
134
- self.vm.flatten_qmp_object(reference))
135
+ self.assertEqual(
136
+ self.vm.flatten_qmp_object(json.loads(json_filename[5:])),
137
+ self.vm.flatten_qmp_object(reference)
138
+ )
139
140
- def cancel_and_wait(self, drive='drive0', force=False, resume=False, wait=60.0):
141
+ def cancel_and_wait(self, drive='drive0', force=False,
142
+ resume=False, wait=60.0):
143
'''Cancel a block job and wait for it to finish, returning the event'''
144
result = self.vm.qmp('block-job-cancel', device=drive, force=force)
145
self.assert_qmp(result, 'return', {})
146
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
147
self.assert_no_active_block_jobs()
148
return result
149
150
- def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0,
151
- error=None):
152
+ def wait_until_completed(self, drive='drive0', check_offset=True,
153
+ wait=60.0, error=None):
154
'''Wait for a block job to finish, returning the event'''
155
while True:
156
for event in self.vm.get_qmp_events(wait=wait):
157
@@ -XXX,XX +XXX,XX @@ def verify_quorum():
158
notrun('quorum support missing')
159
160
def qemu_pipe(*args):
161
- '''Run qemu with an option to print something and exit (e.g. a help option),
162
- and return its output'''
163
+ """
164
+ Run qemu with an option to print something and exit (e.g. a help option).
165
+
166
+ :return: QEMU's stdout output.
167
+ """
168
args = [qemu_prog] + qemu_opts + list(args)
169
subp = subprocess.Popen(args, stdout=subprocess.PIPE,
170
stderr=subprocess.STDOUT,
171
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=(), read_only=False):
172
173
usf_list = list(set(fmts) - set(supported_formats(read_only)))
174
if usf_list:
175
- test_case.case_skip('{}: formats {} are not whitelisted'.format(
176
- test_case, usf_list))
177
+ msg = f'{test_case}: formats {usf_list} are not whitelisted'
178
+ test_case.case_skip(msg)
179
return None
180
else:
181
return func(test_case, *args, **kwargs)
182
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
183
index XXXXXXX..XXXXXXX 100644
184
--- a/tests/qemu-iotests/pylintrc
185
+++ b/tests/qemu-iotests/pylintrc
186
@@ -XXX,XX +XXX,XX @@ disable=invalid-name,
187
too-many-locals,
188
too-many-public-methods,
189
# These are temporary, and should be removed:
190
- line-too-long,
191
missing-docstring,
192
+
193
+[FORMAT]
194
+
195
+# Maximum number of characters on a single line.
196
+max-line-length=79
197
--
198
2.26.2
199
200
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Minor cleanup for HMP functions; helps with line length and consolidates
4
HMP helpers through one implementation function.
5
6
Although we are adding a universal toggle to turn QMP logging on or off,
7
many existing callers to hmp functions don't expect that output to be
8
logged, which causes quite a few changes in the test output.
9
10
For now, offer a use_log parameter.
11
12
Typing notes:
13
14
QMPResponse is just an alias for Dict[str, Any]. It holds no special
15
meanings and it is not a formal subtype of Dict[str, Any]. It is best
16
thought of as a lexical synonym.
17
18
We may well wish to add stricter subtypes in the future for certain
19
shapes of data that are not formalized as Python objects, at which point
20
we can simply retire the alias and allow mypy to more strictly check
21
usages of the name.
22
23
Signed-off-by: John Snow <jsnow@redhat.com>
24
Message-Id: <20200331000014.11581-11-jsnow@redhat.com>
25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
---
29
tests/qemu-iotests/iotests.py | 39 +++++++++++++++++++++--------------
30
1 file changed, 24 insertions(+), 15 deletions(-)
31
32
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
33
index XXXXXXX..XXXXXXX 100644
34
--- a/tests/qemu-iotests/iotests.py
35
+++ b/tests/qemu-iotests/iotests.py
36
@@ -XXX,XX +XXX,XX @@ from qemu import qtest
37
38
assert sys.version_info >= (3, 6)
39
40
+# Type Aliases
41
+QMPResponse = Dict[str, Any]
42
+
43
+
44
faulthandler.enable()
45
46
# This will not work if arguments contain spaces but is necessary if we
47
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
48
self._args.append(addr)
49
return self
50
51
- def pause_drive(self, drive, event=None):
52
- '''Pause drive r/w operations'''
53
+ def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse:
54
+ cmd = 'human-monitor-command'
55
+ kwargs = {'command-line': command_line}
56
+ if use_log:
57
+ return self.qmp_log(cmd, **kwargs)
58
+ else:
59
+ return self.qmp(cmd, **kwargs)
60
+
61
+ def pause_drive(self, drive: str, event: Optional[str] = None) -> None:
62
+ """Pause drive r/w operations"""
63
if not event:
64
self.pause_drive(drive, "read_aio")
65
self.pause_drive(drive, "write_aio")
66
return
67
- self.qmp('human-monitor-command',
68
- command_line='qemu-io %s "break %s bp_%s"'
69
- % (drive, event, drive))
70
-
71
- def resume_drive(self, drive):
72
- self.qmp('human-monitor-command',
73
- command_line='qemu-io %s "remove_break bp_%s"'
74
- % (drive, drive))
75
-
76
- def hmp_qemu_io(self, drive, cmd):
77
- '''Write to a given drive using an HMP command'''
78
- return self.qmp('human-monitor-command',
79
- command_line='qemu-io %s "%s"' % (drive, cmd))
80
+ self.hmp(f'qemu-io {drive} "break {event} bp_{drive}"')
81
+
82
+ def resume_drive(self, drive: str) -> None:
83
+ """Resume drive r/w operations"""
84
+ self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
85
+
86
+ def hmp_qemu_io(self, drive: str, cmd: str,
87
+ use_log: bool = False) -> QMPResponse:
88
+ """Write to a given drive using an HMP command"""
89
+ return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log)
90
91
def flatten_qmp_object(self, obj, output=None, basestr=''):
92
if output is None:
93
--
94
2.26.2
95
96
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Like script_main, but doesn't require a single point of entry.
4
Replace all existing initialization sections with this drop-in replacement.
5
6
This brings debug support to all existing script-style iotests.
7
8
Signed-off-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20200331000014.11581-12-jsnow@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
[mreitz: Give 274 the same treatment]
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/149 | 3 +-
16
tests/qemu-iotests/194 | 4 +-
17
tests/qemu-iotests/202 | 4 +-
18
tests/qemu-iotests/203 | 4 +-
19
tests/qemu-iotests/206 | 2 +-
20
tests/qemu-iotests/207 | 6 ++-
21
tests/qemu-iotests/208 | 2 +-
22
tests/qemu-iotests/209 | 2 +-
23
tests/qemu-iotests/210 | 6 ++-
24
tests/qemu-iotests/211 | 6 ++-
25
tests/qemu-iotests/212 | 6 ++-
26
tests/qemu-iotests/213 | 6 ++-
27
tests/qemu-iotests/216 | 4 +-
28
tests/qemu-iotests/218 | 2 +-
29
tests/qemu-iotests/219 | 2 +-
30
tests/qemu-iotests/222 | 7 ++--
31
tests/qemu-iotests/224 | 4 +-
32
tests/qemu-iotests/228 | 6 ++-
33
tests/qemu-iotests/234 | 4 +-
34
tests/qemu-iotests/235 | 4 +-
35
tests/qemu-iotests/236 | 2 +-
36
tests/qemu-iotests/237 | 2 +-
37
tests/qemu-iotests/238 | 2 +
38
tests/qemu-iotests/242 | 2 +-
39
tests/qemu-iotests/246 | 2 +-
40
tests/qemu-iotests/248 | 2 +-
41
tests/qemu-iotests/254 | 2 +-
42
tests/qemu-iotests/255 | 2 +-
43
tests/qemu-iotests/256 | 2 +-
44
tests/qemu-iotests/258 | 7 ++--
45
tests/qemu-iotests/260 | 4 +-
46
tests/qemu-iotests/262 | 4 +-
47
tests/qemu-iotests/264 | 4 +-
48
tests/qemu-iotests/274 | 4 +-
49
tests/qemu-iotests/277 | 2 +
50
tests/qemu-iotests/280 | 8 ++--
51
tests/qemu-iotests/283 | 4 +-
52
tests/qemu-iotests/iotests.py | 76 +++++++++++++++++++++++------------
53
38 files changed, 132 insertions(+), 83 deletions(-)
54
55
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
56
index XXXXXXX..XXXXXXX 100755
57
--- a/tests/qemu-iotests/149
58
+++ b/tests/qemu-iotests/149
59
@@ -XXX,XX +XXX,XX @@ def test_once(config, qemu_img=False):
60
61
62
# Obviously we only work with the luks image format
63
-iotests.verify_image_format(supported_fmts=['luks'])
64
-iotests.verify_platform()
65
+iotests.script_initialize(supported_fmts=['luks'])
66
67
# We need sudo in order to run cryptsetup to create
68
# dm-crypt devices. This is safe to use on any
69
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
70
index XXXXXXX..XXXXXXX 100755
71
--- a/tests/qemu-iotests/194
72
+++ b/tests/qemu-iotests/194
73
@@ -XXX,XX +XXX,XX @@
74
75
import iotests
76
77
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw'])
78
-iotests.verify_platform(['linux'])
79
+iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'],
80
+ supported_platforms=['linux'])
81
82
with iotests.FilePath('source.img') as source_img_path, \
83
iotests.FilePath('dest.img') as dest_img_path, \
84
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
85
index XXXXXXX..XXXXXXX 100755
86
--- a/tests/qemu-iotests/202
87
+++ b/tests/qemu-iotests/202
88
@@ -XXX,XX +XXX,XX @@
89
90
import iotests
91
92
-iotests.verify_image_format(supported_fmts=['qcow2'])
93
-iotests.verify_platform(['linux'])
94
+iotests.script_initialize(supported_fmts=['qcow2'],
95
+ supported_platforms=['linux'])
96
97
with iotests.FilePath('disk0.img') as disk0_img_path, \
98
iotests.FilePath('disk1.img') as disk1_img_path, \
99
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
100
index XXXXXXX..XXXXXXX 100755
101
--- a/tests/qemu-iotests/203
102
+++ b/tests/qemu-iotests/203
103
@@ -XXX,XX +XXX,XX @@
104
105
import iotests
106
107
-iotests.verify_image_format(supported_fmts=['qcow2'])
108
-iotests.verify_platform(['linux'])
109
+iotests.script_initialize(supported_fmts=['qcow2'],
110
+ supported_platforms=['linux'])
111
112
with iotests.FilePath('disk0.img') as disk0_img_path, \
113
iotests.FilePath('disk1.img') as disk1_img_path, \
114
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/206
117
+++ b/tests/qemu-iotests/206
118
@@ -XXX,XX +XXX,XX @@
119
import iotests
120
from iotests import imgfmt
121
122
-iotests.verify_image_format(supported_fmts=['qcow2'])
123
+iotests.script_initialize(supported_fmts=['qcow2'])
124
125
with iotests.FilePath('t.qcow2') as disk_path, \
126
iotests.FilePath('t.qcow2.base') as backing_path, \
127
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
128
index XXXXXXX..XXXXXXX 100755
129
--- a/tests/qemu-iotests/207
130
+++ b/tests/qemu-iotests/207
131
@@ -XXX,XX +XXX,XX @@ import iotests
132
import subprocess
133
import re
134
135
-iotests.verify_image_format(supported_fmts=['raw'])
136
-iotests.verify_protocol(supported=['ssh'])
137
+iotests.script_initialize(
138
+ supported_fmts=['raw'],
139
+ supported_protocols=['ssh'],
140
+)
141
142
def filter_hash(qmsg):
143
def _filter(key, value):
144
diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208
145
index XXXXXXX..XXXXXXX 100755
146
--- a/tests/qemu-iotests/208
147
+++ b/tests/qemu-iotests/208
148
@@ -XXX,XX +XXX,XX @@
149
150
import iotests
151
152
-iotests.verify_image_format(supported_fmts=['generic'])
153
+iotests.script_initialize(supported_fmts=['generic'])
154
155
with iotests.FilePath('disk.img') as disk_img_path, \
156
iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \
157
diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209
158
index XXXXXXX..XXXXXXX 100755
159
--- a/tests/qemu-iotests/209
160
+++ b/tests/qemu-iotests/209
161
@@ -XXX,XX +XXX,XX @@ import iotests
162
from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \
163
file_path
164
165
-iotests.verify_image_format(supported_fmts=['qcow2'])
166
+iotests.script_initialize(supported_fmts=['qcow2'])
167
168
disk = file_path('disk')
169
nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
170
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
171
index XXXXXXX..XXXXXXX 100755
172
--- a/tests/qemu-iotests/210
173
+++ b/tests/qemu-iotests/210
174
@@ -XXX,XX +XXX,XX @@
175
import iotests
176
from iotests import imgfmt
177
178
-iotests.verify_image_format(supported_fmts=['luks'])
179
-iotests.verify_protocol(supported=['file'])
180
+iotests.script_initialize(
181
+ supported_fmts=['luks'],
182
+ supported_protocols=['file'],
183
+)
184
185
with iotests.FilePath('t.luks') as disk_path, \
186
iotests.VM() as vm:
187
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
188
index XXXXXXX..XXXXXXX 100755
189
--- a/tests/qemu-iotests/211
190
+++ b/tests/qemu-iotests/211
191
@@ -XXX,XX +XXX,XX @@
192
import iotests
193
from iotests import imgfmt
194
195
-iotests.verify_image_format(supported_fmts=['vdi'])
196
-iotests.verify_protocol(supported=['file'])
197
+iotests.script_initialize(
198
+ supported_fmts=['vdi'],
199
+ supported_protocols=['file'],
200
+)
201
202
def blockdev_create(vm, options):
203
error = vm.blockdev_create(options)
204
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
205
index XXXXXXX..XXXXXXX 100755
206
--- a/tests/qemu-iotests/212
207
+++ b/tests/qemu-iotests/212
208
@@ -XXX,XX +XXX,XX @@
209
import iotests
210
from iotests import imgfmt
211
212
-iotests.verify_image_format(supported_fmts=['parallels'])
213
-iotests.verify_protocol(supported=['file'])
214
+iotests.script_initialize(
215
+ supported_fmts=['parallels'],
216
+ supported_protocols=['file'],
217
+)
218
219
with iotests.FilePath('t.parallels') as disk_path, \
220
iotests.VM() as vm:
221
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
222
index XXXXXXX..XXXXXXX 100755
223
--- a/tests/qemu-iotests/213
224
+++ b/tests/qemu-iotests/213
225
@@ -XXX,XX +XXX,XX @@
226
import iotests
227
from iotests import imgfmt
228
229
-iotests.verify_image_format(supported_fmts=['vhdx'])
230
-iotests.verify_protocol(supported=['file'])
231
+iotests.script_initialize(
232
+ supported_fmts=['vhdx'],
233
+ supported_protocols=['file'],
234
+)
235
236
with iotests.FilePath('t.vhdx') as disk_path, \
237
iotests.VM() as vm:
238
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
239
index XXXXXXX..XXXXXXX 100755
240
--- a/tests/qemu-iotests/216
241
+++ b/tests/qemu-iotests/216
242
@@ -XXX,XX +XXX,XX @@ import iotests
243
from iotests import log, qemu_img, qemu_io_silent
244
245
# Need backing file support
246
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
247
-iotests.verify_platform(['linux'])
248
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
249
+ supported_platforms=['linux'])
250
251
log('')
252
log('=== Copy-on-read across nodes ===')
253
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
254
index XXXXXXX..XXXXXXX 100755
255
--- a/tests/qemu-iotests/218
256
+++ b/tests/qemu-iotests/218
257
@@ -XXX,XX +XXX,XX @@
258
import iotests
259
from iotests import log, qemu_img, qemu_io_silent
260
261
-iotests.verify_image_format(supported_fmts=['qcow2', 'raw'])
262
+iotests.script_initialize(supported_fmts=['qcow2', 'raw'])
263
264
265
# Launches the VM, adds two null-co nodes (source and target), and
266
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
267
index XXXXXXX..XXXXXXX 100755
268
--- a/tests/qemu-iotests/219
269
+++ b/tests/qemu-iotests/219
270
@@ -XXX,XX +XXX,XX @@
271
272
import iotests
273
274
-iotests.verify_image_format(supported_fmts=['qcow2'])
275
+iotests.script_initialize(supported_fmts=['qcow2'])
276
277
img_size = 4 * 1024 * 1024
278
279
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
280
index XXXXXXX..XXXXXXX 100755
281
--- a/tests/qemu-iotests/222
282
+++ b/tests/qemu-iotests/222
283
@@ -XXX,XX +XXX,XX @@
284
import iotests
285
from iotests import log, qemu_img, qemu_io, qemu_io_silent
286
287
-iotests.verify_platform(['linux'])
288
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk',
289
- 'vhdx', 'raw'])
290
+iotests.script_initialize(
291
+ supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
292
+ supported_platforms=['linux'],
293
+)
294
295
patterns = [("0x5d", "0", "64k"),
296
("0xd5", "1M", "64k"),
297
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
298
index XXXXXXX..XXXXXXX 100755
299
--- a/tests/qemu-iotests/224
300
+++ b/tests/qemu-iotests/224
301
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
302
import json
303
304
# Need backing file support (for arbitrary backing formats)
305
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
306
-iotests.verify_platform(['linux'])
307
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed'],
308
+ supported_platforms=['linux'])
309
310
311
# There are two variations of this test:
312
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
313
index XXXXXXX..XXXXXXX 100755
314
--- a/tests/qemu-iotests/228
315
+++ b/tests/qemu-iotests/228
316
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
317
filter_qmp_testfiles, filter_qmp_imgfmt
318
319
# Need backing file and change-backing-file support
320
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
321
-iotests.verify_platform(['linux'])
322
+iotests.script_initialize(
323
+ supported_fmts=['qcow2', 'qed'],
324
+ supported_platforms=['linux'],
325
+)
326
327
328
def log_node_info(node):
329
diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234
330
index XXXXXXX..XXXXXXX 100755
331
--- a/tests/qemu-iotests/234
332
+++ b/tests/qemu-iotests/234
333
@@ -XXX,XX +XXX,XX @@
334
import iotests
335
import os
336
337
-iotests.verify_image_format(supported_fmts=['qcow2'])
338
-iotests.verify_platform(['linux'])
339
+iotests.script_initialize(supported_fmts=['qcow2'],
340
+ supported_platforms=['linux'])
341
342
with iotests.FilePath('img') as img_path, \
343
iotests.FilePath('backing') as backing_path, \
344
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
345
index XXXXXXX..XXXXXXX 100755
346
--- a/tests/qemu-iotests/235
347
+++ b/tests/qemu-iotests/235
348
@@ -XXX,XX +XXX,XX @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
349
350
from qemu.machine import QEMUMachine
351
352
+iotests.script_initialize(supported_fmts=['qcow2'])
353
+
354
# Note:
355
# This test was added to check that mirror dead-lock was fixed (see previous
356
# commit before this test addition).
357
@@ -XXX,XX +XXX,XX @@ from qemu.machine import QEMUMachine
358
359
size = 1 * 1024 * 1024 * 1024
360
361
-iotests.verify_image_format(supported_fmts=['qcow2'])
362
-
363
disk = file_path('disk')
364
365
# prepare source image
366
diff --git a/tests/qemu-iotests/236 b/tests/qemu-iotests/236
367
index XXXXXXX..XXXXXXX 100755
368
--- a/tests/qemu-iotests/236
369
+++ b/tests/qemu-iotests/236
370
@@ -XXX,XX +XXX,XX @@
371
import iotests
372
from iotests import log
373
374
-iotests.verify_image_format(supported_fmts=['generic'])
375
+iotests.script_initialize(supported_fmts=['generic'])
376
size = 64 * 1024 * 1024
377
granularity = 64 * 1024
378
379
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
380
index XXXXXXX..XXXXXXX 100755
381
--- a/tests/qemu-iotests/237
382
+++ b/tests/qemu-iotests/237
383
@@ -XXX,XX +XXX,XX @@ import math
384
import iotests
385
from iotests import imgfmt
386
387
-iotests.verify_image_format(supported_fmts=['vmdk'])
388
+iotests.script_initialize(supported_fmts=['vmdk'])
389
390
with iotests.FilePath('t.vmdk') as disk_path, \
391
iotests.FilePath('t.vmdk.1') as extent1_path, \
392
diff --git a/tests/qemu-iotests/238 b/tests/qemu-iotests/238
393
index XXXXXXX..XXXXXXX 100755
394
--- a/tests/qemu-iotests/238
395
+++ b/tests/qemu-iotests/238
396
@@ -XXX,XX +XXX,XX @@ import os
397
import iotests
398
from iotests import log
399
400
+iotests.script_initialize()
401
+
402
virtio_scsi_device = iotests.get_virtio_scsi_device()
403
404
vm = iotests.VM()
405
diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242
406
index XXXXXXX..XXXXXXX 100755
407
--- a/tests/qemu-iotests/242
408
+++ b/tests/qemu-iotests/242
409
@@ -XXX,XX +XXX,XX @@ import struct
410
from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \
411
file_path, img_info_log, log, filter_qemu_io
412
413
-iotests.verify_image_format(supported_fmts=['qcow2'])
414
+iotests.script_initialize(supported_fmts=['qcow2'])
415
416
disk = file_path('disk')
417
chunk = 256 * 1024
418
diff --git a/tests/qemu-iotests/246 b/tests/qemu-iotests/246
419
index XXXXXXX..XXXXXXX 100755
420
--- a/tests/qemu-iotests/246
421
+++ b/tests/qemu-iotests/246
422
@@ -XXX,XX +XXX,XX @@
423
import iotests
424
from iotests import log
425
426
-iotests.verify_image_format(supported_fmts=['qcow2'])
427
+iotests.script_initialize(supported_fmts=['qcow2'])
428
size = 64 * 1024 * 1024 * 1024
429
gran_small = 32 * 1024
430
gran_large = 128 * 1024
431
diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248
432
index XXXXXXX..XXXXXXX 100755
433
--- a/tests/qemu-iotests/248
434
+++ b/tests/qemu-iotests/248
435
@@ -XXX,XX +XXX,XX @@
436
import iotests
437
from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles
438
439
-iotests.verify_image_format(supported_fmts=['qcow2'])
440
+iotests.script_initialize(supported_fmts=['qcow2'])
441
442
source, target = file_path('source', 'target')
443
size = 5 * 1024 * 1024
444
diff --git a/tests/qemu-iotests/254 b/tests/qemu-iotests/254
445
index XXXXXXX..XXXXXXX 100755
446
--- a/tests/qemu-iotests/254
447
+++ b/tests/qemu-iotests/254
448
@@ -XXX,XX +XXX,XX @@
449
import iotests
450
from iotests import qemu_img_create, file_path, log
451
452
-iotests.verify_image_format(supported_fmts=['qcow2'])
453
+iotests.script_initialize(supported_fmts=['qcow2'])
454
455
disk, top = file_path('disk', 'top')
456
size = 1024 * 1024
457
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
458
index XXXXXXX..XXXXXXX 100755
459
--- a/tests/qemu-iotests/255
460
+++ b/tests/qemu-iotests/255
461
@@ -XXX,XX +XXX,XX @@
462
import iotests
463
from iotests import imgfmt
464
465
-iotests.verify_image_format(supported_fmts=['qcow2'])
466
+iotests.script_initialize(supported_fmts=['qcow2'])
467
468
iotests.log('Finishing a commit job with background reads')
469
iotests.log('============================================')
470
diff --git a/tests/qemu-iotests/256 b/tests/qemu-iotests/256
471
index XXXXXXX..XXXXXXX 100755
472
--- a/tests/qemu-iotests/256
473
+++ b/tests/qemu-iotests/256
474
@@ -XXX,XX +XXX,XX @@ import os
475
import iotests
476
from iotests import log
477
478
-iotests.verify_image_format(supported_fmts=['qcow2'])
479
+iotests.script_initialize(supported_fmts=['qcow2'])
480
size = 64 * 1024 * 1024
481
482
with iotests.FilePath('img0') as img0_path, \
483
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
484
index XXXXXXX..XXXXXXX 100755
485
--- a/tests/qemu-iotests/258
486
+++ b/tests/qemu-iotests/258
487
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io_silent, \
488
filter_qmp_testfiles, filter_qmp_imgfmt
489
490
# Need backing file and change-backing-file support
491
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
492
-iotests.verify_platform(['linux'])
493
-
494
+iotests.script_initialize(
495
+ supported_fmts=['qcow2', 'qed'],
496
+ supported_platforms=['linux'],
497
+)
498
499
# Returns a node for blockdev-add
500
def node(node_name, path, backing=None, fmt=None, throttle=None):
501
diff --git a/tests/qemu-iotests/260 b/tests/qemu-iotests/260
502
index XXXXXXX..XXXXXXX 100755
503
--- a/tests/qemu-iotests/260
504
+++ b/tests/qemu-iotests/260
505
@@ -XXX,XX +XXX,XX @@
506
import iotests
507
from iotests import qemu_img_create, file_path, log, filter_qmp_event
508
509
-iotests.verify_image_format(supported_fmts=['qcow2'])
510
+iotests.script_initialize(
511
+ supported_fmts=['qcow2']
512
+)
513
514
base, top = file_path('base', 'top')
515
size = 64 * 1024 * 3
516
diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262
517
index XXXXXXX..XXXXXXX 100755
518
--- a/tests/qemu-iotests/262
519
+++ b/tests/qemu-iotests/262
520
@@ -XXX,XX +XXX,XX @@
521
import iotests
522
import os
523
524
-iotests.verify_image_format(supported_fmts=['qcow2'])
525
-iotests.verify_platform(['linux'])
526
+iotests.script_initialize(supported_fmts=['qcow2'],
527
+ supported_platforms=['linux'])
528
529
with iotests.FilePath('img') as img_path, \
530
iotests.FilePath('mig_fifo') as fifo, \
531
diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264
532
index XXXXXXX..XXXXXXX 100755
533
--- a/tests/qemu-iotests/264
534
+++ b/tests/qemu-iotests/264
535
@@ -XXX,XX +XXX,XX @@ import iotests
536
from iotests import qemu_img_create, qemu_io_silent_check, file_path, \
537
qemu_nbd_popen, log
538
539
-iotests.verify_image_format(supported_fmts=['qcow2'])
540
+iotests.script_initialize(
541
+ supported_fmts=['qcow2'],
542
+)
543
544
disk_a, disk_b, nbd_sock = file_path('disk_a', 'disk_b', 'nbd-sock')
545
nbd_uri = 'nbd+unix:///?socket=' + nbd_sock
546
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
547
index XXXXXXX..XXXXXXX 100755
548
--- a/tests/qemu-iotests/274
549
+++ b/tests/qemu-iotests/274
550
@@ -XXX,XX +XXX,XX @@
551
552
import iotests
553
554
-iotests.verify_image_format(supported_fmts=['qcow2'])
555
-iotests.verify_platform(['linux'])
556
+iotests.script_initialize(supported_fmts=['qcow2'],
557
+ supported_platforms=['linux'])
558
559
size_short = 1 * 1024 * 1024
560
size_long = 2 * 1024 * 1024
561
diff --git a/tests/qemu-iotests/277 b/tests/qemu-iotests/277
562
index XXXXXXX..XXXXXXX 100755
563
--- a/tests/qemu-iotests/277
564
+++ b/tests/qemu-iotests/277
565
@@ -XXX,XX +XXX,XX @@ import subprocess
566
import iotests
567
from iotests import file_path, log
568
569
+iotests.script_initialize()
570
+
571
572
nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf')
573
574
diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280
575
index XXXXXXX..XXXXXXX 100755
576
--- a/tests/qemu-iotests/280
577
+++ b/tests/qemu-iotests/280
578
@@ -XXX,XX +XXX,XX @@
579
import iotests
580
import os
581
582
-iotests.verify_image_format(supported_fmts=['qcow2'])
583
-iotests.verify_protocol(supported=['file'])
584
-iotests.verify_platform(['linux'])
585
+iotests.script_initialize(
586
+ supported_fmts=['qcow2'],
587
+ supported_protocols=['file'],
588
+ supported_platforms=['linux'],
589
+)
590
591
with iotests.FilePath('base') as base_path , \
592
iotests.FilePath('top') as top_path, \
593
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
594
index XXXXXXX..XXXXXXX 100644
595
--- a/tests/qemu-iotests/283
596
+++ b/tests/qemu-iotests/283
597
@@ -XXX,XX +XXX,XX @@
598
import iotests
599
600
# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
601
-iotests.verify_image_format(supported_fmts=['qcow2'])
602
+iotests.script_initialize(
603
+ supported_fmts=['qcow2'],
604
+)
605
606
size = 1024 * 1024
607
608
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
609
index XXXXXXX..XXXXXXX 100644
610
--- a/tests/qemu-iotests/iotests.py
611
+++ b/tests/qemu-iotests/iotests.py
612
@@ -XXX,XX +XXX,XX @@ import signal
613
import struct
614
import subprocess
615
import sys
616
-from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
617
+from typing import (Any, Callable, Dict, Iterable,
618
+ List, Optional, Sequence, TypeVar)
619
import unittest
620
621
# pylint: disable=import-error, wrong-import-position
622
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
623
if not_sup or (imgproto in unsupported):
624
notrun('not suitable for this protocol: %s' % imgproto)
625
626
-def verify_platform(supported=None, unsupported=None):
627
- if unsupported is not None:
628
- if any((sys.platform.startswith(x) for x in unsupported)):
629
- notrun('not suitable for this OS: %s' % sys.platform)
630
+def verify_platform(supported=(), unsupported=()):
631
+ if any((sys.platform.startswith(x) for x in unsupported)):
632
+ notrun('not suitable for this OS: %s' % sys.platform)
633
634
- if supported is not None:
635
+ if supported:
636
if not any((sys.platform.startswith(x) for x in supported)):
637
notrun('not suitable for this OS: %s' % sys.platform)
638
639
@@ -XXX,XX +XXX,XX @@ def skip_if_user_is_root(func):
640
return func(*args, **kwargs)
641
return func_wrapper
642
643
-def execute_unittest(output, verbosity, debug):
644
+def execute_unittest(debug=False):
645
+ """Executes unittests within the calling module."""
646
+
647
+ verbosity = 2 if debug else 1
648
+
649
+ if debug:
650
+ output = sys.stdout
651
+ else:
652
+ # We need to filter out the time taken from the output so that
653
+ # qemu-iotest can reliably diff the results against master output.
654
+ output = io.StringIO()
655
+
656
runner = unittest.TextTestRunner(stream=output, descriptions=True,
657
verbosity=verbosity)
658
try:
659
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
660
# exception
661
unittest.main(testRunner=runner)
662
finally:
663
+ # We need to filter out the time taken from the output so that
664
+ # qemu-iotest can reliably diff the results against master output.
665
if not debug:
666
out = output.getvalue()
667
out = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', out)
668
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
669
670
sys.stderr.write(out)
671
672
-def execute_test(test_function=None,
673
- supported_fmts=(),
674
- supported_platforms=None,
675
- supported_cache_modes=(), supported_aio_modes=(),
676
- unsupported_fmts=(), supported_protocols=(),
677
- unsupported_protocols=()):
678
- """Run either unittest or script-style tests."""
679
+def execute_setup_common(supported_fmts: Sequence[str] = (),
680
+ supported_platforms: Sequence[str] = (),
681
+ supported_cache_modes: Sequence[str] = (),
682
+ supported_aio_modes: Sequence[str] = (),
683
+ unsupported_fmts: Sequence[str] = (),
684
+ supported_protocols: Sequence[str] = (),
685
+ unsupported_protocols: Sequence[str] = ()) -> bool:
686
+ """
687
+ Perform necessary setup for either script-style or unittest-style tests.
688
+
689
+ :return: Bool; Whether or not debug mode has been requested via the CLI.
690
+ """
691
+ # Note: Python 3.6 and pylint do not like 'Collection' so use 'Sequence'.
692
693
# We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
694
# indicate that we're not being run via "check". There may be
695
@@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None,
696
sys.stderr.write('Please run this test via the "check" script\n')
697
sys.exit(os.EX_USAGE)
698
699
- debug = '-d' in sys.argv
700
- verbosity = 1
701
verify_image_format(supported_fmts, unsupported_fmts)
702
verify_protocol(supported_protocols, unsupported_protocols)
703
verify_platform(supported=supported_platforms)
704
verify_cache_mode(supported_cache_modes)
705
verify_aio_mode(supported_aio_modes)
706
707
+ debug = '-d' in sys.argv
708
if debug:
709
- output = sys.stdout
710
- verbosity = 2
711
sys.argv.remove('-d')
712
- else:
713
- # We need to filter out the time taken from the output so that
714
- # qemu-iotest can reliably diff the results against master output.
715
- output = io.StringIO()
716
-
717
logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
718
719
+ return debug
720
+
721
+def execute_test(*args, test_function=None, **kwargs):
722
+ """Run either unittest or script-style tests."""
723
+
724
+ debug = execute_setup_common(*args, **kwargs)
725
if not test_function:
726
- execute_unittest(output, verbosity, debug)
727
+ execute_unittest(debug)
728
else:
729
test_function()
730
731
+# This is called from script-style iotests without a single point of entry
732
+def script_initialize(*args, **kwargs):
733
+ """Initialize script-style tests without running any tests."""
734
+ execute_setup_common(*args, **kwargs)
735
+
736
+# This is called from script-style iotests with a single point of entry
737
def script_main(test_function, *args, **kwargs):
738
"""Run script-style tests outside of the unittest framework"""
739
- execute_test(test_function, *args, **kwargs)
740
+ execute_test(*args, test_function=test_function, **kwargs)
741
742
+# This is called from unittest style iotests
743
def main(*args, **kwargs):
744
"""Run tests using the unittest framework"""
745
- execute_test(None, *args, **kwargs)
746
+ execute_test(*args, **kwargs)
747
--
748
2.26.2
749
750
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Since this one is nicely factored to use a single entry point,
4
use script_main to run the tests.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200331000014.11581-13-jsnow@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/258 | 11 ++++-------
14
1 file changed, 4 insertions(+), 7 deletions(-)
15
16
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/258
19
+++ b/tests/qemu-iotests/258
20
@@ -XXX,XX +XXX,XX @@ import iotests
21
from iotests import log, qemu_img, qemu_io_silent, \
22
filter_qmp_testfiles, filter_qmp_imgfmt
23
24
-# Need backing file and change-backing-file support
25
-iotests.script_initialize(
26
- supported_fmts=['qcow2', 'qed'],
27
- supported_platforms=['linux'],
28
-)
29
-
30
# Returns a node for blockdev-add
31
def node(node_name, path, backing=None, fmt=None, throttle=None):
32
if fmt is None:
33
@@ -XXX,XX +XXX,XX @@ def main():
34
test_concurrent_finish(False)
35
36
if __name__ == '__main__':
37
- main()
38
+ # Need backing file and change-backing-file support
39
+ iotests.script_main(main,
40
+ supported_fmts=['qcow2', 'qed'],
41
+ supported_platforms=['linux'])
42
--
43
2.26.2
44
45
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Mark the verify functions as "private" with a leading underscore, to
4
discourage their use. Update type signatures while we're here.
5
6
(Also, make pending patches not yet using the new entry points fail in a
7
very obvious way.)
8
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20200331000014.11581-14-jsnow@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/iotests.py | 23 +++++++++++++----------
16
1 file changed, 13 insertions(+), 10 deletions(-)
17
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/iotests.py
21
+++ b/tests/qemu-iotests/iotests.py
22
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
23
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
24
' [case not run] ' + reason + '\n')
25
26
-def verify_image_format(supported_fmts=(), unsupported_fmts=()):
27
+def _verify_image_format(supported_fmts: Sequence[str] = (),
28
+ unsupported_fmts: Sequence[str] = ()) -> None:
29
assert not (supported_fmts and unsupported_fmts)
30
31
if 'generic' in supported_fmts and \
32
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=(), unsupported_fmts=()):
33
if not_sup or (imgfmt in unsupported_fmts):
34
notrun('not suitable for this image format: %s' % imgfmt)
35
36
-def verify_protocol(supported=(), unsupported=()):
37
+def _verify_protocol(supported: Sequence[str] = (),
38
+ unsupported: Sequence[str] = ()) -> None:
39
assert not (supported and unsupported)
40
41
if 'generic' in supported:
42
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
43
if not_sup or (imgproto in unsupported):
44
notrun('not suitable for this protocol: %s' % imgproto)
45
46
-def verify_platform(supported=(), unsupported=()):
47
+def _verify_platform(supported: Sequence[str] = (),
48
+ unsupported: Sequence[str] = ()) -> None:
49
if any((sys.platform.startswith(x) for x in unsupported)):
50
notrun('not suitable for this OS: %s' % sys.platform)
51
52
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=(), unsupported=()):
53
if not any((sys.platform.startswith(x) for x in supported)):
54
notrun('not suitable for this OS: %s' % sys.platform)
55
56
-def verify_cache_mode(supported_cache_modes=()):
57
+def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
58
if supported_cache_modes and (cachemode not in supported_cache_modes):
59
notrun('not suitable for this cache mode: %s' % cachemode)
60
61
-def verify_aio_mode(supported_aio_modes=()):
62
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
63
if supported_aio_modes and (aiomode not in supported_aio_modes):
64
notrun('not suitable for this aio mode: %s' % aiomode)
65
66
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
67
sys.stderr.write('Please run this test via the "check" script\n')
68
sys.exit(os.EX_USAGE)
69
70
- verify_image_format(supported_fmts, unsupported_fmts)
71
- verify_protocol(supported_protocols, unsupported_protocols)
72
- verify_platform(supported=supported_platforms)
73
- verify_cache_mode(supported_cache_modes)
74
- verify_aio_mode(supported_aio_modes)
75
+ _verify_image_format(supported_fmts, unsupported_fmts)
76
+ _verify_protocol(supported_protocols, unsupported_protocols)
77
+ _verify_platform(supported=supported_platforms)
78
+ _verify_cache_mode(supported_cache_modes)
79
+ _verify_aio_mode(supported_aio_modes)
80
81
debug = '-d' in sys.argv
82
if debug:
83
--
84
2.26.2
85
86
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
We can turn logging on/off globally instead of per-function.
4
5
Remove use_log from run_job, and use python logging to turn on
6
diffable output when we run through a script entry point.
7
8
iotest 245 changes output order due to buffering reasons.
9
10
An extended note on python logging:
11
12
A NullHandler is added to `qemu.iotests` to stop output from being
13
generated if this code is used as a library without configuring logging.
14
A NullHandler is only needed at the root, so a duplicate handler is not
15
needed for `qemu.iotests.diff_io`.
16
17
When logging is not configured, messages at the 'WARNING' levels or
18
above are printed with default settings. The NullHandler stops this from
19
occurring, which is considered good hygiene for code used as a library.
20
21
See https://docs.python.org/3/howto/logging.html#library-config
22
23
When logging is actually enabled (always at the behest of an explicit
24
call by a client script), a root logger is implicitly created at the
25
root, which allows messages to propagate upwards and be handled/emitted
26
from the root logger with default settings.
27
28
When we want iotest logging, we attach a handler to the
29
qemu.iotests.diff_io logger and disable propagation to avoid possible
30
double-printing.
31
32
For more information on python logging infrastructure, I highly
33
recommend downloading the pip package `logging_tree`, which provides
34
convenient visualizations of the hierarchical logging configuration
35
under different circumstances.
36
37
See https://pypi.org/project/logging_tree/ for more information.
38
39
Signed-off-by: John Snow <jsnow@redhat.com>
40
Reviewed-by: Max Reitz <mreitz@redhat.com>
41
Message-Id: <20200331000014.11581-15-jsnow@redhat.com>
42
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
43
Signed-off-by: Max Reitz <mreitz@redhat.com>
44
---
45
tests/qemu-iotests/030 | 4 +--
46
tests/qemu-iotests/155 | 2 +-
47
tests/qemu-iotests/245 | 1 +
48
tests/qemu-iotests/245.out | 10 +++----
49
tests/qemu-iotests/iotests.py | 53 ++++++++++++++++++++---------------
50
5 files changed, 39 insertions(+), 31 deletions(-)
51
52
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
53
index XXXXXXX..XXXXXXX 100755
54
--- a/tests/qemu-iotests/030
55
+++ b/tests/qemu-iotests/030
56
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
57
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
58
self.assert_qmp(result, 'return', {})
59
60
- self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False)
61
- self.vm.run_job(job='node4', auto_dismiss=True, use_log=False)
62
+ self.vm.run_job(job='drive0', auto_dismiss=True)
63
+ self.vm.run_job(job='node4', auto_dismiss=True)
64
self.assert_no_active_block_jobs()
65
66
# Test a block-stream and a block-commit job in parallel
67
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
68
index XXXXXXX..XXXXXXX 100755
69
--- a/tests/qemu-iotests/155
70
+++ b/tests/qemu-iotests/155
71
@@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass):
72
73
self.assert_qmp(result, 'return', {})
74
75
- self.vm.run_job('mirror-job', use_log=False, auto_finalize=False,
76
+ self.vm.run_job('mirror-job', auto_finalize=False,
77
pre_finalize=self.openBacking, auto_dismiss=True)
78
79
def testFull(self):
80
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
81
index XXXXXXX..XXXXXXX 100755
82
--- a/tests/qemu-iotests/245
83
+++ b/tests/qemu-iotests/245
84
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
85
self.run_test_iothreads(None, 'iothread0')
86
87
if __name__ == '__main__':
88
+ iotests.activate_logging()
89
iotests.main(supported_fmts=["qcow2"],
90
supported_protocols=["file"])
91
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
92
index XXXXXXX..XXXXXXX 100644
93
--- a/tests/qemu-iotests/245.out
94
+++ b/tests/qemu-iotests/245.out
95
@@ -XXX,XX +XXX,XX @@
96
-.....................
97
-----------------------------------------------------------------------
98
-Ran 21 tests
99
-
100
-OK
101
{"execute": "job-finalize", "arguments": {"id": "commit0"}}
102
{"return": {}}
103
{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
104
@@ -XXX,XX +XXX,XX @@ OK
105
{"return": {}}
106
{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
107
{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
108
+.....................
109
+----------------------------------------------------------------------
110
+Ran 21 tests
111
+
112
+OK
113
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
114
index XXXXXXX..XXXXXXX 100644
115
--- a/tests/qemu-iotests/iotests.py
116
+++ b/tests/qemu-iotests/iotests.py
117
@@ -XXX,XX +XXX,XX @@ assert sys.version_info >= (3, 6)
118
QMPResponse = Dict[str, Any]
119
120
121
+# Use this logger for logging messages directly from the iotests module
122
+logger = logging.getLogger('qemu.iotests')
123
+logger.addHandler(logging.NullHandler())
124
+
125
+# Use this logger for messages that ought to be used for diff output.
126
+test_logger = logging.getLogger('qemu.iotests.diff_io')
127
+
128
+
129
faulthandler.enable()
130
131
# This will not work if arguments contain spaces but is necessary if we
132
@@ -XXX,XX +XXX,XX @@ def log(msg: Msg,
133
if isinstance(msg, (dict, list)):
134
# Don't sort if it's already sorted
135
do_sort = not isinstance(msg, OrderedDict)
136
- print(json.dumps(msg, sort_keys=do_sort, indent=indent))
137
+ test_logger.info(json.dumps(msg, sort_keys=do_sort, indent=indent))
138
else:
139
- print(msg)
140
+ test_logger.info(msg)
141
142
class Timeout:
143
def __init__(self, seconds, errmsg="Timeout"):
144
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
145
146
# Returns None on success, and an error string on failure
147
def run_job(self, job, auto_finalize=True, auto_dismiss=False,
148
- pre_finalize=None, cancel=False, use_log=True, wait=60.0):
149
+ pre_finalize=None, cancel=False, wait=60.0):
150
"""
151
run_job moves a job from creation through to dismissal.
152
153
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
154
invoked prior to issuing job-finalize, if any.
155
:param cancel: Bool. When true, cancels the job after the pre_finalize
156
callback.
157
- :param use_log: Bool. When false, does not log QMP messages.
158
:param wait: Float. Timeout value specifying how long to wait for any
159
event, in seconds. Defaults to 60.0.
160
"""
161
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
162
while True:
163
ev = filter_qmp_event(self.events_wait(events, timeout=wait))
164
if ev['event'] != 'JOB_STATUS_CHANGE':
165
- if use_log:
166
- log(ev)
167
+ log(ev)
168
continue
169
status = ev['data']['status']
170
if status == 'aborting':
171
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
172
for j in result['return']:
173
if j['id'] == job:
174
error = j['error']
175
- if use_log:
176
- log('Job failed: %s' % (j['error']))
177
+ log('Job failed: %s' % (j['error']))
178
elif status == 'ready':
179
- if use_log:
180
- self.qmp_log('job-complete', id=job)
181
- else:
182
- self.qmp('job-complete', id=job)
183
+ self.qmp_log('job-complete', id=job)
184
elif status == 'pending' and not auto_finalize:
185
if pre_finalize:
186
pre_finalize()
187
- if cancel and use_log:
188
+ if cancel:
189
self.qmp_log('job-cancel', id=job)
190
- elif cancel:
191
- self.qmp('job-cancel', id=job)
192
- elif use_log:
193
- self.qmp_log('job-finalize', id=job)
194
else:
195
- self.qmp('job-finalize', id=job)
196
+ self.qmp_log('job-finalize', id=job)
197
elif status == 'concluded' and not auto_dismiss:
198
- if use_log:
199
- self.qmp_log('job-dismiss', id=job)
200
- else:
201
- self.qmp('job-dismiss', id=job)
202
+ self.qmp_log('job-dismiss', id=job)
203
elif status == 'null':
204
return error
205
206
@@ -XXX,XX +XXX,XX @@ def notrun(reason):
207
seq = os.path.basename(sys.argv[0])
208
209
open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
210
- print('%s not run: %s' % (seq, reason))
211
+ logger.warning("%s not run: %s", seq, reason)
212
sys.exit(0)
213
214
def case_notrun(reason):
215
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
216
if debug:
217
sys.argv.remove('-d')
218
logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
219
+ logger.debug("iotests debugging messages active")
220
221
return debug
222
223
@@ -XXX,XX +XXX,XX @@ def execute_test(*args, test_function=None, **kwargs):
224
else:
225
test_function()
226
227
+def activate_logging():
228
+ """Activate iotests.log() output to stdout for script-style tests."""
229
+ handler = logging.StreamHandler(stream=sys.stdout)
230
+ formatter = logging.Formatter('%(message)s')
231
+ handler.setFormatter(formatter)
232
+ test_logger.addHandler(handler)
233
+ test_logger.setLevel(logging.INFO)
234
+ test_logger.propagate = False
235
+
236
# This is called from script-style iotests without a single point of entry
237
def script_initialize(*args, **kwargs):
238
"""Initialize script-style tests without running any tests."""
239
+ activate_logging()
240
execute_setup_common(*args, **kwargs)
241
242
# This is called from script-style iotests with a single point of entry
243
def script_main(test_function, *args, **kwargs):
244
"""Run script-style tests outside of the unittest framework"""
245
+ activate_logging()
246
execute_test(*args, test_function=test_function, **kwargs)
247
248
# This is called from unittest style iotests
249
--
250
2.26.2
251
252
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
There are several callers that need to create a new block backend from
4
an existing BDS; make the task slightly easier with a common helper
5
routine.
6
7
Suggested-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Message-Id: <20200424190903.522087-2-eblake@redhat.com>
10
[mreitz: Set @ret only in error paths, see
11
https://lists.nongnu.org/archive/html/qemu-block/2020-04/msg01216.html]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200428192648.749066-2-eblake@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
include/sysemu/block-backend.h | 2 ++
17
block/block-backend.c | 23 +++++++++++++++++++++++
18
block/crypto.c | 9 ++++-----
19
block/parallels.c | 8 ++++----
20
block/qcow.c | 8 ++++----
21
block/qcow2.c | 18 ++++++++----------
22
block/qed.c | 8 ++++----
23
block/sheepdog.c | 10 +++++-----
24
block/vdi.c | 8 ++++----
25
block/vhdx.c | 8 ++++----
26
block/vmdk.c | 9 ++++-----
27
block/vpc.c | 8 ++++----
28
blockdev.c | 8 +++-----
29
blockjob.c | 7 ++-----
30
14 files changed, 75 insertions(+), 59 deletions(-)
31
32
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/sysemu/block-backend.h
35
+++ b/include/sysemu/block-backend.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct BlockBackendPublic {
37
} BlockBackendPublic;
38
39
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm);
40
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
41
+ uint64_t shared_perm, Error **errp);
42
BlockBackend *blk_new_open(const char *filename, const char *reference,
43
QDict *options, int flags, Error **errp);
44
int blk_get_refcnt(BlockBackend *blk);
45
diff --git a/block/block-backend.c b/block/block-backend.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/block-backend.c
48
+++ b/block/block-backend.c
49
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
50
return blk;
51
}
52
53
+/*
54
+ * Create a new BlockBackend connected to an existing BlockDriverState.
55
+ *
56
+ * @perm is a bitmasks of BLK_PERM_* constants which describes the
57
+ * permissions to request for @bs that is attached to this
58
+ * BlockBackend. @shared_perm is a bitmask which describes which
59
+ * permissions may be granted to other users of the attached node.
60
+ * Both sets of permissions can be changed later using blk_set_perm().
61
+ *
62
+ * Return the new BlockBackend on success, null on failure.
63
+ */
64
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
65
+ uint64_t shared_perm, Error **errp)
66
+{
67
+ BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
68
+
69
+ if (blk_insert_bs(blk, bs, errp) < 0) {
70
+ blk_unref(blk);
71
+ return NULL;
72
+ }
73
+ return blk;
74
+}
75
+
76
/*
77
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
78
* The new BlockBackend is in the main AioContext.
79
diff --git a/block/crypto.c b/block/crypto.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block/crypto.c
82
+++ b/block/crypto.c
83
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
84
QCryptoBlock *crypto = NULL;
85
struct BlockCryptoCreateData data;
86
87
- blk = blk_new(bdrv_get_aio_context(bs),
88
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
89
-
90
- ret = blk_insert_bs(blk, bs, errp);
91
- if (ret < 0) {
92
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
93
+ errp);
94
+ if (!blk) {
95
+ ret = -EPERM;
96
goto cleanup;
97
}
98
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
104
return -EIO;
105
}
106
107
- blk = blk_new(bdrv_get_aio_context(bs),
108
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
109
- ret = blk_insert_bs(blk, bs, errp);
110
- if (ret < 0) {
111
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
112
+ errp);
113
+ if (!blk) {
114
+ ret = -EPERM;
115
goto out;
116
}
117
blk_set_allow_write_beyond_eof(blk, true);
118
diff --git a/block/qcow.c b/block/qcow.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/block/qcow.c
121
+++ b/block/qcow.c
122
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
123
return -EIO;
124
}
125
126
- qcow_blk = blk_new(bdrv_get_aio_context(bs),
127
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
128
- ret = blk_insert_bs(qcow_blk, bs, errp);
129
- if (ret < 0) {
130
+ qcow_blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE,
131
+ BLK_PERM_ALL, errp);
132
+ if (!qcow_blk) {
133
+ ret = -EPERM;
134
goto exit;
135
}
136
blk_set_allow_write_beyond_eof(qcow_blk, true);
137
diff --git a/block/qcow2.c b/block/qcow2.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/qcow2.c
140
+++ b/block/qcow2.c
141
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
142
}
143
144
/* Create BlockBackend to write to the image */
145
- blk = blk_new(bdrv_get_aio_context(bs),
146
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
147
- ret = blk_insert_bs(blk, bs, errp);
148
- if (ret < 0) {
149
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
150
+ errp);
151
+ if (!blk) {
152
+ ret = -EPERM;
153
goto out;
154
}
155
blk_set_allow_write_beyond_eof(blk, true);
156
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
157
}
158
159
if (new_size) {
160
- BlockBackend *blk = blk_new(bdrv_get_aio_context(bs),
161
- BLK_PERM_RESIZE, BLK_PERM_ALL);
162
- ret = blk_insert_bs(blk, bs, errp);
163
- if (ret < 0) {
164
- blk_unref(blk);
165
- return ret;
166
+ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
167
+ errp);
168
+ if (!blk) {
169
+ return -EPERM;
170
}
171
172
/*
173
diff --git a/block/qed.c b/block/qed.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/block/qed.c
176
+++ b/block/qed.c
177
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
178
return -EIO;
179
}
180
181
- blk = blk_new(bdrv_get_aio_context(bs),
182
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
183
- ret = blk_insert_bs(blk, bs, errp);
184
- if (ret < 0) {
185
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
186
+ errp);
187
+ if (!blk) {
188
+ ret = -EPERM;
189
goto out;
190
}
191
blk_set_allow_write_beyond_eof(blk, true);
192
diff --git a/block/sheepdog.c b/block/sheepdog.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/sheepdog.c
195
+++ b/block/sheepdog.c
196
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size,
197
void *buf = NULL;
198
int ret;
199
200
- blk = blk_new(bdrv_get_aio_context(bs),
201
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
202
- BLK_PERM_ALL);
203
+ blk = blk_new_with_bs(bs,
204
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
205
+ BLK_PERM_ALL, errp);
206
207
- ret = blk_insert_bs(blk, bs, errp);
208
- if (ret < 0) {
209
+ if (!blk) {
210
+ ret = -EPERM;
211
goto out_with_err_set;
212
}
213
214
diff --git a/block/vdi.c b/block/vdi.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/block/vdi.c
217
+++ b/block/vdi.c
218
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
219
goto exit;
220
}
221
222
- blk = blk_new(bdrv_get_aio_context(bs_file),
223
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
224
- ret = blk_insert_bs(blk, bs_file, errp);
225
- if (ret < 0) {
226
+ blk = blk_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE,
227
+ BLK_PERM_ALL, errp);
228
+ if (!blk) {
229
+ ret = -EPERM;
230
goto exit;
231
}
232
233
diff --git a/block/vhdx.c b/block/vhdx.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/block/vhdx.c
236
+++ b/block/vhdx.c
237
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
238
return -EIO;
239
}
240
241
- blk = blk_new(bdrv_get_aio_context(bs),
242
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
243
- ret = blk_insert_bs(blk, bs, errp);
244
- if (ret < 0) {
245
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
246
+ errp);
247
+ if (!blk) {
248
+ ret = -EPERM;
249
goto delete_and_exit;
250
}
251
blk_set_allow_write_beyond_eof(blk, true);
252
diff --git a/block/vmdk.c b/block/vmdk.c
253
index XXXXXXX..XXXXXXX 100644
254
--- a/block/vmdk.c
255
+++ b/block/vmdk.c
256
@@ -XXX,XX +XXX,XX @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,
257
if (!bs) {
258
return NULL;
259
}
260
- blk = blk_new(bdrv_get_aio_context(bs),
261
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
262
- BLK_PERM_ALL);
263
- if (blk_insert_bs(blk, bs, errp)) {
264
- bdrv_unref(bs);
265
+ blk = blk_new_with_bs(bs,
266
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
267
+ BLK_PERM_ALL, errp);
268
+ if (!blk) {
269
return NULL;
270
}
271
blk_set_allow_write_beyond_eof(blk, true);
272
diff --git a/block/vpc.c b/block/vpc.c
273
index XXXXXXX..XXXXXXX 100644
274
--- a/block/vpc.c
275
+++ b/block/vpc.c
276
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
277
return -EIO;
278
}
279
280
- blk = blk_new(bdrv_get_aio_context(bs),
281
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
282
- ret = blk_insert_bs(blk, bs, errp);
283
- if (ret < 0) {
284
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
285
+ errp);
286
+ if (!blk) {
287
+ ret = -EPERM;
288
goto out;
289
}
290
blk_set_allow_write_beyond_eof(blk, true);
291
diff --git a/blockdev.c b/blockdev.c
292
index XXXXXXX..XXXXXXX 100644
293
--- a/blockdev.c
294
+++ b/blockdev.c
295
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
296
BlockBackend *blk = NULL;
297
BlockDriverState *bs;
298
AioContext *aio_context;
299
- int ret;
300
301
bs = bdrv_lookup_bs(has_device ? device : NULL,
302
has_node_name ? node_name : NULL,
303
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
304
goto out;
305
}
306
307
- blk = blk_new(bdrv_get_aio_context(bs), BLK_PERM_RESIZE, BLK_PERM_ALL);
308
- ret = blk_insert_bs(blk, bs, errp);
309
- if (ret < 0) {
310
+ blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
311
+ if (!blk) {
312
goto out;
313
}
314
315
bdrv_drained_begin(bs);
316
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
317
+ blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
318
bdrv_drained_end(bs);
319
320
out:
321
diff --git a/blockjob.c b/blockjob.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/blockjob.c
324
+++ b/blockjob.c
325
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
326
{
327
BlockBackend *blk;
328
BlockJob *job;
329
- int ret;
330
331
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
332
job_id = bdrv_get_device_name(bs);
333
}
334
335
- blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
336
- ret = blk_insert_bs(blk, bs, errp);
337
- if (ret < 0) {
338
- blk_unref(blk);
339
+ blk = blk_new_with_bs(bs, perm, shared_perm, errp);
340
+ if (!blk) {
341
return NULL;
342
}
343
344
--
345
2.26.2
346
347
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We originally refused to allow resize of images with internal
4
snapshots because the v2 image format did not require the tracking of
5
snapshot size, making it impossible to safely revert to a snapshot
6
with a different size than the current view of the image. But the
7
snapshot size tracking was rectified in v3, and our recent fixes to
8
qemu-img amend (see 0a85af35) guarantee that we always have a valid
9
snapshot size. Thus, we no longer need to artificially limit image
10
resizes, but it does become one more thing that would prevent a
11
downgrade back to v2. And now that we support different-sized
12
snapshots, it's also easy to fix reverting to a snapshot to apply the
13
new size.
14
15
Upgrade iotest 61 to cover this (we previously had NO coverage of
16
refusal to resize while snapshots exist). Note that the amend process
17
can fail but still have effects: in particular, since we break things
18
into upgrade, resize, downgrade, a failure during resize does not roll
19
back changes made during upgrade, nor does failure in downgrade roll
20
back a resize. But this situation is pre-existing even without this
21
patch; and without journaling, the best we could do is minimize the
22
chance of partial failure by collecting all changes prior to doing any
23
writes - which adds a lot of complexity but could still fail with EIO.
24
On the other hand, we are careful that even if we have partial
25
modification but then fail, the image is left viable (that is, we are
26
careful to sequence things so that after each successful cluster
27
write, there may be transient leaked clusters but no corrupt
28
metadata). And complicating the code to make it more transaction-like
29
is not worth the effort: a user can always request multiple 'qemu-img
30
amend' changing one thing each, if they need finer-grained control
31
over detecting the first failure than what they get by letting qemu
32
decide how to sequence multiple changes.
33
34
Signed-off-by: Eric Blake <eblake@redhat.com>
35
Reviewed-by: Max Reitz <mreitz@redhat.com>
36
Message-Id: <20200428192648.749066-3-eblake@redhat.com>
37
Signed-off-by: Max Reitz <mreitz@redhat.com>
38
---
39
block/qcow2-snapshot.c | 20 ++++++++++++++++----
40
block/qcow2.c | 25 ++++++++++++++++++++++---
41
tests/qemu-iotests/061 | 35 +++++++++++++++++++++++++++++++++++
42
tests/qemu-iotests/061.out | 28 ++++++++++++++++++++++++++++
43
4 files changed, 101 insertions(+), 7 deletions(-)
44
45
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2-snapshot.c
48
+++ b/block/qcow2-snapshot.c
49
@@ -XXX,XX +XXX,XX @@
50
*/
51
52
#include "qemu/osdep.h"
53
+#include "sysemu/block-backend.h"
54
#include "qapi/error.h"
55
#include "qcow2.h"
56
#include "qemu/bswap.h"
57
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
58
}
59
60
if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
61
- error_report("qcow2: Loading snapshots with different disk "
62
- "size is not implemented");
63
- ret = -ENOTSUP;
64
- goto fail;
65
+ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
66
+ &local_err);
67
+ if (!blk) {
68
+ error_report_err(local_err);
69
+ ret = -ENOTSUP;
70
+ goto fail;
71
+ }
72
+
73
+ ret = blk_truncate(blk, sn->disk_size, true, PREALLOC_MODE_OFF, 0,
74
+ &local_err);
75
+ blk_unref(blk);
76
+ if (ret < 0) {
77
+ error_report_err(local_err);
78
+ goto fail;
79
+ }
80
}
81
82
/*
83
diff --git a/block/qcow2.c b/block/qcow2.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/block/qcow2.c
86
+++ b/block/qcow2.c
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
88
89
qemu_co_mutex_lock(&s->lock);
90
91
- /* cannot proceed if image has snapshots */
92
- if (s->nb_snapshots) {
93
- error_setg(errp, "Can't resize an image which has snapshots");
94
+ /*
95
+ * Even though we store snapshot size for all images, it was not
96
+ * required until v3, so it is not safe to proceed for v2.
97
+ */
98
+ if (s->nb_snapshots && s->qcow_version < 3) {
99
+ error_setg(errp, "Can't resize a v2 image which has snapshots");
100
ret = -ENOTSUP;
101
goto fail;
102
}
103
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
104
BDRVQcow2State *s = bs->opaque;
105
int current_version = s->qcow_version;
106
int ret;
107
+ int i;
108
109
/* This is qcow2_downgrade(), not qcow2_upgrade() */
110
assert(target_version < current_version);
111
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
112
return -ENOTSUP;
113
}
114
115
+ /*
116
+ * If any internal snapshot has a different size than the current
117
+ * image size, or VM state size that exceeds 32 bits, downgrading
118
+ * is unsafe. Even though we would still use v3-compliant output
119
+ * to preserve that data, other v2 programs might not realize
120
+ * those optional fields are important.
121
+ */
122
+ for (i = 0; i < s->nb_snapshots; i++) {
123
+ if (s->snapshots[i].vm_state_size > UINT32_MAX ||
124
+ s->snapshots[i].disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
125
+ error_setg(errp, "Internal snapshots prevent downgrade of image");
126
+ return -ENOTSUP;
127
+ }
128
+ }
129
+
130
/* clear incompatible features */
131
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
132
ret = qcow2_mark_clean(bs);
133
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
134
index XXXXXXX..XXXXXXX 100755
135
--- a/tests/qemu-iotests/061
136
+++ b/tests/qemu-iotests/061
137
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" dump-header
138
$QEMU_IO -c "read -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
139
_check_test_img
140
141
+echo
142
+echo "=== Testing resize with snapshots ==="
143
+echo
144
+_make_test_img -o "compat=0.10" 32M
145
+$QEMU_IO -c "write -P 0x2a 24M 64k" "$TEST_IMG" | _filter_qemu_io
146
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
147
+$QEMU_IMG resize "$TEST_IMG" 64M &&
148
+ echo "unexpected pass"
149
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
150
+
151
+$QEMU_IMG amend -o "compat=1.1,size=128M" "$TEST_IMG" ||
152
+ echo "unexpected fail"
153
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
154
+
155
+$QEMU_IMG snapshot -c bar "$TEST_IMG"
156
+$QEMU_IMG resize --shrink "$TEST_IMG" 64M ||
157
+ echo "unexpected fail"
158
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
159
+
160
+$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" &&
161
+ echo "unexpected pass"
162
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
163
+
164
+$QEMU_IMG snapshot -a bar "$TEST_IMG" ||
165
+ echo "unexpected fail"
166
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
167
+
168
+$QEMU_IMG snapshot -d bar "$TEST_IMG"
169
+$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" ||
170
+ echo "unexpected fail"
171
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
172
+
173
+_check_test_img
174
+
175
+
176
echo
177
echo "=== Testing dirty lazy_refcounts=off ==="
178
echo
179
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
180
index XXXXXXX..XXXXXXX 100644
181
--- a/tests/qemu-iotests/061.out
182
+++ b/tests/qemu-iotests/061.out
183
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 44040192
184
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
185
No errors were found on the image.
186
187
+=== Testing resize with snapshots ===
188
+
189
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432
190
+wrote 65536/65536 bytes at offset 25165824
191
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
192
+qemu-img: Can't resize a v2 image which has snapshots
193
+version 2
194
+size 33554432
195
+nb_snapshots 1
196
+version 3
197
+size 134217728
198
+nb_snapshots 1
199
+Image resized.
200
+version 3
201
+size 67108864
202
+nb_snapshots 2
203
+qemu-img: Internal snapshots prevent downgrade of image
204
+version 3
205
+size 33554432
206
+nb_snapshots 2
207
+version 3
208
+size 134217728
209
+nb_snapshots 2
210
+version 2
211
+size 33554432
212
+nb_snapshots 1
213
+No errors were found on the image.
214
+
215
=== Testing dirty lazy_refcounts=off ===
216
217
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
218
--
219
2.26.2
220
221
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Our comment did not actually match the code. Rewrite the comment to
4
be less sensitive to any future changes to qcow2-bitmap.c that might
5
implement scenarios that we currently reject.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200428192648.749066-4-eblake@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
20
goto fail;
21
}
22
23
- /* cannot proceed if image has bitmaps */
24
+ /* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */
25
if (qcow2_truncate_bitmaps_check(bs, errp)) {
26
ret = -ENOTSUP;
27
goto fail;
28
--
29
2.26.2
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
It's been a while since we got rid of the sector-based bdrv_read and
4
bdrv_write (commit 2e11d756); let's finish the job on a few remaining
5
comments.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200428213807.776655-1-eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/io.c | 3 ++-
13
block/qcow2-refcount.c | 2 +-
14
block/vvfat.c | 10 +++++-----
15
tests/qemu-iotests/001 | 2 +-
16
tests/qemu-iotests/052 | 2 +-
17
tests/qemu-iotests/134 | 2 +-
18
tests/qemu-iotests/188 | 2 +-
19
7 files changed, 12 insertions(+), 11 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 @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
26
* flags are passed through to bdrv_pwrite_zeroes (e.g. BDRV_REQ_MAY_UNMAP,
27
* BDRV_REQ_FUA).
28
*
29
- * Returns < 0 on error, 0 on success. For error codes see bdrv_write().
30
+ * Returns < 0 on error, 0 on success. For error codes see bdrv_pwrite().
31
*/
32
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
33
{
34
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
35
}
36
}
37
38
+/* return < 0 if error. See bdrv_pwrite() for the return codes */
39
int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
40
{
41
int ret;
42
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/qcow2-refcount.c
45
+++ b/block/qcow2-refcount.c
46
@@ -XXX,XX +XXX,XX @@ fail:
47
* - 0 if writing to this offset will not affect the mentioned metadata
48
* - a positive QCow2MetadataOverlap value indicating one overlapping section
49
* - a negative value (-errno) indicating an error while performing a check,
50
- * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
51
+ * e.g. when bdrv_pread failed on QCOW2_OL_INACTIVE_L2
52
*/
53
int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
54
int64_t size)
55
diff --git a/block/vvfat.c b/block/vvfat.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/vvfat.c
58
+++ b/block/vvfat.c
59
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
60
* - get modified FAT
61
* - compare the two FATs (TODO)
62
* - get buffer for marking used clusters
63
- * - recurse direntries from root (using bs->bdrv_read to make
64
+ * - recurse direntries from root (using bs->bdrv_pread to make
65
* sure to get the new data)
66
* - check that the FAT agrees with the size
67
* - count the number of clusters occupied by this directory and
68
@@ -XXX,XX +XXX,XX @@ static int handle_deletes(BDRVVVFATState* s)
69
/*
70
* synchronize mapping with new state:
71
*
72
- * - copy FAT (with bdrv_read)
73
+ * - copy FAT (with bdrv_pread)
74
* - mark all filenames corresponding to mappings as deleted
75
- * - recurse direntries from root (using bs->bdrv_read)
76
+ * - recurse direntries from root (using bs->bdrv_pread)
77
* - delete files corresponding to mappings marked as deleted
78
*/
79
static int do_commit(BDRVVVFATState* s)
80
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
81
return ret;
82
}
83
84
- /* copy FAT (with bdrv_read) */
85
+ /* copy FAT (with bdrv_pread) */
86
memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
87
88
- /* recurse direntries from root (using bs->bdrv_read) */
89
+ /* recurse direntries from root (using bs->bdrv_pread) */
90
ret = commit_direntries(s, 0, -1);
91
if (ret) {
92
fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
93
diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001
94
index XXXXXXX..XXXXXXX 100755
95
--- a/tests/qemu-iotests/001
96
+++ b/tests/qemu-iotests/001
97
@@ -XXX,XX +XXX,XX @@
98
#!/usr/bin/env bash
99
#
100
-# Test simple read/write using plain bdrv_read/bdrv_write
101
+# Test simple read/write using plain bdrv_pread/bdrv_pwrite
102
#
103
# Copyright (C) 2009 Red Hat, Inc.
104
#
105
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
106
index XXXXXXX..XXXXXXX 100755
107
--- a/tests/qemu-iotests/052
108
+++ b/tests/qemu-iotests/052
109
@@ -XXX,XX +XXX,XX @@
110
#!/usr/bin/env bash
111
#
112
-# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT
113
+# Test bdrv_pread/bdrv_pwrite using BDRV_O_SNAPSHOT
114
#
115
# Copyright (C) 2013 Red Hat, Inc.
116
#
117
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
118
index XXXXXXX..XXXXXXX 100755
119
--- a/tests/qemu-iotests/134
120
+++ b/tests/qemu-iotests/134
121
@@ -XXX,XX +XXX,XX @@
122
#!/usr/bin/env bash
123
#
124
-# Test encrypted read/write using plain bdrv_read/bdrv_write
125
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
126
#
127
# Copyright (C) 2015 Red Hat, Inc.
128
#
129
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
130
index XXXXXXX..XXXXXXX 100755
131
--- a/tests/qemu-iotests/188
132
+++ b/tests/qemu-iotests/188
133
@@ -XXX,XX +XXX,XX @@
134
#!/usr/bin/env bash
135
#
136
-# Test encrypted read/write using plain bdrv_read/bdrv_write
137
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
138
#
139
# Copyright (C) 2017 Red Hat, Inc.
140
#
141
--
142
2.26.2
143
144
diff view generated by jsdifflib
Deleted patch
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
1
3
Commit f62514b3def5fb2acbef64d0e053c0c31fa45aff made qemu-img reject -o "" but this test uses it.
4
Since this test only tries to do a dry-run run of qemu-img amend,
5
replace the -o "" with dummy -o "size=$size".
6
7
Fixes: f62514b3def5fb2acbef64d0e053c0c31fa45aff
8
9
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Message-Id: <20200504131959.9533-1-mlevitsk@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/153 | 2 +-
14
tests/qemu-iotests/153.out | 12 ++++++------
15
2 files changed, 7 insertions(+), 7 deletions(-)
16
17
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/153
20
+++ b/tests/qemu-iotests/153
21
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
22
_run_cmd $QEMU_IMG check $L "${TEST_IMG}"
23
_run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}"
24
_run_cmd $QEMU_IMG map $L "${TEST_IMG}"
25
- _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}"
26
+ _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}"
27
_run_cmd $QEMU_IMG commit $L "${TEST_IMG}"
28
_run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size
29
_run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base"
30
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
31
index XXXXXXX..XXXXXXX 100644
32
--- a/tests/qemu-iotests/153.out
33
+++ b/tests/qemu-iotests/153.out
34
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper map TEST_DIR/t.qcow2
35
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
36
Is another process using the image [TEST_DIR/t.qcow2]?
37
38
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
39
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
40
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
41
Is another process using the image [TEST_DIR/t.qcow2]?
42
43
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
44
45
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
46
47
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
48
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
49
qemu-img: unrecognized option '-U'
50
Try 'qemu-img --help' for more information
51
52
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
53
54
_qemu_img_wrapper map TEST_DIR/t.qcow2
55
56
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
57
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
58
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
59
Is another process using the image [TEST_DIR/t.qcow2]?
60
61
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
62
63
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
64
65
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
66
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
67
qemu-img: unrecognized option '-U'
68
Try 'qemu-img --help' for more information
69
70
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
71
72
_qemu_img_wrapper map TEST_DIR/t.qcow2
73
74
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
75
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
76
77
_qemu_img_wrapper commit TEST_DIR/t.qcow2
78
79
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
80
81
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
82
83
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
84
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
85
qemu-img: unrecognized option '-U'
86
Try 'qemu-img --help' for more information
87
88
--
89
2.26.2
90
91
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to use aio-task-pool API and extend in-flight request
4
structure to be a successor of AioTask, so rename things appropriately.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200429130847.28124-2-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/block-copy.c | 98 +++++++++++++++++++++++-----------------------
12
1 file changed, 48 insertions(+), 50 deletions(-)
13
14
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/block-copy.c
17
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@
19
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
20
#define BLOCK_COPY_MAX_MEM (128 * MiB)
21
22
-typedef struct BlockCopyInFlightReq {
23
+typedef struct BlockCopyTask {
24
int64_t offset;
25
int64_t bytes;
26
- QLIST_ENTRY(BlockCopyInFlightReq) list;
27
- CoQueue wait_queue; /* coroutines blocked on this request */
28
-} BlockCopyInFlightReq;
29
+ QLIST_ENTRY(BlockCopyTask) list;
30
+ CoQueue wait_queue; /* coroutines blocked on this task */
31
+} BlockCopyTask;
32
33
typedef struct BlockCopyState {
34
/*
35
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
36
bool use_copy_range;
37
int64_t copy_size;
38
uint64_t len;
39
- QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;
40
+ QLIST_HEAD(, BlockCopyTask) tasks;
41
42
BdrvRequestFlags write_flags;
43
44
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
45
SharedResource *mem;
46
} BlockCopyState;
47
48
-static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
49
- int64_t offset,
50
- int64_t bytes)
51
+static BlockCopyTask *find_conflicting_task(BlockCopyState *s,
52
+ int64_t offset, int64_t bytes)
53
{
54
- BlockCopyInFlightReq *req;
55
+ BlockCopyTask *t;
56
57
- QLIST_FOREACH(req, &s->inflight_reqs, list) {
58
- if (offset + bytes > req->offset && offset < req->offset + req->bytes) {
59
- return req;
60
+ QLIST_FOREACH(t, &s->tasks, list) {
61
+ if (offset + bytes > t->offset && offset < t->offset + t->bytes) {
62
+ return t;
63
}
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
67
}
68
69
/*
70
- * If there are no intersecting requests return false. Otherwise, wait for the
71
- * first found intersecting request to finish and return true.
72
+ * If there are no intersecting tasks return false. Otherwise, wait for the
73
+ * first found intersecting tasks to finish and return true.
74
*/
75
static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
76
int64_t bytes)
77
{
78
- BlockCopyInFlightReq *req = find_conflicting_inflight_req(s, offset, bytes);
79
+ BlockCopyTask *task = find_conflicting_task(s, offset, bytes);
80
81
- if (!req) {
82
+ if (!task) {
83
return false;
84
}
85
86
- qemu_co_queue_wait(&req->wait_queue, NULL);
87
+ qemu_co_queue_wait(&task->wait_queue, NULL);
88
89
return true;
90
}
91
92
/* Called only on full-dirty region */
93
-static void block_copy_inflight_req_begin(BlockCopyState *s,
94
- BlockCopyInFlightReq *req,
95
- int64_t offset, int64_t bytes)
96
+static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
97
+ int64_t offset, int64_t bytes)
98
{
99
- assert(!find_conflicting_inflight_req(s, offset, bytes));
100
+ assert(!find_conflicting_task(s, offset, bytes));
101
102
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
103
s->in_flight_bytes += bytes;
104
105
- req->offset = offset;
106
- req->bytes = bytes;
107
- qemu_co_queue_init(&req->wait_queue);
108
- QLIST_INSERT_HEAD(&s->inflight_reqs, req, list);
109
+ task->offset = offset;
110
+ task->bytes = bytes;
111
+ qemu_co_queue_init(&task->wait_queue);
112
+ QLIST_INSERT_HEAD(&s->tasks, task, list);
113
}
114
115
/*
116
- * block_copy_inflight_req_shrink
117
+ * block_copy_task_shrink
118
*
119
- * Drop the tail of the request to be handled later. Set dirty bits back and
120
- * wake up all requests waiting for us (may be some of them are not intersecting
121
- * with shrunk request)
122
+ * Drop the tail of the task to be handled later. Set dirty bits back and
123
+ * wake up all tasks waiting for us (may be some of them are not intersecting
124
+ * with shrunk task)
125
*/
126
-static void coroutine_fn block_copy_inflight_req_shrink(BlockCopyState *s,
127
- BlockCopyInFlightReq *req, int64_t new_bytes)
128
+static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
129
+ BlockCopyTask *task,
130
+ int64_t new_bytes)
131
{
132
- if (new_bytes == req->bytes) {
133
+ if (new_bytes == task->bytes) {
134
return;
135
}
136
137
- assert(new_bytes > 0 && new_bytes < req->bytes);
138
+ assert(new_bytes > 0 && new_bytes < task->bytes);
139
140
- s->in_flight_bytes -= req->bytes - new_bytes;
141
+ s->in_flight_bytes -= task->bytes - new_bytes;
142
bdrv_set_dirty_bitmap(s->copy_bitmap,
143
- req->offset + new_bytes, req->bytes - new_bytes);
144
+ task->offset + new_bytes, task->bytes - new_bytes);
145
146
- req->bytes = new_bytes;
147
- qemu_co_queue_restart_all(&req->wait_queue);
148
+ task->bytes = new_bytes;
149
+ qemu_co_queue_restart_all(&task->wait_queue);
150
}
151
152
-static void coroutine_fn block_copy_inflight_req_end(BlockCopyState *s,
153
- BlockCopyInFlightReq *req,
154
- int ret)
155
+static void coroutine_fn block_copy_task_end(BlockCopyState *s,
156
+ BlockCopyTask *task, int ret)
157
{
158
- s->in_flight_bytes -= req->bytes;
159
+ s->in_flight_bytes -= task->bytes;
160
if (ret < 0) {
161
- bdrv_set_dirty_bitmap(s->copy_bitmap, req->offset, req->bytes);
162
+ bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes);
163
}
164
- QLIST_REMOVE(req, list);
165
- qemu_co_queue_restart_all(&req->wait_queue);
166
+ QLIST_REMOVE(task, list);
167
+ qemu_co_queue_restart_all(&task->wait_queue);
168
}
169
170
void block_copy_state_free(BlockCopyState *s)
171
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
172
s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
173
}
174
175
- QLIST_INIT(&s->inflight_reqs);
176
+ QLIST_INIT(&s->tasks);
177
178
return s;
179
}
180
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
181
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
182
183
while (bytes) {
184
- BlockCopyInFlightReq req;
185
+ BlockCopyTask task;
186
int64_t next_zero, cur_bytes, status_bytes;
187
188
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
189
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
190
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
191
cur_bytes = next_zero - offset;
192
}
193
- block_copy_inflight_req_begin(s, &req, offset, cur_bytes);
194
+ block_copy_task_begin(s, &task, offset, cur_bytes);
195
196
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
197
assert(ret >= 0); /* never fail */
198
cur_bytes = MIN(cur_bytes, status_bytes);
199
- block_copy_inflight_req_shrink(s, &req, cur_bytes);
200
+ block_copy_task_shrink(s, &task, cur_bytes);
201
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
202
- block_copy_inflight_req_end(s, &req, 0);
203
+ block_copy_task_end(s, &task, 0);
204
progress_set_remaining(s->progress,
205
bdrv_get_dirty_count(s->copy_bitmap) +
206
s->in_flight_bytes);
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
208
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
209
error_is_read);
210
co_put_to_shres(s->mem, cur_bytes);
211
- block_copy_inflight_req_end(s, &req, ret);
212
+ block_copy_task_end(s, &task, ret);
213
if (ret < 0) {
214
return ret;
215
}
216
--
217
2.26.2
218
219
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to use aio-task-pool API, so tasks will be handled in
4
parallel. We need therefore separate allocated task on each iteration.
5
Introduce this logic now.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200429130847.28124-3-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/block-copy.c | 18 +++++++++++-------
13
1 file changed, 11 insertions(+), 7 deletions(-)
14
15
diff --git a/block/block-copy.c b/block/block-copy.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/block-copy.c
18
+++ b/block/block-copy.c
19
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
20
}
21
22
/* Called only on full-dirty region */
23
-static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
24
- int64_t offset, int64_t bytes)
25
+static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
26
+ int64_t offset, int64_t bytes)
27
{
28
+ BlockCopyTask *task = g_new(BlockCopyTask, 1);
29
+
30
assert(!find_conflicting_task(s, offset, bytes));
31
32
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
33
@@ -XXX,XX +XXX,XX @@ static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
34
task->bytes = bytes;
35
qemu_co_queue_init(&task->wait_queue);
36
QLIST_INSERT_HEAD(&s->tasks, task, list);
37
+
38
+ return task;
39
}
40
41
/*
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
43
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
44
45
while (bytes) {
46
- BlockCopyTask task;
47
+ g_autofree BlockCopyTask *task = NULL;
48
int64_t next_zero, cur_bytes, status_bytes;
49
50
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
52
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
53
cur_bytes = next_zero - offset;
54
}
55
- block_copy_task_begin(s, &task, offset, cur_bytes);
56
+ task = block_copy_task_create(s, offset, cur_bytes);
57
58
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
59
assert(ret >= 0); /* never fail */
60
cur_bytes = MIN(cur_bytes, status_bytes);
61
- block_copy_task_shrink(s, &task, cur_bytes);
62
+ block_copy_task_shrink(s, task, cur_bytes);
63
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
64
- block_copy_task_end(s, &task, 0);
65
+ block_copy_task_end(s, task, 0);
66
progress_set_remaining(s->progress,
67
bdrv_get_dirty_count(s->copy_bitmap) +
68
s->in_flight_bytes);
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
70
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
71
error_is_read);
72
co_put_to_shres(s->mem, cur_bytes);
73
- block_copy_task_end(s, &task, ret);
74
+ block_copy_task_end(s, task, ret);
75
if (ret < 0) {
76
return ret;
77
}
78
--
79
2.26.2
80
81
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to use aio-task-pool API, so we'll need state pointer in
4
BlockCopyTask anyway. Add it now and use where possible.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200429130847.28124-4-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/block-copy.c | 28 +++++++++++++++-------------
12
1 file changed, 15 insertions(+), 13 deletions(-)
13
14
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/block-copy.c
17
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@
19
#define BLOCK_COPY_MAX_MEM (128 * MiB)
20
21
typedef struct BlockCopyTask {
22
+ BlockCopyState *s;
23
int64_t offset;
24
int64_t bytes;
25
QLIST_ENTRY(BlockCopyTask) list;
26
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
27
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
28
s->in_flight_bytes += bytes;
29
30
- task->offset = offset;
31
- task->bytes = bytes;
32
+ *task = (BlockCopyTask) {
33
+ .s = s,
34
+ .offset = offset,
35
+ .bytes = bytes,
36
+ };
37
qemu_co_queue_init(&task->wait_queue);
38
QLIST_INSERT_HEAD(&s->tasks, task, list);
39
40
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
41
* wake up all tasks waiting for us (may be some of them are not intersecting
42
* with shrunk task)
43
*/
44
-static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
45
- BlockCopyTask *task,
46
+static void coroutine_fn block_copy_task_shrink(BlockCopyTask *task,
47
int64_t new_bytes)
48
{
49
if (new_bytes == task->bytes) {
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
51
52
assert(new_bytes > 0 && new_bytes < task->bytes);
53
54
- s->in_flight_bytes -= task->bytes - new_bytes;
55
- bdrv_set_dirty_bitmap(s->copy_bitmap,
56
+ task->s->in_flight_bytes -= task->bytes - new_bytes;
57
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap,
58
task->offset + new_bytes, task->bytes - new_bytes);
59
60
task->bytes = new_bytes;
61
qemu_co_queue_restart_all(&task->wait_queue);
62
}
63
64
-static void coroutine_fn block_copy_task_end(BlockCopyState *s,
65
- BlockCopyTask *task, int ret)
66
+static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
67
{
68
- s->in_flight_bytes -= task->bytes;
69
+ task->s->in_flight_bytes -= task->bytes;
70
if (ret < 0) {
71
- bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes);
72
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
73
}
74
QLIST_REMOVE(task, list);
75
qemu_co_queue_restart_all(&task->wait_queue);
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
77
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
78
assert(ret >= 0); /* never fail */
79
cur_bytes = MIN(cur_bytes, status_bytes);
80
- block_copy_task_shrink(s, task, cur_bytes);
81
+ block_copy_task_shrink(task, cur_bytes);
82
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
83
- block_copy_task_end(s, task, 0);
84
+ block_copy_task_end(task, 0);
85
progress_set_remaining(s->progress,
86
bdrv_get_dirty_count(s->copy_bitmap) +
87
s->in_flight_bytes);
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
89
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
90
error_is_read);
91
co_put_to_shres(s->mem, cur_bytes);
92
- block_copy_task_end(s, task, ret);
93
+ block_copy_task_end(task, ret);
94
if (ret < 0) {
95
return ret;
96
}
97
--
98
2.26.2
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Instead of just relying on the comment "Called only on full-dirty
4
region" in block_copy_task_create() let's move initial dirty area
5
search directly to block_copy_task_create(). Let's also use effective
6
bdrv_dirty_bitmap_next_dirty_area instead of looping through all
7
non-dirty clusters.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200429130847.28124-5-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/block-copy.c | 80 ++++++++++++++++++++++++++--------------------
15
1 file changed, 46 insertions(+), 34 deletions(-)
16
17
diff --git a/block/block-copy.c b/block/block-copy.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/block-copy.c
20
+++ b/block/block-copy.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyTask {
22
CoQueue wait_queue; /* coroutines blocked on this task */
23
} BlockCopyTask;
24
25
+static int64_t task_end(BlockCopyTask *task)
26
+{
27
+ return task->offset + task->bytes;
28
+}
29
+
30
typedef struct BlockCopyState {
31
/*
32
* BdrvChild objects are not owned or managed by block-copy. They are
33
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
34
return true;
35
}
36
37
-/* Called only on full-dirty region */
38
+/*
39
+ * Search for the first dirty area in offset/bytes range and create task at
40
+ * the beginning of it.
41
+ */
42
static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
43
int64_t offset, int64_t bytes)
44
{
45
- BlockCopyTask *task = g_new(BlockCopyTask, 1);
46
+ BlockCopyTask *task;
47
48
+ if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap,
49
+ offset, offset + bytes,
50
+ s->copy_size, &offset, &bytes))
51
+ {
52
+ return NULL;
53
+ }
54
+
55
+ /* region is dirty, so no existent tasks possible in it */
56
assert(!find_conflicting_task(s, offset, bytes));
57
58
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
59
s->in_flight_bytes += bytes;
60
61
+ task = g_new(BlockCopyTask, 1);
62
*task = (BlockCopyTask) {
63
.s = s,
64
.offset = offset,
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
66
{
67
int ret = 0;
68
bool found_dirty = false;
69
+ int64_t end = offset + bytes;
70
71
/*
72
* block_copy() user is responsible for keeping source and target in same
73
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
74
75
while (bytes) {
76
g_autofree BlockCopyTask *task = NULL;
77
- int64_t next_zero, cur_bytes, status_bytes;
78
+ int64_t status_bytes;
79
80
- if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
81
- trace_block_copy_skip(s, offset);
82
- offset += s->cluster_size;
83
- bytes -= s->cluster_size;
84
- continue; /* already copied */
85
+ task = block_copy_task_create(s, offset, bytes);
86
+ if (!task) {
87
+ /* No more dirty bits in the bitmap */
88
+ trace_block_copy_skip_range(s, offset, bytes);
89
+ break;
90
+ }
91
+ if (task->offset > offset) {
92
+ trace_block_copy_skip_range(s, offset, task->offset - offset);
93
}
94
95
found_dirty = true;
96
97
- cur_bytes = MIN(bytes, s->copy_size);
98
-
99
- next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset,
100
- cur_bytes);
101
- if (next_zero >= 0) {
102
- assert(next_zero > offset); /* offset is dirty */
103
- assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
104
- cur_bytes = next_zero - offset;
105
- }
106
- task = block_copy_task_create(s, offset, cur_bytes);
107
-
108
- ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
109
+ ret = block_copy_block_status(s, task->offset, task->bytes,
110
+ &status_bytes);
111
assert(ret >= 0); /* never fail */
112
- cur_bytes = MIN(cur_bytes, status_bytes);
113
- block_copy_task_shrink(task, cur_bytes);
114
+ if (status_bytes < task->bytes) {
115
+ block_copy_task_shrink(task, status_bytes);
116
+ }
117
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
118
block_copy_task_end(task, 0);
119
progress_set_remaining(s->progress,
120
bdrv_get_dirty_count(s->copy_bitmap) +
121
s->in_flight_bytes);
122
- trace_block_copy_skip_range(s, offset, status_bytes);
123
- offset += status_bytes;
124
- bytes -= status_bytes;
125
+ trace_block_copy_skip_range(s, task->offset, task->bytes);
126
+ offset = task_end(task);
127
+ bytes = end - offset;
128
continue;
129
}
130
131
- trace_block_copy_process(s, offset);
132
+ trace_block_copy_process(s, task->offset);
133
134
- co_get_from_shres(s->mem, cur_bytes);
135
- ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
136
- error_is_read);
137
- co_put_to_shres(s->mem, cur_bytes);
138
+ co_get_from_shres(s->mem, task->bytes);
139
+ ret = block_copy_do_copy(s, task->offset, task->bytes,
140
+ ret & BDRV_BLOCK_ZERO, error_is_read);
141
+ co_put_to_shres(s->mem, task->bytes);
142
block_copy_task_end(task, ret);
143
if (ret < 0) {
144
return ret;
145
}
146
147
- progress_work_done(s->progress, cur_bytes);
148
- s->progress_bytes_callback(cur_bytes, s->progress_opaque);
149
- offset += cur_bytes;
150
- bytes -= cur_bytes;
151
+ progress_work_done(s->progress, task->bytes);
152
+ s->progress_bytes_callback(task->bytes, s->progress_opaque);
153
+ offset = task_end(task);
154
+ bytes = end - offset;
155
}
156
157
return found_dirty;
158
--
159
2.26.2
160
161
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Yusuke Okada <okada.yusuke@jp.fujitsu.com>
2
2
3
Run block_copy iterations in parallel in aio tasks.
3
The "%f" specifier in g_date_time_format() is only available in glib
4
2.65.2 or later. If combined with older glib, the function returns null
5
and the timestamp displayed as "(null)".
4
6
5
Changes:
7
For backward compatibility, g_date_time_get_microsecond should be used
6
- BlockCopyTask becomes aio task structure. Add zeroes field to pass
8
to retrieve subsecond.
7
it to block_copy_do_copy
8
- add call state - it's a state of one call of block_copy(), shared
9
between parallel tasks. For now used only to keep information about
10
first error: is it read or not.
11
- convert block_copy_dirty_clusters to aio-task loop.
12
9
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
In this patch the g_date_time_format() leaves subsecond field as "%06d"
14
Message-Id: <20200429130847.28124-6-vsementsov@virtuozzo.com>
11
and let next snprintf to format with g_date_time_get_microsecond.
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
13
Signed-off-by: Yusuke Okada <okada.yusuke@jp.fujitsu.com>
14
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
15
Message-id: 20220818184618.2205172-1-yokada.996@gmail.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
---
17
block/block-copy.c | 119 ++++++++++++++++++++++++++++++++++++++++-----
18
tools/virtiofsd/passthrough_ll.c | 7 +++++--
18
1 file changed, 106 insertions(+), 13 deletions(-)
19
1 file changed, 5 insertions(+), 2 deletions(-)
19
20
20
diff --git a/block/block-copy.c b/block/block-copy.c
21
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/block/block-copy.c
23
--- a/tools/virtiofsd/passthrough_ll.c
23
+++ b/block/block-copy.c
24
+++ b/tools/virtiofsd/passthrough_ll.c
24
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile)
25
#include "block/block-copy.h"
26
static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
26
#include "sysemu/block-backend.h"
27
#include "qemu/units.h"
28
+#include "qemu/coroutine.h"
29
+#include "block/aio_task.h"
30
31
#define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB)
32
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
33
#define BLOCK_COPY_MAX_MEM (128 * MiB)
34
+#define BLOCK_COPY_MAX_WORKERS 64
35
+
36
+static coroutine_fn int block_copy_task_entry(AioTask *task);
37
+
38
+typedef struct BlockCopyCallState {
39
+ bool failed;
40
+ bool error_is_read;
41
+} BlockCopyCallState;
42
43
typedef struct BlockCopyTask {
44
+ AioTask task;
45
+
46
BlockCopyState *s;
47
+ BlockCopyCallState *call_state;
48
int64_t offset;
49
int64_t bytes;
50
+ bool zeroes;
51
QLIST_ENTRY(BlockCopyTask) list;
52
CoQueue wait_queue; /* coroutines blocked on this task */
53
} BlockCopyTask;
54
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
55
* the beginning of it.
56
*/
57
static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
58
+ BlockCopyCallState *call_state,
59
int64_t offset, int64_t bytes)
60
{
27
{
61
BlockCopyTask *task;
28
g_autofree char *localfmt = NULL;
62
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
29
+ char buf[64];
63
30
64
task = g_new(BlockCopyTask, 1);
31
if (current_log_level < level) {
65
*task = (BlockCopyTask) {
32
return;
66
+ .task.func = block_copy_task_entry,
33
@@ -XXX,XX +XXX,XX @@ static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
67
.s = s,
34
fmt);
68
+ .call_state = call_state,
35
} else {
69
.offset = offset,
36
g_autoptr(GDateTime) now = g_date_time_new_now_utc();
70
.bytes = bytes,
37
- g_autofree char *nowstr = g_date_time_format(now, "%Y-%m-%d %H:%M:%S.%f%z");
71
};
38
+ g_autofree char *nowstr = g_date_time_format(now,
72
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
39
+ "%Y-%m-%d %H:%M:%S.%%06d%z");
73
s->progress = pm;
40
+ snprintf(buf, 64, nowstr, g_date_time_get_microsecond(now));
74
}
41
localfmt = g_strdup_printf("[%s] [ID: %08ld] %s",
75
42
- nowstr, syscall(__NR_gettid), fmt);
76
+/*
43
+ buf, syscall(__NR_gettid), fmt);
77
+ * Takes ownership of @task
78
+ *
79
+ * If pool is NULL directly run the task, otherwise schedule it into the pool.
80
+ *
81
+ * Returns: task.func return code if pool is NULL
82
+ * otherwise -ECANCELED if pool status is bad
83
+ * otherwise 0 (successfully scheduled)
84
+ */
85
+static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
86
+ BlockCopyTask *task)
87
+{
88
+ if (!pool) {
89
+ int ret = task->task.func(&task->task);
90
+
91
+ g_free(task);
92
+ return ret;
93
+ }
94
+
95
+ aio_task_pool_wait_slot(pool);
96
+ if (aio_task_pool_status(pool) < 0) {
97
+ co_put_to_shres(task->s->mem, task->bytes);
98
+ block_copy_task_end(task, -ECANCELED);
99
+ g_free(task);
100
+ return -ECANCELED;
101
+ }
102
+
103
+ aio_task_pool_start_task(pool, &task->task);
104
+
105
+ return 0;
106
+}
107
+
108
/*
109
* block_copy_do_copy
110
*
111
@@ -XXX,XX +XXX,XX @@ out:
112
return ret;
113
}
114
115
+static coroutine_fn int block_copy_task_entry(AioTask *task)
116
+{
117
+ BlockCopyTask *t = container_of(task, BlockCopyTask, task);
118
+ bool error_is_read;
119
+ int ret;
120
+
121
+ ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
122
+ &error_is_read);
123
+ if (ret < 0 && !t->call_state->failed) {
124
+ t->call_state->failed = true;
125
+ t->call_state->error_is_read = error_is_read;
126
+ } else {
127
+ progress_work_done(t->s->progress, t->bytes);
128
+ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
129
+ }
130
+ co_put_to_shres(t->s->mem, t->bytes);
131
+ block_copy_task_end(t, ret);
132
+
133
+ return ret;
134
+}
135
+
136
static int block_copy_block_status(BlockCopyState *s, int64_t offset,
137
int64_t bytes, int64_t *pnum)
138
{
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
140
int ret = 0;
141
bool found_dirty = false;
142
int64_t end = offset + bytes;
143
+ AioTaskPool *aio = NULL;
144
+ BlockCopyCallState call_state = {false, false};
145
146
/*
147
* block_copy() user is responsible for keeping source and target in same
148
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
149
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
150
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
151
152
- while (bytes) {
153
- g_autofree BlockCopyTask *task = NULL;
154
+ while (bytes && aio_task_pool_status(aio) == 0) {
155
+ BlockCopyTask *task;
156
int64_t status_bytes;
157
158
- task = block_copy_task_create(s, offset, bytes);
159
+ task = block_copy_task_create(s, &call_state, offset, bytes);
160
if (!task) {
161
/* No more dirty bits in the bitmap */
162
trace_block_copy_skip_range(s, offset, bytes);
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
164
}
44
}
165
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
45
fmt = localfmt;
166
block_copy_task_end(task, 0);
167
+ g_free(task);
168
progress_set_remaining(s->progress,
169
bdrv_get_dirty_count(s->copy_bitmap) +
170
s->in_flight_bytes);
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
172
bytes = end - offset;
173
continue;
174
}
175
+ task->zeroes = ret & BDRV_BLOCK_ZERO;
176
177
trace_block_copy_process(s, task->offset);
178
179
co_get_from_shres(s->mem, task->bytes);
180
- ret = block_copy_do_copy(s, task->offset, task->bytes,
181
- ret & BDRV_BLOCK_ZERO, error_is_read);
182
- co_put_to_shres(s->mem, task->bytes);
183
- block_copy_task_end(task, ret);
184
- if (ret < 0) {
185
- return ret;
186
- }
187
188
- progress_work_done(s->progress, task->bytes);
189
- s->progress_bytes_callback(task->bytes, s->progress_opaque);
190
offset = task_end(task);
191
bytes = end - offset;
192
+
193
+ if (!aio && bytes) {
194
+ aio = aio_task_pool_new(BLOCK_COPY_MAX_WORKERS);
195
+ }
196
+
197
+ ret = block_copy_task_run(aio, task);
198
+ if (ret < 0) {
199
+ goto out;
200
+ }
201
+ }
202
+
203
+out:
204
+ if (aio) {
205
+ aio_task_pool_wait_all(aio);
206
+
207
+ /*
208
+ * We are not really interested in -ECANCELED returned from
209
+ * block_copy_task_run. If it fails, it means some task already failed
210
+ * for real reason, let's return first failure.
211
+ * Still, assert that we don't rewrite failure by success.
212
+ */
213
+ assert(ret == 0 || aio_task_pool_status(aio) < 0);
214
+ ret = aio_task_pool_status(aio);
215
+
216
+ aio_task_pool_free(aio);
217
+ }
218
+ if (error_is_read && ret < 0) {
219
+ *error_is_read = call_state.error_is_read;
220
}
46
}
221
222
- return found_dirty;
223
+ return ret < 0 ? ret : found_dirty;
224
}
225
226
/*
227
--
47
--
228
2.26.2
48
2.37.3
229
230
diff view generated by jsdifflib