1
The following changes since commit bfec359afba088aaacc7d316f43302f28c6e642a:
1
The following changes since commit 5375af3cd7b8adcc10c18d8083b7be63976c9645:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qdev-2017-04-21' into staging (2017-04-21 11:42:03 +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
git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-05-05
8
8
9
for you to fetch changes up to 1507631e438930bc07f776f303af127a9cdb4d41:
9
for you to fetch changes up to 4ce5dd3e9b5ee0fac18625860eb3727399ee965e:
10
10
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-21 08:32:44 -0400)
11
block/block-copy: use aio-task-pool API (2020-05-05 14:03:28 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
Block patches:
15
Block patches for 2.10
15
- Asynchronous copying for block-copy (i.e., the backup job)
16
- Allow resizing of qcow2 images when they have internal snapshots
17
- iotests: Logging improvements for Python tests
18
- iotest 153 fix, and block comment cleanups
16
19
17
----------------------------------------------------------------
20
----------------------------------------------------------------
21
Eric Blake (4):
22
block: Add blk_new_with_bs() helper
23
qcow2: Allow resize of images with internal snapshots
24
qcow2: Tweak comment about bitmaps vs. resize
25
block: Comment cleanups
18
26
19
Ashish Mittal (2):
27
John Snow (14):
20
block/vxhs.c: Add support for a new block device type called "vxhs"
28
iotests: do a light delinting
21
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
29
iotests: don't use 'format' for drive_add
30
iotests: ignore import warnings from pylint
31
iotests: replace mutable list default args
32
iotests: add pylintrc file
33
iotests: alphabetize standard imports
34
iotests: drop pre-Python 3.4 compatibility code
35
iotests: touch up log function signature
36
iotests: limit line length to 79 chars
37
iotests: add hmp helper with logging
38
iotests: add script_initialize
39
iotest 258: use script_main
40
iotests: Mark verify functions as private
41
iotests: use python logging for iotests.log()
22
42
23
Jeff Cody (10):
43
Maxim Levitsky (1):
24
qemu-iotests: exclude vxhs from image creation via protocol
44
Fix iotest 153
25
block: add bdrv_set_read_only() helper function
26
block: do not set BDS read_only if copy_on_read enabled
27
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
28
block: code movement
29
block: introduce bdrv_can_set_read_only()
30
block: use bdrv_can_set_read_only() during reopen
31
block/rbd - update variable names to more apt names
32
block/rbd: Add support for reopen()
33
qemu-iotests: _cleanup_qemu must be called on exit
34
45
35
block.c | 56 +++-
46
Vladimir Sementsov-Ogievskiy (5):
36
block/Makefile.objs | 2 +
47
block/block-copy: rename in-flight requests to tasks
37
block/bochs.c | 5 +-
48
block/block-copy: alloc task on each iteration
38
block/cloop.c | 5 +-
49
block/block-copy: add state pointer to BlockCopyTask
39
block/dmg.c | 6 +-
50
block/block-copy: refactor task creation
40
block/rbd.c | 65 +++--
51
block/block-copy: use aio-task-pool API
41
block/trace-events | 17 ++
52
42
block/vvfat.c | 19 +-
53
include/sysemu/block-backend.h | 2 +
43
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
54
block/block-backend.c | 23 +++
44
configure | 39 +++
55
block/block-copy.c | 279 +++++++++++++++++--------
45
include/block/block.h | 2 +
56
block/crypto.c | 9 +-
46
qapi/block-core.json | 23 +-
57
block/io.c | 3 +-
47
tests/qemu-iotests/017 | 1 +
58
block/parallels.c | 8 +-
48
tests/qemu-iotests/020 | 1 +
59
block/qcow.c | 8 +-
49
tests/qemu-iotests/028 | 1 +
60
block/qcow2-refcount.c | 2 +-
50
tests/qemu-iotests/029 | 1 +
61
block/qcow2-snapshot.c | 20 +-
51
tests/qemu-iotests/073 | 1 +
62
block/qcow2.c | 45 ++--
52
tests/qemu-iotests/094 | 11 +-
63
block/qed.c | 8 +-
53
tests/qemu-iotests/102 | 5 +-
64
block/sheepdog.c | 10 +-
54
tests/qemu-iotests/109 | 1 +
65
block/vdi.c | 8 +-
55
tests/qemu-iotests/114 | 1 +
66
block/vhdx.c | 8 +-
56
tests/qemu-iotests/117 | 1 +
67
block/vmdk.c | 9 +-
57
tests/qemu-iotests/130 | 2 +
68
block/vpc.c | 8 +-
58
tests/qemu-iotests/134 | 1 +
69
block/vvfat.c | 10 +-
59
tests/qemu-iotests/140 | 1 +
70
blockdev.c | 8 +-
60
tests/qemu-iotests/141 | 1 +
71
blockjob.c | 7 +-
61
tests/qemu-iotests/143 | 1 +
72
tests/qemu-iotests/001 | 2 +-
62
tests/qemu-iotests/156 | 2 +
73
tests/qemu-iotests/030 | 4 +-
63
tests/qemu-iotests/158 | 1 +
74
tests/qemu-iotests/052 | 2 +-
64
tests/qemu-iotests/common | 6 +
75
tests/qemu-iotests/055 | 3 +-
65
tests/qemu-iotests/common.config | 13 +
76
tests/qemu-iotests/061 | 35 ++++
66
tests/qemu-iotests/common.filter | 1 +
77
tests/qemu-iotests/061.out | 28 +++
67
tests/qemu-iotests/common.rc | 19 ++
78
tests/qemu-iotests/134 | 2 +-
68
33 files changed, 844 insertions(+), 42 deletions(-)
79
tests/qemu-iotests/149 | 3 +-
69
create mode 100644 block/vxhs.c
80
tests/qemu-iotests/153 | 2 +-
81
tests/qemu-iotests/153.out | 12 +-
82
tests/qemu-iotests/155 | 2 +-
83
tests/qemu-iotests/188 | 2 +-
84
tests/qemu-iotests/194 | 4 +-
85
tests/qemu-iotests/202 | 4 +-
86
tests/qemu-iotests/203 | 4 +-
87
tests/qemu-iotests/206 | 2 +-
88
tests/qemu-iotests/207 | 6 +-
89
tests/qemu-iotests/208 | 2 +-
90
tests/qemu-iotests/209 | 2 +-
91
tests/qemu-iotests/210 | 6 +-
92
tests/qemu-iotests/211 | 6 +-
93
tests/qemu-iotests/212 | 6 +-
94
tests/qemu-iotests/213 | 6 +-
95
tests/qemu-iotests/216 | 4 +-
96
tests/qemu-iotests/218 | 2 +-
97
tests/qemu-iotests/219 | 2 +-
98
tests/qemu-iotests/222 | 7 +-
99
tests/qemu-iotests/224 | 4 +-
100
tests/qemu-iotests/228 | 6 +-
101
tests/qemu-iotests/234 | 4 +-
102
tests/qemu-iotests/235 | 4 +-
103
tests/qemu-iotests/236 | 2 +-
104
tests/qemu-iotests/237 | 2 +-
105
tests/qemu-iotests/238 | 2 +
106
tests/qemu-iotests/242 | 2 +-
107
tests/qemu-iotests/245 | 1 +
108
tests/qemu-iotests/245.out | 10 +-
109
tests/qemu-iotests/246 | 2 +-
110
tests/qemu-iotests/248 | 2 +-
111
tests/qemu-iotests/254 | 2 +-
112
tests/qemu-iotests/255 | 2 +-
113
tests/qemu-iotests/256 | 2 +-
114
tests/qemu-iotests/258 | 10 +-
115
tests/qemu-iotests/260 | 4 +-
116
tests/qemu-iotests/262 | 4 +-
117
tests/qemu-iotests/264 | 4 +-
118
tests/qemu-iotests/274 | 4 +-
119
tests/qemu-iotests/277 | 2 +
120
tests/qemu-iotests/280 | 8 +-
121
tests/qemu-iotests/283 | 4 +-
122
tests/qemu-iotests/iotests.py | 366 ++++++++++++++++++++-------------
123
tests/qemu-iotests/pylintrc | 26 +++
124
71 files changed, 728 insertions(+), 386 deletions(-)
125
create mode 100644 tests/qemu-iotests/pylintrc
70
126
71
--
127
--
72
2.9.3
128
2.26.2
73
129
74
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
1
Introduce check function for setting read_only flags. Will return < 0 on
1
From: John Snow <jsnow@redhat.com>
2
error, with appropriate Error value set. Does not alter any flags.
3
2
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
It shadows (with a different type) the built-in format.
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Use something else.
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
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>
8
---
12
---
9
block.c | 14 +++++++++++++-
13
tests/qemu-iotests/055 | 3 ++-
10
include/block/block.h | 1 +
14
tests/qemu-iotests/iotests.py | 6 +++---
11
2 files changed, 14 insertions(+), 1 deletion(-)
15
2 files changed, 5 insertions(+), 4 deletions(-)
12
16
13
diff --git a/block.c b/block.c
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
14
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
33
--- a/tests/qemu-iotests/iotests.py
16
+++ b/block.c
34
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
35
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
18
return bs->read_only;
36
self._args.append(opts)
19
}
37
return self
20
38
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
39
- def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
40
+ def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt):
23
{
41
'''Add a virtio-blk drive to the VM'''
24
/* Do not set read_only if copy_on_read is enabled */
42
options = ['if=%s' % interface,
25
if (bs->copy_on_read && read_only) {
43
'id=drive%d' % self._num_drives]
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
44
27
return -EPERM;
45
if path is not None:
28
}
46
options.append('file=%s' % path)
29
47
- options.append('format=%s' % format)
30
+ return 0;
48
+ options.append('format=%s' % img_format)
31
+}
49
options.append('cache=%s' % cachemode)
32
+
50
options.append('aio=%s' % aiomode)
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
51
34
+{
52
if opts:
35
+ int ret = 0;
53
options.append(opts)
36
+
54
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
55
- if format == 'luks' and 'key-secret' not in opts:
38
+ if (ret < 0) {
56
+ if img_format == 'luks' and 'key-secret' not in opts:
39
+ return ret;
57
# default luks support
40
+ }
58
if luks_default_secret_object not in self._args:
41
+
59
self.add_object(luks_default_secret_object)
42
bs->read_only = read_only;
43
return 0;
44
}
45
diff --git a/include/block/block.h b/include/block/block.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block.h
48
+++ b/include/block/block.h
49
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
50
int64_t sector_num, int nb_sectors, int *pnum);
51
52
bool bdrv_is_read_only(BlockDriverState *bs);
53
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
54
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
55
bool bdrv_is_sg(BlockDriverState *bs);
56
bool bdrv_is_inserted(BlockDriverState *bs);
57
--
60
--
58
2.9.3
61
2.26.2
59
62
60
63
diff view generated by jsdifflib
1
Update 'clientname' to be 'user', which tracks better with both
1
From: John Snow <jsnow@redhat.com>
2
the QAPI and rados variable naming.
3
2
4
Update 'name' to be 'image_name', as it indicates the rbd image.
3
The right way to solve this is to come up with a virtual environment
5
Naming it 'image' would have been ideal, but we are using that for
4
infrastructure that sets all the paths correctly, and/or to create
6
the rados_image_t value returned by rbd_open().
5
installable python modules that can be imported normally.
7
6
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
That's hard, so just silence this error for now.
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
10
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: b7ec1fb2e1cf36f9b6911631447a5b0422590b7d.1491597120.git.jcody@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>
12
---
15
---
13
block/rbd.c | 33 +++++++++++++++++----------------
16
tests/qemu-iotests/iotests.py | 1 +
14
1 file changed, 17 insertions(+), 16 deletions(-)
17
1 file changed, 1 insertion(+)
15
18
16
diff --git a/block/rbd.c b/block/rbd.c
19
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/block/rbd.c
21
--- a/tests/qemu-iotests/iotests.py
19
+++ b/block/rbd.c
22
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
23
@@ -XXX,XX +XXX,XX @@ import io
21
rados_t cluster;
24
from collections import OrderedDict
22
rados_ioctx_t io_ctx;
25
import faulthandler
23
rbd_image_t image;
26
24
- char *name;
27
+# pylint: disable=import-error, wrong-import-position
25
+ char *image_name;
28
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
26
char *snap;
29
from qemu import qtest
27
} BDRVRBDState;
28
29
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
30
int64_t bytes = 0;
31
int64_t objsize;
32
int obj_order = 0;
33
- const char *pool, *name, *conf, *clientname, *keypairs;
34
+ const char *pool, *image_name, *conf, *user, *keypairs;
35
const char *secretid;
36
rados_t cluster;
37
rados_ioctx_t io_ctx;
38
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
39
*/
40
pool = qdict_get_try_str(options, "pool");
41
conf = qdict_get_try_str(options, "conf");
42
- clientname = qdict_get_try_str(options, "user");
43
- name = qdict_get_try_str(options, "image");
44
+ user = qdict_get_try_str(options, "user");
45
+ image_name = qdict_get_try_str(options, "image");
46
keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
47
48
- ret = rados_create(&cluster, clientname);
49
+ ret = rados_create(&cluster, user);
50
if (ret < 0) {
51
error_setg_errno(errp, -ret, "error initializing");
52
goto exit;
53
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
54
goto shutdown;
55
}
56
57
- ret = rbd_create(io_ctx, name, bytes, &obj_order);
58
+ ret = rbd_create(io_ctx, image_name, bytes, &obj_order);
59
if (ret < 0) {
60
error_setg_errno(errp, -ret, "error rbd create");
61
}
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
63
Error **errp)
64
{
65
BDRVRBDState *s = bs->opaque;
66
- const char *pool, *snap, *conf, *clientname, *name, *keypairs;
67
+ const char *pool, *snap, *conf, *user, *image_name, *keypairs;
68
const char *secretid;
69
QemuOpts *opts;
70
Error *local_err = NULL;
71
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
72
pool = qemu_opt_get(opts, "pool");
73
conf = qemu_opt_get(opts, "conf");
74
snap = qemu_opt_get(opts, "snapshot");
75
- clientname = qemu_opt_get(opts, "user");
76
- name = qemu_opt_get(opts, "image");
77
+ user = qemu_opt_get(opts, "user");
78
+ image_name = qemu_opt_get(opts, "image");
79
keypairs = qemu_opt_get(opts, "=keyvalue-pairs");
80
81
- if (!pool || !name) {
82
+ if (!pool || !image_name) {
83
error_setg(errp, "Parameters 'pool' and 'image' are required");
84
r = -EINVAL;
85
goto failed_opts;
86
}
87
88
- r = rados_create(&s->cluster, clientname);
89
+ r = rados_create(&s->cluster, user);
90
if (r < 0) {
91
error_setg_errno(errp, -r, "error initializing");
92
goto failed_opts;
93
}
94
95
s->snap = g_strdup(snap);
96
- s->name = g_strdup(name);
97
+ s->image_name = g_strdup(image_name);
98
99
/* try default location when conf=NULL, but ignore failure */
100
r = rados_conf_read_file(s->cluster, conf);
101
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
102
}
103
104
/* rbd_open is always r/w */
105
- r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
106
+ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
107
if (r < 0) {
108
- error_setg_errno(errp, -r, "error reading header from %s", s->name);
109
+ error_setg_errno(errp, -r, "error reading header from %s",
110
+ s->image_name);
111
goto failed_open;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ failed_open:
115
failed_shutdown:
116
rados_shutdown(s->cluster);
117
g_free(s->snap);
118
- g_free(s->name);
119
+ g_free(s->image_name);
120
failed_opts:
121
qemu_opts_del(opts);
122
g_free(mon_host);
123
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_close(BlockDriverState *bs)
124
rbd_close(s->image);
125
rados_ioctx_destroy(s->io_ctx);
126
g_free(s->snap);
127
- g_free(s->name);
128
+ g_free(s->image_name);
129
rados_shutdown(s->cluster);
130
}
131
30
132
--
31
--
133
2.9.3
32
2.26.2
134
33
135
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
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
Source code for the qnio library that this code loads can be downloaded from:
3
This allows others to get repeatable results with pylint. If you run
4
https://github.com/VeritasHyperScale/libqnio.git
4
`pylint iotests.py`, you should see a 100% pass.
5
5
6
Sample command line using JSON syntax:
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
./x86_64-softmmu/qemu-system-x86_64 -name instance-00000008 -S -vnc 0.0.0.0:0
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
-k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
8
Message-Id: <20200331000014.11581-6-jsnow@redhat.com>
9
-msg timestamp=on
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
'json:{"driver":"vxhs","vdisk-id":"c3e9095a-a5ee-4dce-afeb-2a59fb387410",
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
"server":{"host":"172.172.17.4","port":"9999"}}'
11
---
12
tests/qemu-iotests/pylintrc | 22 ++++++++++++++++++++++
13
1 file changed, 22 insertions(+)
14
create mode 100644 tests/qemu-iotests/pylintrc
12
15
13
Sample command line using URI syntax:
16
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
14
qemu-img convert -f raw -O raw -n
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
17
18
Sample command line using TLS credentials (run in secure mode):
19
./qemu-io --object
20
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
21
-v 66000 2.5k' 'json:{"server.host": "127.0.0.1", "server.port": "9999",
22
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
23
24
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Jeff Cody <jcody@redhat.com>
27
Signed-off-by: Jeff Cody <jcody@redhat.com>
28
Message-id: 1491277689-24949-2-git-send-email-Ashish.Mittal@veritas.com
29
---
30
block/Makefile.objs | 2 +
31
block/trace-events | 17 ++
32
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++
33
configure | 39 ++++
34
qapi/block-core.json | 23 ++-
35
5 files changed, 654 insertions(+), 2 deletions(-)
36
create mode 100644 block/vxhs.c
37
38
diff --git a/block/Makefile.objs b/block/Makefile.objs
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/Makefile.objs
41
+++ b/block/Makefile.objs
42
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
43
block-obj-$(CONFIG_CURL) += curl.o
44
block-obj-$(CONFIG_RBD) += rbd.o
45
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
46
+block-obj-$(CONFIG_VXHS) += vxhs.o
47
block-obj-$(CONFIG_LIBSSH2) += ssh.o
48
block-obj-y += accounting.o dirty-bitmap.o
49
block-obj-y += write-threshold.o
50
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
51
rbd.o-libs := $(RBD_LIBS)
52
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
53
gluster.o-libs := $(GLUSTERFS_LIBS)
54
+vxhs.o-libs := $(VXHS_LIBS)
55
ssh.o-cflags := $(LIBSSH2_CFLAGS)
56
ssh.o-libs := $(LIBSSH2_LIBS)
57
block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
58
diff --git a/block/trace-events b/block/trace-events
59
index XXXXXXX..XXXXXXX 100644
60
--- a/block/trace-events
61
+++ b/block/trace-events
62
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
63
qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
64
qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
65
qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
66
+
67
+# block/vxhs.c
68
+vxhs_iio_callback(int error) "ctx is NULL: error %d"
69
+vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d"
70
+vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d"
71
+vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d"
72
+vxhs_aio_rw_ioerr(char *guid, int iodir, uint64_t size, uint64_t off, void *acb, int ret, int err) "IO ERROR (vDisk %s) FOR : Read/Write = %d size = %lu offset = %lu ACB = %p. Error = %d, errno = %d"
73
+vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d"
74
+vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %lu"
75
+vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %ld"
76
+vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s"
77
+vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s"
78
+vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState"
79
+vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s"
80
+vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d"
81
+vxhs_close(char *vdisk_guid) "Closing vdisk %s"
82
+vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s"
83
diff --git a/block/vxhs.c b/block/vxhs.c
84
new file mode 100644
17
new file mode 100644
85
index XXXXXXX..XXXXXXX
18
index XXXXXXX..XXXXXXX
86
--- /dev/null
19
--- /dev/null
87
+++ b/block/vxhs.c
20
+++ b/tests/qemu-iotests/pylintrc
88
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
89
+/*
22
+[MESSAGES CONTROL]
90
+ * QEMU Block driver for Veritas HyperScale (VxHS)
91
+ *
92
+ * Copyright (c) 2017 Veritas Technologies LLC.
93
+ *
94
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
95
+ * See the COPYING file in the top-level directory.
96
+ *
97
+ */
98
+
23
+
99
+#include "qemu/osdep.h"
24
+# Disable the message, report, category or checker with the given id(s). You
100
+#include <qnio/qnio_api.h>
25
+# can either give multiple identifiers separated by comma (,) or put this
101
+#include <sys/param.h>
26
+# option multiple times (only on the command line, not in the configuration
102
+#include "block/block_int.h"
27
+# file where it should appear only once). You can also use "--disable=all" to
103
+#include "qapi/qmp/qerror.h"
28
+# disable everything first and then reenable specific checks. For example, if
104
+#include "qapi/qmp/qdict.h"
29
+# you want to run only the similarities checker, you can use "--disable=all
105
+#include "qapi/qmp/qstring.h"
30
+# --enable=similarities". If you want to run only the classes checker, but have
106
+#include "trace.h"
31
+# no Warning level messages displayed, use "--disable=all --enable=classes
107
+#include "qemu/uri.h"
32
+# --disable=W".
108
+#include "qapi/error.h"
33
+disable=invalid-name,
109
+#include "qemu/uuid.h"
34
+ no-else-return,
110
+#include "crypto/tlscredsx509.h"
35
+ too-few-public-methods,
111
+
36
+ too-many-arguments,
112
+#define VXHS_OPT_FILENAME "filename"
37
+ too-many-branches,
113
+#define VXHS_OPT_VDISK_ID "vdisk-id"
38
+ too-many-lines,
114
+#define VXHS_OPT_SERVER "server"
39
+ too-many-locals,
115
+#define VXHS_OPT_HOST "host"
40
+ too-many-public-methods,
116
+#define VXHS_OPT_PORT "port"
41
+ # These are temporary, and should be removed:
117
+
42
+ line-too-long,
118
+/* Only accessed under QEMU global mutex */
43
+ missing-docstring,
119
+static uint32_t vxhs_ref;
120
+
121
+typedef enum {
122
+ VDISK_AIO_READ,
123
+ VDISK_AIO_WRITE,
124
+} VDISKAIOCmd;
125
+
126
+/*
127
+ * HyperScale AIO callbacks structure
128
+ */
129
+typedef struct VXHSAIOCB {
130
+ BlockAIOCB common;
131
+ int err;
132
+} VXHSAIOCB;
133
+
134
+typedef struct VXHSvDiskHostsInfo {
135
+ void *dev_handle; /* Device handle */
136
+ char *host; /* Host name or IP */
137
+ int port; /* Host's port number */
138
+} VXHSvDiskHostsInfo;
139
+
140
+/*
141
+ * Structure per vDisk maintained for state
142
+ */
143
+typedef struct BDRVVXHSState {
144
+ VXHSvDiskHostsInfo vdisk_hostinfo; /* Per host info */
145
+ char *vdisk_guid;
146
+ char *tlscredsid; /* tlscredsid */
147
+} BDRVVXHSState;
148
+
149
+static void vxhs_complete_aio_bh(void *opaque)
150
+{
151
+ VXHSAIOCB *acb = opaque;
152
+ BlockCompletionFunc *cb = acb->common.cb;
153
+ void *cb_opaque = acb->common.opaque;
154
+ int ret = 0;
155
+
156
+ if (acb->err != 0) {
157
+ trace_vxhs_complete_aio(acb, acb->err);
158
+ ret = (-EIO);
159
+ }
160
+
161
+ qemu_aio_unref(acb);
162
+ cb(cb_opaque, ret);
163
+}
164
+
165
+/*
166
+ * Called from a libqnio thread
167
+ */
168
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
169
+{
170
+ VXHSAIOCB *acb = NULL;
171
+
172
+ switch (opcode) {
173
+ case IRP_READ_REQUEST:
174
+ case IRP_WRITE_REQUEST:
175
+
176
+ /*
177
+ * ctx is VXHSAIOCB*
178
+ * ctx is NULL if error is QNIOERROR_CHANNEL_HUP
179
+ */
180
+ if (ctx) {
181
+ acb = ctx;
182
+ } else {
183
+ trace_vxhs_iio_callback(error);
184
+ goto out;
185
+ }
186
+
187
+ if (error) {
188
+ if (!acb->err) {
189
+ acb->err = error;
190
+ }
191
+ trace_vxhs_iio_callback(error);
192
+ }
193
+
194
+ aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
195
+ vxhs_complete_aio_bh, acb);
196
+ break;
197
+
198
+ default:
199
+ if (error == QNIOERROR_HUP) {
200
+ /*
201
+ * Channel failed, spontaneous notification,
202
+ * not in response to I/O
203
+ */
204
+ trace_vxhs_iio_callback_chnfail(error, errno);
205
+ } else {
206
+ trace_vxhs_iio_callback_unknwn(opcode, error);
207
+ }
208
+ break;
209
+ }
210
+out:
211
+ return;
212
+}
213
+
214
+static QemuOptsList runtime_opts = {
215
+ .name = "vxhs",
216
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
217
+ .desc = {
218
+ {
219
+ .name = VXHS_OPT_FILENAME,
220
+ .type = QEMU_OPT_STRING,
221
+ .help = "URI to the Veritas HyperScale image",
222
+ },
223
+ {
224
+ .name = VXHS_OPT_VDISK_ID,
225
+ .type = QEMU_OPT_STRING,
226
+ .help = "UUID of the VxHS vdisk",
227
+ },
228
+ {
229
+ .name = "tls-creds",
230
+ .type = QEMU_OPT_STRING,
231
+ .help = "ID of the TLS/SSL credentials to use",
232
+ },
233
+ { /* end of list */ }
234
+ },
235
+};
236
+
237
+static QemuOptsList runtime_tcp_opts = {
238
+ .name = "vxhs_tcp",
239
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
240
+ .desc = {
241
+ {
242
+ .name = VXHS_OPT_HOST,
243
+ .type = QEMU_OPT_STRING,
244
+ .help = "host address (ipv4 addresses)",
245
+ },
246
+ {
247
+ .name = VXHS_OPT_PORT,
248
+ .type = QEMU_OPT_NUMBER,
249
+ .help = "port number on which VxHSD is listening (default 9999)",
250
+ .def_value_str = "9999"
251
+ },
252
+ { /* end of list */ }
253
+ },
254
+};
255
+
256
+/*
257
+ * Parse incoming URI and populate *options with the host
258
+ * and device information
259
+ */
260
+static int vxhs_parse_uri(const char *filename, QDict *options)
261
+{
262
+ URI *uri = NULL;
263
+ char *port;
264
+ int ret = 0;
265
+
266
+ trace_vxhs_parse_uri_filename(filename);
267
+ uri = uri_parse(filename);
268
+ if (!uri || !uri->server || !uri->path) {
269
+ uri_free(uri);
270
+ return -EINVAL;
271
+ }
272
+
273
+ qdict_put(options, VXHS_OPT_SERVER".host", qstring_from_str(uri->server));
274
+
275
+ if (uri->port) {
276
+ port = g_strdup_printf("%d", uri->port);
277
+ qdict_put(options, VXHS_OPT_SERVER".port", qstring_from_str(port));
278
+ g_free(port);
279
+ }
280
+
281
+ qdict_put(options, "vdisk-id", qstring_from_str(uri->path));
282
+
283
+ trace_vxhs_parse_uri_hostinfo(uri->server, uri->port);
284
+ uri_free(uri);
285
+
286
+ return ret;
287
+}
288
+
289
+static void vxhs_parse_filename(const char *filename, QDict *options,
290
+ Error **errp)
291
+{
292
+ if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) {
293
+ error_setg(errp, "vdisk-id/server and a file name may not be specified "
294
+ "at the same time");
295
+ return;
296
+ }
297
+
298
+ if (strstr(filename, "://")) {
299
+ int ret = vxhs_parse_uri(filename, options);
300
+ if (ret < 0) {
301
+ error_setg(errp, "Invalid URI. URI should be of the form "
302
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
303
+ }
304
+ }
305
+}
306
+
307
+static int vxhs_init_and_ref(void)
308
+{
309
+ if (vxhs_ref++ == 0) {
310
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
311
+ return -ENODEV;
312
+ }
313
+ }
314
+ return 0;
315
+}
316
+
317
+static void vxhs_unref(void)
318
+{
319
+ if (--vxhs_ref == 0) {
320
+ iio_fini();
321
+ }
322
+}
323
+
324
+static void vxhs_get_tls_creds(const char *id, char **cacert,
325
+ char **key, char **cert, Error **errp)
326
+{
327
+ Object *obj;
328
+ QCryptoTLSCreds *creds;
329
+ QCryptoTLSCredsX509 *creds_x509;
330
+
331
+ obj = object_resolve_path_component(
332
+ object_get_objects_root(), id);
333
+
334
+ if (!obj) {
335
+ error_setg(errp, "No TLS credentials with id '%s'",
336
+ id);
337
+ return;
338
+ }
339
+
340
+ creds_x509 = (QCryptoTLSCredsX509 *)
341
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509);
342
+
343
+ if (!creds_x509) {
344
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
345
+ id);
346
+ return;
347
+ }
348
+
349
+ creds = &creds_x509->parent_obj;
350
+
351
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
352
+ error_setg(errp,
353
+ "Expecting TLS credentials with a client endpoint");
354
+ return;
355
+ }
356
+
357
+ /*
358
+ * Get the cacert, client_cert and client_key file names.
359
+ */
360
+ if (!creds->dir) {
361
+ error_setg(errp, "TLS object missing 'dir' property value");
362
+ return;
363
+ }
364
+
365
+ *cacert = g_strdup_printf("%s/%s", creds->dir,
366
+ QCRYPTO_TLS_CREDS_X509_CA_CERT);
367
+ *cert = g_strdup_printf("%s/%s", creds->dir,
368
+ QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
369
+ *key = g_strdup_printf("%s/%s", creds->dir,
370
+ QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
371
+}
372
+
373
+static int vxhs_open(BlockDriverState *bs, QDict *options,
374
+ int bdrv_flags, Error **errp)
375
+{
376
+ BDRVVXHSState *s = bs->opaque;
377
+ void *dev_handlep;
378
+ QDict *backing_options = NULL;
379
+ QemuOpts *opts = NULL;
380
+ QemuOpts *tcp_opts = NULL;
381
+ char *of_vsa_addr = NULL;
382
+ Error *local_err = NULL;
383
+ const char *vdisk_id_opt;
384
+ const char *server_host_opt;
385
+ int ret = 0;
386
+ char *cacert = NULL;
387
+ char *client_key = NULL;
388
+ char *client_cert = NULL;
389
+
390
+ ret = vxhs_init_and_ref();
391
+ if (ret < 0) {
392
+ ret = -EINVAL;
393
+ goto out;
394
+ }
395
+
396
+ /* Create opts info from runtime_opts and runtime_tcp_opts list */
397
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
398
+ tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
399
+
400
+ qemu_opts_absorb_qdict(opts, options, &local_err);
401
+ if (local_err) {
402
+ ret = -EINVAL;
403
+ goto out;
404
+ }
405
+
406
+ /* vdisk-id is the disk UUID */
407
+ vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID);
408
+ if (!vdisk_id_opt) {
409
+ error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID);
410
+ ret = -EINVAL;
411
+ goto out;
412
+ }
413
+
414
+ /* vdisk-id may contain a leading '/' */
415
+ if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) {
416
+ error_setg(&local_err, "vdisk-id cannot be more than %d characters",
417
+ UUID_FMT_LEN);
418
+ ret = -EINVAL;
419
+ goto out;
420
+ }
421
+
422
+ s->vdisk_guid = g_strdup(vdisk_id_opt);
423
+ trace_vxhs_open_vdiskid(vdisk_id_opt);
424
+
425
+ /* get the 'server.' arguments */
426
+ qdict_extract_subqdict(options, &backing_options, VXHS_OPT_SERVER".");
427
+
428
+ qemu_opts_absorb_qdict(tcp_opts, backing_options, &local_err);
429
+ if (local_err != NULL) {
430
+ ret = -EINVAL;
431
+ goto out;
432
+ }
433
+
434
+ server_host_opt = qemu_opt_get(tcp_opts, VXHS_OPT_HOST);
435
+ if (!server_host_opt) {
436
+ error_setg(&local_err, QERR_MISSING_PARAMETER,
437
+ VXHS_OPT_SERVER"."VXHS_OPT_HOST);
438
+ ret = -EINVAL;
439
+ goto out;
440
+ }
441
+
442
+ if (strlen(server_host_opt) > MAXHOSTNAMELEN) {
443
+ error_setg(&local_err, "server.host cannot be more than %d characters",
444
+ MAXHOSTNAMELEN);
445
+ ret = -EINVAL;
446
+ goto out;
447
+ }
448
+
449
+ /* check if we got tls-creds via the --object argument */
450
+ s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds"));
451
+ if (s->tlscredsid) {
452
+ vxhs_get_tls_creds(s->tlscredsid, &cacert, &client_key,
453
+ &client_cert, &local_err);
454
+ if (local_err != NULL) {
455
+ ret = -EINVAL;
456
+ goto out;
457
+ }
458
+ trace_vxhs_get_creds(cacert, client_key, client_cert);
459
+ }
460
+
461
+ s->vdisk_hostinfo.host = g_strdup(server_host_opt);
462
+ s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts,
463
+ VXHS_OPT_PORT),
464
+ NULL, 0);
465
+
466
+ trace_vxhs_open_hostinfo(s->vdisk_hostinfo.host,
467
+ s->vdisk_hostinfo.port);
468
+
469
+ of_vsa_addr = g_strdup_printf("of://%s:%d",
470
+ s->vdisk_hostinfo.host,
471
+ s->vdisk_hostinfo.port);
472
+
473
+ /*
474
+ * Open qnio channel to storage agent if not opened before
475
+ */
476
+ dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0,
477
+ cacert, client_key, client_cert);
478
+ if (dev_handlep == NULL) {
479
+ trace_vxhs_open_iio_open(of_vsa_addr);
480
+ ret = -ENODEV;
481
+ goto out;
482
+ }
483
+ s->vdisk_hostinfo.dev_handle = dev_handlep;
484
+
485
+out:
486
+ g_free(of_vsa_addr);
487
+ QDECREF(backing_options);
488
+ qemu_opts_del(tcp_opts);
489
+ qemu_opts_del(opts);
490
+ g_free(cacert);
491
+ g_free(client_key);
492
+ g_free(client_cert);
493
+
494
+ if (ret < 0) {
495
+ vxhs_unref();
496
+ error_propagate(errp, local_err);
497
+ g_free(s->vdisk_hostinfo.host);
498
+ g_free(s->vdisk_guid);
499
+ g_free(s->tlscredsid);
500
+ s->vdisk_guid = NULL;
501
+ }
502
+
503
+ return ret;
504
+}
505
+
506
+static const AIOCBInfo vxhs_aiocb_info = {
507
+ .aiocb_size = sizeof(VXHSAIOCB)
508
+};
509
+
510
+/*
511
+ * This allocates QEMU-VXHS callback for each IO
512
+ * and is passed to QNIO. When QNIO completes the work,
513
+ * it will be passed back through the callback.
514
+ */
515
+static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
516
+ QEMUIOVector *qiov, int nb_sectors,
517
+ BlockCompletionFunc *cb, void *opaque,
518
+ VDISKAIOCmd iodir)
519
+{
520
+ VXHSAIOCB *acb = NULL;
521
+ BDRVVXHSState *s = bs->opaque;
522
+ size_t size;
523
+ uint64_t offset;
524
+ int iio_flags = 0;
525
+ int ret = 0;
526
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
527
+
528
+ offset = sector_num * BDRV_SECTOR_SIZE;
529
+ size = nb_sectors * BDRV_SECTOR_SIZE;
530
+ acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque);
531
+
532
+ /*
533
+ * Initialize VXHSAIOCB.
534
+ */
535
+ acb->err = 0;
536
+
537
+ iio_flags = IIO_FLAG_ASYNC;
538
+
539
+ switch (iodir) {
540
+ case VDISK_AIO_WRITE:
541
+ ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov,
542
+ offset, (uint64_t)size, iio_flags);
543
+ break;
544
+ case VDISK_AIO_READ:
545
+ ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov,
546
+ offset, (uint64_t)size, iio_flags);
547
+ break;
548
+ default:
549
+ trace_vxhs_aio_rw_invalid(iodir);
550
+ goto errout;
551
+ }
552
+
553
+ if (ret != 0) {
554
+ trace_vxhs_aio_rw_ioerr(s->vdisk_guid, iodir, size, offset,
555
+ acb, ret, errno);
556
+ goto errout;
557
+ }
558
+ return &acb->common;
559
+
560
+errout:
561
+ qemu_aio_unref(acb);
562
+ return NULL;
563
+}
564
+
565
+static BlockAIOCB *vxhs_aio_readv(BlockDriverState *bs,
566
+ int64_t sector_num, QEMUIOVector *qiov,
567
+ int nb_sectors,
568
+ BlockCompletionFunc *cb, void *opaque)
569
+{
570
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
571
+ opaque, VDISK_AIO_READ);
572
+}
573
+
574
+static BlockAIOCB *vxhs_aio_writev(BlockDriverState *bs,
575
+ int64_t sector_num, QEMUIOVector *qiov,
576
+ int nb_sectors,
577
+ BlockCompletionFunc *cb, void *opaque)
578
+{
579
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors,
580
+ cb, opaque, VDISK_AIO_WRITE);
581
+}
582
+
583
+static void vxhs_close(BlockDriverState *bs)
584
+{
585
+ BDRVVXHSState *s = bs->opaque;
586
+
587
+ trace_vxhs_close(s->vdisk_guid);
588
+
589
+ g_free(s->vdisk_guid);
590
+ s->vdisk_guid = NULL;
591
+
592
+ /*
593
+ * Close vDisk device
594
+ */
595
+ if (s->vdisk_hostinfo.dev_handle) {
596
+ iio_close(s->vdisk_hostinfo.dev_handle);
597
+ s->vdisk_hostinfo.dev_handle = NULL;
598
+ }
599
+
600
+ vxhs_unref();
601
+
602
+ /*
603
+ * Free the dynamically allocated host string etc
604
+ */
605
+ g_free(s->vdisk_hostinfo.host);
606
+ g_free(s->tlscredsid);
607
+ s->tlscredsid = NULL;
608
+ s->vdisk_hostinfo.host = NULL;
609
+ s->vdisk_hostinfo.port = 0;
610
+}
611
+
612
+static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s)
613
+{
614
+ int64_t vdisk_size = -1;
615
+ int ret = 0;
616
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
617
+
618
+ ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0);
619
+ if (ret < 0) {
620
+ trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno);
621
+ return -EIO;
622
+ }
623
+
624
+ trace_vxhs_get_vdisk_stat(s->vdisk_guid, vdisk_size);
625
+ return vdisk_size;
626
+}
627
+
628
+/*
629
+ * Returns the size of vDisk in bytes. This is required
630
+ * by QEMU block upper block layer so that it is visible
631
+ * to guest.
632
+ */
633
+static int64_t vxhs_getlength(BlockDriverState *bs)
634
+{
635
+ BDRVVXHSState *s = bs->opaque;
636
+ int64_t vdisk_size;
637
+
638
+ vdisk_size = vxhs_get_vdisk_stat(s);
639
+ if (vdisk_size < 0) {
640
+ return -EIO;
641
+ }
642
+
643
+ return vdisk_size;
644
+}
645
+
646
+static BlockDriver bdrv_vxhs = {
647
+ .format_name = "vxhs",
648
+ .protocol_name = "vxhs",
649
+ .instance_size = sizeof(BDRVVXHSState),
650
+ .bdrv_file_open = vxhs_open,
651
+ .bdrv_parse_filename = vxhs_parse_filename,
652
+ .bdrv_close = vxhs_close,
653
+ .bdrv_getlength = vxhs_getlength,
654
+ .bdrv_aio_readv = vxhs_aio_readv,
655
+ .bdrv_aio_writev = vxhs_aio_writev,
656
+};
657
+
658
+static void bdrv_vxhs_init(void)
659
+{
660
+ bdrv_register(&bdrv_vxhs);
661
+}
662
+
663
+block_init(bdrv_vxhs_init);
664
diff --git a/configure b/configure
665
index XXXXXXX..XXXXXXX 100755
666
--- a/configure
667
+++ b/configure
668
@@ -XXX,XX +XXX,XX @@ numa=""
669
tcmalloc="no"
670
jemalloc="no"
671
replication="yes"
672
+vxhs=""
673
674
supported_cpu="no"
675
supported_os="no"
676
@@ -XXX,XX +XXX,XX @@ for opt do
677
;;
678
--enable-replication) replication="yes"
679
;;
680
+ --disable-vxhs) vxhs="no"
681
+ ;;
682
+ --enable-vxhs) vxhs="yes"
683
+ ;;
684
*)
685
echo "ERROR: unknown option $opt"
686
echo "Try '$0 --help' for more information"
687
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available:
688
xfsctl xfsctl support
689
qom-cast-debug cast debugging support
690
tools build qemu-io, qemu-nbd and qemu-image tools
691
+ vxhs Veritas HyperScale vDisk backend support
692
693
NOTE: The object files are built at the place where configure is launched
694
EOF
695
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
696
fi
697
698
##########################################
699
+# Veritas HyperScale block driver VxHS
700
+# Check if libvxhs is installed
701
+
702
+if test "$vxhs" != "no" ; then
703
+ cat > $TMPC <<EOF
704
+#include <stdint.h>
705
+#include <qnio/qnio_api.h>
706
+
707
+void *vxhs_callback;
708
+
709
+int main(void) {
710
+ iio_init(QNIO_VERSION, vxhs_callback);
711
+ return 0;
712
+}
713
+EOF
714
+ vxhs_libs="-lvxhs -lssl"
715
+ if compile_prog "" "$vxhs_libs" ; then
716
+ vxhs=yes
717
+ else
718
+ if test "$vxhs" = "yes" ; then
719
+ feature_not_found "vxhs block device" "Install libvxhs See github"
720
+ fi
721
+ vxhs=no
722
+ fi
723
+fi
724
+
725
+##########################################
726
# End of CC checks
727
# After here, no more $cc or $ld runs
728
729
@@ -XXX,XX +XXX,XX @@ echo "tcmalloc support $tcmalloc"
730
echo "jemalloc support $jemalloc"
731
echo "avx2 optimization $avx2_opt"
732
echo "replication support $replication"
733
+echo "VxHS block device $vxhs"
734
735
if test "$sdl_too_old" = "yes"; then
736
echo "-> Your SDL version is too old - please upgrade to have SDL support"
737
@@ -XXX,XX +XXX,XX @@ if test "$pthread_setname_np" = "yes" ; then
738
echo "CONFIG_PTHREAD_SETNAME_NP=y" >> $config_host_mak
739
fi
740
741
+if test "$vxhs" = "yes" ; then
742
+ echo "CONFIG_VXHS=y" >> $config_host_mak
743
+ echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak
744
+fi
745
+
746
if test "$tcg_interpreter" = "yes"; then
747
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
748
elif test "$ARCH" = "sparc64" ; then
749
diff --git a/qapi/block-core.json b/qapi/block-core.json
750
index XXXXXXX..XXXXXXX 100644
751
--- a/qapi/block-core.json
752
+++ b/qapi/block-core.json
753
@@ -XXX,XX +XXX,XX @@
754
#
755
# Drivers that are supported in block device operations.
756
#
757
+# @vxhs: Since 2.10
758
+#
759
# Since: 2.9
760
##
761
{ 'enum': 'BlockdevDriver',
762
@@ -XXX,XX +XXX,XX @@
763
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
764
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
765
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
766
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
767
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
768
769
##
770
# @BlockdevOptionsFile:
771
@@ -XXX,XX +XXX,XX @@
772
'data': { '*offset': 'int', '*size': 'int' } }
773
774
##
775
+# @BlockdevOptionsVxHS:
776
+#
777
+# Driver specific block device options for VxHS
778
+#
779
+# @vdisk-id: UUID of VxHS volume
780
+# @server: vxhs server IP, port
781
+# @tls-creds: TLS credentials ID
782
+#
783
+# Since: 2.10
784
+##
785
+{ 'struct': 'BlockdevOptionsVxHS',
786
+ 'data': { 'vdisk-id': 'str',
787
+ 'server': 'InetSocketAddressBase',
788
+ '*tls-creds': 'str' } }
789
+
790
+##
791
# @BlockdevOptions:
792
#
793
# Options for creating a block device. Many options are available for all
794
@@ -XXX,XX +XXX,XX @@
795
'vhdx': 'BlockdevOptionsGenericFormat',
796
'vmdk': 'BlockdevOptionsGenericCOWFormat',
797
'vpc': 'BlockdevOptionsGenericFormat',
798
- 'vvfat': 'BlockdevOptionsVVFAT'
799
+ 'vvfat': 'BlockdevOptionsVVFAT',
800
+ 'vxhs': 'BlockdevOptionsVxHS'
801
} }
802
803
##
804
--
44
--
805
2.9.3
45
2.26.2
806
46
807
47
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
I had to fix a merge conflict, so do this tiny harmless thing while I'm
4
here.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-7-jsnow@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 18 +++++++++---------
14
1 file changed, 9 insertions(+), 9 deletions(-)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#
23
24
+import atexit
25
+from collections import OrderedDict
26
+import faulthandler
27
+import io
28
+import json
29
+import logging
30
import os
31
import re
32
+import signal
33
+import struct
34
import subprocess
35
-import unittest
36
import sys
37
-import struct
38
-import json
39
-import signal
40
-import logging
41
-import atexit
42
-import io
43
-from collections import OrderedDict
44
-import faulthandler
45
+import unittest
46
47
# pylint: disable=import-error, wrong-import-position
48
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
49
--
50
2.26.2
51
52
diff view generated by jsdifflib
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2
3
Reviewed-by: John Snow <jsnow@redhat.com>
3
We no longer need to accommodate <3.4, drop this code.
4
Message-id: 00aed7ffdd7be4b9ed9ce1007d50028a72b34ebe.1491597120.git.jcody@redhat.com
4
(The lines were > 79 chars and it stood out.)
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-8-jsnow@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
11
---
6
block.c | 14 ++++++++------
12
tests/qemu-iotests/iotests.py | 5 +----
7
1 file changed, 8 insertions(+), 6 deletions(-)
13
1 file changed, 1 insertion(+), 4 deletions(-)
8
14
9
diff --git a/block.c b/block.c
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
10
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
17
--- a/tests/qemu-iotests/iotests.py
12
+++ b/block.c
18
+++ b/tests/qemu-iotests/iotests.py
13
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
19
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=(), indent=None):
14
BlockDriver *drv;
20
for flt in filters:
15
QemuOpts *opts;
21
msg = flt(msg)
16
const char *value;
22
if isinstance(msg, (dict, list)):
17
+ bool read_only;
23
- # Python < 3.4 needs to know not to add whitespace when pretty-printing:
18
24
- separators = (', ', ': ') if indent is None else (',', ': ')
19
assert(reopen_state != NULL);
25
# Don't sort if it's already sorted
20
assert(reopen_state->bs->drv != NULL);
26
do_sort = not isinstance(msg, OrderedDict)
21
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
27
- print(json.dumps(msg, sort_keys=do_sort,
22
qdict_put(reopen_state->options, "driver", qstring_from_str(value));
28
- indent=indent, separators=separators))
23
}
29
+ print(json.dumps(msg, sort_keys=do_sort, indent=indent))
24
30
else:
25
- /* if we are to stay read-only, do not allow permission change
31
print(msg)
26
- * to r/w */
27
- if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
28
- reopen_state->flags & BDRV_O_RDWR) {
29
- error_setg(errp, "Node '%s' is read only",
30
- bdrv_get_device_or_node_name(reopen_state->bs));
31
+ /* If we are to stay read-only, do not allow permission change
32
+ * to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
33
+ * not set, or if the BDS still has copy_on_read enabled */
34
+ read_only = !(reopen_state->flags & BDRV_O_RDWR);
35
+ ret = bdrv_can_set_read_only(reopen_state->bs, read_only, &local_err);
36
+ if (local_err) {
37
+ error_propagate(errp, local_err);
38
goto error;
39
}
40
32
41
--
33
--
42
2.9.3
34
2.26.2
43
35
44
36
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
Representing nested, recursive data structures in mypy is notoriously
4
difficult; the best we can reliably do right now is denote the leaf
5
types as "Any" while describing the general shape of the data.
6
7
Regardless, this fully annotates the log() function.
8
9
Typing notes:
10
11
TypeVar is a Type variable that can optionally be constrained by a
12
sequence of possible types. This variable is bound to a specific type
13
per-invocation, like a Generic.
14
15
log() behaves as log<Msg>() now, where the incoming type informs the
16
signature it expects for any filter arguments passed in. If Msg is a
17
str, then filter should take and return a str.
18
19
Signed-off-by: John Snow <jsnow@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Message-Id: <20200331000014.11581-9-jsnow@redhat.com>
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
tests/qemu-iotests/iotests.py | 14 +++++++++++---
26
1 file changed, 11 insertions(+), 3 deletions(-)
27
28
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qemu-iotests/iotests.py
31
+++ b/tests/qemu-iotests/iotests.py
32
@@ -XXX,XX +XXX,XX @@ import signal
33
import struct
34
import subprocess
35
import sys
36
+from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
37
import unittest
38
39
# pylint: disable=import-error, wrong-import-position
40
@@ -XXX,XX +XXX,XX @@ def filter_qmp_imgfmt(qmsg):
41
return value
42
return filter_qmp(qmsg, _filter)
43
44
-def log(msg, filters=(), indent=None):
45
- '''Logs either a string message or a JSON serializable message (like QMP).
46
- If indent is provided, JSON serializable messages are pretty-printed.'''
47
+
48
+Msg = TypeVar('Msg', Dict[str, Any], List[Any], str)
49
+
50
+def log(msg: Msg,
51
+ filters: Iterable[Callable[[Msg], Msg]] = (),
52
+ indent: Optional[int] = None) -> None:
53
+ """
54
+ Logs either a string message or a JSON serializable message (like QMP).
55
+ If indent is provided, JSON serializable messages are pretty-printed.
56
+ """
57
for flt in filters:
58
msg = flt(msg)
59
if isinstance(msg, (dict, list)):
60
--
61
2.26.2
62
63
diff view generated by jsdifflib
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
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
Minor cleanup for HMP functions; helps with line length and consolidates
4
HMP helpers through one implementation function.
5
6
Although we are adding a universal toggle to turn QMP logging on or off,
7
many existing callers to hmp functions don't expect that output to be
8
logged, which causes quite a few changes in the test output.
9
10
For now, offer a use_log parameter.
11
12
Typing notes:
13
14
QMPResponse is just an alias for Dict[str, Any]. It holds no special
15
meanings and it is not a formal subtype of Dict[str, Any]. It is best
16
thought of as a lexical synonym.
17
18
We may well wish to add stricter subtypes in the future for certain
19
shapes of data that are not formalized as Python objects, at which point
20
we can simply retire the alias and allow mypy to more strictly check
21
usages of the name.
22
23
Signed-off-by: John Snow <jsnow@redhat.com>
24
Message-Id: <20200331000014.11581-11-jsnow@redhat.com>
25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
---
29
tests/qemu-iotests/iotests.py | 39 +++++++++++++++++++++--------------
30
1 file changed, 24 insertions(+), 15 deletions(-)
31
32
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
33
index XXXXXXX..XXXXXXX 100644
34
--- a/tests/qemu-iotests/iotests.py
35
+++ b/tests/qemu-iotests/iotests.py
36
@@ -XXX,XX +XXX,XX @@ from qemu import qtest
37
38
assert sys.version_info >= (3, 6)
39
40
+# Type Aliases
41
+QMPResponse = Dict[str, Any]
42
+
43
+
44
faulthandler.enable()
45
46
# This will not work if arguments contain spaces but is necessary if we
47
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
48
self._args.append(addr)
49
return self
50
51
- def pause_drive(self, drive, event=None):
52
- '''Pause drive r/w operations'''
53
+ def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse:
54
+ cmd = 'human-monitor-command'
55
+ kwargs = {'command-line': command_line}
56
+ if use_log:
57
+ return self.qmp_log(cmd, **kwargs)
58
+ else:
59
+ return self.qmp(cmd, **kwargs)
60
+
61
+ def pause_drive(self, drive: str, event: Optional[str] = None) -> None:
62
+ """Pause drive r/w operations"""
63
if not event:
64
self.pause_drive(drive, "read_aio")
65
self.pause_drive(drive, "write_aio")
66
return
67
- self.qmp('human-monitor-command',
68
- command_line='qemu-io %s "break %s bp_%s"'
69
- % (drive, event, drive))
70
-
71
- def resume_drive(self, drive):
72
- self.qmp('human-monitor-command',
73
- command_line='qemu-io %s "remove_break bp_%s"'
74
- % (drive, drive))
75
-
76
- def hmp_qemu_io(self, drive, cmd):
77
- '''Write to a given drive using an HMP command'''
78
- return self.qmp('human-monitor-command',
79
- command_line='qemu-io %s "%s"' % (drive, cmd))
80
+ self.hmp(f'qemu-io {drive} "break {event} bp_{drive}"')
81
+
82
+ def resume_drive(self, drive: str) -> None:
83
+ """Resume drive r/w operations"""
84
+ self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
85
+
86
+ def hmp_qemu_io(self, drive: str, cmd: str,
87
+ use_log: bool = False) -> QMPResponse:
88
+ """Write to a given drive using an HMP command"""
89
+ return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log)
90
91
def flatten_qmp_object(self, obj, output=None, basestr=''):
92
if output is None:
93
--
94
2.26.2
95
96
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
Like script_main, but doesn't require a single point of entry.
4
Replace all existing initialization sections with this drop-in replacement.
5
6
This brings debug support to all existing script-style iotests.
7
8
Signed-off-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20200331000014.11581-12-jsnow@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
[mreitz: Give 274 the same treatment]
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/149 | 3 +-
16
tests/qemu-iotests/194 | 4 +-
17
tests/qemu-iotests/202 | 4 +-
18
tests/qemu-iotests/203 | 4 +-
19
tests/qemu-iotests/206 | 2 +-
20
tests/qemu-iotests/207 | 6 ++-
21
tests/qemu-iotests/208 | 2 +-
22
tests/qemu-iotests/209 | 2 +-
23
tests/qemu-iotests/210 | 6 ++-
24
tests/qemu-iotests/211 | 6 ++-
25
tests/qemu-iotests/212 | 6 ++-
26
tests/qemu-iotests/213 | 6 ++-
27
tests/qemu-iotests/216 | 4 +-
28
tests/qemu-iotests/218 | 2 +-
29
tests/qemu-iotests/219 | 2 +-
30
tests/qemu-iotests/222 | 7 ++--
31
tests/qemu-iotests/224 | 4 +-
32
tests/qemu-iotests/228 | 6 ++-
33
tests/qemu-iotests/234 | 4 +-
34
tests/qemu-iotests/235 | 4 +-
35
tests/qemu-iotests/236 | 2 +-
36
tests/qemu-iotests/237 | 2 +-
37
tests/qemu-iotests/238 | 2 +
38
tests/qemu-iotests/242 | 2 +-
39
tests/qemu-iotests/246 | 2 +-
40
tests/qemu-iotests/248 | 2 +-
41
tests/qemu-iotests/254 | 2 +-
42
tests/qemu-iotests/255 | 2 +-
43
tests/qemu-iotests/256 | 2 +-
44
tests/qemu-iotests/258 | 7 ++--
45
tests/qemu-iotests/260 | 4 +-
46
tests/qemu-iotests/262 | 4 +-
47
tests/qemu-iotests/264 | 4 +-
48
tests/qemu-iotests/274 | 4 +-
49
tests/qemu-iotests/277 | 2 +
50
tests/qemu-iotests/280 | 8 ++--
51
tests/qemu-iotests/283 | 4 +-
52
tests/qemu-iotests/iotests.py | 76 +++++++++++++++++++++++------------
53
38 files changed, 132 insertions(+), 83 deletions(-)
54
55
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
56
index XXXXXXX..XXXXXXX 100755
57
--- a/tests/qemu-iotests/149
58
+++ b/tests/qemu-iotests/149
59
@@ -XXX,XX +XXX,XX @@ def test_once(config, qemu_img=False):
60
61
62
# Obviously we only work with the luks image format
63
-iotests.verify_image_format(supported_fmts=['luks'])
64
-iotests.verify_platform()
65
+iotests.script_initialize(supported_fmts=['luks'])
66
67
# We need sudo in order to run cryptsetup to create
68
# dm-crypt devices. This is safe to use on any
69
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
70
index XXXXXXX..XXXXXXX 100755
71
--- a/tests/qemu-iotests/194
72
+++ b/tests/qemu-iotests/194
73
@@ -XXX,XX +XXX,XX @@
74
75
import iotests
76
77
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw'])
78
-iotests.verify_platform(['linux'])
79
+iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'],
80
+ supported_platforms=['linux'])
81
82
with iotests.FilePath('source.img') as source_img_path, \
83
iotests.FilePath('dest.img') as dest_img_path, \
84
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
85
index XXXXXXX..XXXXXXX 100755
86
--- a/tests/qemu-iotests/202
87
+++ b/tests/qemu-iotests/202
88
@@ -XXX,XX +XXX,XX @@
89
90
import iotests
91
92
-iotests.verify_image_format(supported_fmts=['qcow2'])
93
-iotests.verify_platform(['linux'])
94
+iotests.script_initialize(supported_fmts=['qcow2'],
95
+ supported_platforms=['linux'])
96
97
with iotests.FilePath('disk0.img') as disk0_img_path, \
98
iotests.FilePath('disk1.img') as disk1_img_path, \
99
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
100
index XXXXXXX..XXXXXXX 100755
101
--- a/tests/qemu-iotests/203
102
+++ b/tests/qemu-iotests/203
103
@@ -XXX,XX +XXX,XX @@
104
105
import iotests
106
107
-iotests.verify_image_format(supported_fmts=['qcow2'])
108
-iotests.verify_platform(['linux'])
109
+iotests.script_initialize(supported_fmts=['qcow2'],
110
+ supported_platforms=['linux'])
111
112
with iotests.FilePath('disk0.img') as disk0_img_path, \
113
iotests.FilePath('disk1.img') as disk1_img_path, \
114
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/206
117
+++ b/tests/qemu-iotests/206
118
@@ -XXX,XX +XXX,XX @@
119
import iotests
120
from iotests import imgfmt
121
122
-iotests.verify_image_format(supported_fmts=['qcow2'])
123
+iotests.script_initialize(supported_fmts=['qcow2'])
124
125
with iotests.FilePath('t.qcow2') as disk_path, \
126
iotests.FilePath('t.qcow2.base') as backing_path, \
127
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
128
index XXXXXXX..XXXXXXX 100755
129
--- a/tests/qemu-iotests/207
130
+++ b/tests/qemu-iotests/207
131
@@ -XXX,XX +XXX,XX @@ import iotests
132
import subprocess
133
import re
134
135
-iotests.verify_image_format(supported_fmts=['raw'])
136
-iotests.verify_protocol(supported=['ssh'])
137
+iotests.script_initialize(
138
+ supported_fmts=['raw'],
139
+ supported_protocols=['ssh'],
140
+)
141
142
def filter_hash(qmsg):
143
def _filter(key, value):
144
diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208
145
index XXXXXXX..XXXXXXX 100755
146
--- a/tests/qemu-iotests/208
147
+++ b/tests/qemu-iotests/208
148
@@ -XXX,XX +XXX,XX @@
149
150
import iotests
151
152
-iotests.verify_image_format(supported_fmts=['generic'])
153
+iotests.script_initialize(supported_fmts=['generic'])
154
155
with iotests.FilePath('disk.img') as disk_img_path, \
156
iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \
157
diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209
158
index XXXXXXX..XXXXXXX 100755
159
--- a/tests/qemu-iotests/209
160
+++ b/tests/qemu-iotests/209
161
@@ -XXX,XX +XXX,XX @@ import iotests
162
from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \
163
file_path
164
165
-iotests.verify_image_format(supported_fmts=['qcow2'])
166
+iotests.script_initialize(supported_fmts=['qcow2'])
167
168
disk = file_path('disk')
169
nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
170
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
171
index XXXXXXX..XXXXXXX 100755
172
--- a/tests/qemu-iotests/210
173
+++ b/tests/qemu-iotests/210
174
@@ -XXX,XX +XXX,XX @@
175
import iotests
176
from iotests import imgfmt
177
178
-iotests.verify_image_format(supported_fmts=['luks'])
179
-iotests.verify_protocol(supported=['file'])
180
+iotests.script_initialize(
181
+ supported_fmts=['luks'],
182
+ supported_protocols=['file'],
183
+)
184
185
with iotests.FilePath('t.luks') as disk_path, \
186
iotests.VM() as vm:
187
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
188
index XXXXXXX..XXXXXXX 100755
189
--- a/tests/qemu-iotests/211
190
+++ b/tests/qemu-iotests/211
191
@@ -XXX,XX +XXX,XX @@
192
import iotests
193
from iotests import imgfmt
194
195
-iotests.verify_image_format(supported_fmts=['vdi'])
196
-iotests.verify_protocol(supported=['file'])
197
+iotests.script_initialize(
198
+ supported_fmts=['vdi'],
199
+ supported_protocols=['file'],
200
+)
201
202
def blockdev_create(vm, options):
203
error = vm.blockdev_create(options)
204
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
205
index XXXXXXX..XXXXXXX 100755
206
--- a/tests/qemu-iotests/212
207
+++ b/tests/qemu-iotests/212
208
@@ -XXX,XX +XXX,XX @@
209
import iotests
210
from iotests import imgfmt
211
212
-iotests.verify_image_format(supported_fmts=['parallels'])
213
-iotests.verify_protocol(supported=['file'])
214
+iotests.script_initialize(
215
+ supported_fmts=['parallels'],
216
+ supported_protocols=['file'],
217
+)
218
219
with iotests.FilePath('t.parallels') as disk_path, \
220
iotests.VM() as vm:
221
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
222
index XXXXXXX..XXXXXXX 100755
223
--- a/tests/qemu-iotests/213
224
+++ b/tests/qemu-iotests/213
225
@@ -XXX,XX +XXX,XX @@
226
import iotests
227
from iotests import imgfmt
228
229
-iotests.verify_image_format(supported_fmts=['vhdx'])
230
-iotests.verify_protocol(supported=['file'])
231
+iotests.script_initialize(
232
+ supported_fmts=['vhdx'],
233
+ supported_protocols=['file'],
234
+)
235
236
with iotests.FilePath('t.vhdx') as disk_path, \
237
iotests.VM() as vm:
238
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
239
index XXXXXXX..XXXXXXX 100755
240
--- a/tests/qemu-iotests/216
241
+++ b/tests/qemu-iotests/216
242
@@ -XXX,XX +XXX,XX @@ import iotests
243
from iotests import log, qemu_img, qemu_io_silent
244
245
# Need backing file support
246
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
247
-iotests.verify_platform(['linux'])
248
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
249
+ supported_platforms=['linux'])
250
251
log('')
252
log('=== Copy-on-read across nodes ===')
253
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
254
index XXXXXXX..XXXXXXX 100755
255
--- a/tests/qemu-iotests/218
256
+++ b/tests/qemu-iotests/218
257
@@ -XXX,XX +XXX,XX @@
258
import iotests
259
from iotests import log, qemu_img, qemu_io_silent
260
261
-iotests.verify_image_format(supported_fmts=['qcow2', 'raw'])
262
+iotests.script_initialize(supported_fmts=['qcow2', 'raw'])
263
264
265
# Launches the VM, adds two null-co nodes (source and target), and
266
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
267
index XXXXXXX..XXXXXXX 100755
268
--- a/tests/qemu-iotests/219
269
+++ b/tests/qemu-iotests/219
270
@@ -XXX,XX +XXX,XX @@
271
272
import iotests
273
274
-iotests.verify_image_format(supported_fmts=['qcow2'])
275
+iotests.script_initialize(supported_fmts=['qcow2'])
276
277
img_size = 4 * 1024 * 1024
278
279
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
280
index XXXXXXX..XXXXXXX 100755
281
--- a/tests/qemu-iotests/222
282
+++ b/tests/qemu-iotests/222
283
@@ -XXX,XX +XXX,XX @@
284
import iotests
285
from iotests import log, qemu_img, qemu_io, qemu_io_silent
286
287
-iotests.verify_platform(['linux'])
288
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk',
289
- 'vhdx', 'raw'])
290
+iotests.script_initialize(
291
+ supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
292
+ supported_platforms=['linux'],
293
+)
294
295
patterns = [("0x5d", "0", "64k"),
296
("0xd5", "1M", "64k"),
297
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
298
index XXXXXXX..XXXXXXX 100755
299
--- a/tests/qemu-iotests/224
300
+++ b/tests/qemu-iotests/224
301
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
302
import json
303
304
# Need backing file support (for arbitrary backing formats)
305
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
306
-iotests.verify_platform(['linux'])
307
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed'],
308
+ supported_platforms=['linux'])
309
310
311
# There are two variations of this test:
312
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
313
index XXXXXXX..XXXXXXX 100755
314
--- a/tests/qemu-iotests/228
315
+++ b/tests/qemu-iotests/228
316
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
317
filter_qmp_testfiles, filter_qmp_imgfmt
318
319
# Need backing file and change-backing-file support
320
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
321
-iotests.verify_platform(['linux'])
322
+iotests.script_initialize(
323
+ supported_fmts=['qcow2', 'qed'],
324
+ supported_platforms=['linux'],
325
+)
326
327
328
def log_node_info(node):
329
diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234
330
index XXXXXXX..XXXXXXX 100755
331
--- a/tests/qemu-iotests/234
332
+++ b/tests/qemu-iotests/234
333
@@ -XXX,XX +XXX,XX @@
334
import iotests
335
import os
336
337
-iotests.verify_image_format(supported_fmts=['qcow2'])
338
-iotests.verify_platform(['linux'])
339
+iotests.script_initialize(supported_fmts=['qcow2'],
340
+ supported_platforms=['linux'])
341
342
with iotests.FilePath('img') as img_path, \
343
iotests.FilePath('backing') as backing_path, \
344
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
345
index XXXXXXX..XXXXXXX 100755
346
--- a/tests/qemu-iotests/235
347
+++ b/tests/qemu-iotests/235
348
@@ -XXX,XX +XXX,XX @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
349
350
from qemu.machine import QEMUMachine
351
352
+iotests.script_initialize(supported_fmts=['qcow2'])
353
+
354
# Note:
355
# This test was added to check that mirror dead-lock was fixed (see previous
356
# commit before this test addition).
357
@@ -XXX,XX +XXX,XX @@ from qemu.machine import QEMUMachine
358
359
size = 1 * 1024 * 1024 * 1024
360
361
-iotests.verify_image_format(supported_fmts=['qcow2'])
362
-
363
disk = file_path('disk')
364
365
# prepare source image
366
diff --git a/tests/qemu-iotests/236 b/tests/qemu-iotests/236
367
index XXXXXXX..XXXXXXX 100755
368
--- a/tests/qemu-iotests/236
369
+++ b/tests/qemu-iotests/236
370
@@ -XXX,XX +XXX,XX @@
371
import iotests
372
from iotests import log
373
374
-iotests.verify_image_format(supported_fmts=['generic'])
375
+iotests.script_initialize(supported_fmts=['generic'])
376
size = 64 * 1024 * 1024
377
granularity = 64 * 1024
378
379
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
380
index XXXXXXX..XXXXXXX 100755
381
--- a/tests/qemu-iotests/237
382
+++ b/tests/qemu-iotests/237
383
@@ -XXX,XX +XXX,XX @@ import math
384
import iotests
385
from iotests import imgfmt
386
387
-iotests.verify_image_format(supported_fmts=['vmdk'])
388
+iotests.script_initialize(supported_fmts=['vmdk'])
389
390
with iotests.FilePath('t.vmdk') as disk_path, \
391
iotests.FilePath('t.vmdk.1') as extent1_path, \
392
diff --git a/tests/qemu-iotests/238 b/tests/qemu-iotests/238
393
index XXXXXXX..XXXXXXX 100755
394
--- a/tests/qemu-iotests/238
395
+++ b/tests/qemu-iotests/238
396
@@ -XXX,XX +XXX,XX @@ import os
397
import iotests
398
from iotests import log
399
400
+iotests.script_initialize()
401
+
402
virtio_scsi_device = iotests.get_virtio_scsi_device()
403
404
vm = iotests.VM()
405
diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242
406
index XXXXXXX..XXXXXXX 100755
407
--- a/tests/qemu-iotests/242
408
+++ b/tests/qemu-iotests/242
409
@@ -XXX,XX +XXX,XX @@ import struct
410
from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \
411
file_path, img_info_log, log, filter_qemu_io
412
413
-iotests.verify_image_format(supported_fmts=['qcow2'])
414
+iotests.script_initialize(supported_fmts=['qcow2'])
415
416
disk = file_path('disk')
417
chunk = 256 * 1024
418
diff --git a/tests/qemu-iotests/246 b/tests/qemu-iotests/246
419
index XXXXXXX..XXXXXXX 100755
420
--- a/tests/qemu-iotests/246
421
+++ b/tests/qemu-iotests/246
422
@@ -XXX,XX +XXX,XX @@
423
import iotests
424
from iotests import log
425
426
-iotests.verify_image_format(supported_fmts=['qcow2'])
427
+iotests.script_initialize(supported_fmts=['qcow2'])
428
size = 64 * 1024 * 1024 * 1024
429
gran_small = 32 * 1024
430
gran_large = 128 * 1024
431
diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248
432
index XXXXXXX..XXXXXXX 100755
433
--- a/tests/qemu-iotests/248
434
+++ b/tests/qemu-iotests/248
435
@@ -XXX,XX +XXX,XX @@
436
import iotests
437
from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles
438
439
-iotests.verify_image_format(supported_fmts=['qcow2'])
440
+iotests.script_initialize(supported_fmts=['qcow2'])
441
442
source, target = file_path('source', 'target')
443
size = 5 * 1024 * 1024
444
diff --git a/tests/qemu-iotests/254 b/tests/qemu-iotests/254
445
index XXXXXXX..XXXXXXX 100755
446
--- a/tests/qemu-iotests/254
447
+++ b/tests/qemu-iotests/254
448
@@ -XXX,XX +XXX,XX @@
449
import iotests
450
from iotests import qemu_img_create, file_path, log
451
452
-iotests.verify_image_format(supported_fmts=['qcow2'])
453
+iotests.script_initialize(supported_fmts=['qcow2'])
454
455
disk, top = file_path('disk', 'top')
456
size = 1024 * 1024
457
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
458
index XXXXXXX..XXXXXXX 100755
459
--- a/tests/qemu-iotests/255
460
+++ b/tests/qemu-iotests/255
461
@@ -XXX,XX +XXX,XX @@
462
import iotests
463
from iotests import imgfmt
464
465
-iotests.verify_image_format(supported_fmts=['qcow2'])
466
+iotests.script_initialize(supported_fmts=['qcow2'])
467
468
iotests.log('Finishing a commit job with background reads')
469
iotests.log('============================================')
470
diff --git a/tests/qemu-iotests/256 b/tests/qemu-iotests/256
471
index XXXXXXX..XXXXXXX 100755
472
--- a/tests/qemu-iotests/256
473
+++ b/tests/qemu-iotests/256
474
@@ -XXX,XX +XXX,XX @@ import os
475
import iotests
476
from iotests import log
477
478
-iotests.verify_image_format(supported_fmts=['qcow2'])
479
+iotests.script_initialize(supported_fmts=['qcow2'])
480
size = 64 * 1024 * 1024
481
482
with iotests.FilePath('img0') as img0_path, \
483
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
484
index XXXXXXX..XXXXXXX 100755
485
--- a/tests/qemu-iotests/258
486
+++ b/tests/qemu-iotests/258
487
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io_silent, \
488
filter_qmp_testfiles, filter_qmp_imgfmt
489
490
# Need backing file and change-backing-file support
491
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
492
-iotests.verify_platform(['linux'])
493
-
494
+iotests.script_initialize(
495
+ supported_fmts=['qcow2', 'qed'],
496
+ supported_platforms=['linux'],
497
+)
498
499
# Returns a node for blockdev-add
500
def node(node_name, path, backing=None, fmt=None, throttle=None):
501
diff --git a/tests/qemu-iotests/260 b/tests/qemu-iotests/260
502
index XXXXXXX..XXXXXXX 100755
503
--- a/tests/qemu-iotests/260
504
+++ b/tests/qemu-iotests/260
505
@@ -XXX,XX +XXX,XX @@
506
import iotests
507
from iotests import qemu_img_create, file_path, log, filter_qmp_event
508
509
-iotests.verify_image_format(supported_fmts=['qcow2'])
510
+iotests.script_initialize(
511
+ supported_fmts=['qcow2']
512
+)
513
514
base, top = file_path('base', 'top')
515
size = 64 * 1024 * 3
516
diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262
517
index XXXXXXX..XXXXXXX 100755
518
--- a/tests/qemu-iotests/262
519
+++ b/tests/qemu-iotests/262
520
@@ -XXX,XX +XXX,XX @@
521
import iotests
522
import os
523
524
-iotests.verify_image_format(supported_fmts=['qcow2'])
525
-iotests.verify_platform(['linux'])
526
+iotests.script_initialize(supported_fmts=['qcow2'],
527
+ supported_platforms=['linux'])
528
529
with iotests.FilePath('img') as img_path, \
530
iotests.FilePath('mig_fifo') as fifo, \
531
diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264
532
index XXXXXXX..XXXXXXX 100755
533
--- a/tests/qemu-iotests/264
534
+++ b/tests/qemu-iotests/264
535
@@ -XXX,XX +XXX,XX @@ import iotests
536
from iotests import qemu_img_create, qemu_io_silent_check, file_path, \
537
qemu_nbd_popen, log
538
539
-iotests.verify_image_format(supported_fmts=['qcow2'])
540
+iotests.script_initialize(
541
+ supported_fmts=['qcow2'],
542
+)
543
544
disk_a, disk_b, nbd_sock = file_path('disk_a', 'disk_b', 'nbd-sock')
545
nbd_uri = 'nbd+unix:///?socket=' + nbd_sock
546
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
547
index XXXXXXX..XXXXXXX 100755
548
--- a/tests/qemu-iotests/274
549
+++ b/tests/qemu-iotests/274
550
@@ -XXX,XX +XXX,XX @@
551
552
import iotests
553
554
-iotests.verify_image_format(supported_fmts=['qcow2'])
555
-iotests.verify_platform(['linux'])
556
+iotests.script_initialize(supported_fmts=['qcow2'],
557
+ supported_platforms=['linux'])
558
559
size_short = 1 * 1024 * 1024
560
size_long = 2 * 1024 * 1024
561
diff --git a/tests/qemu-iotests/277 b/tests/qemu-iotests/277
562
index XXXXXXX..XXXXXXX 100755
563
--- a/tests/qemu-iotests/277
564
+++ b/tests/qemu-iotests/277
565
@@ -XXX,XX +XXX,XX @@ import subprocess
566
import iotests
567
from iotests import file_path, log
568
569
+iotests.script_initialize()
570
+
571
572
nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf')
573
574
diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280
575
index XXXXXXX..XXXXXXX 100755
576
--- a/tests/qemu-iotests/280
577
+++ b/tests/qemu-iotests/280
578
@@ -XXX,XX +XXX,XX @@
579
import iotests
580
import os
581
582
-iotests.verify_image_format(supported_fmts=['qcow2'])
583
-iotests.verify_protocol(supported=['file'])
584
-iotests.verify_platform(['linux'])
585
+iotests.script_initialize(
586
+ supported_fmts=['qcow2'],
587
+ supported_protocols=['file'],
588
+ supported_platforms=['linux'],
589
+)
590
591
with iotests.FilePath('base') as base_path , \
592
iotests.FilePath('top') as top_path, \
593
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
594
index XXXXXXX..XXXXXXX 100644
595
--- a/tests/qemu-iotests/283
596
+++ b/tests/qemu-iotests/283
597
@@ -XXX,XX +XXX,XX @@
598
import iotests
599
600
# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
601
-iotests.verify_image_format(supported_fmts=['qcow2'])
602
+iotests.script_initialize(
603
+ supported_fmts=['qcow2'],
604
+)
605
606
size = 1024 * 1024
607
608
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
609
index XXXXXXX..XXXXXXX 100644
610
--- a/tests/qemu-iotests/iotests.py
611
+++ b/tests/qemu-iotests/iotests.py
612
@@ -XXX,XX +XXX,XX @@ import signal
613
import struct
614
import subprocess
615
import sys
616
-from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
617
+from typing import (Any, Callable, Dict, Iterable,
618
+ List, Optional, Sequence, TypeVar)
619
import unittest
620
621
# pylint: disable=import-error, wrong-import-position
622
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
623
if not_sup or (imgproto in unsupported):
624
notrun('not suitable for this protocol: %s' % imgproto)
625
626
-def verify_platform(supported=None, unsupported=None):
627
- if unsupported is not None:
628
- if any((sys.platform.startswith(x) for x in unsupported)):
629
- notrun('not suitable for this OS: %s' % sys.platform)
630
+def verify_platform(supported=(), unsupported=()):
631
+ if any((sys.platform.startswith(x) for x in unsupported)):
632
+ notrun('not suitable for this OS: %s' % sys.platform)
633
634
- if supported is not None:
635
+ if supported:
636
if not any((sys.platform.startswith(x) for x in supported)):
637
notrun('not suitable for this OS: %s' % sys.platform)
638
639
@@ -XXX,XX +XXX,XX @@ def skip_if_user_is_root(func):
640
return func(*args, **kwargs)
641
return func_wrapper
642
643
-def execute_unittest(output, verbosity, debug):
644
+def execute_unittest(debug=False):
645
+ """Executes unittests within the calling module."""
646
+
647
+ verbosity = 2 if debug else 1
648
+
649
+ if debug:
650
+ output = sys.stdout
651
+ else:
652
+ # We need to filter out the time taken from the output so that
653
+ # qemu-iotest can reliably diff the results against master output.
654
+ output = io.StringIO()
655
+
656
runner = unittest.TextTestRunner(stream=output, descriptions=True,
657
verbosity=verbosity)
658
try:
659
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
660
# exception
661
unittest.main(testRunner=runner)
662
finally:
663
+ # We need to filter out the time taken from the output so that
664
+ # qemu-iotest can reliably diff the results against master output.
665
if not debug:
666
out = output.getvalue()
667
out = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', out)
668
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
669
670
sys.stderr.write(out)
671
672
-def execute_test(test_function=None,
673
- supported_fmts=(),
674
- supported_platforms=None,
675
- supported_cache_modes=(), supported_aio_modes=(),
676
- unsupported_fmts=(), supported_protocols=(),
677
- unsupported_protocols=()):
678
- """Run either unittest or script-style tests."""
679
+def execute_setup_common(supported_fmts: Sequence[str] = (),
680
+ supported_platforms: Sequence[str] = (),
681
+ supported_cache_modes: Sequence[str] = (),
682
+ supported_aio_modes: Sequence[str] = (),
683
+ unsupported_fmts: Sequence[str] = (),
684
+ supported_protocols: Sequence[str] = (),
685
+ unsupported_protocols: Sequence[str] = ()) -> bool:
686
+ """
687
+ Perform necessary setup for either script-style or unittest-style tests.
688
+
689
+ :return: Bool; Whether or not debug mode has been requested via the CLI.
690
+ """
691
+ # Note: Python 3.6 and pylint do not like 'Collection' so use 'Sequence'.
692
693
# We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
694
# indicate that we're not being run via "check". There may be
695
@@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None,
696
sys.stderr.write('Please run this test via the "check" script\n')
697
sys.exit(os.EX_USAGE)
698
699
- debug = '-d' in sys.argv
700
- verbosity = 1
701
verify_image_format(supported_fmts, unsupported_fmts)
702
verify_protocol(supported_protocols, unsupported_protocols)
703
verify_platform(supported=supported_platforms)
704
verify_cache_mode(supported_cache_modes)
705
verify_aio_mode(supported_aio_modes)
706
707
+ debug = '-d' in sys.argv
708
if debug:
709
- output = sys.stdout
710
- verbosity = 2
711
sys.argv.remove('-d')
712
- else:
713
- # We need to filter out the time taken from the output so that
714
- # qemu-iotest can reliably diff the results against master output.
715
- output = io.StringIO()
716
-
717
logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
718
719
+ return debug
720
+
721
+def execute_test(*args, test_function=None, **kwargs):
722
+ """Run either unittest or script-style tests."""
723
+
724
+ debug = execute_setup_common(*args, **kwargs)
725
if not test_function:
726
- execute_unittest(output, verbosity, debug)
727
+ execute_unittest(debug)
728
else:
729
test_function()
730
731
+# This is called from script-style iotests without a single point of entry
732
+def script_initialize(*args, **kwargs):
733
+ """Initialize script-style tests without running any tests."""
734
+ execute_setup_common(*args, **kwargs)
735
+
736
+# This is called from script-style iotests with a single point of entry
737
def script_main(test_function, *args, **kwargs):
738
"""Run script-style tests outside of the unittest framework"""
739
- execute_test(test_function, *args, **kwargs)
740
+ execute_test(*args, test_function=test_function, **kwargs)
741
742
+# This is called from unittest style iotests
743
def main(*args, **kwargs):
744
"""Run tests using the unittest framework"""
745
- execute_test(None, *args, **kwargs)
746
+ execute_test(*args, **kwargs)
747
--
748
2.26.2
749
750
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
Since this one is nicely factored to use a single entry point,
4
use script_main to run the tests.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200331000014.11581-13-jsnow@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/258 | 11 ++++-------
14
1 file changed, 4 insertions(+), 7 deletions(-)
15
16
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/258
19
+++ b/tests/qemu-iotests/258
20
@@ -XXX,XX +XXX,XX @@ import iotests
21
from iotests import log, qemu_img, qemu_io_silent, \
22
filter_qmp_testfiles, filter_qmp_imgfmt
23
24
-# Need backing file and change-backing-file support
25
-iotests.script_initialize(
26
- supported_fmts=['qcow2', 'qed'],
27
- supported_platforms=['linux'],
28
-)
29
-
30
# Returns a node for blockdev-add
31
def node(node_name, path, backing=None, fmt=None, throttle=None):
32
if fmt is None:
33
@@ -XXX,XX +XXX,XX @@ def main():
34
test_concurrent_finish(False)
35
36
if __name__ == '__main__':
37
- main()
38
+ # Need backing file and change-backing-file support
39
+ iotests.script_main(main,
40
+ supported_fmts=['qcow2', 'qed'],
41
+ supported_platforms=['linux'])
42
--
43
2.26.2
44
45
diff view generated by jsdifflib
1
For the tests that use the common.qemu functions for running a QEMU
1
From: John Snow <jsnow@redhat.com>
2
process, _cleanup_qemu must be called in the exit function.
3
2
4
If it is not, if the qemu process aborts, then not all of the droppings
3
Mark the verify functions as "private" with a leading underscore, to
5
are cleaned up (e.g. pidfile, fifos).
4
discourage their use. Update type signatures while we're here.
6
5
7
This updates those tests that did not have a cleanup in qemu-iotests.
6
(Also, make pending patches not yet using the new entry points fail in a
7
very obvious way.)
8
8
9
(I swapped spaces for tabs in test 102 as well)
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20200331000014.11581-14-jsnow@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/iotests.py | 23 +++++++++++++----------
16
1 file changed, 13 insertions(+), 10 deletions(-)
10
17
11
Reported-by: Eric Blake <eblake@redhat.com>
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
Reviewed-by: Eric Blake <eblake@redhat.com>
19
index XXXXXXX..XXXXXXX 100644
13
Signed-off-by: Jeff Cody <jcody@redhat.com>
20
--- a/tests/qemu-iotests/iotests.py
14
Message-id: d59c2f6ad6c1da8b9b3c7f357c94a7122ccfc55a.1492544096.git.jcody@redhat.com
21
+++ b/tests/qemu-iotests/iotests.py
15
---
22
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
16
tests/qemu-iotests/028 | 1 +
23
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
17
tests/qemu-iotests/094 | 11 ++++++++---
24
' [case not run] ' + reason + '\n')
18
tests/qemu-iotests/102 | 5 +++--
25
19
tests/qemu-iotests/109 | 1 +
26
-def verify_image_format(supported_fmts=(), unsupported_fmts=()):
20
tests/qemu-iotests/117 | 1 +
27
+def _verify_image_format(supported_fmts: Sequence[str] = (),
21
tests/qemu-iotests/130 | 1 +
28
+ unsupported_fmts: Sequence[str] = ()) -> None:
22
tests/qemu-iotests/140 | 1 +
29
assert not (supported_fmts and unsupported_fmts)
23
tests/qemu-iotests/141 | 1 +
30
24
tests/qemu-iotests/143 | 1 +
31
if 'generic' in supported_fmts and \
25
tests/qemu-iotests/156 | 1 +
32
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=(), unsupported_fmts=()):
26
10 files changed, 19 insertions(+), 5 deletions(-)
33
if not_sup or (imgfmt in unsupported_fmts):
27
34
notrun('not suitable for this image format: %s' % imgfmt)
28
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
35
29
index XXXXXXX..XXXXXXX 100755
36
-def verify_protocol(supported=(), unsupported=()):
30
--- a/tests/qemu-iotests/028
37
+def _verify_protocol(supported: Sequence[str] = (),
31
+++ b/tests/qemu-iotests/028
38
+ unsupported: Sequence[str] = ()) -> None:
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
39
assert not (supported and unsupported)
33
40
34
_cleanup()
41
if 'generic' in supported:
35
{
42
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
36
+ _cleanup_qemu
43
if not_sup or (imgproto in unsupported):
37
rm -f "${TEST_IMG}.copy"
44
notrun('not suitable for this protocol: %s' % imgproto)
38
_cleanup_test_img
45
39
}
46
-def verify_platform(supported=(), unsupported=()):
40
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
47
+def _verify_platform(supported: Sequence[str] = (),
41
index XXXXXXX..XXXXXXX 100755
48
+ unsupported: Sequence[str] = ()) -> None:
42
--- a/tests/qemu-iotests/094
49
if any((sys.platform.startswith(x) for x in unsupported)):
43
+++ b/tests/qemu-iotests/094
50
notrun('not suitable for this OS: %s' % sys.platform)
44
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
51
45
here="$PWD"
52
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=(), unsupported=()):
46
status=1    # failure is the default!
53
if not any((sys.platform.startswith(x) for x in supported)):
47
54
notrun('not suitable for this OS: %s' % sys.platform)
48
-trap "exit \$status" 0 1 2 3 15
55
49
+_cleanup()
56
-def verify_cache_mode(supported_cache_modes=()):
50
+{
57
+def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
51
+ _cleanup_qemu
58
if supported_cache_modes and (cachemode not in supported_cache_modes):
52
+ _cleanup_test_img
59
notrun('not suitable for this cache mode: %s' % cachemode)
53
+ rm -f "$TEST_DIR/source.$IMGFMT"
60
54
+}
61
-def verify_aio_mode(supported_aio_modes=()):
55
+
62
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
63
if supported_aio_modes and (aiomode not in supported_aio_modes):
57
64
notrun('not suitable for this aio mode: %s' % aiomode)
58
# get standard environment, filters and checks
65
59
. ./common.rc
66
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
60
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
67
sys.stderr.write('Please run this test via the "check" script\n')
61
68
sys.exit(os.EX_USAGE)
62
wait=1 _cleanup_qemu
69
63
70
- verify_image_format(supported_fmts, unsupported_fmts)
64
-_cleanup_test_img
71
- verify_protocol(supported_protocols, unsupported_protocols)
65
-rm -f "$TEST_DIR/source.$IMGFMT"
72
- verify_platform(supported=supported_platforms)
66
73
- verify_cache_mode(supported_cache_modes)
67
# success, all done
74
- verify_aio_mode(supported_aio_modes)
68
echo '*** done'
75
+ _verify_image_format(supported_fmts, unsupported_fmts)
69
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
76
+ _verify_protocol(supported_protocols, unsupported_protocols)
70
index XXXXXXX..XXXXXXX 100755
77
+ _verify_platform(supported=supported_platforms)
71
--- a/tests/qemu-iotests/102
78
+ _verify_cache_mode(supported_cache_modes)
72
+++ b/tests/qemu-iotests/102
79
+ _verify_aio_mode(supported_aio_modes)
73
@@ -XXX,XX +XXX,XX @@ seq=$(basename $0)
80
74
echo "QA output created by $seq"
81
debug = '-d' in sys.argv
75
82
if debug:
76
here=$PWD
77
-status=1    # failure is the default!
78
+status=1 # failure is the default!
79
80
_cleanup()
81
{
82
-    _cleanup_test_img
83
+ _cleanup_qemu
84
+ _cleanup_test_img
85
}
86
trap "_cleanup; exit \$status" 0 1 2 3 15
87
88
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
89
index XXXXXXX..XXXXXXX 100755
90
--- a/tests/qemu-iotests/109
91
+++ b/tests/qemu-iotests/109
92
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
93
94
_cleanup()
95
{
96
+ _cleanup_qemu
97
rm -f $TEST_IMG.src
98
    _cleanup_test_img
99
}
100
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
101
index XXXXXXX..XXXXXXX 100755
102
--- a/tests/qemu-iotests/117
103
+++ b/tests/qemu-iotests/117
104
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
105
106
_cleanup()
107
{
108
+ _cleanup_qemu
109
    _cleanup_test_img
110
}
111
trap "_cleanup; exit \$status" 0 1 2 3 15
112
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
113
index XXXXXXX..XXXXXXX 100755
114
--- a/tests/qemu-iotests/130
115
+++ b/tests/qemu-iotests/130
116
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
117
118
_cleanup()
119
{
120
+ _cleanup_qemu
121
_cleanup_test_img
122
}
123
trap "_cleanup; exit \$status" 0 1 2 3 15
124
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
125
index XXXXXXX..XXXXXXX 100755
126
--- a/tests/qemu-iotests/140
127
+++ b/tests/qemu-iotests/140
128
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
129
130
_cleanup()
131
{
132
+ _cleanup_qemu
133
_cleanup_test_img
134
rm -f "$TEST_DIR/nbd"
135
}
136
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
137
index XXXXXXX..XXXXXXX 100755
138
--- a/tests/qemu-iotests/141
139
+++ b/tests/qemu-iotests/141
140
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
141
142
_cleanup()
143
{
144
+ _cleanup_qemu
145
_cleanup_test_img
146
rm -f "$TEST_DIR/{b,m,o}.$IMGFMT"
147
}
148
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
149
index XXXXXXX..XXXXXXX 100755
150
--- a/tests/qemu-iotests/143
151
+++ b/tests/qemu-iotests/143
152
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
153
154
_cleanup()
155
{
156
+ _cleanup_qemu
157
rm -f "$TEST_DIR/nbd"
158
}
159
trap "_cleanup; exit \$status" 0 1 2 3 15
160
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
161
index XXXXXXX..XXXXXXX 100755
162
--- a/tests/qemu-iotests/156
163
+++ b/tests/qemu-iotests/156
164
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
165
166
_cleanup()
167
{
168
+ _cleanup_qemu
169
rm -f "$TEST_IMG{,.target}{,.backing,.overlay}"
170
}
171
trap "_cleanup; exit \$status" 0 1 2 3 15
172
--
83
--
173
2.9.3
84
2.26.2
174
85
175
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
New patch
1
1
From: Eric Blake <eblake@redhat.com>
2
3
There are several callers that need to create a new block backend from
4
an existing BDS; make the task slightly easier with a common helper
5
routine.
6
7
Suggested-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Message-Id: <20200424190903.522087-2-eblake@redhat.com>
10
[mreitz: Set @ret only in error paths, see
11
https://lists.nongnu.org/archive/html/qemu-block/2020-04/msg01216.html]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200428192648.749066-2-eblake@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
include/sysemu/block-backend.h | 2 ++
17
block/block-backend.c | 23 +++++++++++++++++++++++
18
block/crypto.c | 9 ++++-----
19
block/parallels.c | 8 ++++----
20
block/qcow.c | 8 ++++----
21
block/qcow2.c | 18 ++++++++----------
22
block/qed.c | 8 ++++----
23
block/sheepdog.c | 10 +++++-----
24
block/vdi.c | 8 ++++----
25
block/vhdx.c | 8 ++++----
26
block/vmdk.c | 9 ++++-----
27
block/vpc.c | 8 ++++----
28
blockdev.c | 8 +++-----
29
blockjob.c | 7 ++-----
30
14 files changed, 75 insertions(+), 59 deletions(-)
31
32
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/sysemu/block-backend.h
35
+++ b/include/sysemu/block-backend.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct BlockBackendPublic {
37
} BlockBackendPublic;
38
39
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm);
40
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
41
+ uint64_t shared_perm, Error **errp);
42
BlockBackend *blk_new_open(const char *filename, const char *reference,
43
QDict *options, int flags, Error **errp);
44
int blk_get_refcnt(BlockBackend *blk);
45
diff --git a/block/block-backend.c b/block/block-backend.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/block-backend.c
48
+++ b/block/block-backend.c
49
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
50
return blk;
51
}
52
53
+/*
54
+ * Create a new BlockBackend connected to an existing BlockDriverState.
55
+ *
56
+ * @perm is a bitmasks of BLK_PERM_* constants which describes the
57
+ * permissions to request for @bs that is attached to this
58
+ * BlockBackend. @shared_perm is a bitmask which describes which
59
+ * permissions may be granted to other users of the attached node.
60
+ * Both sets of permissions can be changed later using blk_set_perm().
61
+ *
62
+ * Return the new BlockBackend on success, null on failure.
63
+ */
64
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
65
+ uint64_t shared_perm, Error **errp)
66
+{
67
+ BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
68
+
69
+ if (blk_insert_bs(blk, bs, errp) < 0) {
70
+ blk_unref(blk);
71
+ return NULL;
72
+ }
73
+ return blk;
74
+}
75
+
76
/*
77
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
78
* The new BlockBackend is in the main AioContext.
79
diff --git a/block/crypto.c b/block/crypto.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block/crypto.c
82
+++ b/block/crypto.c
83
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
84
QCryptoBlock *crypto = NULL;
85
struct BlockCryptoCreateData data;
86
87
- blk = blk_new(bdrv_get_aio_context(bs),
88
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
89
-
90
- ret = blk_insert_bs(blk, bs, errp);
91
- if (ret < 0) {
92
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
93
+ errp);
94
+ if (!blk) {
95
+ ret = -EPERM;
96
goto cleanup;
97
}
98
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
104
return -EIO;
105
}
106
107
- blk = blk_new(bdrv_get_aio_context(bs),
108
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
109
- ret = blk_insert_bs(blk, bs, errp);
110
- if (ret < 0) {
111
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
112
+ errp);
113
+ if (!blk) {
114
+ ret = -EPERM;
115
goto out;
116
}
117
blk_set_allow_write_beyond_eof(blk, true);
118
diff --git a/block/qcow.c b/block/qcow.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/block/qcow.c
121
+++ b/block/qcow.c
122
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
123
return -EIO;
124
}
125
126
- qcow_blk = blk_new(bdrv_get_aio_context(bs),
127
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
128
- ret = blk_insert_bs(qcow_blk, bs, errp);
129
- if (ret < 0) {
130
+ qcow_blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE,
131
+ BLK_PERM_ALL, errp);
132
+ if (!qcow_blk) {
133
+ ret = -EPERM;
134
goto exit;
135
}
136
blk_set_allow_write_beyond_eof(qcow_blk, true);
137
diff --git a/block/qcow2.c b/block/qcow2.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/qcow2.c
140
+++ b/block/qcow2.c
141
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
142
}
143
144
/* Create BlockBackend to write to the image */
145
- blk = blk_new(bdrv_get_aio_context(bs),
146
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
147
- ret = blk_insert_bs(blk, bs, errp);
148
- if (ret < 0) {
149
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
150
+ errp);
151
+ if (!blk) {
152
+ ret = -EPERM;
153
goto out;
154
}
155
blk_set_allow_write_beyond_eof(blk, true);
156
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
157
}
158
159
if (new_size) {
160
- BlockBackend *blk = blk_new(bdrv_get_aio_context(bs),
161
- BLK_PERM_RESIZE, BLK_PERM_ALL);
162
- ret = blk_insert_bs(blk, bs, errp);
163
- if (ret < 0) {
164
- blk_unref(blk);
165
- return ret;
166
+ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
167
+ errp);
168
+ if (!blk) {
169
+ return -EPERM;
170
}
171
172
/*
173
diff --git a/block/qed.c b/block/qed.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/block/qed.c
176
+++ b/block/qed.c
177
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
178
return -EIO;
179
}
180
181
- blk = blk_new(bdrv_get_aio_context(bs),
182
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
183
- ret = blk_insert_bs(blk, bs, errp);
184
- if (ret < 0) {
185
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
186
+ errp);
187
+ if (!blk) {
188
+ ret = -EPERM;
189
goto out;
190
}
191
blk_set_allow_write_beyond_eof(blk, true);
192
diff --git a/block/sheepdog.c b/block/sheepdog.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/sheepdog.c
195
+++ b/block/sheepdog.c
196
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size,
197
void *buf = NULL;
198
int ret;
199
200
- blk = blk_new(bdrv_get_aio_context(bs),
201
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
202
- BLK_PERM_ALL);
203
+ blk = blk_new_with_bs(bs,
204
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
205
+ BLK_PERM_ALL, errp);
206
207
- ret = blk_insert_bs(blk, bs, errp);
208
- if (ret < 0) {
209
+ if (!blk) {
210
+ ret = -EPERM;
211
goto out_with_err_set;
212
}
213
214
diff --git a/block/vdi.c b/block/vdi.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/block/vdi.c
217
+++ b/block/vdi.c
218
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
219
goto exit;
220
}
221
222
- blk = blk_new(bdrv_get_aio_context(bs_file),
223
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
224
- ret = blk_insert_bs(blk, bs_file, errp);
225
- if (ret < 0) {
226
+ blk = blk_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE,
227
+ BLK_PERM_ALL, errp);
228
+ if (!blk) {
229
+ ret = -EPERM;
230
goto exit;
231
}
232
233
diff --git a/block/vhdx.c b/block/vhdx.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/block/vhdx.c
236
+++ b/block/vhdx.c
237
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
238
return -EIO;
239
}
240
241
- blk = blk_new(bdrv_get_aio_context(bs),
242
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
243
- ret = blk_insert_bs(blk, bs, errp);
244
- if (ret < 0) {
245
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
246
+ errp);
247
+ if (!blk) {
248
+ ret = -EPERM;
249
goto delete_and_exit;
250
}
251
blk_set_allow_write_beyond_eof(blk, true);
252
diff --git a/block/vmdk.c b/block/vmdk.c
253
index XXXXXXX..XXXXXXX 100644
254
--- a/block/vmdk.c
255
+++ b/block/vmdk.c
256
@@ -XXX,XX +XXX,XX @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,
257
if (!bs) {
258
return NULL;
259
}
260
- blk = blk_new(bdrv_get_aio_context(bs),
261
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
262
- BLK_PERM_ALL);
263
- if (blk_insert_bs(blk, bs, errp)) {
264
- bdrv_unref(bs);
265
+ blk = blk_new_with_bs(bs,
266
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
267
+ BLK_PERM_ALL, errp);
268
+ if (!blk) {
269
return NULL;
270
}
271
blk_set_allow_write_beyond_eof(blk, true);
272
diff --git a/block/vpc.c b/block/vpc.c
273
index XXXXXXX..XXXXXXX 100644
274
--- a/block/vpc.c
275
+++ b/block/vpc.c
276
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
277
return -EIO;
278
}
279
280
- blk = blk_new(bdrv_get_aio_context(bs),
281
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
282
- ret = blk_insert_bs(blk, bs, errp);
283
- if (ret < 0) {
284
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
285
+ errp);
286
+ if (!blk) {
287
+ ret = -EPERM;
288
goto out;
289
}
290
blk_set_allow_write_beyond_eof(blk, true);
291
diff --git a/blockdev.c b/blockdev.c
292
index XXXXXXX..XXXXXXX 100644
293
--- a/blockdev.c
294
+++ b/blockdev.c
295
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
296
BlockBackend *blk = NULL;
297
BlockDriverState *bs;
298
AioContext *aio_context;
299
- int ret;
300
301
bs = bdrv_lookup_bs(has_device ? device : NULL,
302
has_node_name ? node_name : NULL,
303
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
304
goto out;
305
}
306
307
- blk = blk_new(bdrv_get_aio_context(bs), BLK_PERM_RESIZE, BLK_PERM_ALL);
308
- ret = blk_insert_bs(blk, bs, errp);
309
- if (ret < 0) {
310
+ blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
311
+ if (!blk) {
312
goto out;
313
}
314
315
bdrv_drained_begin(bs);
316
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
317
+ blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
318
bdrv_drained_end(bs);
319
320
out:
321
diff --git a/blockjob.c b/blockjob.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/blockjob.c
324
+++ b/blockjob.c
325
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
326
{
327
BlockBackend *blk;
328
BlockJob *job;
329
- int ret;
330
331
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
332
job_id = bdrv_get_device_name(bs);
333
}
334
335
- blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
336
- ret = blk_insert_bs(blk, bs, errp);
337
- if (ret < 0) {
338
- blk_unref(blk);
339
+ blk = blk_new_with_bs(bs, perm, shared_perm, errp);
340
+ if (!blk) {
341
return NULL;
342
}
343
344
--
345
2.26.2
346
347
diff view generated by jsdifflib
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
The BDRV_O_ALLOW_RDWR flag allows / prohibits the changing of
1
From: Eric Blake <eblake@redhat.com>
2
the BDS 'read_only' state, but there are a few places where it
3
is ignored. In the bdrv_set_read_only() helper, make sure to
4
honor the flag.
5
2
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Our comment did not actually match the code. Rewrite the comment to
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
be less sensitive to any future changes to qcow2-bitmap.c that might
8
Reviewed-by: John Snow <jsnow@redhat.com>
5
implement scenarios that we currently reject.
9
Message-id: be2e5fb2d285cbece2b6d06bed54a6f56520d251.1491597120.git.jcody@redhat.com
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200428192648.749066-4-eblake@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
---
11
block.c | 7 +++++++
12
block/qcow2.c | 2 +-
12
1 file changed, 7 insertions(+)
13
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
14
diff --git a/block.c b/block.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
17
--- a/block/qcow2.c
17
+++ b/block.c
18
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
19
return -EINVAL;
20
goto fail;
20
}
21
}
21
22
22
+ /* Do not clear read_only if it is prohibited */
23
- /* cannot proceed if image has bitmaps */
23
+ if (!read_only && !(bs->open_flags & BDRV_O_ALLOW_RDWR)) {
24
+ /* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */
24
+ error_setg(errp, "Node '%s' is read only",
25
if (qcow2_truncate_bitmaps_check(bs, errp)) {
25
+ bdrv_get_device_or_node_name(bs));
26
ret = -ENOTSUP;
26
+ return -EPERM;
27
goto fail;
27
+ }
28
+
29
bs->read_only = read_only;
30
return 0;
31
}
32
--
28
--
33
2.9.3
29
2.26.2
34
30
35
31
diff view generated by jsdifflib
1
We have a helper wrapper for checking for the BDS read_only flag,
1
From: Eric Blake <eblake@redhat.com>
2
add a helper wrapper to set the read_only flag as well.
3
2
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
It's been a while since we got rid of the sector-based bdrv_read and
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
4
bdrv_write (commit 2e11d756); let's finish the job on a few remaining
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
comments.
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200428213807.776655-1-eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
11
---
9
block.c | 5 +++++
12
block/io.c | 3 ++-
10
block/bochs.c | 2 +-
13
block/qcow2-refcount.c | 2 +-
11
block/cloop.c | 2 +-
14
block/vvfat.c | 10 +++++-----
12
block/dmg.c | 2 +-
15
tests/qemu-iotests/001 | 2 +-
13
block/rbd.c | 2 +-
16
tests/qemu-iotests/052 | 2 +-
14
block/vvfat.c | 4 ++--
17
tests/qemu-iotests/134 | 2 +-
15
include/block/block.h | 1 +
18
tests/qemu-iotests/188 | 2 +-
16
7 files changed, 12 insertions(+), 6 deletions(-)
19
7 files changed, 12 insertions(+), 11 deletions(-)
17
20
18
diff --git a/block.c b/block.c
21
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
23
--- a/block/io.c
21
+++ b/block.c
24
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
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)
23
}
35
}
24
}
36
}
25
37
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
38
+/* return < 0 if error. See bdrv_pwrite() for the return codes */
27
+{
39
int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
28
+ bs->read_only = read_only;
40
{
29
+}
41
int ret;
30
+
42
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
32
const char *backing,
33
char *dest, size_t sz,
34
diff --git a/block/bochs.c b/block/bochs.c
35
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
36
--- a/block/bochs.c
44
--- a/block/qcow2-refcount.c
37
+++ b/block/bochs.c
45
+++ b/block/qcow2-refcount.c
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
46
@@ -XXX,XX +XXX,XX @@ fail:
39
return -EINVAL;
47
* - 0 if writing to this offset will not affect the mentioned metadata
40
}
48
* - a positive QCow2MetadataOverlap value indicating one overlapping section
41
49
* - a negative value (-errno) indicating an error while performing a check,
42
- bs->read_only = true; /* no write support yet */
50
- * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
43
+ bdrv_set_read_only(bs, true); /* no write support yet */
51
+ * e.g. when bdrv_pread failed on QCOW2_OL_INACTIVE_L2
44
52
*/
45
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
53
int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
46
if (ret < 0) {
54
int64_t size)
47
diff --git a/block/cloop.c b/block/cloop.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/cloop.c
50
+++ b/block/cloop.c
51
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
52
return -EINVAL;
53
}
54
55
- bs->read_only = true;
56
+ bdrv_set_read_only(bs, true);
57
58
/* read header */
59
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
60
diff --git a/block/dmg.c b/block/dmg.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/dmg.c
63
+++ b/block/dmg.c
64
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
65
}
66
67
block_module_load_one("dmg-bz2");
68
- bs->read_only = true;
69
+ bdrv_set_read_only(bs, true);
70
71
s->n_chunks = 0;
72
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
73
diff --git a/block/rbd.c b/block/rbd.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/rbd.c
76
+++ b/block/rbd.c
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
78
goto failed_open;
79
}
80
81
- bs->read_only = (s->snap != NULL);
82
+ bdrv_set_read_only(bs, (s->snap != NULL));
83
84
qemu_opts_del(opts);
85
return 0;
86
diff --git a/block/vvfat.c b/block/vvfat.c
55
diff --git a/block/vvfat.c b/block/vvfat.c
87
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
88
--- a/block/vvfat.c
57
--- a/block/vvfat.c
89
+++ b/block/vvfat.c
58
+++ b/block/vvfat.c
90
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
59
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
91
s->current_cluster=0xffffffff;
60
* - get modified FAT
92
61
* - compare the two FATs (TODO)
93
/* read only is the default for safety */
62
* - get buffer for marking used clusters
94
- bs->read_only = true;
63
- * - recurse direntries from root (using bs->bdrv_read to make
95
+ bdrv_set_read_only(bs, true);
64
+ * - recurse direntries from root (using bs->bdrv_pread to make
96
s->qcow = NULL;
65
* sure to get the new data)
97
s->qcow_filename = NULL;
66
* - check that the FAT agrees with the size
98
s->fat2 = NULL;
67
* - count the number of clusters occupied by this directory and
99
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
68
@@ -XXX,XX +XXX,XX @@ static int handle_deletes(BDRVVVFATState* s)
100
if (ret < 0) {
69
/*
101
goto fail;
70
* synchronize mapping with new state:
102
}
71
*
103
- bs->read_only = false;
72
- * - copy FAT (with bdrv_read)
104
+ bdrv_set_read_only(bs, false);
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;
105
}
82
}
106
83
107
bs->total_sectors = cyls * heads * secs;
84
- /* copy FAT (with bdrv_read) */
108
diff --git a/include/block/block.h b/include/block/block.h
85
+ /* copy FAT (with bdrv_pread) */
109
index XXXXXXX..XXXXXXX 100644
86
memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
110
--- a/include/block/block.h
87
111
+++ b/include/block/block.h
88
- /* recurse direntries from root (using bs->bdrv_read) */
112
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
89
+ /* recurse direntries from root (using bs->bdrv_pread) */
113
int64_t sector_num, int nb_sectors, int *pnum);
90
ret = commit_direntries(s, 0, -1);
114
91
if (ret) {
115
bool bdrv_is_read_only(BlockDriverState *bs);
92
fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
116
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
93
diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001
117
bool bdrv_is_sg(BlockDriverState *bs);
94
index XXXXXXX..XXXXXXX 100755
118
bool bdrv_is_inserted(BlockDriverState *bs);
95
--- a/tests/qemu-iotests/001
119
int bdrv_media_changed(BlockDriverState *bs);
96
+++ b/tests/qemu-iotests/001
97
@@ -XXX,XX +XXX,XX @@
98
#!/usr/bin/env bash
99
#
100
-# Test simple read/write using plain bdrv_read/bdrv_write
101
+# Test simple read/write using plain bdrv_pread/bdrv_pwrite
102
#
103
# Copyright (C) 2009 Red Hat, Inc.
104
#
105
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
106
index XXXXXXX..XXXXXXX 100755
107
--- a/tests/qemu-iotests/052
108
+++ b/tests/qemu-iotests/052
109
@@ -XXX,XX +XXX,XX @@
110
#!/usr/bin/env bash
111
#
112
-# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT
113
+# Test bdrv_pread/bdrv_pwrite using BDRV_O_SNAPSHOT
114
#
115
# Copyright (C) 2013 Red Hat, Inc.
116
#
117
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
118
index XXXXXXX..XXXXXXX 100755
119
--- a/tests/qemu-iotests/134
120
+++ b/tests/qemu-iotests/134
121
@@ -XXX,XX +XXX,XX @@
122
#!/usr/bin/env bash
123
#
124
-# Test encrypted read/write using plain bdrv_read/bdrv_write
125
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
126
#
127
# Copyright (C) 2015 Red Hat, Inc.
128
#
129
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
130
index XXXXXXX..XXXXXXX 100755
131
--- a/tests/qemu-iotests/188
132
+++ b/tests/qemu-iotests/188
133
@@ -XXX,XX +XXX,XX @@
134
#!/usr/bin/env bash
135
#
136
-# Test encrypted read/write using plain bdrv_read/bdrv_write
137
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
138
#
139
# Copyright (C) 2017 Red Hat, Inc.
140
#
120
--
141
--
121
2.9.3
142
2.26.2
122
143
123
144
diff view generated by jsdifflib
1
The protocol VXHS does not support image creation. Some tests expect
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
to be able to create images through the protocol. Exclude VXHS from
3
these tests.
4
2
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Commit f62514b3def5fb2acbef64d0e053c0c31fa45aff made qemu-img reject -o "" but this test uses it.
4
Since this test only tries to do a dry-run run of qemu-img amend,
5
replace the -o "" with dummy -o "size=$size".
6
7
Fixes: f62514b3def5fb2acbef64d0e053c0c31fa45aff
8
9
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Message-Id: <20200504131959.9533-1-mlevitsk@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
12
---
7
tests/qemu-iotests/017 | 1 +
13
tests/qemu-iotests/153 | 2 +-
8
tests/qemu-iotests/020 | 1 +
14
tests/qemu-iotests/153.out | 12 ++++++------
9
tests/qemu-iotests/029 | 1 +
15
2 files changed, 7 insertions(+), 7 deletions(-)
10
tests/qemu-iotests/073 | 1 +
11
tests/qemu-iotests/114 | 1 +
12
tests/qemu-iotests/130 | 1 +
13
tests/qemu-iotests/134 | 1 +
14
tests/qemu-iotests/156 | 1 +
15
tests/qemu-iotests/158 | 1 +
16
9 files changed, 9 insertions(+)
17
16
18
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
17
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
19
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/017
19
--- a/tests/qemu-iotests/153
21
+++ b/tests/qemu-iotests/017
20
+++ b/tests/qemu-iotests/153
22
@@ -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
23
# Any format supporting backing files
22
_run_cmd $QEMU_IMG check $L "${TEST_IMG}"
24
_supported_fmt qcow qcow2 vmdk qed
23
_run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}"
25
_supported_proto generic
24
_run_cmd $QEMU_IMG map $L "${TEST_IMG}"
26
+_unsupported_proto vxhs
25
- _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}"
27
_supported_os Linux
26
+ _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}"
28
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
27
_run_cmd $QEMU_IMG commit $L "${TEST_IMG}"
29
28
_run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size
30
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
29
_run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base"
31
index XXXXXXX..XXXXXXX 100755
30
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
32
--- a/tests/qemu-iotests/020
31
index XXXXXXX..XXXXXXX 100644
33
+++ b/tests/qemu-iotests/020
32
--- a/tests/qemu-iotests/153.out
34
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
33
+++ b/tests/qemu-iotests/153.out
35
# Any format supporting backing files
34
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper map TEST_DIR/t.qcow2
36
_supported_fmt qcow qcow2 vmdk qed
35
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
37
_supported_proto generic
36
Is another process using the image [TEST_DIR/t.qcow2]?
38
+_unsupported_proto vxhs
37
39
_supported_os Linux
38
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
40
_unsupported_imgopts "subformat=monolithicFlat" \
39
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
41
"subformat=twoGbMaxExtentFlat" \
40
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
42
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
41
Is another process using the image [TEST_DIR/t.qcow2]?
43
index XXXXXXX..XXXXXXX 100755
42
44
--- a/tests/qemu-iotests/029
43
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
45
+++ b/tests/qemu-iotests/029
44
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
45
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
47
# Any format supporting intenal snapshots
46
48
_supported_fmt qcow2
47
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
49
_supported_proto generic
48
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
50
+_unsupported_proto vxhs
49
qemu-img: unrecognized option '-U'
51
_supported_os Linux
50
Try 'qemu-img --help' for more information
52
# Internal snapshots are (currently) impossible with refcount_bits=1
51
53
_unsupported_imgopts 'refcount_bits=1[^0-9]'
52
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
54
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
53
55
index XXXXXXX..XXXXXXX 100755
54
_qemu_img_wrapper map TEST_DIR/t.qcow2
56
--- a/tests/qemu-iotests/073
55
57
+++ b/tests/qemu-iotests/073
56
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
58
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
57
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
59
58
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
60
_supported_fmt qcow2
59
Is another process using the image [TEST_DIR/t.qcow2]?
61
_supported_proto generic
60
62
+_unsupported_proto vxhs
61
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
63
_supported_os Linux
62
64
63
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
65
CLUSTER_SIZE=64k
64
66
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
65
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
67
index XXXXXXX..XXXXXXX 100755
66
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
68
--- a/tests/qemu-iotests/114
67
qemu-img: unrecognized option '-U'
69
+++ b/tests/qemu-iotests/114
68
Try 'qemu-img --help' for more information
70
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
69
71
70
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
72
_supported_fmt qcow2
71
73
_supported_proto generic
72
_qemu_img_wrapper map TEST_DIR/t.qcow2
74
+_unsupported_proto vxhs
73
75
_supported_os Linux
74
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
76
75
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
77
76
78
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
77
_qemu_img_wrapper commit TEST_DIR/t.qcow2
79
index XXXXXXX..XXXXXXX 100755
78
80
--- a/tests/qemu-iotests/130
79
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
81
+++ b/tests/qemu-iotests/130
80
82
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
81
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
83
82
84
_supported_fmt qcow2
83
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
85
_supported_proto generic
84
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
86
+_unsupported_proto vxhs
85
qemu-img: unrecognized option '-U'
87
_supported_os Linux
86
Try 'qemu-img --help' for more information
88
89
qemu_comm_method="monitor"
90
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
91
index XXXXXXX..XXXXXXX 100755
92
--- a/tests/qemu-iotests/134
93
+++ b/tests/qemu-iotests/134
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
95
96
_supported_fmt qcow2
97
_supported_proto generic
98
+_unsupported_proto vxhs
99
_supported_os Linux
100
101
102
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
103
index XXXXXXX..XXXXXXX 100755
104
--- a/tests/qemu-iotests/156
105
+++ b/tests/qemu-iotests/156
106
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
_supported_fmt qcow2 qed
109
_supported_proto generic
110
+_unsupported_proto vxhs
111
_supported_os Linux
112
113
# Create source disk
114
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/158
117
+++ b/tests/qemu-iotests/158
118
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
119
120
_supported_fmt qcow2
121
_supported_proto generic
122
+_unsupported_proto vxhs
123
_supported_os Linux
124
125
87
126
--
88
--
127
2.9.3
89
2.26.2
128
90
129
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
Move bdrv_is_read_only() up with its friends.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
We are going to use aio-task-pool API, so tasks will be handled in
4
Reviewed-by: John Snow <jsnow@redhat.com>
4
parallel. We need therefore separate allocated task on each iteration.
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
Introduce this logic now.
6
Message-id: 73b2399459760c32506f9407efb9dddb3a2789de.1491597120.git.jcody@redhat.com
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200429130847.28124-3-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
11
---
8
block.c | 10 +++++-----
12
block/block-copy.c | 18 +++++++++++-------
9
1 file changed, 5 insertions(+), 5 deletions(-)
13
1 file changed, 11 insertions(+), 7 deletions(-)
10
14
11
diff --git a/block.c b/block.c
15
diff --git a/block/block-copy.c b/block/block-copy.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
17
--- a/block/block-copy.c
14
+++ b/block.c
18
+++ b/block/block-copy.c
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
19
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
16
}
17
}
20
}
18
21
19
+bool bdrv_is_read_only(BlockDriverState *bs)
22
/* Called only on full-dirty region */
20
+{
23
-static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
21
+ return bs->read_only;
24
- int64_t offset, int64_t bytes)
22
+}
25
+static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
26
+ int64_t offset, int64_t bytes)
27
{
28
+ BlockCopyTask *task = g_new(BlockCopyTask, 1);
23
+
29
+
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
30
assert(!find_conflicting_task(s, offset, bytes));
25
{
31
26
/* Do not set read_only if copy_on_read is enabled */
32
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
33
@@ -XXX,XX +XXX,XX @@ static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
34
task->bytes = bytes;
35
qemu_co_queue_init(&task->wait_queue);
36
QLIST_INSERT_HEAD(&s->tasks, task, list);
37
+
38
+ return task;
29
}
39
}
30
40
31
-bool bdrv_is_read_only(BlockDriverState *bs)
41
/*
32
-{
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
33
- return bs->read_only;
43
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
34
-}
44
35
-
45
while (bytes) {
36
bool bdrv_is_sg(BlockDriverState *bs)
46
- BlockCopyTask task;
37
{
47
+ g_autofree BlockCopyTask *task = NULL;
38
return bs->sg;
48
int64_t next_zero, cur_bytes, status_bytes;
49
50
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
52
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
53
cur_bytes = next_zero - offset;
54
}
55
- block_copy_task_begin(s, &task, offset, cur_bytes);
56
+ task = block_copy_task_create(s, offset, cur_bytes);
57
58
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
59
assert(ret >= 0); /* never fail */
60
cur_bytes = MIN(cur_bytes, status_bytes);
61
- block_copy_task_shrink(s, &task, cur_bytes);
62
+ block_copy_task_shrink(s, task, cur_bytes);
63
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
64
- block_copy_task_end(s, &task, 0);
65
+ block_copy_task_end(s, task, 0);
66
progress_set_remaining(s->progress,
67
bdrv_get_dirty_count(s->copy_bitmap) +
68
s->in_flight_bytes);
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
70
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
71
error_is_read);
72
co_put_to_shres(s->mem, cur_bytes);
73
- block_copy_task_end(s, &task, ret);
74
+ block_copy_task_end(s, task, ret);
75
if (ret < 0) {
76
return ret;
77
}
39
--
78
--
40
2.9.3
79
2.26.2
41
80
42
81
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
These changes use a vxhs test server that is a part of the following
3
We are going to use aio-task-pool API, so we'll need state pointer in
4
repository:
4
BlockCopyTask anyway. Add it now and use where possible.
5
https://github.com/VeritasHyperScale/libqnio.git
6
5
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
Message-Id: <20200429130847.28124-4-vsementsov@virtuozzo.com>
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 1491277689-24949-3-git-send-email-Ashish.Mittal@veritas.com
12
---
10
---
13
tests/qemu-iotests/common | 6 ++++++
11
block/block-copy.c | 28 +++++++++++++++-------------
14
tests/qemu-iotests/common.config | 13 +++++++++++++
12
1 file changed, 15 insertions(+), 13 deletions(-)
15
tests/qemu-iotests/common.filter | 1 +
16
tests/qemu-iotests/common.rc | 19 +++++++++++++++++++
17
4 files changed, 39 insertions(+)
18
13
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
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/tests/qemu-iotests/common
16
--- a/block/block-copy.c
22
+++ b/tests/qemu-iotests/common
17
+++ b/block/block-copy.c
23
@@ -XXX,XX +XXX,XX @@ check options
18
@@ -XXX,XX +XXX,XX @@
24
-ssh test ssh
19
#define BLOCK_COPY_MAX_MEM (128 * MiB)
25
-nfs test nfs
20
26
-luks test luks
21
typedef struct BlockCopyTask {
27
+ -vxhs test vxhs
22
+ BlockCopyState *s;
28
-xdiff graphical mode diff
23
int64_t offset;
29
-nocache use O_DIRECT on backing file
24
int64_t bytes;
30
-misalign misalign memory allocations
25
QLIST_ENTRY(BlockCopyTask) list;
31
@@ -XXX,XX +XXX,XX @@ testlist options
26
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
32
xpand=false
27
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
33
;;
28
s->in_flight_bytes += bytes;
34
29
35
+ -vxhs)
30
- task->offset = offset;
36
+ IMGPROTO=vxhs
31
- task->bytes = bytes;
37
+ xpand=false
32
+ *task = (BlockCopyTask) {
38
+ ;;
33
+ .s = s,
39
+
34
+ .offset = offset,
40
-ssh)
35
+ .bytes = bytes,
41
IMGPROTO=ssh
36
+ };
42
xpand=false
37
qemu_co_queue_init(&task->wait_queue);
43
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
38
QLIST_INSERT_HEAD(&s->tasks, task, list);
44
index XXXXXXX..XXXXXXX 100644
39
45
--- a/tests/qemu-iotests/common.config
40
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
46
+++ b/tests/qemu-iotests/common.config
41
* wake up all tasks waiting for us (may be some of them are not intersecting
47
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_NBD_PROG" ]; then
42
* with shrunk task)
48
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
43
*/
49
fi
44
-static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
50
45
- BlockCopyTask *task,
51
+if [ -z "$QEMU_VXHS_PROG" ]; then
46
+static void coroutine_fn block_copy_task_shrink(BlockCopyTask *task,
52
+ export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
47
int64_t new_bytes)
53
+fi
54
+
55
_qemu_wrapper()
56
{
48
{
57
(
49
if (new_bytes == task->bytes) {
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
59
)
51
52
assert(new_bytes > 0 && new_bytes < task->bytes);
53
54
- s->in_flight_bytes -= task->bytes - new_bytes;
55
- bdrv_set_dirty_bitmap(s->copy_bitmap,
56
+ task->s->in_flight_bytes -= task->bytes - new_bytes;
57
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap,
58
task->offset + new_bytes, task->bytes - new_bytes);
59
60
task->bytes = new_bytes;
61
qemu_co_queue_restart_all(&task->wait_queue);
60
}
62
}
61
63
62
+_qemu_vxhs_wrapper()
64
-static void coroutine_fn block_copy_task_end(BlockCopyState *s,
63
+{
65
- BlockCopyTask *task, int ret)
64
+ (
66
+static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
65
+ echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
67
{
66
+ exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
68
- s->in_flight_bytes -= task->bytes;
67
+ )
69
+ task->s->in_flight_bytes -= task->bytes;
68
+}
70
if (ret < 0) {
69
+
71
- bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes);
70
export QEMU=_qemu_wrapper
72
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
71
export QEMU_IMG=_qemu_img_wrapper
73
}
72
export QEMU_IO=_qemu_io_wrapper
74
QLIST_REMOVE(task, list);
73
export QEMU_NBD=_qemu_nbd_wrapper
75
qemu_co_queue_restart_all(&task->wait_queue);
74
+export QEMU_VXHS=_qemu_vxhs_wrapper
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
75
77
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
76
QEMU_IMG_EXTRA_ARGS=
78
assert(ret >= 0); /* never fail */
77
if [ "$IMGOPTSSYNTAX" = "true" ]; then
79
cur_bytes = MIN(cur_bytes, status_bytes);
78
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
80
- block_copy_task_shrink(s, task, cur_bytes);
79
index XXXXXXX..XXXXXXX 100644
81
+ block_copy_task_shrink(task, cur_bytes);
80
--- a/tests/qemu-iotests/common.filter
82
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
81
+++ b/tests/qemu-iotests/common.filter
83
- block_copy_task_end(s, task, 0);
82
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
84
+ block_copy_task_end(task, 0);
83
-e "s#$TEST_DIR#TEST_DIR#g" \
85
progress_set_remaining(s->progress,
84
-e "s#$IMGFMT#IMGFMT#g" \
86
bdrv_get_dirty_count(s->copy_bitmap) +
85
-e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \
87
s->in_flight_bytes);
86
+ -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
87
-e "/encrypted: yes/d" \
89
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
88
-e "/cluster_size: [0-9]\\+/d" \
90
error_is_read);
89
-e "/table_size: [0-9]\\+/d" \
91
co_put_to_shres(s->mem, cur_bytes);
90
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
92
- block_copy_task_end(s, task, ret);
91
index XXXXXXX..XXXXXXX 100644
93
+ block_copy_task_end(task, ret);
92
--- a/tests/qemu-iotests/common.rc
94
if (ret < 0) {
93
+++ b/tests/qemu-iotests/common.rc
95
return ret;
94
@@ -XXX,XX +XXX,XX @@ else
96
}
95
elif [ "$IMGPROTO" = "nfs" ]; then
96
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
97
TEST_IMG=$TEST_DIR/t.$IMGFMT
98
+ elif [ "$IMGPROTO" = "vxhs" ]; then
99
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
100
+ TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT"
101
else
102
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
103
fi
104
@@ -XXX,XX +XXX,XX @@ _make_test_img()
105
eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE >/dev/null &"
106
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
107
fi
108
+
109
+ # Start QNIO server on image directory for vxhs protocol
110
+ if [ $IMGPROTO = "vxhs" ]; then
111
+ eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &"
112
+ sleep 1 # Wait for server to come up.
113
+ fi
114
}
115
116
_rm_test_img()
117
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img()
118
fi
119
rm -f "$TEST_IMG_FILE"
120
;;
121
+ vxhs)
122
+ if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
123
+ local QEMU_VXHS_PID
124
+ read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
125
+ kill ${QEMU_VXHS_PID} >/dev/null 2>&1
126
+ rm -f "${TEST_DIR}/qemu-vxhs.pid"
127
+ fi
128
+ rm -f "$TEST_IMG_FILE"
129
+ ;;
130
+
131
file)
132
_rm_test_img "$TEST_DIR/t.$IMGFMT"
133
_rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
134
--
97
--
135
2.9.3
98
2.26.2
136
99
137
100
diff view generated by jsdifflib
1
A few block drivers will set the BDS read_only flag from their
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
.bdrv_open() function. This means the bs->read_only flag could
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
4
flag check occurs prior to the call to bdrv->bdrv_open().
5
2
6
This adds an error return to bdrv_set_read_only(), and an error will be
3
Instead of just relying on the comment "Called only on full-dirty
7
return if we try to set the BDS to read_only while copy_on_read is
4
region" in block_copy_task_create() let's move initial dirty area
8
enabled.
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.
9
8
10
This patch also changes the behavior of vvfat. Before, vvfat could
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
override the drive 'readonly' flag with its own, internal 'rw' flag.
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200429130847.28124-5-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/block-copy.c | 80 ++++++++++++++++++++++++++--------------------
15
1 file changed, 46 insertions(+), 34 deletions(-)
12
16
13
For instance, this -drive parameter would result in a writable image:
17
diff --git a/block/block-copy.c b/block/block-copy.c
14
15
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
16
17
This is not correct. Now, attempting to use the above -drive parameter
18
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').
19
20
Signed-off-by: Jeff Cody <jcody@redhat.com>
21
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: John Snow <jsnow@redhat.com>
23
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
24
---
25
block.c | 10 +++++++++-
26
block/bochs.c | 5 ++++-
27
block/cloop.c | 5 ++++-
28
block/dmg.c | 6 +++++-
29
block/rbd.c | 11 ++++++++++-
30
block/vvfat.c | 19 +++++++++++++++----
31
include/block/block.h | 2 +-
32
7 files changed, 48 insertions(+), 10 deletions(-)
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
19
--- a/block/block-copy.c
37
+++ b/block.c
20
+++ b/block/block-copy.c
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
21
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyTask {
39
}
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;
40
}
35
}
41
36
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
37
-/* Called only on full-dirty region */
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
38
+/*
39
+ * Search for the first dirty area in offset/bytes range and create task at
40
+ * the beginning of it.
41
+ */
42
static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
43
int64_t offset, int64_t bytes)
44
{
44
{
45
+ /* Do not set read_only if copy_on_read is enabled */
45
- BlockCopyTask *task = g_new(BlockCopyTask, 1);
46
+ if (bs->copy_on_read && read_only) {
46
+ BlockCopyTask *task;
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
47
48
+ bdrv_get_device_or_node_name(bs));
48
+ if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap,
49
+ return -EINVAL;
49
+ offset, offset + bytes,
50
+ s->copy_size, &offset, &bytes))
51
+ {
52
+ return NULL;
50
+ }
53
+ }
51
+
54
+
52
bs->read_only = read_only;
55
+ /* region is dirty, so no existent tasks possible in it */
53
+ return 0;
56
assert(!find_conflicting_task(s, offset, bytes));
54
}
57
55
58
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
56
void bdrv_get_full_backing_filename_from_filename(const char *backed,
59
s->in_flight_bytes += bytes;
57
diff --git a/block/bochs.c b/block/bochs.c
60
58
index XXXXXXX..XXXXXXX 100644
61
+ task = g_new(BlockCopyTask, 1);
59
--- a/block/bochs.c
62
*task = (BlockCopyTask) {
60
+++ b/block/bochs.c
63
.s = s,
61
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
64
.offset = offset,
62
return -EINVAL;
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
66
{
67
int ret = 0;
68
bool found_dirty = false;
69
+ int64_t end = offset + bytes;
70
71
/*
72
* block_copy() user is responsible for keeping source and target in same
73
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
74
75
while (bytes) {
76
g_autofree BlockCopyTask *task = NULL;
77
- int64_t next_zero, cur_bytes, status_bytes;
78
+ int64_t status_bytes;
79
80
- if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
81
- trace_block_copy_skip(s, offset);
82
- offset += s->cluster_size;
83
- bytes -= s->cluster_size;
84
- continue; /* already copied */
85
+ task = block_copy_task_create(s, offset, bytes);
86
+ if (!task) {
87
+ /* No more dirty bits in the bitmap */
88
+ trace_block_copy_skip_range(s, offset, bytes);
89
+ break;
90
+ }
91
+ if (task->offset > offset) {
92
+ trace_block_copy_skip_range(s, offset, task->offset - offset);
93
}
94
95
found_dirty = true;
96
97
- cur_bytes = MIN(bytes, s->copy_size);
98
-
99
- next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset,
100
- cur_bytes);
101
- if (next_zero >= 0) {
102
- assert(next_zero > offset); /* offset is dirty */
103
- assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
104
- cur_bytes = next_zero - offset;
105
- }
106
- task = block_copy_task_create(s, offset, cur_bytes);
107
-
108
- ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
109
+ ret = block_copy_block_status(s, task->offset, task->bytes,
110
+ &status_bytes);
111
assert(ret >= 0); /* never fail */
112
- cur_bytes = MIN(cur_bytes, status_bytes);
113
- block_copy_task_shrink(task, cur_bytes);
114
+ if (status_bytes < task->bytes) {
115
+ block_copy_task_shrink(task, status_bytes);
116
+ }
117
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
118
block_copy_task_end(task, 0);
119
progress_set_remaining(s->progress,
120
bdrv_get_dirty_count(s->copy_bitmap) +
121
s->in_flight_bytes);
122
- trace_block_copy_skip_range(s, offset, status_bytes);
123
- offset += status_bytes;
124
- bytes -= status_bytes;
125
+ trace_block_copy_skip_range(s, task->offset, task->bytes);
126
+ offset = task_end(task);
127
+ bytes = end - offset;
128
continue;
129
}
130
131
- trace_block_copy_process(s, offset);
132
+ trace_block_copy_process(s, task->offset);
133
134
- co_get_from_shres(s->mem, cur_bytes);
135
- ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
136
- error_is_read);
137
- co_put_to_shres(s->mem, cur_bytes);
138
+ co_get_from_shres(s->mem, task->bytes);
139
+ ret = block_copy_do_copy(s, task->offset, task->bytes,
140
+ ret & BDRV_BLOCK_ZERO, error_is_read);
141
+ co_put_to_shres(s->mem, task->bytes);
142
block_copy_task_end(task, ret);
143
if (ret < 0) {
144
return ret;
145
}
146
147
- progress_work_done(s->progress, cur_bytes);
148
- s->progress_bytes_callback(cur_bytes, s->progress_opaque);
149
- offset += cur_bytes;
150
- bytes -= cur_bytes;
151
+ progress_work_done(s->progress, task->bytes);
152
+ s->progress_bytes_callback(task->bytes, s->progress_opaque);
153
+ offset = task_end(task);
154
+ bytes = end - offset;
63
}
155
}
64
156
65
- bdrv_set_read_only(bs, true); /* no write support yet */
157
return found_dirty;
66
+ ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
67
+ if (ret < 0) {
68
+ return ret;
69
+ }
70
71
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
72
if (ret < 0) {
73
diff --git a/block/cloop.c b/block/cloop.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/cloop.c
76
+++ b/block/cloop.c
77
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
78
return -EINVAL;
79
}
80
81
- bdrv_set_read_only(bs, true);
82
+ ret = bdrv_set_read_only(bs, true, errp);
83
+ if (ret < 0) {
84
+ return ret;
85
+ }
86
87
/* read header */
88
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
89
diff --git a/block/dmg.c b/block/dmg.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/dmg.c
92
+++ b/block/dmg.c
93
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
94
return -EINVAL;
95
}
96
97
+ ret = bdrv_set_read_only(bs, true, errp);
98
+ if (ret < 0) {
99
+ return ret;
100
+ }
101
+
102
block_module_load_one("dmg-bz2");
103
- bdrv_set_read_only(bs, true);
104
105
s->n_chunks = 0;
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
107
diff --git a/block/rbd.c b/block/rbd.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/rbd.c
110
+++ b/block/rbd.c
111
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
112
goto failed_shutdown;
113
}
114
115
+ /* rbd_open is always r/w */
116
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
117
if (r < 0) {
118
error_setg_errno(errp, -r, "error reading header from %s", s->name);
119
goto failed_open;
120
}
121
122
- bdrv_set_read_only(bs, (s->snap != NULL));
123
+ /* If we are using an rbd snapshot, we must be r/o, otherwise
124
+ * leave as-is */
125
+ if (s->snap != NULL) {
126
+ r = bdrv_set_read_only(bs, true, &local_err);
127
+ if (r < 0) {
128
+ error_propagate(errp, local_err);
129
+ goto failed_open;
130
+ }
131
+ }
132
133
qemu_opts_del(opts);
134
return 0;
135
diff --git a/block/vvfat.c b/block/vvfat.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/vvfat.c
138
+++ b/block/vvfat.c
139
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
140
141
s->current_cluster=0xffffffff;
142
143
- /* read only is the default for safety */
144
- bdrv_set_read_only(bs, true);
145
s->qcow = NULL;
146
s->qcow_filename = NULL;
147
s->fat2 = NULL;
148
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
149
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
150
151
if (qemu_opt_get_bool(opts, "rw", false)) {
152
- ret = enable_write_target(bs, errp);
153
+ if (!bdrv_is_read_only(bs)) {
154
+ ret = enable_write_target(bs, errp);
155
+ if (ret < 0) {
156
+ goto fail;
157
+ }
158
+ } else {
159
+ ret = -EPERM;
160
+ error_setg(errp,
161
+ "Unable to set VVFAT to 'rw' when drive is read-only");
162
+ goto fail;
163
+ }
164
+ } else {
165
+ /* read only is the default for safety */
166
+ ret = bdrv_set_read_only(bs, true, &local_err);
167
if (ret < 0) {
168
+ error_propagate(errp, local_err);
169
goto fail;
170
}
171
- bdrv_set_read_only(bs, false);
172
}
173
174
bs->total_sectors = cyls * heads * secs;
175
diff --git a/include/block/block.h b/include/block/block.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/include/block/block.h
178
+++ b/include/block/block.h
179
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
180
int64_t sector_num, int nb_sectors, int *pnum);
181
182
bool bdrv_is_read_only(BlockDriverState *bs);
183
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
184
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
185
bool bdrv_is_sg(BlockDriverState *bs);
186
bool bdrv_is_inserted(BlockDriverState *bs);
187
int bdrv_media_changed(BlockDriverState *bs);
188
--
158
--
189
2.9.3
159
2.26.2
190
160
191
161
diff view generated by jsdifflib
1
This adds support for reopen in rbd, for changing between r/w and r/o.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Note, that this is only a flag change, but we will block a change from
3
Run block_copy iterations in parallel in aio tasks.
4
r/o to r/w if we are using an RBD internal snapshot.
4
5
5
Changes:
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
- BlockCopyTask becomes aio task structure. Add zeroes field to pass
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
it to block_copy_do_copy
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
- add call state - it's a state of one call of block_copy(), shared
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
9
between parallel tasks. For now used only to keep information about
10
first error: is it read or not.
11
- convert block_copy_dirty_clusters to aio-task loop.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-Id: <20200429130847.28124-6-vsementsov@virtuozzo.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
16
---
11
block/rbd.c | 21 +++++++++++++++++++++
17
block/block-copy.c | 119 ++++++++++++++++++++++++++++++++++++++++-----
12
1 file changed, 21 insertions(+)
18
1 file changed, 106 insertions(+), 13 deletions(-)
13
19
14
diff --git a/block/rbd.c b/block/rbd.c
20
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
22
--- a/block/block-copy.c
17
+++ b/block/rbd.c
23
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
24
@@ -XXX,XX +XXX,XX @@
19
return r;
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;
20
}
74
}
21
75
22
+
76
+/*
23
+/* Since RBD is currently always opened R/W via the API,
77
+ * Takes ownership of @task
24
+ * we just need to check if we are using a snapshot or not, in
78
+ *
25
+ * order to determine if we will allow it to be R/W */
79
+ * If pool is NULL directly run the task, otherwise schedule it into the pool.
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
80
+ *
27
+ BlockReopenQueue *queue, Error **errp)
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)
28
+{
87
+{
29
+ BDRVRBDState *s = state->bs->opaque;
88
+ if (!pool) {
30
+ int ret = 0;
89
+ int ret = task->task.func(&task->task);
31
+
90
+
32
+ if (s->snap && state->flags & BDRV_O_RDWR) {
91
+ g_free(task);
33
+ error_setg(errp,
92
+ return ret;
34
+ "Cannot change node '%s' to r/w when using RBD snapshot",
93
+ }
35
+ bdrv_get_device_or_node_name(state->bs));
94
+
36
+ ret = -EINVAL;
95
+ aio_task_pool_wait_slot(pool);
37
+ }
96
+ if (aio_task_pool_status(pool) < 0) {
97
+ co_put_to_shres(task->s->mem, task->bytes);
98
+ block_copy_task_end(task, -ECANCELED);
99
+ g_free(task);
100
+ return -ECANCELED;
101
+ }
102
+
103
+ aio_task_pool_start_task(pool, &task->task);
104
+
105
+ return 0;
106
+}
107
+
108
/*
109
* block_copy_do_copy
110
*
111
@@ -XXX,XX +XXX,XX @@ out:
112
return ret;
113
}
114
115
+static coroutine_fn int block_copy_task_entry(AioTask *task)
116
+{
117
+ BlockCopyTask *t = container_of(task, BlockCopyTask, task);
118
+ bool error_is_read;
119
+ int ret;
120
+
121
+ ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
122
+ &error_is_read);
123
+ if (ret < 0 && !t->call_state->failed) {
124
+ t->call_state->failed = true;
125
+ t->call_state->error_is_read = error_is_read;
126
+ } else {
127
+ progress_work_done(t->s->progress, t->bytes);
128
+ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
129
+ }
130
+ co_put_to_shres(t->s->mem, t->bytes);
131
+ block_copy_task_end(t, ret);
38
+
132
+
39
+ return ret;
133
+ return ret;
40
+}
134
+}
41
+
135
+
42
static void qemu_rbd_close(BlockDriverState *bs)
136
static int block_copy_block_status(BlockCopyState *s, int64_t offset,
137
int64_t bytes, int64_t *pnum)
43
{
138
{
44
BDRVRBDState *s = bs->opaque;
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
140
int ret = 0;
46
.bdrv_parse_filename = qemu_rbd_parse_filename,
141
bool found_dirty = false;
47
.bdrv_file_open = qemu_rbd_open,
142
int64_t end = offset + bytes;
48
.bdrv_close = qemu_rbd_close,
143
+ AioTaskPool *aio = NULL;
49
+ .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
144
+ BlockCopyCallState call_state = {false, false};
50
.bdrv_create = qemu_rbd_create,
145
51
.bdrv_has_zero_init = bdrv_has_zero_init_1,
146
/*
52
.bdrv_get_info = qemu_rbd_getinfo,
147
* block_copy() user is responsible for keeping source and target in same
148
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
149
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
150
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
151
152
- while (bytes) {
153
- g_autofree BlockCopyTask *task = NULL;
154
+ while (bytes && aio_task_pool_status(aio) == 0) {
155
+ BlockCopyTask *task;
156
int64_t status_bytes;
157
158
- task = block_copy_task_create(s, offset, bytes);
159
+ task = block_copy_task_create(s, &call_state, offset, bytes);
160
if (!task) {
161
/* No more dirty bits in the bitmap */
162
trace_block_copy_skip_range(s, offset, bytes);
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
164
}
165
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
166
block_copy_task_end(task, 0);
167
+ g_free(task);
168
progress_set_remaining(s->progress,
169
bdrv_get_dirty_count(s->copy_bitmap) +
170
s->in_flight_bytes);
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
172
bytes = end - offset;
173
continue;
174
}
175
+ task->zeroes = ret & BDRV_BLOCK_ZERO;
176
177
trace_block_copy_process(s, task->offset);
178
179
co_get_from_shres(s->mem, task->bytes);
180
- ret = block_copy_do_copy(s, task->offset, task->bytes,
181
- ret & BDRV_BLOCK_ZERO, error_is_read);
182
- co_put_to_shres(s->mem, task->bytes);
183
- block_copy_task_end(task, ret);
184
- if (ret < 0) {
185
- return ret;
186
- }
187
188
- progress_work_done(s->progress, task->bytes);
189
- s->progress_bytes_callback(task->bytes, s->progress_opaque);
190
offset = task_end(task);
191
bytes = end - offset;
192
+
193
+ if (!aio && bytes) {
194
+ aio = aio_task_pool_new(BLOCK_COPY_MAX_WORKERS);
195
+ }
196
+
197
+ ret = block_copy_task_run(aio, task);
198
+ if (ret < 0) {
199
+ goto out;
200
+ }
201
+ }
202
+
203
+out:
204
+ if (aio) {
205
+ aio_task_pool_wait_all(aio);
206
+
207
+ /*
208
+ * We are not really interested in -ECANCELED returned from
209
+ * block_copy_task_run. If it fails, it means some task already failed
210
+ * for real reason, let's return first failure.
211
+ * Still, assert that we don't rewrite failure by success.
212
+ */
213
+ assert(ret == 0 || aio_task_pool_status(aio) < 0);
214
+ ret = aio_task_pool_status(aio);
215
+
216
+ aio_task_pool_free(aio);
217
+ }
218
+ if (error_is_read && ret < 0) {
219
+ *error_is_read = call_state.error_is_read;
220
}
221
222
- return found_dirty;
223
+ return ret < 0 ? ret : found_dirty;
224
}
225
226
/*
53
--
227
--
54
2.9.3
228
2.26.2
55
229
56
230
diff view generated by jsdifflib