1
The following changes since commit 23919ddfd56135cad3cb468a8f54d5a595f024f4:
1
The following changes since commit 5375af3cd7b8adcc10c18d8083b7be63976c9645:
2
2
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190827' into staging (2019-08-27 15:52:36 +0100)
3
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-05-04 15:51:09 +0100)
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-2019-08-27
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-05-05
8
8
9
for you to fetch changes up to bb043c056cffcc2f3ce88bfdaf2e76e455c09e2c:
9
for you to fetch changes up to 4ce5dd3e9b5ee0fac18625860eb3727399ee965e:
10
10
11
iotests: Unify cache mode quoting (2019-08-27 19:48:44 +0200)
11
block/block-copy: use aio-task-pool API (2020-05-05 14:03:28 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Block patches:
15
- qemu-io now accepts a file to read a write pattern from
15
- Asynchronous copying for block-copy (i.e., the backup job)
16
- Ensure that raw files have their first block allocated so we can probe
16
- Allow resizing of qcow2 images when they have internal snapshots
17
the O_DIRECT alignment if necessary
17
- iotests: Logging improvements for Python tests
18
- Various fixes
18
- iotest 153 fix, and block comment cleanups
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
Denis Plotnikov (1):
21
Eric Blake (4):
22
qemu-io: add pattern file for write command
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
23
26
24
Max Reitz (7):
27
John Snow (14):
25
iotests: Fix _filter_img_create()
28
iotests: do a light delinting
26
vmdk: Use bdrv_dirname() for relative extent paths
29
iotests: don't use 'format' for drive_add
27
iotests: Keep testing broken relative extent paths
30
iotests: ignore import warnings from pylint
28
vmdk: Reject invalid compressed writes
31
iotests: replace mutable list default args
29
iotests: Disable broken streamOptimized tests
32
iotests: add pylintrc file
30
iotests: Disable 110 for vmdk.twoGbMaxExtentSparse
33
iotests: alphabetize standard imports
31
iotests: Disable 126 for flat vmdk subformats
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()
32
42
33
Nir Soffer (3):
43
Maxim Levitsky (1):
34
block: posix: Always allocate the first block
44
Fix iotest 153
35
iotests: Test allocate_first_block() with O_DIRECT
36
iotests: Unify cache mode quoting
37
45
38
Stefan Hajnoczi (1):
46
Vladimir Sementsov-Ogievskiy (5):
39
file-posix: fix request_alignment typo
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
40
52
41
Thomas Huth (2):
53
include/sysemu/block-backend.h | 2 +
42
iotests: Check for enabled drivers before testing them
54
block/block-backend.c | 23 +++
43
tests/check-block: Skip iotests when sanitizers are enabled
55
block/block-copy.c | 279 +++++++++++++++++--------
44
56
block/crypto.c | 9 +-
45
Vladimir Sementsov-Ogievskiy (1):
57
block/io.c | 3 +-
46
block: fix permission update in bdrv_replace_node
58
block/parallels.c | 8 +-
47
59
block/qcow.c | 8 +-
48
block.c | 5 +-
60
block/qcow2-refcount.c | 2 +-
49
block/file-posix.c | 53 +++++++++-
61
block/qcow2-snapshot.c | 20 +-
50
block/vmdk.c | 64 ++++++++----
62
block/qcow2.c | 45 ++--
51
qemu-io-cmds.c | 99 +++++++++++++++++--
63
block/qed.c | 8 +-
52
tests/check-block.sh | 5 +
64
block/sheepdog.c | 10 +-
53
tests/qemu-iotests/002 | 1 +
65
block/vdi.c | 8 +-
54
tests/qemu-iotests/003 | 1 +
66
block/vhdx.c | 8 +-
55
tests/qemu-iotests/005 | 3 +-
67
block/vmdk.c | 9 +-
56
tests/qemu-iotests/009 | 1 +
68
block/vpc.c | 8 +-
57
tests/qemu-iotests/010 | 1 +
69
block/vvfat.c | 10 +-
58
tests/qemu-iotests/011 | 1 +
70
blockdev.c | 8 +-
59
tests/qemu-iotests/017 | 3 +-
71
blockjob.c | 7 +-
60
tests/qemu-iotests/018 | 3 +-
72
tests/qemu-iotests/001 | 2 +-
61
tests/qemu-iotests/019 | 3 +-
73
tests/qemu-iotests/030 | 4 +-
62
tests/qemu-iotests/020 | 3 +-
74
tests/qemu-iotests/052 | 2 +-
63
tests/qemu-iotests/026 | 4 +-
75
tests/qemu-iotests/055 | 3 +-
64
tests/qemu-iotests/027 | 1 +
76
tests/qemu-iotests/061 | 35 ++++
65
tests/qemu-iotests/032 | 1 +
77
tests/qemu-iotests/061.out | 28 +++
66
tests/qemu-iotests/033 | 1 +
78
tests/qemu-iotests/134 | 2 +-
67
tests/qemu-iotests/034 | 3 +-
79
tests/qemu-iotests/149 | 3 +-
68
tests/qemu-iotests/037 | 3 +-
80
tests/qemu-iotests/153 | 2 +-
69
tests/qemu-iotests/039 | 4 +-
81
tests/qemu-iotests/153.out | 12 +-
70
tests/qemu-iotests/052 | 2 +-
82
tests/qemu-iotests/155 | 2 +-
71
tests/qemu-iotests/059 | 34 ++++++-
83
tests/qemu-iotests/188 | 2 +-
72
tests/qemu-iotests/059.out | 26 +++--
84
tests/qemu-iotests/194 | 4 +-
73
tests/qemu-iotests/063 | 3 +-
85
tests/qemu-iotests/202 | 4 +-
74
tests/qemu-iotests/071 | 1 +
86
tests/qemu-iotests/203 | 4 +-
75
tests/qemu-iotests/072 | 1 +
87
tests/qemu-iotests/206 | 2 +-
76
tests/qemu-iotests/081 | 4 +-
88
tests/qemu-iotests/207 | 6 +-
77
tests/qemu-iotests/091 | 4 +-
89
tests/qemu-iotests/208 | 2 +-
78
tests/qemu-iotests/099 | 1 +
90
tests/qemu-iotests/209 | 2 +-
79
tests/qemu-iotests/105 | 3 +-
91
tests/qemu-iotests/210 | 6 +-
80
tests/qemu-iotests/110 | 3 +-
92
tests/qemu-iotests/211 | 6 +-
81
tests/qemu-iotests/120 | 1 +
93
tests/qemu-iotests/212 | 6 +-
82
tests/qemu-iotests/126 | 2 +
94
tests/qemu-iotests/213 | 6 +-
83
tests/qemu-iotests/{150.out => 150.out.qcow2} | 0
95
tests/qemu-iotests/216 | 4 +-
84
tests/qemu-iotests/150.out.raw | 12 +++
96
tests/qemu-iotests/218 | 2 +-
85
tests/qemu-iotests/162 | 4 +-
97
tests/qemu-iotests/219 | 2 +-
86
tests/qemu-iotests/175 | 47 +++++++--
98
tests/qemu-iotests/222 | 7 +-
87
tests/qemu-iotests/175.out | 16 ++-
99
tests/qemu-iotests/224 | 4 +-
88
tests/qemu-iotests/178.out.qcow2 | 4 +-
100
tests/qemu-iotests/228 | 6 +-
89
tests/qemu-iotests/184 | 1 +
101
tests/qemu-iotests/234 | 4 +-
90
tests/qemu-iotests/186 | 1 +
102
tests/qemu-iotests/235 | 4 +-
91
tests/qemu-iotests/197 | 1 +
103
tests/qemu-iotests/236 | 2 +-
92
tests/qemu-iotests/215 | 1 +
104
tests/qemu-iotests/237 | 2 +-
93
tests/qemu-iotests/221.out | 12 ++-
105
tests/qemu-iotests/238 | 2 +
94
tests/qemu-iotests/251 | 1 +
106
tests/qemu-iotests/242 | 2 +-
95
tests/qemu-iotests/253.out | 12 ++-
107
tests/qemu-iotests/245 | 1 +
96
tests/qemu-iotests/common.filter | 4 +-
108
tests/qemu-iotests/245.out | 10 +-
97
tests/qemu-iotests/common.rc | 14 +++
109
tests/qemu-iotests/246 | 2 +-
98
50 files changed, 391 insertions(+), 87 deletions(-)
110
tests/qemu-iotests/248 | 2 +-
99
rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%)
111
tests/qemu-iotests/254 | 2 +-
100
create mode 100644 tests/qemu-iotests/150.out.raw
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
101
126
102
--
127
--
103
2.21.0
128
2.26.2
104
129
105
130
diff view generated by jsdifflib
New patch
1
1
From: John Snow <jsnow@redhat.com>
2
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
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
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
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
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
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
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
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
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
1
From: Thomas Huth <thuth@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
The sanitizers (especially the address sanitizer from Clang) are
3
I had to fix a merge conflict, so do this tiny harmless thing while I'm
4
sometimes printing out warnings or false positives - this spoils
4
here.
5
the output of the iotests, causing some of the tests to fail.
6
Thus let's skip the automatic iotests during "make check" when the
7
user configured QEMU with --enable-sanitizers.
8
5
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-id: 20190823084203.29734-1-thuth@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>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
12
---
13
tests/check-block.sh | 5 +++++
13
tests/qemu-iotests/iotests.py | 18 +++++++++---------
14
1 file changed, 5 insertions(+)
14
1 file changed, 9 insertions(+), 9 deletions(-)
15
15
16
diff --git a/tests/check-block.sh b/tests/check-block.sh
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/check-block.sh
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/check-block.sh
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ if grep -q "TARGET_GPROF=y" *-softmmu/config-target.mak 2>/dev/null ; then
20
@@ -XXX,XX +XXX,XX @@
21
exit 0
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
fi
22
#
23
23
24
+if grep -q "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null ; then
24
+import atexit
25
+ echo "Sanitizers are enabled ==> Not running the qemu-iotests."
25
+from collections import OrderedDict
26
+ exit 0
26
+import faulthandler
27
+fi
27
+import io
28
+
28
+import json
29
if [ -z "$(find . -name 'qemu-system-*' -print)" ]; then
29
+import logging
30
echo "No qemu-system binary available ==> Not running the qemu-iotests."
30
import os
31
exit 0
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'))
32
--
49
--
33
2.21.0
50
2.26.2
34
51
35
52
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
It is possible to enable only a subset of the block drivers with the
3
We no longer need to accommodate <3.4, drop this code.
4
"--block-drv-rw-whitelist" option of the "configure" script. All other
4
(The lines were > 79 chars and it stood out.)
5
drivers are marked as unusable (or only included as read-only with the
6
"--block-drv-ro-whitelist" option). If an iotest is now using such a
7
disabled block driver, it is failing - which is bad, since at least the
8
tests in the "auto" group should be able to deal with this situation.
9
Thus let's introduce a "_require_drivers" function that can be used by
10
the shell tests to check for the availability of certain drivers first,
11
and marks the test as "not run" if one of the drivers is missing.
12
5
13
This patch mainly targets the test in the "auto" group which should
6
Signed-off-by: John Snow <jsnow@redhat.com>
14
never fail in such a case, but also improves some of the other tests
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
along the way. Note that we also assume that the "qcow2" and "file"
8
Message-Id: <20200331000014.11581-8-jsnow@redhat.com>
16
drivers are always available - otherwise it does not make sense to
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
run "make check-block" at all (which only tests with qcow2 by default).
18
19
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Message-id: 20190823133552.11680-1-thuth@redhat.com
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
11
---
23
tests/qemu-iotests/071 | 1 +
12
tests/qemu-iotests/iotests.py | 5 +----
24
tests/qemu-iotests/081 | 4 +---
13
1 file changed, 1 insertion(+), 4 deletions(-)
25
tests/qemu-iotests/099 | 1 +
26
tests/qemu-iotests/120 | 1 +
27
tests/qemu-iotests/162 | 4 +---
28
tests/qemu-iotests/184 | 1 +
29
tests/qemu-iotests/186 | 1 +
30
tests/qemu-iotests/common.rc | 14 ++++++++++++++
31
8 files changed, 21 insertions(+), 6 deletions(-)
32
14
33
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
34
index XXXXXXX..XXXXXXX 100755
35
--- a/tests/qemu-iotests/071
36
+++ b/tests/qemu-iotests/071
37
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
38
39
_supported_fmt qcow2
40
_supported_proto file
41
+_require_drivers blkdebug blkverify
42
43
do_run_qemu()
44
{
45
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
46
index XXXXXXX..XXXXXXX 100755
47
--- a/tests/qemu-iotests/081
48
+++ b/tests/qemu-iotests/081
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
50
_supported_fmt raw
51
_supported_proto file
52
_supported_os Linux
53
+_require_drivers quorum
54
55
do_run_qemu()
56
{
57
@@ -XXX,XX +XXX,XX @@ run_qemu()
58
| _filter_qemu_io | _filter_generated_node_ids
59
}
60
61
-test_quorum=$($QEMU_IMG --help|grep quorum)
62
-[ "$test_quorum" = "" ] && _supported_fmt quorum
63
-
64
quorum="driver=raw,file.driver=quorum,file.vote-threshold=2"
65
quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
66
quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
67
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
68
index XXXXXXX..XXXXXXX 100755
69
--- a/tests/qemu-iotests/099
70
+++ b/tests/qemu-iotests/099
71
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
72
_supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc
73
_supported_proto file
74
_supported_os Linux
75
+_require_drivers blkdebug blkverify
76
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
77
"subformat=twoGbMaxExtentSparse"
78
79
diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120
80
index XXXXXXX..XXXXXXX 100755
81
--- a/tests/qemu-iotests/120
82
+++ b/tests/qemu-iotests/120
83
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
84
_supported_fmt generic
85
_supported_proto file
86
_unsupported_fmt luks
87
+_require_drivers raw
88
89
_make_test_img 64M
90
91
diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/162
94
+++ b/tests/qemu-iotests/162
95
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
96
. ./common.filter
97
98
_supported_fmt generic
99
-
100
-test_ssh=$($QEMU_IMG --help | grep '^Supported formats:.* ssh\( \|$\)')
101
-[ "$test_ssh" = "" ] && _notrun "ssh support required"
102
+_require_drivers ssh
103
104
echo
105
echo '=== NBD ==='
106
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
107
index XXXXXXX..XXXXXXX 100755
108
--- a/tests/qemu-iotests/184
109
+++ b/tests/qemu-iotests/184
110
@@ -XXX,XX +XXX,XX @@ trap "exit \$status" 0 1 2 3 15
111
. ./common.filter
112
113
_supported_os Linux
114
+_require_drivers throttle
115
116
do_run_qemu()
117
{
118
diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186
119
index XXXXXXX..XXXXXXX 100755
120
--- a/tests/qemu-iotests/186
121
+++ b/tests/qemu-iotests/186
122
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
123
124
_supported_fmt qcow2
125
_supported_proto file
126
+_require_drivers null-co
127
128
if [ "$QEMU_DEFAULT_MACHINE" != "pc" ]; then
129
_notrun "Requires a PC machine"
130
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
131
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
132
--- a/tests/qemu-iotests/common.rc
17
--- a/tests/qemu-iotests/iotests.py
133
+++ b/tests/qemu-iotests/common.rc
18
+++ b/tests/qemu-iotests/iotests.py
134
@@ -XXX,XX +XXX,XX @@ _require_command()
19
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=(), indent=None):
135
[ -x "$c" ] || _notrun "$1 utility required, skipped this test"
20
for flt in filters:
136
}
21
msg = flt(msg)
137
22
if isinstance(msg, (dict, list)):
138
+# Check that a set of drivers has been whitelisted in the QEMU binary
23
- # Python < 3.4 needs to know not to add whitespace when pretty-printing:
139
+#
24
- separators = (', ', ': ') if indent is None else (',', ': ')
140
+_require_drivers()
25
# Don't sort if it's already sorted
141
+{
26
do_sort = not isinstance(msg, OrderedDict)
142
+ available=$($QEMU -drive format=help | \
27
- print(json.dumps(msg, sort_keys=do_sort,
143
+ sed -e '/Supported formats:/!d' -e 's/Supported formats://')
28
- indent=indent, separators=separators))
144
+ for driver
29
+ print(json.dumps(msg, sort_keys=do_sort, indent=indent))
145
+ do
30
else:
146
+ if ! echo "$available" | grep -q " $driver\( \|$\)"; then
31
print(msg)
147
+ _notrun "$driver not available"
32
148
+ fi
149
+ done
150
+}
151
+
152
# make sure this script returns success
153
true
154
--
33
--
155
2.21.0
34
2.26.2
156
35
157
36
diff view generated by jsdifflib
1
iotest 126 requires backing file support, which flat vmdks cannot offer.
1
From: John Snow <jsnow@redhat.com>
2
Skip this test for such subformats.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Representing nested, recursive data structures in mypy is notoriously
5
Message-id: 20190815153638.4600-8-mreitz@redhat.com
4
difficult; the best we can reliably do right now is denote the leaf
6
Reviewed-by: John Snow <jsnow@redhat.com>
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>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
24
---
9
tests/qemu-iotests/126 | 2 ++
25
tests/qemu-iotests/iotests.py | 14 +++++++++++---
10
1 file changed, 2 insertions(+)
26
1 file changed, 11 insertions(+), 3 deletions(-)
11
27
12
diff --git a/tests/qemu-iotests/126 b/tests/qemu-iotests/126
28
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
13
index XXXXXXX..XXXXXXX 100755
29
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/126
30
--- a/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/126
31
+++ b/tests/qemu-iotests/iotests.py
16
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
32
@@ -XXX,XX +XXX,XX @@ import signal
17
33
import struct
18
# Needs backing file support
34
import subprocess
19
_supported_fmt qcow qcow2 qed vmdk
35
import sys
20
+_unsupported_imgopts "subformat=monolithicFlat" \
36
+from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
21
+ "subformat=twoGbMaxExtentFlat"
37
import unittest
22
# This is the default protocol (and we want to test the difference between
38
23
# colons which separate a protocol prefix from the rest and colons which are
39
# pylint: disable=import-error, wrong-import-position
24
# just part of the filename, so we cannot test protocols which require a prefix)
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)):
25
--
60
--
26
2.21.0
61
2.26.2
27
62
28
63
diff view generated by jsdifflib
New patch
1
1
From: John Snow <jsnow@redhat.com>
2
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
1
We had a test for a case where relative extent paths did not work, but
1
From: John Snow <jsnow@redhat.com>
2
unfortunately we just fixed the underlying problem, so it works now.
3
This patch adds a new test case that still fails.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Minor cleanup for HMP functions; helps with line length and consolidates
6
Reviewed-by: John Snow <jsnow@redhat.com>
4
HMP helpers through one implementation function.
7
Message-id: 20190815153638.4600-4-mreitz@redhat.com
5
8
Reviewed-by: John Snow <jsnow@redhat.com>
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>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
28
---
11
tests/qemu-iotests/059 | 27 +++++++++++++++++++++++++++
29
tests/qemu-iotests/iotests.py | 39 +++++++++++++++++++++--------------
12
tests/qemu-iotests/059.out | 4 ++++
30
1 file changed, 24 insertions(+), 15 deletions(-)
13
2 files changed, 31 insertions(+)
14
31
15
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
32
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100755
33
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/059
34
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/059
35
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2
36
@@ -XXX,XX +XXX,XX @@ from qemu import qtest
20
37
21
echo
38
assert sys.version_info >= (3, 6)
22
echo "=== Testing monolithicFlat with internally generated JSON file name ==="
39
23
+
40
+# Type Aliases
24
+echo '--- blkdebug ---'
41
+QMPResponse = Dict[str, Any]
25
# Should work, because bdrv_dirname() works fine with blkdebug
26
IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
27
$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
28
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TE
29
| _filter_testdir | _filter_imgfmt | _filter_img_info
30
_cleanup_test_img
31
32
+echo '--- quorum ---'
33
+# Should not work, because bdrv_dirname() does not work with quorum
34
+IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
35
+cp "$TEST_IMG" "$TEST_IMG.orig"
36
+
37
+filename="json:{
38
+ \"driver\": \"$IMGFMT\",
39
+ \"file\": {
40
+ \"driver\": \"quorum\",
41
+ \"children\": [ {
42
+ \"driver\": \"file\",
43
+ \"filename\": \"$TEST_IMG\"
44
+ }, {
45
+ \"driver\": \"file\",
46
+ \"filename\": \"$TEST_IMG.orig\"
47
+ } ],
48
+ \"vote-threshold\": 1
49
+ } }"
50
+
51
+filename=$(echo "$filename" | tr '\n' ' ' | sed -e 's/\s\+/ /g')
52
+$QEMU_IMG info "$filename" 2>&1 \
53
+ | sed -e "s/'json:[^']*'/\$QUORUM_FILE/g" \
54
+ | _filter_testdir | _filter_imgfmt | _filter_img_info
55
+
42
+
56
+
43
+
57
echo
44
faulthandler.enable()
58
echo "=== Testing version 3 ==="
45
59
_use_sample_img iotest-version3.vmdk.bz2
46
# This will not work if arguments contain spaces but is necessary if we
60
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
47
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
61
index XXXXXXX..XXXXXXX 100644
48
self._args.append(addr)
62
--- a/tests/qemu-iotests/059.out
49
return self
63
+++ b/tests/qemu-iotests/059.out
50
64
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
51
- def pause_drive(self, drive, event=None):
65
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
52
- '''Pause drive r/w operations'''
66
53
+ def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse:
67
=== Testing monolithicFlat with internally generated JSON file name ===
54
+ cmd = 'human-monitor-command'
68
+--- blkdebug ---
55
+ kwargs = {'command-line': command_line}
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
56
+ if use_log:
70
format name: IMGFMT
57
+ return self.qmp_log(cmd, **kwargs)
71
cluster size: 0 bytes
58
+ else:
72
vm state offset: 0 bytes
59
+ return self.qmp(cmd, **kwargs)
73
+--- quorum ---
60
+
74
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
61
+ def pause_drive(self, drive: str, event: Optional[str] = None) -> None:
75
+qemu-img: Could not open $QUORUM_FILE: Cannot use relative paths with VMDK descriptor file $QUORUM_FILE: Cannot generate a base directory for quorum nodes
62
+ """Pause drive r/w operations"""
76
63
if not event:
77
=== Testing version 3 ===
64
self.pause_drive(drive, "read_aio")
78
image: TEST_DIR/iotest-version3.IMGFMT
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:
79
--
93
--
80
2.21.0
94
2.26.2
81
95
82
96
diff view generated by jsdifflib
1
streamOptimized does not support writes that do not span exactly one
1
From: John Snow <jsnow@redhat.com>
2
cluster. Furthermore, it cannot rewrite already allocated clusters.
3
As such, many iotests do not work with it. Disable them.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Like script_main, but doesn't require a single point of entry.
6
Message-id: 20190815153638.4600-6-mreitz@redhat.com
4
Replace all existing initialization sections with this drop-in replacement.
7
Reviewed-by: John Snow <jsnow@redhat.com>
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]
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
14
---
10
tests/qemu-iotests/002 | 1 +
15
tests/qemu-iotests/149 | 3 +-
11
tests/qemu-iotests/003 | 1 +
16
tests/qemu-iotests/194 | 4 +-
12
tests/qemu-iotests/005 | 3 ++-
17
tests/qemu-iotests/202 | 4 +-
13
tests/qemu-iotests/009 | 1 +
18
tests/qemu-iotests/203 | 4 +-
14
tests/qemu-iotests/010 | 1 +
19
tests/qemu-iotests/206 | 2 +-
15
tests/qemu-iotests/011 | 1 +
20
tests/qemu-iotests/207 | 6 ++-
16
tests/qemu-iotests/017 | 3 ++-
21
tests/qemu-iotests/208 | 2 +-
17
tests/qemu-iotests/018 | 3 ++-
22
tests/qemu-iotests/209 | 2 +-
18
tests/qemu-iotests/019 | 3 ++-
23
tests/qemu-iotests/210 | 6 ++-
19
tests/qemu-iotests/020 | 3 ++-
24
tests/qemu-iotests/211 | 6 ++-
20
tests/qemu-iotests/027 | 1 +
25
tests/qemu-iotests/212 | 6 ++-
21
tests/qemu-iotests/032 | 1 +
26
tests/qemu-iotests/213 | 6 ++-
22
tests/qemu-iotests/033 | 1 +
27
tests/qemu-iotests/216 | 4 +-
23
tests/qemu-iotests/034 | 3 ++-
28
tests/qemu-iotests/218 | 2 +-
24
tests/qemu-iotests/037 | 3 ++-
29
tests/qemu-iotests/219 | 2 +-
25
tests/qemu-iotests/063 | 3 ++-
30
tests/qemu-iotests/222 | 7 ++--
26
tests/qemu-iotests/072 | 1 +
31
tests/qemu-iotests/224 | 4 +-
27
tests/qemu-iotests/105 | 3 ++-
32
tests/qemu-iotests/228 | 6 ++-
28
tests/qemu-iotests/197 | 1 +
33
tests/qemu-iotests/234 | 4 +-
29
tests/qemu-iotests/215 | 1 +
34
tests/qemu-iotests/235 | 4 +-
30
tests/qemu-iotests/251 | 1 +
35
tests/qemu-iotests/236 | 2 +-
31
21 files changed, 30 insertions(+), 9 deletions(-)
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(-)
32
54
33
diff --git a/tests/qemu-iotests/002 b/tests/qemu-iotests/002
55
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
34
index XXXXXXX..XXXXXXX 100755
56
index XXXXXXX..XXXXXXX 100755
35
--- a/tests/qemu-iotests/002
57
--- a/tests/qemu-iotests/149
36
+++ b/tests/qemu-iotests/002
58
+++ b/tests/qemu-iotests/149
37
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
59
@@ -XXX,XX +XXX,XX @@ def test_once(config, qemu_img=False):
38
60
39
_supported_fmt generic
61
40
_supported_proto generic
62
# Obviously we only work with the luks image format
41
+_unsupported_imgopts "subformat=streamOptimized"
63
-iotests.verify_image_format(supported_fmts=['luks'])
42
64
-iotests.verify_platform()
43
65
+iotests.script_initialize(supported_fmts=['luks'])
44
size=128M
66
45
diff --git a/tests/qemu-iotests/003 b/tests/qemu-iotests/003
67
# We need sudo in order to run cryptsetup to create
46
index XXXXXXX..XXXXXXX 100755
68
# dm-crypt devices. This is safe to use on any
47
--- a/tests/qemu-iotests/003
69
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
48
+++ b/tests/qemu-iotests/003
70
index XXXXXXX..XXXXXXX 100755
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
71
--- a/tests/qemu-iotests/194
50
72
+++ b/tests/qemu-iotests/194
51
_supported_fmt generic
73
@@ -XXX,XX +XXX,XX @@
52
_supported_proto generic
74
53
+_unsupported_imgopts "subformat=streamOptimized"
75
import iotests
54
76
55
size=128M
77
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw'])
56
offset=67M
78
-iotests.verify_platform(['linux'])
57
diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005
79
+iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'],
58
index XXXXXXX..XXXXXXX 100755
80
+ supported_platforms=['linux'])
59
--- a/tests/qemu-iotests/005
81
60
+++ b/tests/qemu-iotests/005
82
with iotests.FilePath('source.img') as source_img_path, \
61
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
83
iotests.FilePath('dest.img') as dest_img_path, \
62
_supported_proto generic
84
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
63
_supported_os Linux
85
index XXXXXXX..XXXXXXX 100755
64
_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
86
--- a/tests/qemu-iotests/202
65
- "subformat=twoGbMaxExtentSparse"
87
+++ b/tests/qemu-iotests/202
66
+ "subformat=twoGbMaxExtentSparse" \
88
@@ -XXX,XX +XXX,XX @@
67
+ "subformat=streamOptimized"
89
68
90
import iotests
69
# vpc is limited to 127GB, so we can't test it here
91
70
if [ "$IMGFMT" = "vpc" ]; then
92
-iotests.verify_image_format(supported_fmts=['qcow2'])
71
diff --git a/tests/qemu-iotests/009 b/tests/qemu-iotests/009
93
-iotests.verify_platform(['linux'])
72
index XXXXXXX..XXXXXXX 100755
94
+iotests.script_initialize(supported_fmts=['qcow2'],
73
--- a/tests/qemu-iotests/009
95
+ supported_platforms=['linux'])
74
+++ b/tests/qemu-iotests/009
96
75
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
97
with iotests.FilePath('disk0.img') as disk0_img_path, \
76
98
iotests.FilePath('disk1.img') as disk1_img_path, \
77
_supported_fmt generic
99
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
78
_supported_proto generic
100
index XXXXXXX..XXXXXXX 100755
79
+_unsupported_imgopts "subformat=streamOptimized"
101
--- a/tests/qemu-iotests/203
80
102
+++ b/tests/qemu-iotests/203
81
103
@@ -XXX,XX +XXX,XX @@
82
size=6G
104
83
diff --git a/tests/qemu-iotests/010 b/tests/qemu-iotests/010
105
import iotests
84
index XXXXXXX..XXXXXXX 100755
106
85
--- a/tests/qemu-iotests/010
107
-iotests.verify_image_format(supported_fmts=['qcow2'])
86
+++ b/tests/qemu-iotests/010
108
-iotests.verify_platform(['linux'])
87
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
109
+iotests.script_initialize(supported_fmts=['qcow2'],
88
110
+ supported_platforms=['linux'])
89
_supported_fmt generic
111
90
_supported_proto generic
112
with iotests.FilePath('disk0.img') as disk0_img_path, \
91
+_unsupported_imgopts "subformat=streamOptimized"
113
iotests.FilePath('disk1.img') as disk1_img_path, \
92
114
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
93
115
index XXXXXXX..XXXXXXX 100755
94
size=6G
116
--- a/tests/qemu-iotests/206
95
diff --git a/tests/qemu-iotests/011 b/tests/qemu-iotests/011
117
+++ b/tests/qemu-iotests/206
96
index XXXXXXX..XXXXXXX 100755
118
@@ -XXX,XX +XXX,XX @@
97
--- a/tests/qemu-iotests/011
119
import iotests
98
+++ b/tests/qemu-iotests/011
120
from iotests import imgfmt
99
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
121
100
122
-iotests.verify_image_format(supported_fmts=['qcow2'])
101
_supported_fmt generic
123
+iotests.script_initialize(supported_fmts=['qcow2'])
102
_supported_proto generic
124
103
+_unsupported_imgopts "subformat=streamOptimized"
125
with iotests.FilePath('t.qcow2') as disk_path, \
104
126
iotests.FilePath('t.qcow2.base') as backing_path, \
105
127
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
106
size=6G
128
index XXXXXXX..XXXXXXX 100755
107
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
129
--- a/tests/qemu-iotests/207
108
index XXXXXXX..XXXXXXX 100755
130
+++ b/tests/qemu-iotests/207
109
--- a/tests/qemu-iotests/017
131
@@ -XXX,XX +XXX,XX @@ import iotests
110
+++ b/tests/qemu-iotests/017
132
import subprocess
111
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
133
import re
112
_supported_fmt qcow qcow2 vmdk qed
134
113
_supported_proto generic
135
-iotests.verify_image_format(supported_fmts=['raw'])
114
_unsupported_proto vxhs
136
-iotests.verify_protocol(supported=['ssh'])
115
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
137
+iotests.script_initialize(
116
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
138
+ supported_fmts=['raw'],
117
+ "subformat=streamOptimized"
139
+ supported_protocols=['ssh'],
118
140
+)
119
TEST_OFFSETS="0 4294967296"
141
120
142
def filter_hash(qmsg):
121
diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018
143
def _filter(key, value):
122
index XXXXXXX..XXXXXXX 100755
144
diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208
123
--- a/tests/qemu-iotests/018
145
index XXXXXXX..XXXXXXX 100755
124
+++ b/tests/qemu-iotests/018
146
--- a/tests/qemu-iotests/208
125
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
147
+++ b/tests/qemu-iotests/208
126
_supported_fmt qcow qcow2 vmdk qed
148
@@ -XXX,XX +XXX,XX @@
127
_supported_proto file
149
128
_supported_os Linux
150
import iotests
129
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
151
130
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
152
-iotests.verify_image_format(supported_fmts=['generic'])
131
+ "streamOptimized"
153
+iotests.script_initialize(supported_fmts=['generic'])
132
154
133
TEST_OFFSETS="0 4294967296"
155
with iotests.FilePath('disk.img') as disk_img_path, \
134
156
iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \
135
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
157
diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209
136
index XXXXXXX..XXXXXXX 100755
158
index XXXXXXX..XXXXXXX 100755
137
--- a/tests/qemu-iotests/019
159
--- a/tests/qemu-iotests/209
138
+++ b/tests/qemu-iotests/019
160
+++ b/tests/qemu-iotests/209
139
@@ -XXX,XX +XXX,XX @@ _supported_proto file
161
@@ -XXX,XX +XXX,XX @@ import iotests
140
_supported_os Linux
162
from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \
141
_unsupported_imgopts "subformat=monolithicFlat" \
163
file_path
142
"subformat=twoGbMaxExtentFlat" \
164
143
- "subformat=twoGbMaxExtentSparse"
165
-iotests.verify_image_format(supported_fmts=['qcow2'])
144
+ "subformat=twoGbMaxExtentSparse" \
166
+iotests.script_initialize(supported_fmts=['qcow2'])
145
+ "subformat=streamOptimized"
167
146
168
disk = file_path('disk')
147
TEST_OFFSETS="0 4294967296"
169
nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
148
CLUSTER_SIZE=65536
170
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
149
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
171
index XXXXXXX..XXXXXXX 100755
150
index XXXXXXX..XXXXXXX 100755
172
--- a/tests/qemu-iotests/210
151
--- a/tests/qemu-iotests/020
173
+++ b/tests/qemu-iotests/210
152
+++ b/tests/qemu-iotests/020
174
@@ -XXX,XX +XXX,XX @@
153
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed
175
import iotests
154
_supported_proto file
176
from iotests import imgfmt
155
_unsupported_imgopts "subformat=monolithicFlat" \
177
156
"subformat=twoGbMaxExtentFlat" \
178
-iotests.verify_image_format(supported_fmts=['luks'])
157
- "subformat=twoGbMaxExtentSparse"
179
-iotests.verify_protocol(supported=['file'])
158
+ "subformat=twoGbMaxExtentSparse" \
180
+iotests.script_initialize(
159
+ "subformat=streamOptimized"
181
+ supported_fmts=['luks'],
160
182
+ supported_protocols=['file'],
161
TEST_OFFSETS="0 4294967296"
183
+)
162
184
163
diff --git a/tests/qemu-iotests/027 b/tests/qemu-iotests/027
185
with iotests.FilePath('t.luks') as disk_path, \
164
index XXXXXXX..XXXXXXX 100755
186
iotests.VM() as vm:
165
--- a/tests/qemu-iotests/027
187
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
166
+++ b/tests/qemu-iotests/027
188
index XXXXXXX..XXXXXXX 100755
167
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
189
--- a/tests/qemu-iotests/211
168
190
+++ b/tests/qemu-iotests/211
169
_supported_fmt vmdk qcow qcow2 qed
191
@@ -XXX,XX +XXX,XX @@
170
_supported_proto generic
192
import iotests
171
+_unsupported_imgopts "subformat=streamOptimized"
193
from iotests import imgfmt
172
194
173
195
-iotests.verify_image_format(supported_fmts=['vdi'])
174
size=128M
196
-iotests.verify_protocol(supported=['file'])
175
diff --git a/tests/qemu-iotests/032 b/tests/qemu-iotests/032
197
+iotests.script_initialize(
176
index XXXXXXX..XXXXXXX 100755
198
+ supported_fmts=['vdi'],
177
--- a/tests/qemu-iotests/032
199
+ supported_protocols=['file'],
178
+++ b/tests/qemu-iotests/032
200
+)
179
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
201
180
# This works for any image format (though unlikely to segfault for raw)
202
def blockdev_create(vm, options):
181
_supported_fmt generic
203
error = vm.blockdev_create(options)
182
_supported_proto generic
204
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
183
+_unsupported_imgopts "subformat=streamOptimized"
205
index XXXXXXX..XXXXXXX 100755
184
206
--- a/tests/qemu-iotests/212
185
echo
207
+++ b/tests/qemu-iotests/212
186
echo === Prepare image ===
208
@@ -XXX,XX +XXX,XX @@
187
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
209
import iotests
188
index XXXXXXX..XXXXXXX 100755
210
from iotests import imgfmt
189
--- a/tests/qemu-iotests/033
211
190
+++ b/tests/qemu-iotests/033
212
-iotests.verify_image_format(supported_fmts=['parallels'])
191
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
213
-iotests.verify_protocol(supported=['file'])
192
214
+iotests.script_initialize(
193
_supported_fmt generic
215
+ supported_fmts=['parallels'],
194
_supported_proto generic
216
+ supported_protocols=['file'],
195
+_unsupported_imgopts "subformat=streamOptimized"
217
+)
196
218
197
219
with iotests.FilePath('t.parallels') as disk_path, \
198
size=128M
220
iotests.VM() as vm:
199
diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034
221
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
200
index XXXXXXX..XXXXXXX 100755
222
index XXXXXXX..XXXXXXX 100755
201
--- a/tests/qemu-iotests/034
223
--- a/tests/qemu-iotests/213
202
+++ b/tests/qemu-iotests/034
224
+++ b/tests/qemu-iotests/213
203
@@ -XXX,XX +XXX,XX @@ _supported_proto file
225
@@ -XXX,XX +XXX,XX @@
204
_supported_os Linux
226
import iotests
205
_unsupported_imgopts "subformat=monolithicFlat" \
227
from iotests import imgfmt
206
"subformat=twoGbMaxExtentFlat" \
228
207
- "subformat=twoGbMaxExtentSparse"
229
-iotests.verify_image_format(supported_fmts=['vhdx'])
208
+ "subformat=twoGbMaxExtentSparse" \
230
-iotests.verify_protocol(supported=['file'])
209
+ "subformat=streamOptimized"
231
+iotests.script_initialize(
210
232
+ supported_fmts=['vhdx'],
211
CLUSTER_SIZE=4k
233
+ supported_protocols=['file'],
212
size=128M
234
+)
213
diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037
235
214
index XXXXXXX..XXXXXXX 100755
236
with iotests.FilePath('t.vhdx') as disk_path, \
215
--- a/tests/qemu-iotests/037
237
iotests.VM() as vm:
216
+++ b/tests/qemu-iotests/037
238
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
217
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed
239
index XXXXXXX..XXXXXXX 100755
218
_supported_proto file
240
--- a/tests/qemu-iotests/216
219
_unsupported_imgopts "subformat=monolithicFlat" \
241
+++ b/tests/qemu-iotests/216
220
"subformat=twoGbMaxExtentFlat" \
242
@@ -XXX,XX +XXX,XX @@ import iotests
221
- "subformat=twoGbMaxExtentSparse"
243
from iotests import log, qemu_img, qemu_io_silent
222
+ "subformat=twoGbMaxExtentSparse" \
244
223
+ "subformat=streamOptimized"
245
# Need backing file support
224
246
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
225
CLUSTER_SIZE=4k
247
-iotests.verify_platform(['linux'])
226
size=128M
248
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
227
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
249
+ supported_platforms=['linux'])
228
index XXXXXXX..XXXXXXX 100755
250
229
--- a/tests/qemu-iotests/063
251
log('')
230
+++ b/tests/qemu-iotests/063
252
log('=== Copy-on-read across nodes ===')
231
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed raw
253
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
232
_supported_proto file
254
index XXXXXXX..XXXXXXX 100755
233
_unsupported_imgopts "subformat=monolithicFlat" \
255
--- a/tests/qemu-iotests/218
234
"subformat=twoGbMaxExtentFlat" \
256
+++ b/tests/qemu-iotests/218
235
- "subformat=twoGbMaxExtentSparse"
257
@@ -XXX,XX +XXX,XX @@
236
+ "subformat=twoGbMaxExtentSparse" \
258
import iotests
237
+ "subformat=streamOptimized"
259
from iotests import log, qemu_img, qemu_io_silent
238
260
239
_make_test_img 4M
261
-iotests.verify_image_format(supported_fmts=['qcow2', 'raw'])
240
262
+iotests.script_initialize(supported_fmts=['qcow2', 'raw'])
241
diff --git a/tests/qemu-iotests/072 b/tests/qemu-iotests/072
263
242
index XXXXXXX..XXXXXXX 100755
264
243
--- a/tests/qemu-iotests/072
265
# Launches the VM, adds two null-co nodes (source and target), and
244
+++ b/tests/qemu-iotests/072
266
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
245
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
267
index XXXXXXX..XXXXXXX 100755
246
268
--- a/tests/qemu-iotests/219
247
_supported_fmt vpc vmdk vhdx vdi qed qcow2 qcow
269
+++ b/tests/qemu-iotests/219
248
_supported_proto file
270
@@ -XXX,XX +XXX,XX @@
249
+_unsupported_imgopts "subformat=streamOptimized"
271
250
272
import iotests
251
IMG_SIZE=64M
273
252
274
-iotests.verify_image_format(supported_fmts=['qcow2'])
253
diff --git a/tests/qemu-iotests/105 b/tests/qemu-iotests/105
275
+iotests.script_initialize(supported_fmts=['qcow2'])
254
index XXXXXXX..XXXXXXX 100755
276
255
--- a/tests/qemu-iotests/105
277
img_size = 4 * 1024 * 1024
256
+++ b/tests/qemu-iotests/105
278
257
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
279
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
258
_supported_fmt qcow2 vmdk vhdx qed
280
index XXXXXXX..XXXXXXX 100755
259
_supported_proto generic
281
--- a/tests/qemu-iotests/222
260
_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
282
+++ b/tests/qemu-iotests/222
261
- "subformat=twoGbMaxExtentSparse"
283
@@ -XXX,XX +XXX,XX @@
262
+ "subformat=twoGbMaxExtentSparse" \
284
import iotests
263
+ "subformat=streamOptimized"
285
from iotests import log, qemu_img, qemu_io, qemu_io_silent
264
286
265
echo
287
-iotests.verify_platform(['linux'])
266
echo "creating large image"
288
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk',
267
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
289
- 'vhdx', 'raw'])
268
index XXXXXXX..XXXXXXX 100755
290
+iotests.script_initialize(
269
--- a/tests/qemu-iotests/197
291
+ supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
270
+++ b/tests/qemu-iotests/197
292
+ supported_platforms=['linux'],
271
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
293
+)
272
_supported_proto generic
294
273
# LUKS support may be possible, but it complicates things.
295
patterns = [("0x5d", "0", "64k"),
274
_unsupported_fmt luks
296
("0xd5", "1M", "64k"),
275
+_unsupported_imgopts "subformat=streamOptimized"
297
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
276
298
index XXXXXXX..XXXXXXX 100755
277
echo
299
--- a/tests/qemu-iotests/224
278
echo '=== Copy-on-read ==='
300
+++ b/tests/qemu-iotests/224
279
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
301
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
280
index XXXXXXX..XXXXXXX 100755
302
import json
281
--- a/tests/qemu-iotests/215
303
282
+++ b/tests/qemu-iotests/215
304
# Need backing file support (for arbitrary backing formats)
283
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
305
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
284
_supported_proto generic
306
-iotests.verify_platform(['linux'])
285
# LUKS support may be possible, but it complicates things.
307
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed'],
286
_unsupported_fmt luks
308
+ supported_platforms=['linux'])
287
+_unsupported_imgopts "subformat=streamOptimized"
309
288
310
289
echo
311
# There are two variations of this test:
290
echo '=== Copy-on-read ==='
312
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
291
diff --git a/tests/qemu-iotests/251 b/tests/qemu-iotests/251
313
index XXXXXXX..XXXXXXX 100755
292
index XXXXXXX..XXXXXXX 100755
314
--- a/tests/qemu-iotests/228
293
--- a/tests/qemu-iotests/251
315
+++ b/tests/qemu-iotests/228
294
+++ b/tests/qemu-iotests/251
316
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
295
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
317
filter_qmp_testfiles, filter_qmp_imgfmt
296
_supported_fmt generic
318
297
_supported_proto file
319
# Need backing file and change-backing-file support
298
_supported_os Linux
320
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
299
+_unsupported_imgopts "subformat=streamOptimized"
321
-iotests.verify_platform(['linux'])
300
322
+iotests.script_initialize(
301
if [ "$IMGOPTSSYNTAX" = "true" ]; then
323
+ supported_fmts=['qcow2', 'qed'],
302
# We use json:{} filenames here, so we cannot work with additional options.
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)
303
--
747
--
304
2.21.0
748
2.26.2
305
749
306
750
diff view generated by jsdifflib
1
Compressed writes generally have to write full clusters, not just in
1
From: John Snow <jsnow@redhat.com>
2
theory but also in practice when it comes to vmdk's streamOptimized
3
subformat. It currently is just silently broken for writes with
4
non-zero in-cluster offsets:
5
2
6
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
3
Since this one is nicely factored to use a single entry point,
7
$ qemu-io -c 'write 4k 4k' -c 'read 4k 4k' foo.vmdk
4
use script_main to run the tests.
8
wrote 4096/4096 bytes at offset 4096
9
4 KiB, 1 ops; 00.01 sec (443.724 KiB/sec and 110.9309 ops/sec)
10
read failed: Invalid argument
11
5
12
(The technical reason is that vmdk_write_extent() just writes the
6
Signed-off-by: John Snow <jsnow@redhat.com>
13
incomplete compressed data actually to offset 4k. When reading the
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
data, vmdk_read_extent() looks at offset 0 and finds the compressed data
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
size to be 0, because that is what it reads from there. This yields an
9
Message-Id: <20200331000014.11581-13-jsnow@redhat.com>
16
error.)
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
18
For incomplete writes with zero in-cluster offsets, the error path when
19
reading the rest of the cluster is a bit different, but the result is
20
the same:
21
22
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
23
$ qemu-io -c 'write 0k 4k' -c 'read 4k 4k' foo.vmdk
24
wrote 4096/4096 bytes at offset 0
25
4 KiB, 1 ops; 00.01 sec (362.641 KiB/sec and 90.6603 ops/sec)
26
read failed: Invalid argument
27
28
(Here, vmdk_read_extent() finds the data and then sees that the
29
uncompressed data is short.)
30
31
It is better to reject invalid writes than to make the user believe they
32
might have succeeded and then fail when trying to read it back.
33
34
Signed-off-by: Max Reitz <mreitz@redhat.com>
35
Reviewed-by: John Snow <jsnow@redhat.com>
36
Message-id: 20190815153638.4600-5-mreitz@redhat.com
37
Reviewed-by: John Snow <jsnow@redhat.com>
38
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
39
---
12
---
40
block/vmdk.c | 10 ++++++++++
13
tests/qemu-iotests/258 | 11 ++++-------
41
1 file changed, 10 insertions(+)
14
1 file changed, 4 insertions(+), 7 deletions(-)
42
15
43
diff --git a/block/vmdk.c b/block/vmdk.c
16
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
44
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100755
45
--- a/block/vmdk.c
18
--- a/tests/qemu-iotests/258
46
+++ b/block/vmdk.c
19
+++ b/tests/qemu-iotests/258
47
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
20
@@ -XXX,XX +XXX,XX @@ import iotests
48
if (extent->compressed) {
21
from iotests import log, qemu_img, qemu_io_silent, \
49
void *compressed_data;
22
filter_qmp_testfiles, filter_qmp_imgfmt
50
23
51
+ /* Only whole clusters */
24
-# Need backing file and change-backing-file support
52
+ if (offset_in_cluster ||
25
-iotests.script_initialize(
53
+ n_bytes > (extent->cluster_sectors * SECTOR_SIZE) ||
26
- supported_fmts=['qcow2', 'qed'],
54
+ (n_bytes < (extent->cluster_sectors * SECTOR_SIZE) &&
27
- supported_platforms=['linux'],
55
+ offset + n_bytes != extent->end_sector * SECTOR_SIZE))
28
-)
56
+ {
29
-
57
+ ret = -EINVAL;
30
# Returns a node for blockdev-add
58
+ goto out;
31
def node(node_name, path, backing=None, fmt=None, throttle=None):
59
+ }
32
if fmt is None:
60
+
33
@@ -XXX,XX +XXX,XX @@ def main():
61
if (!extent->has_marker) {
34
test_concurrent_finish(False)
62
ret = -EINVAL;
35
63
goto out;
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'])
64
--
42
--
65
2.21.0
43
2.26.2
66
44
67
45
diff view generated by jsdifflib
1
fe646693acc changed qemu-img create's output so that it no longer prints
1
From: John Snow <jsnow@redhat.com>
2
single quotes around parameter values. The subformat and adapter_type
3
filters in _filter_img_create() have never been adapted to that change.
4
2
5
Fixes: fe646693acc13ac48b98435d14149ab04dc597bc
3
Mark the verify functions as "private" with a leading underscore, to
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
discourage their use. Update type signatures while we're here.
7
Reviewed-by: John Snow <jsnow@redhat.com>
5
8
Message-id: 20190815153638.4600-2-mreitz@redhat.com
6
(Also, make pending patches not yet using the new entry points fail in a
9
Reviewed-by: John Snow <jsnow@redhat.com>
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>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
14
---
12
tests/qemu-iotests/059.out | 16 ++++++++--------
15
tests/qemu-iotests/iotests.py | 23 +++++++++++++----------
13
tests/qemu-iotests/common.filter | 4 ++--
16
1 file changed, 13 insertions(+), 10 deletions(-)
14
2 files changed, 10 insertions(+), 10 deletions(-)
15
17
16
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/059.out
20
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/059.out
21
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
22
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
21
qemu-io: can't open device TEST_DIR/t.vmdk: L1 size too big
23
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
22
24
' [case not run] ' + reason + '\n')
23
=== Testing monolithicFlat creation and opening ===
25
24
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
26
-def verify_image_format(supported_fmts=(), unsupported_fmts=()):
25
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
27
+def _verify_image_format(supported_fmts: Sequence[str] = (),
26
image: TEST_DIR/t.IMGFMT
28
+ unsupported_fmts: Sequence[str] = ()) -> None:
27
file format: IMGFMT
29
assert not (supported_fmts and unsupported_fmts)
28
virtual size: 2 GiB (2147483648 bytes)
30
29
31
if 'generic' in supported_fmts and \
30
=== Testing monolithicFlat with zeroed_grain ===
32
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=(), unsupported_fmts=()):
31
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
33
if not_sup or (imgfmt in unsupported_fmts):
32
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
34
notrun('not suitable for this image format: %s' % imgfmt)
33
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
35
34
36
-def verify_protocol(supported=(), unsupported=()):
35
=== Testing big twoGbMaxExtentFlat ===
37
+def _verify_protocol(supported: Sequence[str] = (),
36
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMaxExtentFlat
38
+ unsupported: Sequence[str] = ()) -> None:
37
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000
39
assert not (supported and unsupported)
38
image: TEST_DIR/t.vmdk
40
39
file format: vmdk
41
if 'generic' in supported:
40
virtual size: 0.977 TiB (1073741824000 bytes)
42
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
41
@@ -XXX,XX +XXX,XX @@ Format specific information:
43
if not_sup or (imgproto in unsupported):
42
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
44
notrun('not suitable for this protocol: %s' % imgproto)
43
45
44
=== Testing truncated sparse ===
46
-def verify_platform(supported=(), unsupported=()):
45
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400 subformat=monolithicSparse
47
+def _verify_platform(supported: Sequence[str] = (),
46
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
48
+ unsupported: Sequence[str] = ()) -> None:
47
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': File truncated, expecting at least 13172736 bytes
49
if any((sys.platform.startswith(x) for x in unsupported)):
48
50
notrun('not suitable for this OS: %s' % sys.platform)
49
=== Converting to streamOptimized from image with small cluster size===
51
50
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
52
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=(), unsupported=()):
51
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
if not any((sys.platform.startswith(x) for x in supported)):
52
54
notrun('not suitable for this OS: %s' % sys.platform)
53
=== Testing monolithicFlat with internally generated JSON file name ===
55
54
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 subformat=monolithicFlat
56
-def verify_cache_mode(supported_cache_modes=()):
55
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
57
+def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
56
qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
58
if supported_cache_modes and (cachemode not in supported_cache_modes):
57
59
notrun('not suitable for this cache mode: %s' % cachemode)
58
=== Testing version 3 ===
60
59
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 64931328
61
-def verify_aio_mode(supported_aio_modes=()):
60
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
62
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
61
63
if supported_aio_modes and (aiomode not in supported_aio_modes):
62
=== Testing 4TB monolithicFlat creation and IO ===
64
notrun('not suitable for this aio mode: %s' % aiomode)
63
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4398046511104 subformat=monolithicFlat
65
64
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4398046511104
66
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
65
image: TEST_DIR/t.IMGFMT
67
sys.stderr.write('Please run this test via the "check" script\n')
66
file format: IMGFMT
68
sys.exit(os.EX_USAGE)
67
virtual size: 4 TiB (4398046511104 bytes)
69
68
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 966367641600
70
- verify_image_format(supported_fmts, unsupported_fmts)
69
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
- verify_protocol(supported_protocols, unsupported_protocols)
70
72
- verify_platform(supported=supported_platforms)
71
=== Testing qemu-img map on extents ===
73
- verify_cache_mode(supported_cache_modes)
72
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544 subformat=monolithicSparse
74
- verify_aio_mode(supported_aio_modes)
73
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544
75
+ _verify_image_format(supported_fmts, unsupported_fmts)
74
wrote 1024/1024 bytes at offset 65024
76
+ _verify_protocol(supported_protocols, unsupported_protocols)
75
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
77
+ _verify_platform(supported=supported_platforms)
76
wrote 1024/1024 bytes at offset 2147483136
78
+ _verify_cache_mode(supported_cache_modes)
77
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
79
+ _verify_aio_mode(supported_aio_modes)
78
0 0x20000 0x3f0000 TEST_DIR/t.vmdk
80
79
0x7fff0000 0x20000 0x410000 TEST_DIR/t.vmdk
81
debug = '-d' in sys.argv
80
0x140000000 0x10000 0x430000 TEST_DIR/t.vmdk
82
if debug:
81
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544 subformat=twoGbMaxExtentSparse
82
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544
83
wrote 1024/1024 bytes at offset 65024
84
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
85
wrote 1024/1024 bytes at offset 2147483136
86
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
87
index XXXXXXX..XXXXXXX 100644
88
--- a/tests/qemu-iotests/common.filter
89
+++ b/tests/qemu-iotests/common.filter
90
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
91
-e "s# compat6=\\(on\\|off\\)##g" \
92
-e "s# static=\\(on\\|off\\)##g" \
93
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
94
- -e "s# subformat='[^']*'##g" \
95
- -e "s# adapter_type='[^']*'##g" \
96
+ -e "s# subformat=[^ ]*##g" \
97
+ -e "s# adapter_type=[^ ]*##g" \
98
-e "s# hwversion=[^ ]*##g" \
99
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
100
-e "s# block_size=[0-9]\\+##g" \
101
--
83
--
102
2.21.0
84
2.26.2
103
85
104
86
diff view generated by jsdifflib
New patch
1
1
From: John Snow <jsnow@redhat.com>
2
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
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
The patch allows to provide a pattern file for write
3
There are several callers that need to create a new block backend from
4
command. There was no similar ability before.
4
an existing BDS; make the task slightly easier with a common helper
5
5
routine.
6
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
6
7
Message-id: 20190820164616.4072-1-dplotnikov@virtuozzo.com
7
Suggested-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
[mreitz: Keep optstring in alphabetical order]
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>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
15
---
12
qemu-io-cmds.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++---
16
include/sysemu/block-backend.h | 2 ++
13
1 file changed, 93 insertions(+), 6 deletions(-)
17
block/block-backend.c | 23 +++++++++++++++++++++++
14
18
block/crypto.c | 9 ++++-----
15
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
19
block/parallels.c | 8 ++++----
16
index XXXXXXX..XXXXXXX 100644
20
block/qcow.c | 8 ++++----
17
--- a/qemu-io-cmds.c
21
block/qcow2.c | 18 ++++++++----------
18
+++ b/qemu-io-cmds.c
22
block/qed.c | 8 ++++----
19
@@ -XXX,XX +XXX,XX @@ static void qemu_io_free(void *p)
23
block/sheepdog.c | 10 +++++-----
20
qemu_vfree(p);
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;
21
}
51
}
22
52
23
+/*
53
+/*
24
+ * qemu_io_alloc_from_file()
54
+ * Create a new BlockBackend connected to an existing BlockDriverState.
25
+ *
55
+ *
26
+ * Allocates the buffer and populates it with the content of the given file
56
+ * @perm is a bitmasks of BLK_PERM_* constants which describes the
27
+ * up to @len bytes. If the file length is less than @len, then the buffer
57
+ * permissions to request for @bs that is attached to this
28
+ * is populated with the file content cyclically.
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().
29
+ *
61
+ *
30
+ * @blk - the block backend where the buffer content is going to be written to
62
+ * Return the new BlockBackend on success, null on failure.
31
+ * @len - the buffer length
32
+ * @file_name - the file to read the content from
33
+ *
34
+ * Returns: the buffer pointer on success
35
+ * NULL on error
36
+ */
63
+ */
37
+static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
64
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
38
+ const char *file_name)
65
+ uint64_t shared_perm, Error **errp)
39
+{
66
+{
40
+ char *buf, *buf_origin;
67
+ BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
41
+ FILE *f = fopen(file_name, "r");
42
+ int pattern_len;
43
+
68
+
44
+ if (!f) {
69
+ if (blk_insert_bs(blk, bs, errp) < 0) {
45
+ perror(file_name);
70
+ blk_unref(blk);
46
+ return NULL;
71
+ return NULL;
47
+ }
72
+ }
48
+
73
+ return blk;
49
+ if (qemuio_misalign) {
50
+ len += MISALIGN_OFFSET;
51
+ }
52
+
53
+ buf_origin = buf = blk_blockalign(blk, len);
54
+
55
+ if (qemuio_misalign) {
56
+ buf_origin += MISALIGN_OFFSET;
57
+ buf += MISALIGN_OFFSET;
58
+ len -= MISALIGN_OFFSET;
59
+ }
60
+
61
+ pattern_len = fread(buf_origin, 1, len, f);
62
+
63
+ if (ferror(f)) {
64
+ perror(file_name);
65
+ goto error;
66
+ }
67
+
68
+ if (pattern_len == 0) {
69
+ fprintf(stderr, "%s: file is empty\n", file_name);
70
+ goto error;
71
+ }
72
+
73
+ fclose(f);
74
+
75
+ if (len > pattern_len) {
76
+ len -= pattern_len;
77
+ buf += pattern_len;
78
+
79
+ while (len > 0) {
80
+ size_t len_to_copy = MIN(pattern_len, len);
81
+
82
+ memcpy(buf, buf_origin, len_to_copy);
83
+
84
+ len -= len_to_copy;
85
+ buf += len_to_copy;
86
+ }
87
+ }
88
+
89
+ return buf_origin;
90
+
91
+error:
92
+ qemu_io_free(buf_origin);
93
+ return NULL;
94
+}
74
+}
95
+
75
+
96
static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
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,
97
{
326
{
98
uint64_t i;
327
BlockBackend *blk;
99
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
328
BlockJob *job;
100
" -n, -- with -z, don't allow slow fallback\n"
329
- int ret;
101
" -p, -- ignored for backwards compatibility\n"
330
102
" -P, -- use different pattern to fill file\n"
331
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
103
+" -s, -- use a pattern file to fill the write buffer\n"
332
job_id = bdrv_get_device_name(bs);
104
" -C, -- report statistics in a machine parsable format\n"
333
}
105
" -q, -- quiet mode, do not show I/O statistics\n"
334
106
" -u, -- with -z, allow unmapping\n"
335
- blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
107
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = {
336
- ret = blk_insert_bs(blk, bs, errp);
108
.perm = BLK_PERM_WRITE,
337
- if (ret < 0) {
109
.argmin = 2,
338
- blk_unref(blk);
110
.argmax = -1,
339
+ blk = blk_new_with_bs(bs, perm, shared_perm, errp);
111
- .args = "[-bcCfnquz] [-P pattern] off len",
340
+ if (!blk) {
112
+ .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
341
return NULL;
113
.oneline = "writes a number of bytes at a specified offset",
342
}
114
.help = write_help,
343
115
};
116
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
117
{
118
struct timespec t1, t2;
119
bool Cflag = false, qflag = false, bflag = false;
120
- bool Pflag = false, zflag = false, cflag = false;
121
+ bool Pflag = false, zflag = false, cflag = false, sflag = false;
122
int flags = 0;
123
int c, cnt, ret;
124
char *buf = NULL;
125
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
126
/* Some compilers get confused and warn if this is not initialized. */
127
int64_t total = 0;
128
int pattern = 0xcd;
129
+ const char *file_name = NULL;
130
131
- while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
132
+ while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
133
switch (c) {
134
case 'b':
135
bflag = true;
136
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
137
case 'q':
138
qflag = true;
139
break;
140
+ case 's':
141
+ sflag = true;
142
+ file_name = optarg;
143
+ break;
144
case 'u':
145
flags |= BDRV_REQ_MAY_UNMAP;
146
break;
147
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
148
return -EINVAL;
149
}
150
151
- if (zflag && Pflag) {
152
- printf("-z and -P cannot be specified at the same time\n");
153
+ if (zflag + Pflag + sflag > 1) {
154
+ printf("Only one of -z, -P, and -s "
155
+ "can be specified at the same time\n");
156
return -EINVAL;
157
}
158
159
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
160
}
161
162
if (!zflag) {
163
- buf = qemu_io_alloc(blk, count, pattern);
164
+ if (sflag) {
165
+ buf = qemu_io_alloc_from_file(blk, count, file_name);
166
+ if (!buf) {
167
+ return -EINVAL;
168
+ }
169
+ } else {
170
+ buf = qemu_io_alloc(blk, count, pattern);
171
+ }
172
}
173
174
clock_gettime(CLOCK_MONOTONIC, &t1);
175
--
344
--
176
2.21.0
345
2.26.2
177
346
178
347
diff view generated by jsdifflib
New patch
1
1
From: Eric Blake <eblake@redhat.com>
2
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
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
Fixes: a6b257a08e3d72219f03e461a52152672fec0612
3
Our comment did not actually match the code. Rewrite the comment to
4
("file-posix: Handle undetectable alignment")
4
be less sensitive to any future changes to qcow2-bitmap.c that might
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
implement scenarios that we currently reject.
6
Message-id: 20190827101328.4062-1-stefanha@redhat.com
6
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
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>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
11
---
10
block/file-posix.c | 2 +-
12
block/qcow2.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
14
13
diff --git a/block/file-posix.c b/block/file-posix.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
17
--- a/block/qcow2.c
16
+++ b/block/file-posix.c
18
+++ b/block/qcow2.c
17
@@ -XXX,XX +XXX,XX @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
18
for (i = 0; i < ARRAY_SIZE(alignments); i++) {
20
goto fail;
19
align = alignments[i];
21
}
20
if (raw_is_io_aligned(fd, buf + align, max_align)) {
22
21
- /* Fallback to request_aligment. */
23
- /* cannot proceed if image has bitmaps */
22
+ /* Fallback to request_alignment. */
24
+ /* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */
23
s->buf_align = (align != 1) ? align : bs->bl.request_alignment;
25
if (qcow2_truncate_bitmaps_check(bs, errp)) {
24
break;
26
ret = -ENOTSUP;
25
}
27
goto fail;
26
--
28
--
27
2.21.0
29
2.26.2
28
30
29
31
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
Quoting cache mode is not needed, and most tests use unquoted values.
3
It's been a while since we got rid of the sector-based bdrv_read and
4
Unify all test to use the same style.
4
bdrv_write (commit 2e11d756); let's finish the job on a few remaining
5
comments.
5
6
6
Message-id: 20190827173432.7656-1-nsoffer@redhat.com
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
8
Message-Id: <20200428213807.776655-1-eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
11
---
10
tests/qemu-iotests/026 | 4 ++--
12
block/io.c | 3 ++-
11
tests/qemu-iotests/039 | 4 ++--
13
block/qcow2-refcount.c | 2 +-
12
tests/qemu-iotests/052 | 2 +-
14
block/vvfat.c | 10 +++++-----
13
tests/qemu-iotests/091 | 4 ++--
15
tests/qemu-iotests/001 | 2 +-
14
4 files changed, 7 insertions(+), 7 deletions(-)
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(-)
15
20
16
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
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
17
index XXXXXXX..XXXXXXX 100755
94
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/026
95
--- a/tests/qemu-iotests/001
19
+++ b/tests/qemu-iotests/026
96
+++ b/tests/qemu-iotests/001
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
97
@@ -XXX,XX +XXX,XX @@
21
# Currently only qcow2 supports rebasing
98
#!/usr/bin/env bash
22
_supported_fmt qcow2
99
#
23
_supported_proto file
100
-# Test simple read/write using plain bdrv_read/bdrv_write
24
-_default_cache_mode "writethrough"
101
+# Test simple read/write using plain bdrv_pread/bdrv_pwrite
25
-_supported_cache_modes "writethrough" "none"
102
#
26
+_default_cache_mode writethrough
103
# Copyright (C) 2009 Red Hat, Inc.
27
+_supported_cache_modes writethrough none
104
#
28
# The refcount table tests expect a certain minimum width for refcount entries
29
# (so that the refcount table actually needs to grow); that minimum is 16 bits,
30
# being the default refcount entry width.
31
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
32
index XXXXXXX..XXXXXXX 100755
33
--- a/tests/qemu-iotests/039
34
+++ b/tests/qemu-iotests/039
35
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
36
_supported_fmt qcow2
37
_supported_proto file
38
_supported_os Linux
39
-_default_cache_mode "writethrough"
40
-_supported_cache_modes "writethrough"
41
+_default_cache_mode writethrough
42
+_supported_cache_modes writethrough
43
44
size=128M
45
46
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
105
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
47
index XXXXXXX..XXXXXXX 100755
106
index XXXXXXX..XXXXXXX 100755
48
--- a/tests/qemu-iotests/052
107
--- a/tests/qemu-iotests/052
49
+++ b/tests/qemu-iotests/052
108
+++ b/tests/qemu-iotests/052
50
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
109
@@ -XXX,XX +XXX,XX @@
51
_supported_proto file
110
#!/usr/bin/env bash
52
111
#
53
# Don't do O_DIRECT on tmpfs
112
-# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT
54
-_supported_cache_modes "writeback" "writethrough" "unsafe"
113
+# Test bdrv_pread/bdrv_pwrite using BDRV_O_SNAPSHOT
55
+_supported_cache_modes writeback writethrough unsafe
114
#
56
115
# Copyright (C) 2013 Red Hat, Inc.
57
size=128M
116
#
58
_make_test_img $size
117
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
59
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
60
index XXXXXXX..XXXXXXX 100755
118
index XXXXXXX..XXXXXXX 100755
61
--- a/tests/qemu-iotests/091
119
--- a/tests/qemu-iotests/134
62
+++ b/tests/qemu-iotests/091
120
+++ b/tests/qemu-iotests/134
63
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
121
@@ -XXX,XX +XXX,XX @@
64
_supported_fmt qcow2
122
#!/usr/bin/env bash
65
_supported_proto file
123
#
66
_supported_os Linux
124
-# Test encrypted read/write using plain bdrv_read/bdrv_write
67
-_default_cache_mode "none"
125
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
68
-_supported_cache_modes "writethrough" "none" "writeback"
126
#
69
+_default_cache_mode none
127
# Copyright (C) 2015 Red Hat, Inc.
70
+_supported_cache_modes writethrough none writeback
128
#
71
129
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
72
size=1G
130
index XXXXXXX..XXXXXXX 100755
73
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
#
74
--
141
--
75
2.21.0
142
2.26.2
76
143
77
144
diff view generated by jsdifflib
1
The error message for the test case where we have a quorum node for
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
which no directory name can be generated is different: For
3
twoGbMaxExtentSparse, it complains that it cannot open the extent file.
4
For other (sub)formats, it just notes that it cannot determine the
5
backing file path. Both are fine, but just disable twoGbMaxExtentSparse
6
for simplicity's sake.
7
2
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Commit f62514b3def5fb2acbef64d0e053c0c31fa45aff made qemu-img reject -o "" but this test uses it.
9
Reviewed-by: John Snow <jsnow@redhat.com>
4
Since this test only tries to do a dry-run run of qemu-img amend,
10
Message-id: 20190815153638.4600-7-mreitz@redhat.com
5
replace the -o "" with dummy -o "size=$size".
11
Reviewed-by: John Snow <jsnow@redhat.com>
6
7
Fixes: f62514b3def5fb2acbef64d0e053c0c31fa45aff
8
9
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Message-Id: <20200504131959.9533-1-mlevitsk@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
12
---
14
tests/qemu-iotests/110 | 3 ++-
13
tests/qemu-iotests/153 | 2 +-
15
1 file changed, 2 insertions(+), 1 deletion(-)
14
tests/qemu-iotests/153.out | 12 ++++++------
15
2 files changed, 7 insertions(+), 7 deletions(-)
16
16
17
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
17
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
18
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/110
19
--- a/tests/qemu-iotests/153
20
+++ b/tests/qemu-iotests/110
20
+++ b/tests/qemu-iotests/153
21
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
21
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
22
# Any format supporting backing files
22
_run_cmd $QEMU_IMG check $L "${TEST_IMG}"
23
_supported_fmt qed qcow qcow2 vmdk
23
_run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}"
24
_supported_proto file
24
_run_cmd $QEMU_IMG map $L "${TEST_IMG}"
25
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
25
- _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}"
26
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
26
+ _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}"
27
+ "subformat=twoGbMaxExtentSparse"
27
_run_cmd $QEMU_IMG commit $L "${TEST_IMG}"
28
28
_run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size
29
TEST_IMG_REL=$(basename "$TEST_IMG")
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
30
87
31
--
88
--
32
2.21.0
89
2.26.2
33
90
34
91
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
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
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Using block_resize we can test allocate_first_block() with file
3
We are going to use aio-task-pool API, so tasks will be handled in
4
descriptor opened with O_DIRECT, ensuring that it works for any size
4
parallel. We need therefore separate allocated task on each iteration.
5
larger than 4096 bytes.
5
Introduce this logic now.
6
6
7
Testing smaller sizes is tricky as the result depends on the filesystem
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
used for testing. For example on NFS any size will work since O_DIRECT
9
does not require any alignment.
10
11
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20190827010528.8818-3-nsoffer@redhat.com
9
Message-Id: <20200429130847.28124-3-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
11
---
16
tests/qemu-iotests/175 | 28 ++++++++++++++++++++++++++++
12
block/block-copy.c | 18 +++++++++++-------
17
tests/qemu-iotests/175.out | 8 ++++++++
13
1 file changed, 11 insertions(+), 7 deletions(-)
18
2 files changed, 36 insertions(+)
19
14
20
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
15
diff --git a/block/block-copy.c b/block/block-copy.c
21
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/175
17
--- a/block/block-copy.c
23
+++ b/tests/qemu-iotests/175
18
+++ b/block/block-copy.c
24
@@ -XXX,XX +XXX,XX @@ _filter_blocks()
19
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
25
-e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/"
26
}
20
}
27
21
28
+# Resize image using block_resize.
22
/* Called only on full-dirty region */
29
+# Parameter 1: image path
23
-static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
30
+# Parameter 2: new size
24
- int64_t offset, int64_t bytes)
31
+_block_resize()
25
+static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
32
+{
26
+ int64_t offset, int64_t bytes)
33
+ local path=$1
27
{
34
+ local size=$2
28
+ BlockCopyTask *task = g_new(BlockCopyTask, 1);
35
+
29
+
36
+ $QEMU -qmp stdio -nographic -nodefaults \
30
assert(!find_conflicting_task(s, offset, bytes));
37
+ -blockdev file,node-name=file,filename=$path,cache.direct=on \
31
38
+ <<EOF
32
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
39
+{'execute': 'qmp_capabilities'}
33
@@ -XXX,XX +XXX,XX @@ static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
40
+{'execute': 'block_resize', 'arguments': {'node-name': 'file', 'size': $size}}
34
task->bytes = bytes;
41
+{'execute': 'quit'}
35
qemu_co_queue_init(&task->wait_queue);
42
+EOF
36
QLIST_INSERT_HEAD(&s->tasks, task, list);
43
+}
44
+
37
+
45
# get standard environment, filters and checks
38
+ return task;
46
. ./common.rc
39
}
47
. ./common.filter
40
48
@@ -XXX,XX +XXX,XX @@ _supported_fmt raw
41
/*
49
_supported_proto file
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
50
_supported_os Linux
43
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
51
44
52
+_default_cache_mode none
45
while (bytes) {
53
+_supported_cache_modes none directsync
46
- BlockCopyTask task;
54
+
47
+ g_autofree BlockCopyTask *task = NULL;
55
size=$((1 * 1024 * 1024))
48
int64_t next_zero, cur_bytes, status_bytes;
56
49
57
touch "$TEST_DIR/empty"
50
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
58
@@ -XXX,XX +XXX,XX @@ for mode in off full falloc; do
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
59
stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
52
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
60
done
53
cur_bytes = next_zero - offset;
61
54
}
62
+for new_size in 4096 1048576; do
55
- block_copy_task_begin(s, &task, offset, cur_bytes);
63
+ echo
56
+ task = block_copy_task_create(s, offset, cur_bytes);
64
+ echo "== resize empty image with block_resize =="
57
65
+ _make_test_img 0 | _filter_imgfmt
58
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
66
+ _block_resize $TEST_IMG $new_size >/dev/null
59
assert(ret >= 0); /* never fail */
67
+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size
60
cur_bytes = MIN(cur_bytes, status_bytes);
68
+done
61
- block_copy_task_shrink(s, &task, cur_bytes);
69
+
62
+ block_copy_task_shrink(s, task, cur_bytes);
70
# success, all done
63
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
71
echo "*** done"
64
- block_copy_task_end(s, &task, 0);
72
rm -f $seq.full
65
+ block_copy_task_end(s, task, 0);
73
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
66
progress_set_remaining(s->progress,
74
index XXXXXXX..XXXXXXX 100644
67
bdrv_get_dirty_count(s->copy_bitmap) +
75
--- a/tests/qemu-iotests/175.out
68
s->in_flight_bytes);
76
+++ b/tests/qemu-iotests/175.out
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
77
@@ -XXX,XX +XXX,XX @@ size=1048576, max allocation
70
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
78
== creating image with preallocation falloc ==
71
error_is_read);
79
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
72
co_put_to_shres(s->mem, cur_bytes);
80
size=1048576, max allocation
73
- block_copy_task_end(s, &task, ret);
81
+
74
+ block_copy_task_end(s, task, ret);
82
+== resize empty image with block_resize ==
75
if (ret < 0) {
83
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
76
return ret;
84
+size=4096, min allocation
77
}
85
+
86
+== resize empty image with block_resize ==
87
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
88
+size=1048576, min allocation
89
*** done
90
--
78
--
91
2.21.0
79
2.26.2
92
80
93
81
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
It's wrong to OR shared permissions. It may lead to crash on further
3
We are going to use aio-task-pool API, so we'll need state pointer in
4
permission updates.
4
BlockCopyTask anyway. Add it now and use where possible.
5
Also, no needs to consider previously calculated permissions, as at
6
this point we already bind all new parents and bdrv_get_cumulative_perm
7
result is enough. So fix the bug by just set permissions by
8
bdrv_get_cumulative_perm result.
9
10
Bug was introduced in long ago 234ac1a9025, in 2.9.
11
5
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-id: 20190824100740.61635-1-vsementsov@virtuozzo.com
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200429130847.28124-4-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
10
---
16
block.c | 5 ++---
11
block/block-copy.c | 28 +++++++++++++++-------------
17
1 file changed, 2 insertions(+), 3 deletions(-)
12
1 file changed, 15 insertions(+), 13 deletions(-)
18
13
19
diff --git a/block.c b/block.c
14
diff --git a/block/block-copy.c b/block/block-copy.c
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
16
--- a/block/block-copy.c
22
+++ b/block.c
17
+++ b/block/block-copy.c
23
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
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)
24
{
48
{
25
BdrvChild *c, *next;
49
if (new_bytes == task->bytes) {
26
GSList *list = NULL, *p;
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
27
- uint64_t old_perm, old_shared;
51
28
uint64_t perm = 0, shared = BLK_PERM_ALL;
52
assert(new_bytes > 0 && new_bytes < task->bytes);
29
int ret;
53
30
54
- s->in_flight_bytes -= task->bytes - new_bytes;
31
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
55
- bdrv_set_dirty_bitmap(s->copy_bitmap,
32
bdrv_unref(from);
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);
33
}
73
}
34
74
QLIST_REMOVE(task, list);
35
- bdrv_get_cumulative_perm(to, &old_perm, &old_shared);
75
qemu_co_queue_restart_all(&task->wait_queue);
36
- bdrv_set_perm(to, old_perm | perm, old_shared | shared);
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
37
+ bdrv_get_cumulative_perm(to, &perm, &shared);
77
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
38
+ bdrv_set_perm(to, perm, shared);
78
assert(ret >= 0); /* never fail */
39
79
cur_bytes = MIN(cur_bytes, status_bytes);
40
out:
80
- block_copy_task_shrink(s, task, cur_bytes);
41
g_slist_free(list);
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
}
42
--
97
--
43
2.21.0
98
2.26.2
44
99
45
100
diff view generated by jsdifflib
1
This makes iotest 033 pass with e.g. subformat=monolithicFlat. It also
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
turns a former error in 059 into success.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Instead of just relying on the comment "Called only on full-dirty
5
Message-id: 20190815153638.4600-3-mreitz@redhat.com
4
region" in block_copy_task_create() let's move initial dirty area
6
Reviewed-by: John Snow <jsnow@redhat.com>
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>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
13
---
9
block/vmdk.c | 54 ++++++++++++++++++++++++--------------
14
block/block-copy.c | 80 ++++++++++++++++++++++++++--------------------
10
tests/qemu-iotests/059 | 7 +++--
15
1 file changed, 46 insertions(+), 34 deletions(-)
11
tests/qemu-iotests/059.out | 4 ++-
12
3 files changed, 42 insertions(+), 23 deletions(-)
13
16
14
diff --git a/block/vmdk.c b/block/vmdk.c
17
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vmdk.c
19
--- a/block/block-copy.c
17
+++ b/block/vmdk.c
20
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@ static const char *next_line(const char *s)
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;
19
}
35
}
20
36
21
static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
37
-/* Called only on full-dirty region */
22
- const char *desc_file_path, QDict *options,
38
+/*
23
- Error **errp)
39
+ * Search for the first dirty area in offset/bytes range and create task at
24
+ QDict *options, Error **errp)
40
+ * the beginning of it.
41
+ */
42
static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
43
int64_t offset, int64_t bytes)
25
{
44
{
26
int ret;
45
- BlockCopyTask *task = g_new(BlockCopyTask, 1);
27
int matches;
46
+ BlockCopyTask *task;
28
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
47
29
const char *p, *np;
48
+ if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap,
30
int64_t sectors = 0;
49
+ offset, offset + bytes,
31
int64_t flat_offset;
50
+ s->copy_size, &offset, &bytes))
32
+ char *desc_file_dir = NULL;
51
+ {
33
char *extent_path;
52
+ return NULL;
34
BdrvChild *extent_file;
53
+ }
35
BDRVVmdkState *s = bs->opaque;
54
+
36
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
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;
37
continue;
128
continue;
38
}
129
}
39
130
40
- if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
131
- trace_block_copy_process(s, offset);
41
- !desc_file_path[0])
132
+ trace_block_copy_process(s, task->offset);
42
- {
133
43
- bdrv_refresh_filename(bs->file->bs);
134
- co_get_from_shres(s->mem, cur_bytes);
44
- error_setg(errp, "Cannot use relative extent paths with VMDK "
135
- ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
45
- "descriptor file '%s'", bs->file->bs->filename);
136
- error_is_read);
46
- return -EINVAL;
137
- co_put_to_shres(s->mem, cur_bytes);
47
- }
138
+ co_get_from_shres(s->mem, task->bytes);
48
+ if (path_is_absolute(fname)) {
139
+ ret = block_copy_do_copy(s, task->offset, task->bytes,
49
+ extent_path = g_strdup(fname);
140
+ ret & BDRV_BLOCK_ZERO, error_is_read);
50
+ } else {
141
+ co_put_to_shres(s->mem, task->bytes);
51
+ if (!desc_file_dir) {
142
block_copy_task_end(task, ret);
52
+ desc_file_dir = bdrv_dirname(bs->file->bs, errp);
143
if (ret < 0) {
53
+ if (!desc_file_dir) {
144
return ret;
54
+ bdrv_refresh_filename(bs->file->bs);
55
+ error_prepend(errp, "Cannot use relative paths with VMDK "
56
+ "descriptor file '%s': ",
57
+ bs->file->bs->filename);
58
+ ret = -EINVAL;
59
+ goto out;
60
+ }
61
+ }
62
63
- extent_path = path_combine(desc_file_path, fname);
64
+ extent_path = g_strconcat(desc_file_dir, fname, NULL);
65
+ }
66
67
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
68
assert(ret < 32);
69
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
70
g_free(extent_path);
71
if (local_err) {
72
error_propagate(errp, local_err);
73
- return -EINVAL;
74
+ ret = -EINVAL;
75
+ goto out;
76
}
145
}
77
146
78
/* save to extents array */
147
- progress_work_done(s->progress, cur_bytes);
79
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
148
- s->progress_bytes_callback(cur_bytes, s->progress_opaque);
80
0, 0, 0, 0, 0, &extent, errp);
149
- offset += cur_bytes;
81
if (ret < 0) {
150
- bytes -= cur_bytes;
82
bdrv_unref_child(bs, extent_file);
151
+ progress_work_done(s->progress, task->bytes);
83
- return ret;
152
+ s->progress_bytes_callback(task->bytes, s->progress_opaque);
84
+ goto out;
153
+ offset = task_end(task);
85
}
154
+ bytes = end - offset;
86
extent->flat_start_offset = flat_offset << 9;
87
} else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
88
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
89
g_free(buf);
90
if (ret) {
91
bdrv_unref_child(bs, extent_file);
92
- return ret;
93
+ goto out;
94
}
95
extent = &s->extents[s->num_extents - 1];
96
} else if (!strcmp(type, "SESPARSE")) {
97
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
98
if (ret) {
99
bdrv_unref_child(bs, extent_file);
100
- return ret;
101
+ goto out;
102
}
103
extent = &s->extents[s->num_extents - 1];
104
} else {
105
error_setg(errp, "Unsupported extent type '%s'", type);
106
bdrv_unref_child(bs, extent_file);
107
- return -ENOTSUP;
108
+ ret = -ENOTSUP;
109
+ goto out;
110
}
111
extent->type = g_strdup(type);
112
}
155
}
113
- return 0;
156
114
+
157
return found_dirty;
115
+ ret = 0;
116
+ goto out;
117
118
invalid:
119
np = next_line(p);
120
@@ -XXX,XX +XXX,XX @@ invalid:
121
np--;
122
}
123
error_setg(errp, "Invalid extent line: %.*s", (int)(np - p), p);
124
- return -EINVAL;
125
+ ret = -EINVAL;
126
+
127
+out:
128
+ g_free(desc_file_dir);
129
+ return ret;
130
}
131
132
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
133
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
134
}
135
s->create_type = g_strdup(ct);
136
s->desc_offset = 0;
137
- ret = vmdk_parse_extents(buf, bs, bs->file->bs->exact_filename, options,
138
- errp);
139
+ ret = vmdk_parse_extents(buf, bs, options, errp);
140
exit:
141
return ret;
142
}
143
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
144
index XXXXXXX..XXXXXXX 100755
145
--- a/tests/qemu-iotests/059
146
+++ b/tests/qemu-iotests/059
147
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2
148
149
echo
150
echo "=== Testing monolithicFlat with internally generated JSON file name ==="
151
+# Should work, because bdrv_dirname() works fine with blkdebug
152
IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
153
-$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" 2>&1 \
154
- | _filter_testdir | _filter_imgfmt
155
+$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
156
+ -c info \
157
+ 2>&1 \
158
+ | _filter_testdir | _filter_imgfmt | _filter_img_info
159
_cleanup_test_img
160
161
echo
162
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
163
index XXXXXXX..XXXXXXX 100644
164
--- a/tests/qemu-iotests/059.out
165
+++ b/tests/qemu-iotests/059.out
166
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
167
168
=== Testing monolithicFlat with internally generated JSON file name ===
169
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
170
-qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
171
+format name: IMGFMT
172
+cluster size: 0 bytes
173
+vm state offset: 0 bytes
174
175
=== Testing version 3 ===
176
image: TEST_DIR/iotest-version3.IMGFMT
177
--
158
--
178
2.21.0
159
2.26.2
179
160
180
161
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
When creating an image with preallocation "off" or "falloc", the first
3
Run block_copy iterations in parallel in aio tasks.
4
block of the image is typically not allocated. When using Gluster
4
5
storage backed by XFS filesystem, reading this block using direct I/O
5
Changes:
6
succeeds regardless of request length, fooling alignment detection.
6
- BlockCopyTask becomes aio task structure. Add zeroes field to pass
7
7
it to block_copy_do_copy
8
In this case we fallback to a safe value (4096) instead of the optimal
8
- add call state - it's a state of one call of block_copy(), shared
9
value (512), which may lead to unneeded data copying when aligning
9
between parallel tasks. For now used only to keep information about
10
requests. Allocating the first block avoids the fallback.
10
first error: is it read or not.
11
11
- convert block_copy_dirty_clusters to aio-task loop.
12
Since we allocate the first block even with preallocation=off, we no
12
13
longer create images with zero disk size:
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
14
Message-Id: <20200429130847.28124-6-vsementsov@virtuozzo.com>
15
$ ./qemu-img create -f raw test.raw 1g
16
Formatting 'test.raw', fmt=raw size=1073741824
17
18
$ ls -lhs test.raw
19
4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw
20
21
And converting the image requires additional cluster:
22
23
$ ./qemu-img measure -f raw -O qcow2 test.raw
24
required size: 458752
25
fully allocated size: 1074135040
26
27
When using format like vmdk with multiple files per image, we allocate
28
one block per file:
29
30
$ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g
31
Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat
32
33
$ ls -lhs test*.vmdk
34
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk
35
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk
36
4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk
37
38
I did quick performance test for copying disks with qemu-img convert to
39
new raw target image to Gluster storage with sector size of 512 bytes:
40
41
for i in $(seq 10); do
42
rm -f dst.raw
43
sleep 10
44
time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw
45
done
46
47
Here is a table comparing the total time spent:
48
49
Type Before(s) After(s) Diff(%)
50
---------------------------------------
51
real 530.028 469.123 -11.4
52
user 17.204 10.768 -37.4
53
sys 17.881 7.011 -60.7
54
55
We can see very clear improvement in CPU usage.
56
57
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
58
Message-id: 20190827010528.8818-2-nsoffer@redhat.com
59
Reviewed-by: Max Reitz <mreitz@redhat.com>
60
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
61
---
16
---
62
block/file-posix.c | 51 +++++++++++++++++++
17
block/block-copy.c | 119 ++++++++++++++++++++++++++++++++++++++++-----
63
tests/qemu-iotests/059.out | 2 +-
18
1 file changed, 106 insertions(+), 13 deletions(-)
64
tests/qemu-iotests/{150.out => 150.out.qcow2} | 0
19
65
tests/qemu-iotests/150.out.raw | 12 +++++
20
diff --git a/block/block-copy.c b/block/block-copy.c
66
tests/qemu-iotests/175 | 19 ++++---
67
tests/qemu-iotests/175.out | 8 +--
68
tests/qemu-iotests/178.out.qcow2 | 4 +-
69
tests/qemu-iotests/221.out | 12 +++--
70
tests/qemu-iotests/253.out | 12 +++--
71
9 files changed, 99 insertions(+), 21 deletions(-)
72
rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%)
73
create mode 100644 tests/qemu-iotests/150.out.raw
74
75
diff --git a/block/file-posix.c b/block/file-posix.c
76
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
77
--- a/block/file-posix.c
22
--- a/block/block-copy.c
78
+++ b/block/file-posix.c
23
+++ b/block/block-copy.c
79
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_discard(void *opaque)
24
@@ -XXX,XX +XXX,XX @@
25
#include "block/block-copy.h"
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
{
61
BlockCopyTask *task;
62
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
63
64
task = g_new(BlockCopyTask, 1);
65
*task = (BlockCopyTask) {
66
+ .task.func = block_copy_task_entry,
67
.s = s,
68
+ .call_state = call_state,
69
.offset = offset,
70
.bytes = bytes,
71
};
72
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
73
s->progress = pm;
74
}
75
76
+/*
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:
80
return ret;
112
return ret;
81
}
113
}
82
114
83
+/*
115
+static coroutine_fn int block_copy_task_entry(AioTask *task)
84
+ * Help alignment probing by allocating the first block.
85
+ *
86
+ * When reading with direct I/O from unallocated area on Gluster backed by XFS,
87
+ * reading succeeds regardless of request length. In this case we fallback to
88
+ * safe alignment which is not optimal. Allocating the first block avoids this
89
+ * fallback.
90
+ *
91
+ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or
92
+ * request alignment, so we use safe values.
93
+ *
94
+ * Returns: 0 on success, -errno on failure. Since this is an optimization,
95
+ * caller may ignore failures.
96
+ */
97
+static int allocate_first_block(int fd, size_t max_size)
98
+{
116
+{
99
+ size_t write_size = (max_size < MAX_BLOCKSIZE)
117
+ BlockCopyTask *t = container_of(task, BlockCopyTask, task);
100
+ ? BDRV_SECTOR_SIZE
118
+ bool error_is_read;
101
+ : MAX_BLOCKSIZE;
102
+ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize());
103
+ void *buf;
104
+ ssize_t n;
105
+ int ret;
119
+ int ret;
106
+
120
+
107
+ buf = qemu_memalign(max_align, write_size);
121
+ ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
108
+ memset(buf, 0, write_size);
122
+ &error_is_read);
109
+
123
+ if (ret < 0 && !t->call_state->failed) {
110
+ do {
124
+ t->call_state->failed = true;
111
+ n = pwrite(fd, buf, write_size, 0);
125
+ t->call_state->error_is_read = error_is_read;
112
+ } while (n == -1 && errno == EINTR);
126
+ } else {
113
+
127
+ progress_work_done(t->s->progress, t->bytes);
114
+ ret = (n == -1) ? -errno : 0;
128
+ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
115
+
129
+ }
116
+ qemu_vfree(buf);
130
+ co_put_to_shres(t->s->mem, t->bytes);
131
+ block_copy_task_end(t, ret);
132
+
117
+ return ret;
133
+ return ret;
118
+}
134
+}
119
+
135
+
120
static int handle_aiocb_truncate(void *opaque)
136
static int block_copy_block_status(BlockCopyState *s, int64_t offset,
137
int64_t bytes, int64_t *pnum)
121
{
138
{
122
RawPosixAIOData *aiocb = opaque;
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
123
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(void *opaque)
140
int ret = 0;
124
/* posix_fallocate() doesn't set errno. */
141
bool found_dirty = false;
125
error_setg_errno(errp, -result,
142
int64_t end = offset + bytes;
126
"Could not preallocate new data");
143
+ AioTaskPool *aio = NULL;
127
+ } else if (current_length == 0) {
144
+ BlockCopyCallState call_state = {false, false};
128
+ /*
145
129
+ * posix_fallocate() uses fallocate() if the filesystem
146
/*
130
+ * supports it, or fallback to manually writing zeroes. If
147
* block_copy() user is responsible for keeping source and target in same
131
+ * fallocate() was used, unaligned reads from the fallocated
148
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
132
+ * area in raw_probe_alignment() will succeed, hence we need to
149
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
133
+ * allocate the first block.
150
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
134
+ *
151
135
+ * Optimize future alignment probing; ignore failures.
152
- while (bytes) {
136
+ */
153
- g_autofree BlockCopyTask *task = NULL;
137
+ allocate_first_block(fd, offset);
154
+ while (bytes && aio_task_pool_status(aio) == 0) {
138
}
155
+ BlockCopyTask *task;
139
} else {
156
int64_t status_bytes;
140
result = 0;
157
141
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(void *opaque)
158
- task = block_copy_task_create(s, offset, bytes);
142
if (ftruncate(fd, offset) != 0) {
159
+ task = block_copy_task_create(s, &call_state, offset, bytes);
143
result = -errno;
160
if (!task) {
144
error_setg_errno(errp, -result, "Could not resize file");
161
/* No more dirty bits in the bitmap */
145
+ } else if (current_length == 0 && offset > current_length) {
162
trace_block_copy_skip_range(s, offset, bytes);
146
+ /* Optimize future alignment probing; ignore failures. */
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
147
+ allocate_first_block(fd, offset);
148
}
164
}
149
return result;
165
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
150
default:
166
block_copy_task_end(task, 0);
151
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
167
+ g_free(task);
152
index XXXXXXX..XXXXXXX 100644
168
progress_set_remaining(s->progress,
153
--- a/tests/qemu-iotests/059.out
169
bdrv_get_dirty_count(s->copy_bitmap) +
154
+++ b/tests/qemu-iotests/059.out
170
s->in_flight_bytes);
155
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
156
image: TEST_DIR/t.vmdk
172
bytes = end - offset;
157
file format: vmdk
173
continue;
158
virtual size: 0.977 TiB (1073741824000 bytes)
174
}
159
-disk size: 16 KiB
175
+ task->zeroes = ret & BDRV_BLOCK_ZERO;
160
+disk size: 1.97 MiB
176
161
Format specific information:
177
trace_block_copy_process(s, task->offset);
162
cid: XXXXXXXX
178
163
parent cid: XXXXXXXX
179
co_get_from_shres(s->mem, task->bytes);
164
diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out.qcow2
180
- ret = block_copy_do_copy(s, task->offset, task->bytes,
165
similarity index 100%
181
- ret & BDRV_BLOCK_ZERO, error_is_read);
166
rename from tests/qemu-iotests/150.out
182
- co_put_to_shres(s->mem, task->bytes);
167
rename to tests/qemu-iotests/150.out.qcow2
183
- block_copy_task_end(task, ret);
168
diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw
184
- if (ret < 0) {
169
new file mode 100644
185
- return ret;
170
index XXXXXXX..XXXXXXX
186
- }
171
--- /dev/null
187
172
+++ b/tests/qemu-iotests/150.out.raw
188
- progress_work_done(s->progress, task->bytes);
173
@@ -XXX,XX +XXX,XX @@
189
- s->progress_bytes_callback(task->bytes, s->progress_opaque);
174
+QA output created by 150
190
offset = task_end(task);
175
+
191
bytes = end - offset;
176
+=== Mapping sparse conversion ===
192
+
177
+
193
+ if (!aio && bytes) {
178
+Offset Length File
194
+ aio = aio_task_pool_new(BLOCK_COPY_MAX_WORKERS);
179
+0 0x1000 TEST_DIR/t.IMGFMT
195
+ }
180
+
196
+
181
+=== Mapping non-sparse conversion ===
197
+ ret = block_copy_task_run(aio, task);
182
+
198
+ if (ret < 0) {
183
+Offset Length File
199
+ goto out;
184
+0 0x100000 TEST_DIR/t.IMGFMT
200
+ }
185
+*** done
201
+ }
186
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
202
+
187
index XXXXXXX..XXXXXXX 100755
203
+out:
188
--- a/tests/qemu-iotests/175
204
+ if (aio) {
189
+++ b/tests/qemu-iotests/175
205
+ aio_task_pool_wait_all(aio);
190
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
206
+
191
# the file size. This function hides the resulting difference in the
207
+ /*
192
# stat -c '%b' output.
208
+ * We are not really interested in -ECANCELED returned from
193
# Parameter 1: Number of blocks an empty file occupies
209
+ * block_copy_task_run. If it fails, it means some task already failed
194
-# Parameter 2: Image size in bytes
210
+ * for real reason, let's return first failure.
195
+# Parameter 2: Minimal number of blocks in an image
211
+ * Still, assert that we don't rewrite failure by success.
196
+# Parameter 3: Image size in bytes
212
+ */
197
_filter_blocks()
213
+ assert(ret == 0 || aio_task_pool_status(aio) < 0);
198
{
214
+ ret = aio_task_pool_status(aio);
199
extra_blocks=$1
215
+
200
- img_size=$2
216
+ aio_task_pool_free(aio);
201
+ min_blocks=$2
217
+ }
202
+ img_size=$3
218
+ if (error_is_read && ret < 0) {
203
219
+ *error_is_read = call_state.error_is_read;
204
- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \
220
}
205
- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/"
221
206
+ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \
222
- return found_dirty;
207
+ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/"
223
+ return ret < 0 ? ret : found_dirty;
208
}
224
}
209
225
210
# get standard environment, filters and checks
226
/*
211
@@ -XXX,XX +XXX,XX @@ size=$((1 * 1024 * 1024))
212
touch "$TEST_DIR/empty"
213
extra_blocks=$(stat -c '%b' "$TEST_DIR/empty")
214
215
+# We always write the first byte; check how many blocks this filesystem
216
+# allocates to match empty image alloation.
217
+printf "\0" > "$TEST_DIR/empty"
218
+min_blocks=$(stat -c '%b' "$TEST_DIR/empty")
219
+
220
echo
221
echo "== creating image with default preallocation =="
222
_make_test_img $size | _filter_imgfmt
223
-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
224
+stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
225
226
for mode in off full falloc; do
227
echo
228
echo "== creating image with preallocation $mode =="
229
IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
230
- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
231
+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
232
done
233
234
# success, all done
235
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
236
index XXXXXXX..XXXXXXX 100644
237
--- a/tests/qemu-iotests/175.out
238
+++ b/tests/qemu-iotests/175.out
239
@@ -XXX,XX +XXX,XX @@ QA output created by 175
240
241
== creating image with default preallocation ==
242
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
243
-size=1048576, nothing allocated
244
+size=1048576, min allocation
245
246
== creating image with preallocation off ==
247
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off
248
-size=1048576, nothing allocated
249
+size=1048576, min allocation
250
251
== creating image with preallocation full ==
252
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full
253
-size=1048576, everything allocated
254
+size=1048576, max allocation
255
256
== creating image with preallocation falloc ==
257
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
258
-size=1048576, everything allocated
259
+size=1048576, max allocation
260
*** done
261
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
262
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/qemu-iotests/178.out.qcow2
264
+++ b/tests/qemu-iotests/178.out.qcow2
265
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 196608
266
== raw input image with data (human) ==
267
268
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
269
-required size: 393216
270
+required size: 458752
271
fully allocated size: 1074135040
272
wrote 512/512 bytes at offset 512
273
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
274
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 196608
275
276
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
277
{
278
- "required": 393216,
279
+ "required": 458752,
280
"fully-allocated": 1074135040
281
}
282
wrote 512/512 bytes at offset 512
283
diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out
284
index XXXXXXX..XXXXXXX 100644
285
--- a/tests/qemu-iotests/221.out
286
+++ b/tests/qemu-iotests/221.out
287
@@ -XXX,XX +XXX,XX @@ QA output created by 221
288
=== Check mapping of unaligned raw image ===
289
290
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537
291
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
292
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
293
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
294
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
295
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
296
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
297
wrote 1/1 bytes at offset 65536
298
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
299
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
300
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
301
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
302
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
303
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
304
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
305
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
306
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
307
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
308
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
309
*** done
310
diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out
311
index XXXXXXX..XXXXXXX 100644
312
--- a/tests/qemu-iotests/253.out
313
+++ b/tests/qemu-iotests/253.out
314
@@ -XXX,XX +XXX,XX @@ QA output created by 253
315
=== Check mapping of unaligned raw image ===
316
317
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575
318
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
319
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
320
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
321
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
322
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
323
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
324
wrote 65535/65535 bytes at offset 983040
325
63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
326
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
327
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
328
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
329
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
330
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
331
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
332
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
333
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
334
*** done
335
--
227
--
336
2.21.0
228
2.26.2
337
229
338
230
diff view generated by jsdifflib