1
The following changes since commit 9f55925b8f50a962d1d08d815044db7767ae3838:
1
The following changes since commit 5375af3cd7b8adcc10c18d8083b7be63976c9645:
2
2
3
Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-3.0-pull-request' into staging (2018-06-11 12:46:16 +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/XanClic/qemu.git tags/pull-block-2018-06-11
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-05-05
8
8
9
for you to fetch changes up to c50abd175a88cd41c2c08339de91f6f6e4a7b162:
9
for you to fetch changes up to 4ce5dd3e9b5ee0fac18625860eb3727399ee965e:
10
10
11
iotests: Add case for a corrupted inactive image (2018-06-11 16:18:45 +0200)
11
block/block-copy: use aio-task-pool API (2020-05-05 14:03:28 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Block patches:
15
- Various bug fixes
15
- Asynchronous copying for block-copy (i.e., the backup job)
16
- Removal of qemu-img convert's deprecated -s option
16
- Allow resizing of qcow2 images when they have internal snapshots
17
- qemu-io now exits with an error when a command failed
17
- iotests: Logging improvements for Python tests
18
- iotest 153 fix, and block comment cleanups
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
Alberto Garcia (1):
21
Eric Blake (4):
21
throttle: Fix crash on reopen
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
22
26
23
Max Reitz (25):
27
John Snow (14):
24
block/file-posix: Pass FD to locking helpers
28
iotests: do a light delinting
25
block/file-posix: File locking during creation
29
iotests: don't use 'format' for drive_add
26
iotests: Add creation test to 153
30
iotests: ignore import warnings from pylint
27
qemu-img: Amendment support implies create_opts
31
iotests: replace mutable list default args
28
block: Add Error parameter to bdrv_amend_options
32
iotests: add pylintrc file
29
qemu-option: Pull out "Supported options" print
33
iotests: alphabetize standard imports
30
qemu-img: Add print_amend_option_help()
34
iotests: drop pre-Python 3.4 compatibility code
31
qemu-img: Recognize no creation support in -o help
35
iotests: touch up log function signature
32
iotests: Test help option for unsupporting formats
36
iotests: limit line length to 79 chars
33
iotests: Rework 113
37
iotests: add hmp helper with logging
34
qcow2: Repair OFLAG_COPIED when fixing leaks
38
iotests: add script_initialize
35
iotests: Repairing error during snapshot deletion
39
iotest 258: use script_main
36
qemu-io: Drop command functions' return values
40
iotests: Mark verify functions as private
37
qemu-io: Let command functions return error code
41
iotests: use python logging for iotests.log()
38
qemu-io: Exit with error when a command failed
39
iotests.py: Add qemu_io_silent
40
iotests: Let 216 make use of qemu-io's exit code
41
qemu-img: Resolve relative backing paths in rebase
42
iotests: Add test for rebasing with relative paths
43
qemu-img: Special post-backing convert handling
44
iotests: Test post-backing convert target behavior
45
iotests: Fix 219's timing
46
block: Make bdrv_is_writable() public
47
qcow2: Do not mark inactive images corrupt
48
iotests: Add case for a corrupted inactive image
49
42
50
Thomas Huth (1):
43
Maxim Levitsky (1):
51
qemu-img: Remove deprecated -s snapshot_id_or_name option
44
Fix iotest 153
52
45
53
Vladimir Sementsov-Ogievskiy (2):
46
Vladimir Sementsov-Ogievskiy (5):
54
iotests: improve pause_job
47
block/block-copy: rename in-flight requests to tasks
55
block/qcow2-bitmap: fix free_bitmap_clusters
48
block/block-copy: alloc task on each iteration
49
block/block-copy: add state pointer to BlockCopyTask
50
block/block-copy: refactor task creation
51
block/block-copy: use aio-task-pool API
56
52
57
include/block/block.h | 4 +-
53
include/sysemu/block-backend.h | 2 +
58
include/block/block_int.h | 3 +-
54
block/block-backend.c | 23 +++
59
include/qemu-io.h | 9 +-
55
block/block-copy.c | 279 +++++++++++++++++--------
60
block.c | 25 ++-
56
block/crypto.c | 9 +-
61
block/file-posix.c | 64 ++++++--
57
block/io.c | 3 +-
62
block/qcow2-bitmap.c | 1 -
58
block/parallels.c | 8 +-
63
block/qcow2-refcount.c | 25 ++-
59
block/qcow.c | 8 +-
64
block/qcow2.c | 74 +++++----
60
block/qcow2-refcount.c | 2 +-
65
block/throttle.c | 54 ++++---
61
block/qcow2-snapshot.c | 20 +-
66
qemu-img.c | 108 +++++++++++--
62
block/qcow2.c | 45 ++--
67
qemu-io-cmds.c | 276 +++++++++++++++++++---------------
63
block/qed.c | 8 +-
68
qemu-io.c | 62 +++++---
64
block/sheepdog.c | 10 +-
69
util/qemu-option.c | 1 -
65
block/vdi.c | 8 +-
70
qemu-doc.texi | 7 -
66
block/vhdx.c | 8 +-
71
qemu-img-cmds.hx | 4 +-
67
block/vmdk.c | 9 +-
72
qemu-img.texi | 7 +-
68
block/vpc.c | 8 +-
73
tests/qemu-iotests/024 | 82 +++++++++-
69
block/vvfat.c | 10 +-
74
tests/qemu-iotests/024.out | 30 ++++
70
blockdev.c | 8 +-
75
tests/qemu-iotests/029 | 2 +-
71
blockjob.c | 7 +-
76
tests/qemu-iotests/060 | 30 ++++
72
tests/qemu-iotests/001 | 2 +-
77
tests/qemu-iotests/060.out | 18 ++-
73
tests/qemu-iotests/030 | 4 +-
78
tests/qemu-iotests/061.out | 7 -
74
tests/qemu-iotests/052 | 2 +-
79
tests/qemu-iotests/080 | 4 +-
75
tests/qemu-iotests/055 | 3 +-
80
tests/qemu-iotests/080.out | 4 +-
76
tests/qemu-iotests/061 | 35 ++++
81
tests/qemu-iotests/082 | 9 ++
77
tests/qemu-iotests/061.out | 28 +++
82
tests/qemu-iotests/082.out | 53 ++++---
78
tests/qemu-iotests/134 | 2 +-
83
tests/qemu-iotests/112.out | 5 +-
79
tests/qemu-iotests/149 | 3 +-
84
tests/qemu-iotests/113 | 19 ++-
80
tests/qemu-iotests/153 | 2 +-
85
tests/qemu-iotests/113.out | 7 +-
81
tests/qemu-iotests/153.out | 12 +-
86
tests/qemu-iotests/122 | 42 ++++++
82
tests/qemu-iotests/155 | 2 +-
87
tests/qemu-iotests/122.out | 18 +++
83
tests/qemu-iotests/188 | 2 +-
88
tests/qemu-iotests/153 | 18 +++
84
tests/qemu-iotests/194 | 4 +-
89
tests/qemu-iotests/153.out | 13 ++
85
tests/qemu-iotests/202 | 4 +-
90
tests/qemu-iotests/216 | 23 +--
86
tests/qemu-iotests/203 | 4 +-
91
tests/qemu-iotests/216.out | 17 +--
87
tests/qemu-iotests/206 | 2 +-
92
tests/qemu-iotests/217 | 90 +++++++++++
88
tests/qemu-iotests/207 | 6 +-
93
tests/qemu-iotests/217.out | 42 ++++++
89
tests/qemu-iotests/208 | 2 +-
94
tests/qemu-iotests/219 | 26 +++-
90
tests/qemu-iotests/209 | 2 +-
95
tests/qemu-iotests/219.out | 10 +-
91
tests/qemu-iotests/210 | 6 +-
96
tests/qemu-iotests/group | 1 +
92
tests/qemu-iotests/211 | 6 +-
97
tests/qemu-iotests/iotests.py | 18 ++-
93
tests/qemu-iotests/212 | 6 +-
98
41 files changed, 970 insertions(+), 342 deletions(-)
94
tests/qemu-iotests/213 | 6 +-
99
create mode 100755 tests/qemu-iotests/217
95
tests/qemu-iotests/216 | 4 +-
100
create mode 100644 tests/qemu-iotests/217.out
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
101
126
102
--
127
--
103
2.17.1
128
2.26.2
104
129
105
130
diff view generated by jsdifflib
Deleted patch
1
raw_apply_lock_bytes() and raw_check_lock_bytes() currently take a
2
BDRVRawState *, but they only use the lock_fd field. During image
3
creation, we do not have a BDRVRawState, but we do have an FD; so if we
4
want to reuse the functions there, we should modify them to receive only
5
the FD.
6
1
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Message-id: 20180509215336.31304-2-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/file-posix.c | 27 ++++++++++++++-------------
13
1 file changed, 14 insertions(+), 13 deletions(-)
14
15
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ typedef enum {
20
* file; if @unlock == true, also unlock the unneeded bytes.
21
* @shared_perm_lock_bits is the mask of all permissions that are NOT shared.
22
*/
23
-static int raw_apply_lock_bytes(BDRVRawState *s,
24
+static int raw_apply_lock_bytes(int fd,
25
uint64_t perm_lock_bits,
26
uint64_t shared_perm_lock_bits,
27
bool unlock, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s,
29
PERM_FOREACH(i) {
30
int off = RAW_LOCK_PERM_BASE + i;
31
if (perm_lock_bits & (1ULL << i)) {
32
- ret = qemu_lock_fd(s->lock_fd, off, 1, false);
33
+ ret = qemu_lock_fd(fd, off, 1, false);
34
if (ret) {
35
error_setg(errp, "Failed to lock byte %d", off);
36
return ret;
37
}
38
} else if (unlock) {
39
- ret = qemu_unlock_fd(s->lock_fd, off, 1);
40
+ ret = qemu_unlock_fd(fd, off, 1);
41
if (ret) {
42
error_setg(errp, "Failed to unlock byte %d", off);
43
return ret;
44
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s,
45
PERM_FOREACH(i) {
46
int off = RAW_LOCK_SHARED_BASE + i;
47
if (shared_perm_lock_bits & (1ULL << i)) {
48
- ret = qemu_lock_fd(s->lock_fd, off, 1, false);
49
+ ret = qemu_lock_fd(fd, off, 1, false);
50
if (ret) {
51
error_setg(errp, "Failed to lock byte %d", off);
52
return ret;
53
}
54
} else if (unlock) {
55
- ret = qemu_unlock_fd(s->lock_fd, off, 1);
56
+ ret = qemu_unlock_fd(fd, off, 1);
57
if (ret) {
58
error_setg(errp, "Failed to unlock byte %d", off);
59
return ret;
60
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s,
61
}
62
63
/* Check "unshared" bytes implied by @perm and ~@shared_perm in the file. */
64
-static int raw_check_lock_bytes(BDRVRawState *s,
65
- uint64_t perm, uint64_t shared_perm,
66
+static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
67
Error **errp)
68
{
69
int ret;
70
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(BDRVRawState *s,
71
int off = RAW_LOCK_SHARED_BASE + i;
72
uint64_t p = 1ULL << i;
73
if (perm & p) {
74
- ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
75
+ ret = qemu_lock_fd_test(fd, off, 1, true);
76
if (ret) {
77
char *perm_name = bdrv_perm_names(p);
78
error_setg(errp,
79
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(BDRVRawState *s,
80
int off = RAW_LOCK_PERM_BASE + i;
81
uint64_t p = 1ULL << i;
82
if (!(shared_perm & p)) {
83
- ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
84
+ ret = qemu_lock_fd_test(fd, off, 1, true);
85
if (ret) {
86
char *perm_name = bdrv_perm_names(p);
87
error_setg(errp,
88
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
89
90
switch (op) {
91
case RAW_PL_PREPARE:
92
- ret = raw_apply_lock_bytes(s, s->perm | new_perm,
93
+ ret = raw_apply_lock_bytes(s->lock_fd, s->perm | new_perm,
94
~s->shared_perm | ~new_shared,
95
false, errp);
96
if (!ret) {
97
- ret = raw_check_lock_bytes(s, new_perm, new_shared, errp);
98
+ ret = raw_check_lock_bytes(s->lock_fd, new_perm, new_shared, errp);
99
if (!ret) {
100
return 0;
101
}
102
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
103
op = RAW_PL_ABORT;
104
/* fall through to unlock bytes. */
105
case RAW_PL_ABORT:
106
- raw_apply_lock_bytes(s, s->perm, ~s->shared_perm, true, &local_err);
107
+ raw_apply_lock_bytes(s->lock_fd, s->perm, ~s->shared_perm,
108
+ true, &local_err);
109
if (local_err) {
110
/* Theoretically the above call only unlocks bytes and it cannot
111
* fail. Something weird happened, report it.
112
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
113
}
114
break;
115
case RAW_PL_COMMIT:
116
- raw_apply_lock_bytes(s, new_perm, ~new_shared, true, &local_err);
117
+ raw_apply_lock_bytes(s->lock_fd, new_perm, ~new_shared,
118
+ true, &local_err);
119
if (local_err) {
120
/* Theoretically the above call only unlocks bytes and it cannot
121
* fail. Something weird happened, report it.
122
--
123
2.17.1
124
125
diff view generated by jsdifflib
1
Reviewed-by: John Snow <jsnow@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
Tested-by: Jeff Cody <jcody@redhat.com>
2
3
Reviewed-by: Jeff Cody <jcody@redhat.com>
3
This doesn't fix everything in here, but it does help clean up the
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
pylint report considerably.
5
Message-id: 20180606193702.7113-4-mreitz@redhat.com
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>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
16
---
8
tests/qemu-iotests/060 | 30 ++++++++++++++++++++++++++++++
17
tests/qemu-iotests/iotests.py | 83 ++++++++++++++++++-----------------
9
tests/qemu-iotests/060.out | 14 ++++++++++++++
18
1 file changed, 43 insertions(+), 40 deletions(-)
10
2 files changed, 44 insertions(+)
19
11
20
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/iotests.py
14
--- a/tests/qemu-iotests/060
23
+++ b/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/060
24
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ echo "{'execute': 'qmp_capabilities'}
25
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
-drive if=none,node-name=drive,file="$TEST_IMG",driver=qcow2 \
26
#
18
| _filter_qmp | _filter_qemu_io
27
19
28
-import errno
20
+echo
29
import os
21
+echo "=== Testing incoming inactive corrupted image ==="
30
import re
22
+echo
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]
23
+
76
+
24
+_make_test_img 64M
77
+ return exitcode, subp.communicate()[0] if exitcode else ''
25
+# Create an unaligned L1 entry, so qemu will signal a corruption when
78
26
+# reading from the covered area
79
def qemu_nbd_popen(*args):
27
+poke_file "$TEST_IMG" "$l1_offset" "\x00\x00\x00\x00\x2a\x2a\x2a\x2a"
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))
28
+
189
+
29
+# Inactive images are effectively read-only images, so this should be a
190
+ node = next(node for node in graph['nodes']
30
+# non-fatal corruption (which does not modify the image)
191
+ if node['id'] == node_id)
31
+echo "{'execute': 'qmp_capabilities'}
192
32
+ {'execute': 'human-monitor-command',
193
- node = next(node for node in graph['nodes'] \
33
+ 'arguments': {'command-line': 'qemu-io drive \"read 0 512\"'}}
194
- if node['id'] == node_id)
34
+ {'execute': 'quit'}" \
195
except StopIteration:
35
+ | $QEMU -qmp stdio -nographic -nodefaults \
196
node = None
36
+ -blockdev "{'node-name': 'drive',
197
37
+ 'driver': 'qcow2',
198
@@ -XXX,XX +XXX,XX @@ index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
38
+ 'file': {
199
class QMPTestCase(unittest.TestCase):
39
+ 'driver': 'file',
200
'''Abstract base class for QMP test cases'''
40
+ 'filename': '$TEST_IMG'
201
41
+ }}" \
202
+ def __init__(self, *args, **kwargs):
42
+ -incoming exec:'cat /dev/null' \
203
+ super().__init__(*args, **kwargs)
43
+ 2>&1 \
204
+ # Many users of this class set a VM property we rely on heavily
44
+ | _filter_qmp | _filter_qemu_io
205
+ # in the methods below.
206
+ self.vm = None
45
+
207
+
46
+echo
208
def dictpath(self, d, path):
47
+# Image should not have been marked corrupt
209
'''Traverse a path in a nested dict'''
48
+_img_info --format-specific | grep 'corrupt:'
210
for component in path.split('/'):
49
+
211
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
50
# success, all done
212
else:
51
echo "*** done"
213
self.assertEqual(result, value,
52
rm -f $seq.full
214
'"%s" is "%s", expected "%s"'
53
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
215
- % (path, str(result), str(value)))
54
index XXXXXXX..XXXXXXX 100644
216
+ % (path, str(result), str(value)))
55
--- a/tests/qemu-iotests/060.out
217
56
+++ b/tests/qemu-iotests/060.out
218
def assert_no_active_block_jobs(self):
57
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
219
result = self.vm.qmp('query-block-jobs')
58
{"return": ""}
220
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
59
{"return": {}}
221
"""Issue a query-named-block-nodes and assert node_name and/or
60
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
222
file_name is present in the result"""
61
+
223
def check_equal_or_none(a, b):
62
+=== Testing incoming inactive corrupted image ===
224
- return a == None or b == None or a == b
63
+
225
+ return a is None or b is None or a == b
64
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
226
assert node_name or file_name
65
+QMP_VERSION
227
result = self.vm.qmp('query-named-block-nodes')
66
+{"return": {}}
228
for x in result["return"]:
67
+qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
229
if check_equal_or_none(x.get("node-name"), node_name) and \
68
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}}
230
check_equal_or_none(x.get("file"), file_name):
69
+read failed: Input/output error
231
return
70
+{"return": ""}
232
- self.assertTrue(False, "Cannot find %s %s in result:\n%s" % \
71
+{"return": {}}
233
- (node_name, file_name, result))
72
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
234
+ self.fail("Cannot find %s %s in result:\n%s" %
73
+
235
+ (node_name, file_name, result))
74
+ corrupt: false
236
75
*** done
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
76
--
293
--
77
2.17.1
294
2.26.2
78
295
79
296
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
The throttle block filter can be reopened, and with this it is
3
It shadows (with a different type) the built-in format.
4
possible to change the throttle group that the filter belongs to.
4
Use something else.
5
5
6
The way the code does that is the following:
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
- On throttle_reopen_prepare(): create a new ThrottleGroupMember
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
and attach it to the new throttle group.
9
Message-Id: <20200331000014.11581-3-jsnow@redhat.com>
10
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
- On throttle_reopen_commit(): detach the old ThrottleGroupMember,
12
delete it and replace it with the new one.
13
14
The problem with this is that by replacing the ThrottleGroupMember the
15
previous value of io_limits_disabled is lost, causing an assertion
16
failure in throttle_co_drain_end().
17
18
This problem can be reproduced by reopening a throttle node:
19
20
$QEMU -monitor stdio
21
-object throttle-group,id=tg0,x-iops-total=1000 \
22
-blockdev node-name=hd0,driver=qcow2,file.driver=file,file.filename=hd.qcow2 \
23
-blockdev node-name=root,driver=throttle,throttle-group=tg0,file=hd0,read-only=on
24
25
(qemu) block_stream root
26
block/throttle.c:214: throttle_co_drain_end: Assertion `tgm->io_limits_disabled' failed.
27
28
Since we only want to change the throttle group on reopen there's no
29
need to create a ThrottleGroupMember and discard the old one. It's
30
easier if we simply detach it from its current group and attach it to
31
the new one.
32
33
Signed-off-by: Alberto Garcia <berto@igalia.com>
34
Message-id: 20180608151536.7378-1-berto@igalia.com
35
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
36
---
12
---
37
block/throttle.c | 54 +++++++++++++++++++++++++++++-------------------
13
tests/qemu-iotests/055 | 3 ++-
38
1 file changed, 33 insertions(+), 21 deletions(-)
14
tests/qemu-iotests/iotests.py | 6 +++---
15
2 files changed, 5 insertions(+), 4 deletions(-)
39
16
40
diff --git a/block/throttle.c b/block/throttle.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
41
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
42
--- a/block/throttle.c
33
--- a/tests/qemu-iotests/iotests.py
43
+++ b/block/throttle.c
34
+++ b/tests/qemu-iotests/iotests.py
44
@@ -XXX,XX +XXX,XX @@ static QemuOptsList throttle_opts = {
35
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
45
},
36
self._args.append(opts)
46
};
37
return self
47
38
48
-static int throttle_configure_tgm(BlockDriverState *bs,
39
- def add_drive(self, path, opts='', interface='virtio', format=imgfmt):
49
- ThrottleGroupMember *tgm,
40
+ def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt):
50
- QDict *options, Error **errp)
41
'''Add a virtio-blk drive to the VM'''
51
+/*
42
options = ['if=%s' % interface,
52
+ * If this function succeeds then the throttle group name is stored in
43
'id=drive%d' % self._num_drives]
53
+ * @group and must be freed by the caller.
44
54
+ * If there's an error then @group remains unmodified.
45
if path is not None:
55
+ */
46
options.append('file=%s' % path)
56
+static int throttle_parse_options(QDict *options, char **group, Error **errp)
47
- options.append('format=%s' % format)
57
{
48
+ options.append('format=%s' % img_format)
58
int ret;
49
options.append('cache=%s' % cachemode)
59
const char *group_name;
50
options.append('aio=%s' % aiomode)
60
@@ -XXX,XX +XXX,XX @@ static int throttle_configure_tgm(BlockDriverState *bs,
51
61
goto fin;
52
if opts:
62
}
53
options.append(opts)
63
54
64
- /* Register membership to group with name group_name */
55
- if format == 'luks' and 'key-secret' not in opts:
65
- throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
56
+ if img_format == 'luks' and 'key-secret' not in opts:
66
+ *group = g_strdup(group_name);
57
# default luks support
67
ret = 0;
58
if luks_default_secret_object not in self._args:
68
fin:
59
self.add_object(luks_default_secret_object)
69
qemu_opts_del(opts);
70
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
71
int flags, Error **errp)
72
{
73
ThrottleGroupMember *tgm = bs->opaque;
74
+ char *group;
75
+ int ret;
76
77
bs->file = bdrv_open_child(NULL, options, "file", bs,
78
&child_file, false, errp);
79
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
80
bs->supported_zero_flags = bs->file->bs->supported_zero_flags |
81
BDRV_REQ_WRITE_UNCHANGED;
82
83
- return throttle_configure_tgm(bs, tgm, options, errp);
84
+ ret = throttle_parse_options(options, &group, errp);
85
+ if (ret == 0) {
86
+ /* Register membership to group with name group_name */
87
+ throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
88
+ g_free(group);
89
+ }
90
+
91
+ return ret;
92
}
93
94
static void throttle_close(BlockDriverState *bs)
95
@@ -XXX,XX +XXX,XX @@ static void throttle_attach_aio_context(BlockDriverState *bs,
96
static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
97
BlockReopenQueue *queue, Error **errp)
98
{
99
- ThrottleGroupMember *tgm;
100
+ int ret;
101
+ char *group = NULL;
102
103
assert(reopen_state != NULL);
104
assert(reopen_state->bs != NULL);
105
106
- reopen_state->opaque = g_new0(ThrottleGroupMember, 1);
107
- tgm = reopen_state->opaque;
108
-
109
- return throttle_configure_tgm(reopen_state->bs, tgm, reopen_state->options,
110
- errp);
111
+ ret = throttle_parse_options(reopen_state->options, &group, errp);
112
+ reopen_state->opaque = group;
113
+ return ret;
114
}
115
116
static void throttle_reopen_commit(BDRVReopenState *reopen_state)
117
{
118
- ThrottleGroupMember *old_tgm = reopen_state->bs->opaque;
119
- ThrottleGroupMember *new_tgm = reopen_state->opaque;
120
+ BlockDriverState *bs = reopen_state->bs;
121
+ ThrottleGroupMember *tgm = bs->opaque;
122
+ char *group = reopen_state->opaque;
123
+
124
+ assert(group);
125
126
- throttle_group_unregister_tgm(old_tgm);
127
- g_free(old_tgm);
128
- reopen_state->bs->opaque = new_tgm;
129
+ if (strcmp(group, throttle_group_get_name(tgm))) {
130
+ throttle_group_unregister_tgm(tgm);
131
+ throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
132
+ }
133
+ g_free(reopen_state->opaque);
134
reopen_state->opaque = NULL;
135
}
136
137
static void throttle_reopen_abort(BDRVReopenState *reopen_state)
138
{
139
- ThrottleGroupMember *tgm = reopen_state->opaque;
140
-
141
- throttle_group_unregister_tgm(tgm);
142
- g_free(tgm);
143
+ g_free(reopen_state->opaque);
144
reopen_state->opaque = NULL;
145
}
146
147
--
60
--
148
2.17.1
61
2.26.2
149
62
150
63
diff view generated by jsdifflib
1
219 has two issues that may lead to sporadic failure, both of which are
1
From: John Snow <jsnow@redhat.com>
2
the result of issuing query-jobs too early after a job has been
3
modified. This can then lead to different results based on whether the
4
modification has taken effect already or not.
5
2
6
First, query-jobs is issued right after the job has been created.
3
The right way to solve this is to come up with a virtual environment
7
Besides its current progress possibly being in any random state (which
4
infrastructure that sets all the paths correctly, and/or to create
8
has already been taken care of), its total progress too is basically
5
installable python modules that can be imported normally.
9
arbitrary, because the job may not yet have been able to determine it.
10
This patch addresses this by just filtering the total progress, like
11
what has been done for the current progress already. However, for more
12
clarity, the filtering is changed to replace the values by a string
13
'FILTERED' instead of deleting them.
14
6
15
Secondly, query-jobs is issued right after a job has been resumed. The
7
That's hard, so just silence this error for now.
16
job may or may not yet have had the time to actually perform any I/O,
17
and thus its current progress may or may not have advanced. To make
18
sure it has indeed advanced (which is what the reference output already
19
assumes), keep querying it until it has.
20
8
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20180606190628.8170-1-mreitz@redhat.com
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
23
Reviewed-by: Eric Blake <eblake@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>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
15
---
26
tests/qemu-iotests/219 | 26 ++++++++++++++++++++------
16
tests/qemu-iotests/iotests.py | 1 +
27
tests/qemu-iotests/219.out | 10 +++++-----
17
1 file changed, 1 insertion(+)
28
2 files changed, 25 insertions(+), 11 deletions(-)
29
18
30
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
19
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
31
index XXXXXXX..XXXXXXX 100755
32
--- a/tests/qemu-iotests/219
33
+++ b/tests/qemu-iotests/219
34
@@ -XXX,XX +XXX,XX @@ def test_pause_resume(vm):
35
iotests.log(vm.qmp(pause_cmd, **{pause_arg: 'job0'}))
36
pause_wait(vm, 'job0')
37
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
38
- iotests.log(vm.qmp('query-jobs'))
39
+ result = vm.qmp('query-jobs')
40
+ iotests.log(result)
41
+
42
+ old_progress = result['return'][0]['current-progress']
43
+ total_progress = result['return'][0]['total-progress']
44
45
iotests.log(vm.qmp(resume_cmd, **{resume_arg: 'job0'}))
46
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
47
- iotests.log(vm.qmp('query-jobs'))
48
+ if old_progress < total_progress:
49
+ # Wait for the job to advance
50
+ while result['return'][0]['current-progress'] == old_progress:
51
+ result = vm.qmp('query-jobs')
52
+ iotests.log(result)
53
+ else:
54
+ # Already reached the end, so the job cannot advance
55
+ # any further; therefore, the query-jobs result can be
56
+ # logged immediately
57
+ iotests.log(vm.qmp('query-jobs'))
58
59
def test_job_lifecycle(vm, job, job_args, has_ready=False):
60
iotests.log('')
61
@@ -XXX,XX +XXX,XX @@ def test_job_lifecycle(vm, job, job_args, has_ready=False):
62
iotests.log(vm.qmp(job, job_id='job0', **job_args))
63
64
# Depending on the storage, the first request may or may not have completed
65
- # yet, so filter out the progress. Later query-job calls don't need the
66
- # filtering because the progress is made deterministic by the block job
67
- # speed
68
+ # yet (and the total progress may not have been fully determined yet), so
69
+ # filter out the progress. Later query-job calls don't need the filtering
70
+ # because the progress is made deterministic by the block job speed
71
result = vm.qmp('query-jobs')
72
for j in result['return']:
73
- del j['current-progress']
74
+ j['current-progress'] = 'FILTERED'
75
+ j['total-progress'] = 'FILTERED'
76
iotests.log(result)
77
78
# undefined -> created -> running
79
diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out
80
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
81
--- a/tests/qemu-iotests/219.out
21
--- a/tests/qemu-iotests/iotests.py
82
+++ b/tests/qemu-iotests/219.out
22
+++ b/tests/qemu-iotests/iotests.py
83
@@ -XXX,XX +XXX,XX @@ Launching VM...
23
@@ -XXX,XX +XXX,XX @@ import io
84
24
from collections import OrderedDict
85
Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True)
25
import faulthandler
86
{u'return': {}}
26
87
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]}
27
+# pylint: disable=import-error, wrong-import-position
88
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'mirror'}]}
28
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
89
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
29
from qemu import qtest
90
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
91
92
@@ -XXX,XX +XXX,XX @@ Waiting for PENDING state...
93
94
Starting block job: drive-backup (auto-finalize: True; auto-dismiss: True)
95
{u'return': {}}
96
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]}
97
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]}
98
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
99
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
100
101
@@ -XXX,XX +XXX,XX @@ Waiting for PENDING state...
102
103
Starting block job: drive-backup (auto-finalize: True; auto-dismiss: False)
104
{u'return': {}}
105
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]}
106
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]}
107
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
108
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
109
110
@@ -XXX,XX +XXX,XX @@ Waiting for PENDING state...
111
112
Starting block job: drive-backup (auto-finalize: False; auto-dismiss: True)
113
{u'return': {}}
114
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]}
115
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]}
116
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
117
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
118
119
@@ -XXX,XX +XXX,XX @@ Waiting for PENDING state...
120
121
Starting block job: drive-backup (auto-finalize: False; auto-dismiss: False)
122
{u'return': {}}
123
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]}
124
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]}
125
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
126
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'}
127
30
128
--
31
--
129
2.17.1
32
2.26.2
130
33
131
34
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
It has been marked as deprecated since QEMU v2.0 already, so it
3
It's bad hygiene: if we modify this list, it will be modified across all
4
is time now to finally remove it.
4
invocations.
5
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
(Remaining bad usages are fixed in a subsequent patch which changes the
7
Message-id: 1528288551-31641-1-git-send-email-thuth@redhat.com
7
function signature anyway.)
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
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>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
15
---
11
qemu-img.c | 7 +------
16
tests/qemu-iotests/iotests.py | 24 ++++++++++++------------
12
qemu-doc.texi | 7 -------
17
1 file changed, 12 insertions(+), 12 deletions(-)
13
qemu-img-cmds.hx | 4 ++--
14
qemu-img.texi | 7 ++-----
15
tests/qemu-iotests/029 | 2 +-
16
tests/qemu-iotests/080 | 4 ++--
17
6 files changed, 8 insertions(+), 23 deletions(-)
18
18
19
diff --git a/qemu-img.c b/qemu-img.c
19
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/qemu-img.c
21
--- a/tests/qemu-iotests/iotests.py
22
+++ b/qemu-img.c
22
+++ b/tests/qemu-iotests/iotests.py
23
@@ -XXX,XX +XXX,XX @@ static void QEMU_NORETURN help(void)
23
@@ -XXX,XX +XXX,XX @@ def qemu_img_log(*args):
24
" 'snapshot_param' is param used for internal snapshot, format\n"
24
log(result, filters=[filter_testfiles])
25
" is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
25
return result
26
" '[ID_OR_NAME]'\n"
26
27
- " 'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
27
-def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
28
- " instead\n"
28
+def img_info_log(filename, filter_path=None, imgopts=False, extra_args=()):
29
" '-c' indicates that target image must be compressed (qcow format only)\n"
29
args = ['info']
30
" '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
30
if imgopts:
31
" new backing file match exactly. The image doesn't need a working\n"
31
args.append('--image-opts')
32
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
32
@@ -XXX,XX +XXX,XX @@ def filter_qmp_imgfmt(qmsg):
33
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
33
return value
34
{0, 0, 0, 0}
34
return filter_qmp(qmsg, _filter)
35
};
35
36
- c = getopt_long(argc, argv, ":hf:O:B:co:s:l:S:pt:T:qnm:WU",
36
-def log(msg, filters=[], indent=None):
37
+ c = getopt_long(argc, argv, ":hf:O:B:co:l:S:pt:T:qnm:WU",
37
+def log(msg, filters=(), indent=None):
38
long_options, NULL);
38
'''Logs either a string message or a JSON serializable message (like QMP).
39
if (c == -1) {
39
If indent is provided, JSON serializable messages are pretty-printed.'''
40
break;
40
for flt in filters:
41
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
41
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
42
g_free(old_options);
42
result.append(filter_qmp_event(ev))
43
}
43
return result
44
break;
44
45
- case 's':
45
- def qmp_log(self, cmd, filters=[], indent=None, **kwargs):
46
- snapshot_name = optarg;
46
+ def qmp_log(self, cmd, filters=(), indent=None, **kwargs):
47
- break;
47
full_cmd = OrderedDict((
48
case 'l':
48
("execute", cmd),
49
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
49
("arguments", ordered_qmp(kwargs))
50
sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
50
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
51
diff --git a/qemu-doc.texi b/qemu-doc.texi
51
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
52
index XXXXXXX..XXXXXXX 100644
52
' [case not run] ' + reason + '\n')
53
--- a/qemu-doc.texi
53
54
+++ b/qemu-doc.texi
54
-def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
55
@@ -XXX,XX +XXX,XX @@ Option @option{-virtioconsole} has been replaced by
55
+def verify_image_format(supported_fmts=(), unsupported_fmts=()):
56
The @code{-clock} option is ignored since QEMU version 1.7.0. There is no
56
assert not (supported_fmts and unsupported_fmts)
57
replacement since it is not needed anymore.
57
58
58
if 'generic' in supported_fmts and \
59
-@section qemu-img command line arguments
59
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
60
-
60
if not_sup or (imgfmt in unsupported_fmts):
61
-@subsection convert -s (since 2.0.0)
61
notrun('not suitable for this image format: %s' % imgfmt)
62
-
62
63
-The ``convert -s snapshot_id_or_name'' argument is obsoleted
63
-def verify_protocol(supported=[], unsupported=[]):
64
-by the ``convert -l snapshot_param'' argument instead.
64
+def verify_protocol(supported=(), unsupported=()):
65
-
65
assert not (supported and unsupported)
66
@section QEMU Machine Protocol (QMP) commands
66
67
67
if 'generic' in supported:
68
@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
68
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=None, unsupported=None):
69
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
69
if not any((sys.platform.startswith(x) for x in supported)):
70
index XXXXXXX..XXXXXXX 100644
70
notrun('not suitable for this OS: %s' % sys.platform)
71
--- a/qemu-img-cmds.hx
71
72
+++ b/qemu-img-cmds.hx
72
-def verify_cache_mode(supported_cache_modes=[]):
73
@@ -XXX,XX +XXX,XX @@ STEXI
73
+def verify_cache_mode(supported_cache_modes=()):
74
ETEXI
74
if supported_cache_modes and (cachemode not in supported_cache_modes):
75
75
notrun('not suitable for this cache mode: %s' % cachemode)
76
DEF("convert", img_convert,
76
77
- "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
77
-def verify_aio_mode(supported_aio_modes=[]):
78
+ "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
78
+def verify_aio_mode(supported_aio_modes=()):
79
STEXI
79
if supported_aio_modes and (aiomode not in supported_aio_modes):
80
-@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
80
notrun('not suitable for this aio mode: %s' % aiomode)
81
+@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
81
82
ETEXI
82
@@ -XXX,XX +XXX,XX @@ def supported_formats(read_only=False):
83
83
84
DEF("create", img_create,
84
return supported_formats.formats[read_only]
85
diff --git a/qemu-img.texi b/qemu-img.texi
85
86
index XXXXXXX..XXXXXXX 100644
86
-def skip_if_unsupported(required_formats=[], read_only=False):
87
--- a/qemu-img.texi
87
+def skip_if_unsupported(required_formats=(), read_only=False):
88
+++ b/qemu-img.texi
88
'''Skip Test Decorator
89
@@ -XXX,XX +XXX,XX @@ by the used format or see the format descriptions below for details.
89
Runs the test if all the required formats are whitelisted'''
90
is param used for internal snapshot, format is
90
def skip_test_decorator(func):
91
'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'
91
@@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug):
92
92
sys.stderr.write(out)
93
-@item snapshot_id_or_name
93
94
-is deprecated, use snapshot_param instead
94
def execute_test(test_function=None,
95
-
95
- supported_fmts=[],
96
@end table
96
+ supported_fmts=(),
97
97
supported_platforms=None,
98
@table @option
98
- supported_cache_modes=[], supported_aio_modes={},
99
@@ -XXX,XX +XXX,XX @@ Error on reading data
99
- unsupported_fmts=[], supported_protocols=[],
100
100
- unsupported_protocols=[]):
101
@end table
101
+ supported_cache_modes=(), supported_aio_modes=(),
102
102
+ unsupported_fmts=(), supported_protocols=(),
103
-@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
103
+ unsupported_protocols=()):
104
+@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
104
"""Run either unittest or script-style tests."""
105
105
106
-Convert the disk image @var{filename} or a snapshot @var{snapshot_param}(@var{snapshot_id_or_name} is deprecated)
106
# We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
107
+Convert the disk image @var{filename} or a snapshot @var{snapshot_param}
108
to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c}
109
option) or use any format specific options like encryption (@code{-o} option).
110
111
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
112
index XXXXXXX..XXXXXXX 100755
113
--- a/tests/qemu-iotests/029
114
+++ b/tests/qemu-iotests/029
115
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
116
{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
117
poke_file "$TEST_IMG" "$offset_size" "\x00\x00\x00\x00\x00\x00\x02\x00"
118
poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
119
-{ $QEMU_IMG convert -s foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
120
+{ $QEMU_IMG convert -l foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
121
122
123
# success, all done
124
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
125
index XXXXXXX..XXXXXXX 100755
126
--- a/tests/qemu-iotests/080
127
+++ b/tests/qemu-iotests/080
128
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
129
{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
130
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
131
poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x00"
132
-{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
133
+{ $QEMU_IMG convert -l test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
134
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
135
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
136
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
137
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
138
{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
139
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
140
poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
141
-{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
142
+{ $QEMU_IMG convert -l test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
143
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
144
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
145
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
146
--
107
--
147
2.17.1
108
2.26.2
148
109
149
110
diff view generated by jsdifflib
1
This adds a test for an I/O error during snapshot deletion, and maybe
1
From: John Snow <jsnow@redhat.com>
2
more importantly, for how to repair the resulting image. If the
3
snapshot has been deleted before the error occurs, the only negative
4
result will be leaked clusters -- and those should be repairable with
5
qemu-img check -r leaks.
6
2
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
This allows others to get repeatable results with pylint. If you run
8
Reviewed-by: Eric Blake <eblake@redhat.com>
4
`pylint iotests.py`, you should see a 100% pass.
9
Message-id: 20180509200059.31125-3-mreitz@redhat.com
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200331000014.11581-6-jsnow@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
11
---
12
tests/qemu-iotests/217 | 90 ++++++++++++++++++++++++++++++++++++++
12
tests/qemu-iotests/pylintrc | 22 ++++++++++++++++++++++
13
tests/qemu-iotests/217.out | 42 ++++++++++++++++++
13
1 file changed, 22 insertions(+)
14
tests/qemu-iotests/group | 1 +
14
create mode 100644 tests/qemu-iotests/pylintrc
15
3 files changed, 133 insertions(+)
16
create mode 100755 tests/qemu-iotests/217
17
create mode 100644 tests/qemu-iotests/217.out
18
15
19
diff --git a/tests/qemu-iotests/217 b/tests/qemu-iotests/217
16
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
20
new file mode 100755
21
index XXXXXXX..XXXXXXX
22
--- /dev/null
23
+++ b/tests/qemu-iotests/217
24
@@ -XXX,XX +XXX,XX @@
25
+#!/bin/bash
26
+#
27
+# I/O errors when working with internal qcow2 snapshots, and repairing
28
+# the result
29
+#
30
+# Copyright (C) 2018 Red Hat, Inc.
31
+#
32
+# This program is free software; you can redistribute it and/or modify
33
+# it under the terms of the GNU General Public License as published by
34
+# the Free Software Foundation; either version 2 of the License, or
35
+# (at your option) any later version.
36
+#
37
+# This program is distributed in the hope that it will be useful,
38
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+# GNU General Public License for more details.
41
+#
42
+# You should have received a copy of the GNU General Public License
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
44
+
45
+seq=$(basename $0)
46
+echo "QA output created by $seq"
47
+
48
+status=1    # failure is the default!
49
+
50
+_cleanup()
51
+{
52
+ _cleanup_test_img
53
+ rm -f "$TEST_DIR/blkdebug.conf"
54
+}
55
+trap "_cleanup; exit \$status" 0 1 2 3 15
56
+
57
+# get standard environment, filters and checks
58
+. ./common.rc
59
+. ./common.filter
60
+
61
+# This test is specific to qcow2
62
+_supported_fmt qcow2
63
+_supported_proto file
64
+_supported_os Linux
65
+
66
+# This test needs clusters with at least a refcount of 2 so that
67
+# OFLAG_COPIED is not set. refcount_bits=1 is therefore unsupported.
68
+_unsupported_imgopts 'refcount_bits=1[^0-9]'
69
+
70
+echo
71
+echo '=== Simulating an I/O error during snapshot deletion ==='
72
+echo
73
+
74
+_make_test_img 64M
75
+$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
76
+
77
+# Create the snapshot
78
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
79
+
80
+# Verify the snapshot is there
81
+echo
82
+_img_info | grep 'Snapshot list'
83
+echo '(Snapshot filtered)'
84
+echo
85
+
86
+# Try to delete the snapshot (with an error happening when freeing the
87
+# then leaked clusters)
88
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
89
+[inject-error]
90
+event = "cluster_free"
91
+errno = "5"
92
+EOF
93
+$QEMU_IMG snapshot -d foo "blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG"
94
+
95
+# Verify the snapshot is gone
96
+echo
97
+_img_info | grep 'Snapshot list'
98
+
99
+# Should only show leaks
100
+echo '--- Checking test image ---'
101
+_check_test_img
102
+
103
+echo
104
+
105
+# As there are only leaks, this should be able to fully repair the
106
+# image
107
+echo '--- Repairing test image ---'
108
+_check_test_img -r leaks
109
+
110
+
111
+# success, all done
112
+echo '*** done'
113
+rm -f $seq.full
114
+status=0
115
diff --git a/tests/qemu-iotests/217.out b/tests/qemu-iotests/217.out
116
new file mode 100644
17
new file mode 100644
117
index XXXXXXX..XXXXXXX
18
index XXXXXXX..XXXXXXX
118
--- /dev/null
19
--- /dev/null
119
+++ b/tests/qemu-iotests/217.out
20
+++ b/tests/qemu-iotests/pylintrc
120
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
121
+QA output created by 217
22
+[MESSAGES CONTROL]
122
+
23
+
123
+=== Simulating an I/O error during snapshot deletion ===
24
+# Disable the message, report, category or checker with the given id(s). You
124
+
25
+# can either give multiple identifiers separated by comma (,) or put this
125
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
26
+# option multiple times (only on the command line, not in the configuration
126
+wrote 65536/65536 bytes at offset 0
27
+# file where it should appear only once). You can also use "--disable=all" to
127
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
28
+# disable everything first and then reenable specific checks. For example, if
128
+
29
+# you want to run only the similarities checker, you can use "--disable=all
129
+Snapshot list:
30
+# --enable=similarities". If you want to run only the classes checker, but have
130
+(Snapshot filtered)
31
+# no Warning level messages displayed, use "--disable=all --enable=classes
131
+
32
+# --disable=W".
132
+qcow2_free_clusters failed: Input/output error
33
+disable=invalid-name,
133
+qemu-img: Could not delete snapshot 'foo': Failed to free the cluster and L1 table: Input/output error
34
+ no-else-return,
134
+
35
+ too-few-public-methods,
135
+--- Checking test image ---
36
+ too-many-arguments,
136
+Leaked cluster 4 refcount=2 reference=1
37
+ too-many-branches,
137
+Leaked cluster 5 refcount=2 reference=1
38
+ too-many-lines,
138
+Leaked cluster 6 refcount=1 reference=0
39
+ too-many-locals,
139
+Leaked cluster 7 refcount=1 reference=0
40
+ too-many-public-methods,
140
+
41
+ # These are temporary, and should be removed:
141
+4 leaked clusters were found on the image.
42
+ line-too-long,
142
+This means waste of disk space, but no harm to data.
43
+ missing-docstring,
143
+
144
+--- Repairing test image ---
145
+Leaked cluster 4 refcount=2 reference=1
146
+Leaked cluster 5 refcount=2 reference=1
147
+Leaked cluster 6 refcount=1 reference=0
148
+Leaked cluster 7 refcount=1 reference=0
149
+Repairing cluster 4 refcount=2 reference=1
150
+Repairing cluster 5 refcount=2 reference=1
151
+Repairing cluster 6 refcount=1 reference=0
152
+Repairing cluster 7 refcount=1 reference=0
153
+Repairing OFLAG_COPIED L2 cluster: l1_index=0 l1_entry=40000 refcount=1
154
+Repairing OFLAG_COPIED data cluster: l2_entry=50000 refcount=1
155
+The following inconsistencies were found and repaired:
156
+
157
+ 4 leaked clusters
158
+ 2 corruptions
159
+
160
+Double checking the fixed image now...
161
+No errors were found on the image.
162
+*** done
163
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
164
index XXXXXXX..XXXXXXX 100644
165
--- a/tests/qemu-iotests/group
166
+++ b/tests/qemu-iotests/group
167
@@ -XXX,XX +XXX,XX @@
168
214 rw auto
169
215 rw auto quick
170
216 rw auto quick
171
+217 rw auto quick
172
218 rw auto quick
173
219 rw auto
174
--
44
--
175
2.17.1
45
2.26.2
176
46
177
47
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
2
3
Message-id: 20180509182002.8044-3-mreitz@redhat.com
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>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
12
---
6
tests/qemu-iotests/024 | 82 ++++++++++++++++++++++++++++++++++++--
13
tests/qemu-iotests/iotests.py | 18 +++++++++---------
7
tests/qemu-iotests/024.out | 30 ++++++++++++++
14
1 file changed, 9 insertions(+), 9 deletions(-)
8
2 files changed, 109 insertions(+), 3 deletions(-)
9
15
10
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/024
13
+++ b/tests/qemu-iotests/024
14
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
15
16
_cleanup()
17
{
18
-    _cleanup_test_img
19
-    rm -f "$TEST_DIR/t.$IMGFMT.base_old"
20
-    rm -f "$TEST_DIR/t.$IMGFMT.base_new"
21
+ _cleanup_test_img
22
+ rm -f "$TEST_DIR/t.$IMGFMT.base_old"
23
+ rm -f "$TEST_DIR/t.$IMGFMT.base_new"
24
+
25
+ rm -f "$TEST_DIR/subdir/t.$IMGFMT"
26
+ rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_old"
27
+ rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_new"
28
+ rmdir "$TEST_DIR/subdir" 2> /dev/null
29
}
30
trap "_cleanup; exit \$status" 0 1 2 3 15
31
32
@@ -XXX,XX +XXX,XX @@ io_pattern readv $((13 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
33
io_pattern readv $((14 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
34
io_pattern readv $((15 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
35
36
+echo
37
+echo "=== Test rebase in a subdirectory of the working directory ==="
38
+echo
39
+
40
+# Clean up the old images beforehand so they do not interfere with
41
+# this test
42
+_cleanup
43
+
44
+mkdir "$TEST_DIR/subdir"
45
+
46
+# Relative to the overlay
47
+BASE_OLD_OREL="t.$IMGFMT.base_old"
48
+BASE_NEW_OREL="t.$IMGFMT.base_new"
49
+
50
+# Relative to $TEST_DIR (which is going to be our working directory)
51
+OVERLAY_WREL="subdir/t.$IMGFMT"
52
+
53
+BASE_OLD="$TEST_DIR/subdir/$BASE_OLD_OREL"
54
+BASE_NEW="$TEST_DIR/subdir/$BASE_NEW_OREL"
55
+OVERLAY="$TEST_DIR/$OVERLAY_WREL"
56
+
57
+# Test done here:
58
+#
59
+# Backing (old): 11 11 -- 11
60
+# Backing (new): -- 22 22 11
61
+# Overlay: -- -- -- --
62
+#
63
+# Rebasing works, we have verified that above. Here, we just want to
64
+# see that rebasing is done for the correct target backing file.
65
+
66
+TEST_IMG=$BASE_OLD _make_test_img 1M
67
+TEST_IMG=$BASE_NEW _make_test_img 1M
68
+TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD_OREL" 1M
69
+
70
+echo
71
+
72
+$QEMU_IO "$BASE_OLD" \
73
+ -c "write -P 0x11 $((0 * CLUSTER_SIZE)) $((2 * CLUSTER_SIZE))" \
74
+ -c "write -P 0x11 $((3 * CLUSTER_SIZE)) $((1 * CLUSTER_SIZE))" \
75
+ | _filter_qemu_io
76
+
77
+$QEMU_IO "$BASE_NEW" \
78
+ -c "write -P 0x22 $((1 * CLUSTER_SIZE)) $((2 * CLUSTER_SIZE))" \
79
+ -c "write -P 0x11 $((3 * CLUSTER_SIZE)) $((1 * CLUSTER_SIZE))" \
80
+ | _filter_qemu_io
81
+
82
+echo
83
+
84
+pushd "$TEST_DIR" >/dev/null
85
+$QEMU_IMG rebase -f "$IMGFMT" -b "$BASE_NEW_OREL" "$OVERLAY_WREL"
86
+popd >/dev/null
87
+
88
+# Verify the backing path is correct
89
+TEST_IMG=$OVERLAY _img_info | grep '^backing file'
90
+
91
+echo
92
+
93
+# Verify the data is correct
94
+$QEMU_IO "$OVERLAY" \
95
+ -c "read -P 0x11 $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
96
+ -c "read -P 0x11 $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
97
+ -c "read -P 0x00 $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
98
+ -c "read -P 0x11 $((3 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
99
+ | _filter_qemu_io
100
+
101
+echo
102
+
103
+# Verify that cluster #3 is not allocated (because it is the same in
104
+# $BASE_OLD and $BASE_NEW)
105
+$QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map
106
+
107
108
# success, all done
109
echo "*** done"
110
diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out
111
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/024.out
18
--- a/tests/qemu-iotests/iotests.py
113
+++ b/tests/qemu-iotests/024.out
19
+++ b/tests/qemu-iotests/iotests.py
114
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 917504
20
@@ -XXX,XX +XXX,XX @@
115
=== IO: pattern 0x00
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
116
read 65536/65536 bytes at offset 983040
22
#
117
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
23
118
+
24
+import atexit
119
+=== Test rebase in a subdirectory of the working directory ===
25
+from collections import OrderedDict
120
+
26
+import faulthandler
121
+Formatting 'TEST_DIR/subdir/t.IMGFMT.base_old', fmt=IMGFMT size=1048576
27
+import io
122
+Formatting 'TEST_DIR/subdir/t.IMGFMT.base_new', fmt=IMGFMT size=1048576
28
+import json
123
+Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base_old
29
+import logging
124
+
30
import os
125
+wrote 131072/131072 bytes at offset 0
31
import re
126
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
32
+import signal
127
+wrote 65536/65536 bytes at offset 196608
33
+import struct
128
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
34
import subprocess
129
+wrote 131072/131072 bytes at offset 65536
35
-import unittest
130
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
36
import sys
131
+wrote 65536/65536 bytes at offset 196608
37
-import struct
132
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
38
-import json
133
+
39
-import signal
134
+backing file: t.IMGFMT.base_new (actual path: TEST_DIR/subdir/t.IMGFMT.base_new)
40
-import logging
135
+
41
-import atexit
136
+read 65536/65536 bytes at offset 0
42
-import io
137
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
43
-from collections import OrderedDict
138
+read 65536/65536 bytes at offset 65536
44
-import faulthandler
139
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
45
+import unittest
140
+read 65536/65536 bytes at offset 131072
46
141
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
47
# pylint: disable=import-error, wrong-import-position
142
+read 65536/65536 bytes at offset 196608
48
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
143
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
144
+
145
+Offset Length File
146
+0 0x30000 TEST_DIR/subdir/t.IMGFMT
147
+0x30000 0x10000 TEST_DIR/subdir/t.IMGFMT.base_new
148
*** done
149
--
49
--
150
2.17.1
50
2.26.2
151
51
152
52
diff view generated by jsdifflib
1
The only users of print_block_option_help() are qemu-img create and
1
From: John Snow <jsnow@redhat.com>
2
qemu-img convert for the output image, so this function is always used
3
for image creation (it used to be used for amendment also, but that is
4
no longer the case).
5
2
6
So if image creation is not supported by either the format or the
3
We no longer need to accommodate <3.4, drop this code.
7
protocol, there is no need to print any option description, because the
4
(The lines were > 79 chars and it stood out.)
8
user cannot create an image like this anyway.
9
5
10
This also fixes an assertion failure:
6
Signed-off-by: John Snow <jsnow@redhat.com>
11
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
$ qemu-img create -f bochs -o help
8
Message-Id: <20200331000014.11581-8-jsnow@redhat.com>
13
Supported options:
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
qemu-img: util/qemu-option.c:219:
15
qemu_opts_print_help: Assertion `list' failed.
16
[1] 24831 abort (core dumped) qemu-img create -f bochs -o help
17
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Reviewed-by: John Snow <jsnow@redhat.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Message-id: 20180509210023.20283-6-mreitz@redhat.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
11
---
24
qemu-img.c | 10 ++++++++++
12
tests/qemu-iotests/iotests.py | 5 +----
25
1 file changed, 10 insertions(+)
13
1 file changed, 1 insertion(+), 4 deletions(-)
26
14
27
diff --git a/qemu-img.c b/qemu-img.c
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
28
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
29
--- a/qemu-img.c
17
--- a/tests/qemu-iotests/iotests.py
30
+++ b/qemu-img.c
18
+++ b/tests/qemu-iotests/iotests.py
31
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
19
@@ -XXX,XX +XXX,XX @@ def log(msg, filters=(), indent=None):
32
return 1;
20
for flt in filters:
33
}
21
msg = flt(msg)
34
22
if isinstance(msg, (dict, list)):
35
+ if (!drv->create_opts) {
23
- # Python < 3.4 needs to know not to add whitespace when pretty-printing:
36
+ error_report("Format driver '%s' does not support image creation", fmt);
24
- separators = (', ', ': ') if indent is None else (',', ': ')
37
+ return 1;
25
# Don't sort if it's already sorted
38
+ }
26
do_sort = not isinstance(msg, OrderedDict)
39
+
27
- print(json.dumps(msg, sort_keys=do_sort,
40
create_opts = qemu_opts_append(create_opts, drv->create_opts);
28
- indent=indent, separators=separators))
41
if (filename) {
29
+ print(json.dumps(msg, sort_keys=do_sort, indent=indent))
42
proto_drv = bdrv_find_protocol(filename, true, &local_err);
30
else:
43
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
31
print(msg)
44
qemu_opts_free(create_opts);
45
return 1;
46
}
47
+ if (!proto_drv->create_opts) {
48
+ error_report("Protocal driver '%s' does not support image creation",
49
+ proto_drv->format_name);
50
+ return 1;
51
+ }
52
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
53
}
54
32
55
--
33
--
56
2.17.1
34
2.26.2
57
35
58
36
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
It's possible, that job was finished during waiting. In this case we
3
Representing nested, recursive data structures in mypy is notoriously
4
will see error message "Timeout waiting for job to pause" which is not
4
difficult; the best we can reliably do right now is denote the leaf
5
very informative. So, let's check during waiting iteration that the job
5
types as "Any" while describing the general shape of the data.
6
exists.
7
6
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Regardless, this fully annotates the log() function.
9
Message-id: 20180601115923.17159-1-vsementsov@virtuozzo.com
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>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
24
---
12
tests/qemu-iotests/iotests.py | 9 +++++++--
25
tests/qemu-iotests/iotests.py | 14 +++++++++++---
13
1 file changed, 7 insertions(+), 2 deletions(-)
26
1 file changed, 11 insertions(+), 3 deletions(-)
14
27
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
28
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
30
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
31
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
32
@@ -XXX,XX +XXX,XX @@ import signal
20
with Timeout(1, "Timeout waiting for job to pause"):
33
import struct
21
while True:
34
import subprocess
22
result = self.vm.qmp('query-block-jobs')
35
import sys
23
+ found = False
36
+from typing import (Any, Callable, Dict, Iterable, List, Optional, TypeVar)
24
for job in result['return']:
37
import unittest
25
- if job['device'] == job_id and job['paused'] == True and job['busy'] == False:
38
26
- return job
39
# pylint: disable=import-error, wrong-import-position
27
+ if job['device'] == job_id:
40
@@ -XXX,XX +XXX,XX @@ def filter_qmp_imgfmt(qmsg):
28
+ found = True
41
return value
29
+ if job['paused'] == True and job['busy'] == False:
42
return filter_qmp(qmsg, _filter)
30
+ return job
43
31
+ break
44
-def log(msg, filters=(), indent=None):
32
+ assert found
45
- '''Logs either a string message or a JSON serializable message (like QMP).
33
46
- If indent is provided, JSON serializable messages are pretty-printed.'''
34
def pause_job(self, job_id='job0', wait=True):
47
+
35
result = self.vm.qmp('block-job-pause', device=job_id)
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)):
36
--
60
--
37
2.17.1
61
2.26.2
38
62
39
63
diff view generated by jsdifflib
1
With qemu-io now returning a useful exit code, some tests may find it
1
From: John Snow <jsnow@redhat.com>
2
sufficient to just query that instead of logging (and filtering) the
2
3
whole output.
3
79 is the PEP8 recommendation. This recommendation works well for
4
4
reading patch diffs in TUI email clients.
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Message-id: 20180509194302.21585-5-mreitz@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>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
11
---
10
tests/qemu-iotests/iotests.py | 9 +++++++++
12
tests/qemu-iotests/iotests.py | 64 +++++++++++++++++++++++------------
11
1 file changed, 9 insertions(+)
13
tests/qemu-iotests/pylintrc | 6 +++-
14
2 files changed, 47 insertions(+), 23 deletions(-)
12
15
13
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/iotests.py
18
--- a/tests/qemu-iotests/iotests.py
16
+++ b/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):
17
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args):
54
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args):
18
sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(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)))
19
return subp.communicate()[0]
61
return subp.communicate()[0]
20
62
21
+def qemu_io_silent(*args):
63
def qemu_io_log(*args):
22
+ '''Run qemu-io and return the exit code, suppressing stdout'''
64
@@ -XXX,XX +XXX,XX @@ win32_re = re.compile(r"\r")
23
+ args = qemu_io_args + list(args)
65
def filter_win32(msg):
24
+ exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
66
return win32_re.sub("", msg)
25
+ if exitcode < 0:
67
26
+ sys.stderr.write('qemu-io received signal %i: %s\n' %
68
-qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* \([0-9\/.inf]* [EPTGMKiBbytes]*\/sec and [0-9\/.inf]* ops\/sec\)")
27
+ (-exitcode, ' '.join(args)))
69
+qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* "
28
+ return exitcode
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).
29
+
165
+
30
166
+ :return: QEMU's stdout output.
31
class QemuIoInteractive:
167
+ """
32
def __init__(self, *args):
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
33
--
197
--
34
2.17.1
198
2.26.2
35
199
36
200
diff view generated by jsdifflib
1
This adds a test case to 122 for what happens when you convert to a
1
From: John Snow <jsnow@redhat.com>
2
target with a backing file that is shorter than the target, and the
3
image format does not support efficient zero writes (as is the case with
4
qcow2 v2).
5
2
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Minor cleanup for HMP functions; helps with line length and consolidates
7
Message-id: 20180501165750.19242-3-mreitz@redhat.com
4
HMP helpers through one implementation function.
8
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
28
---
11
tests/qemu-iotests/122 | 42 ++++++++++++++++++++++++++++++++++++++
29
tests/qemu-iotests/iotests.py | 39 +++++++++++++++++++++--------------
12
tests/qemu-iotests/122.out | 18 ++++++++++++++++
30
1 file changed, 24 insertions(+), 15 deletions(-)
13
2 files changed, 60 insertions(+)
14
31
15
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
32
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100755
33
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/122
34
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/122
35
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig
36
@@ -XXX,XX +XXX,XX @@ from qemu import qtest
20
$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir
37
21
38
assert sys.version_info >= (3, 6)
22
39
23
+echo
40
+# Type Aliases
24
+echo "=== Converting to an overlay larger than its backing file ==="
41
+QMPResponse = Dict[str, Any]
25
+echo
26
+
27
+TEST_IMG="$TEST_IMG".base _make_test_img 256M
28
+# Needs to be at least how much an L2 table covers
29
+# (64 kB/entry * 64 kB / 8 B/entry = 512 MB)
30
+# That way, qcow2 will yield at least two status request responses.
31
+# With just a single response, it would always say "Allocated in the
32
+# backing file", so the optimization qemu-img convert tries to do is
33
+# done automatically. Once it has to be queried twice, however (and
34
+# one of the queries is completely after the end of the backing file),
35
+# the block layer will automatically add a ZERO flag that qemu-img
36
+# convert used to follow up with a zero write to the target.
37
+# We do not want such a zero write, however, because we are past the
38
+# end of the backing file on the target as well, so we do not need to
39
+# write anything there.
40
+_make_test_img -b "$TEST_IMG".base 768M
41
+
42
+# Use compat=0.10 as the output so there is no zero cluster support
43
+$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \
44
+ "$TEST_IMG" "$TEST_IMG".orig
45
+# See that nothing has been allocated past 64M
46
+$QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map
47
+
48
+echo
49
+
50
+# Just before the end of the backing file
51
+$QEMU_IO -c 'write -P 0x11 255M 1M' "$TEST_IMG".base 2>&1 | _filter_qemu_io
52
+# Somewhere in the second L2 table
53
+$QEMU_IO -c 'write -P 0x22 600M 1M' "$TEST_IMG" 2>&1 | _filter_qemu_io
54
+
55
+$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \
56
+ "$TEST_IMG" "$TEST_IMG".orig
57
+
58
+$QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map
59
+$QEMU_IO -c 'read -P 0x11 255M 1M' \
60
+ -c 'read -P 0x22 600M 1M' \
61
+ "$TEST_IMG".orig \
62
+ | _filter_qemu_io
63
+
42
+
64
+
43
+
65
echo
44
faulthandler.enable()
66
echo "=== Concatenate multiple source images ==="
45
67
echo
46
# This will not work if arguments contain spaces but is necessary if we
68
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
47
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
69
index XXXXXXX..XXXXXXX 100644
48
self._args.append(addr)
70
--- a/tests/qemu-iotests/122.out
49
return self
71
+++ b/tests/qemu-iotests/122.out
50
72
@@ -XXX,XX +XXX,XX @@ read 3145728/3145728 bytes at offset 0
51
- def pause_drive(self, drive, event=None):
73
read 3145728/3145728 bytes at offset 0
52
- '''Pause drive r/w operations'''
74
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
+ def hmp(self, command_line: str, use_log: bool = False) -> QMPResponse:
75
54
+ cmd = 'human-monitor-command'
76
+=== Converting to an overlay larger than its backing file ===
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)
77
+
60
+
78
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=268435456
61
+ def pause_drive(self, drive: str, event: Optional[str] = None) -> None:
79
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=805306368 backing_file=TEST_DIR/t.IMGFMT.base
62
+ """Pause drive r/w operations"""
80
+Offset Length File
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
+
81
+
82
+wrote 1048576/1048576 bytes at offset 267386880
82
+ def resume_drive(self, drive: str) -> None:
83
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
83
+ """Resume drive r/w operations"""
84
+wrote 1048576/1048576 bytes at offset 629145600
84
+ self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
85
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
+Offset Length File
87
+0xff00000 0x100000 TEST_DIR/t.IMGFMT.base
88
+0x25800000 0x100000 TEST_DIR/t.IMGFMT.orig
89
+read 1048576/1048576 bytes at offset 267386880
90
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
91
+read 1048576/1048576 bytes at offset 629145600
92
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
93
+
85
+
94
=== Concatenate multiple source images ===
86
+ def hmp_qemu_io(self, drive: str, cmd: str,
95
87
+ use_log: bool = False) -> QMPResponse:
96
Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=4194304
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:
97
--
93
--
98
2.17.1
94
2.26.2
99
95
100
96
diff view generated by jsdifflib
1
As a showcase of how you can use qemu-io's exit code to determine
1
From: John Snow <jsnow@redhat.com>
2
success or failure (same for qemu-img), this test is changed to use
3
qemu_io_silent() instead of qemu_io(), and to assert the exit code
4
instead of logging the filtered result.
5
2
6
One real advantage of this is that in case of an error, you get a
3
Like script_main, but doesn't require a single point of entry.
7
backtrace that helps you locate the issue in the test file quickly.
4
Replace all existing initialization sections with this drop-in replacement.
8
5
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
This brings debug support to all existing script-style iotests.
10
Reviewed-by: Eric Blake <eblake@redhat.com>
7
11
Message-id: 20180509194302.21585-6-mreitz@redhat.com
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]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
---
14
tests/qemu-iotests/216 | 23 ++++++++++++-----------
15
tests/qemu-iotests/149 | 3 +-
15
tests/qemu-iotests/216.out | 17 ++---------------
16
tests/qemu-iotests/194 | 4 +-
16
2 files changed, 14 insertions(+), 26 deletions(-)
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(-)
17
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:
18
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
238
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
19
index XXXXXXX..XXXXXXX 100755
239
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/216
240
--- a/tests/qemu-iotests/216
21
+++ b/tests/qemu-iotests/216
241
+++ b/tests/qemu-iotests/216
22
@@ -XXX,XX +XXX,XX @@
242
@@ -XXX,XX +XXX,XX @@ import iotests
23
# Creator/Owner: Max Reitz <mreitz@redhat.com>
243
from iotests import log, qemu_img, qemu_io_silent
24
25
import iotests
26
-from iotests import log, qemu_img_pipe, qemu_io, filter_qemu_io
27
+from iotests import log, qemu_img, qemu_io_silent
28
244
29
# Need backing file support
245
# Need backing file support
30
iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
246
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
31
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
247
-iotests.verify_platform(['linux'])
32
log('--- Setting up images ---')
248
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
33
log('')
249
+ supported_platforms=['linux'])
34
250
35
- qemu_img_pipe('create', '-f', iotests.imgfmt, base_img_path, '64M')
251
log('')
36
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
252
log('=== Copy-on-read across nodes ===')
37
+ assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
253
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
38
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
254
index XXXXXXX..XXXXXXX 100755
39
+ top_img_path) == 0
255
--- a/tests/qemu-iotests/218
40
+ assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
256
+++ b/tests/qemu-iotests/218
41
257
@@ -XXX,XX +XXX,XX @@
42
- log(filter_qemu_io(qemu_io(base_img_path, '-c', 'write -P 1 0M 1M')))
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'])
43
-
362
-
44
- qemu_img_pipe('create', '-f', iotests.imgfmt, '-b', base_img_path,
363
disk = file_path('disk')
45
- top_img_path)
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'])
46
-
493
-
47
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'write -P 2 1M 1M')))
494
+iotests.script_initialize(
48
+ log('Done')
495
+ supported_fmts=['qcow2', 'qed'],
49
496
+ supported_platforms=['linux'],
50
log('')
497
+)
51
log('--- Doing COR ---')
498
52
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
499
# Returns a node for blockdev-add
53
log('--- Checking COR result ---')
500
def node(node_name, path, backing=None, fmt=None, throttle=None):
54
log('')
501
diff --git a/tests/qemu-iotests/260 b/tests/qemu-iotests/260
55
502
index XXXXXXX..XXXXXXX 100755
56
- log(filter_qemu_io(qemu_io(base_img_path, '-c', 'discard 0 64M')))
503
--- a/tests/qemu-iotests/260
57
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 1 0M 1M')))
504
+++ b/tests/qemu-iotests/260
58
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 2 1M 1M')))
505
@@ -XXX,XX +XXX,XX @@
59
+ assert qemu_io_silent(base_img_path, '-c', 'discard 0 64M') == 0
506
import iotests
60
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 1 0M 1M') == 0
507
from iotests import qemu_img_create, file_path, log, filter_qmp_event
61
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
508
62
+
509
-iotests.verify_image_format(supported_fmts=['qcow2'])
63
+ log('Done')
510
+iotests.script_initialize(
64
diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out
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
65
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
66
--- a/tests/qemu-iotests/216.out
595
--- a/tests/qemu-iotests/283
67
+++ b/tests/qemu-iotests/216.out
596
+++ b/tests/qemu-iotests/283
68
@@ -XXX,XX +XXX,XX @@
597
@@ -XXX,XX +XXX,XX @@
69
598
import iotests
70
--- Setting up images ---
599
71
600
# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
72
-wrote 1048576/1048576 bytes at offset 0
601
-iotests.verify_image_format(supported_fmts=['qcow2'])
73
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
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()
74
-
716
-
75
-wrote 1048576/1048576 bytes at offset 1048576
717
logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
76
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
718
77
-
719
+ return debug
78
+Done
720
+
79
721
+def execute_test(*args, test_function=None, **kwargs):
80
--- Doing COR ---
722
+ """Run either unittest or script-style tests."""
81
723
+
82
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 1048576
724
+ debug = execute_setup_common(*args, **kwargs)
83
725
if not test_function:
84
--- Checking COR result ---
726
- execute_unittest(output, verbosity, debug)
85
727
+ execute_unittest(debug)
86
-discard 67108864/67108864 bytes at offset 0
728
else:
87
-64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
729
test_function()
88
-
730
89
-read 1048576/1048576 bytes at offset 0
731
+# This is called from script-style iotests without a single point of entry
90
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
732
+def script_initialize(*args, **kwargs):
91
-
733
+ """Initialize script-style tests without running any tests."""
92
-read 1048576/1048576 bytes at offset 1048576
734
+ execute_setup_common(*args, **kwargs)
93
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
735
+
94
-
736
+# This is called from script-style iotests with a single point of entry
95
+Done
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)
96
--
747
--
97
2.17.1
748
2.26.2
98
749
99
750
diff view generated by jsdifflib
1
Currently, rebase interprets a relative path for the new backing image
1
From: John Snow <jsnow@redhat.com>
2
as follows:
3
(1) Open the new backing image with the given relative path (thus relative to
4
qemu-img's working directory).
5
(2) Write it directly into the overlay's backing path field (thus
6
relative to the overlay).
7
2
8
If the overlay is not in qemu-img's working directory, both will be
3
Since this one is nicely factored to use a single entry point,
9
different interpretations, which may either lead to an error somewhere
4
use script_main to run the tests.
10
(either rebase fails because it cannot open the new backing image, or
11
your overlay becomes unusable because its backing path does not point to
12
a file), or, even worse, it may result in your rebase being performed
13
for a different backing file than what your overlay will point to after
14
the rebase.
15
5
16
Fix this by interpreting the target backing path as relative to the
6
Signed-off-by: John Snow <jsnow@redhat.com>
17
overlay, like qemu-img does everywhere else.
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1569835
9
Message-Id: <20200331000014.11581-13-jsnow@redhat.com>
20
Cc: qemu-stable@nongnu.org
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Message-id: 20180509182002.8044-2-mreitz@redhat.com
23
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
12
---
26
qemu-img.c | 23 ++++++++++++++++++++++-
13
tests/qemu-iotests/258 | 11 ++++-------
27
1 file changed, 22 insertions(+), 1 deletion(-)
14
1 file changed, 4 insertions(+), 7 deletions(-)
28
15
29
diff --git a/qemu-img.c b/qemu-img.c
16
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100755
31
--- a/qemu-img.c
18
--- a/tests/qemu-iotests/258
32
+++ b/qemu-img.c
19
+++ b/tests/qemu-iotests/258
33
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
20
@@ -XXX,XX +XXX,XX @@ import iotests
34
}
21
from iotests import log, qemu_img, qemu_io_silent, \
35
22
filter_qmp_testfiles, filter_qmp_imgfmt
36
if (out_baseimg[0]) {
23
37
+ const char *overlay_filename;
24
-# Need backing file and change-backing-file support
38
+ char *out_real_path;
25
-iotests.script_initialize(
39
+
26
- supported_fmts=['qcow2', 'qed'],
40
options = qdict_new();
27
- supported_platforms=['linux'],
41
if (out_basefmt) {
28
-)
42
qdict_put_str(options, "driver", out_basefmt);
29
-
43
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
30
# Returns a node for blockdev-add
44
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
31
def node(node_name, path, backing=None, fmt=None, throttle=None):
45
}
32
if fmt is None:
46
33
@@ -XXX,XX +XXX,XX @@ def main():
47
- blk_new_backing = blk_new_open(out_baseimg, NULL,
34
test_concurrent_finish(False)
48
+ overlay_filename = bs->exact_filename[0] ? bs->exact_filename
35
49
+ : bs->filename;
36
if __name__ == '__main__':
50
+ out_real_path = g_malloc(PATH_MAX);
37
- main()
51
+
38
+ # Need backing file and change-backing-file support
52
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
39
+ iotests.script_main(main,
53
+ out_baseimg,
40
+ supported_fmts=['qcow2', 'qed'],
54
+ out_real_path,
41
+ supported_platforms=['linux'])
55
+ PATH_MAX,
56
+ &local_err);
57
+ if (local_err) {
58
+ error_reportf_err(local_err,
59
+ "Could not resolve backing filename: ");
60
+ ret = -1;
61
+ g_free(out_real_path);
62
+ goto out;
63
+ }
64
+
65
+ blk_new_backing = blk_new_open(out_real_path, NULL,
66
options, src_flags, &local_err);
67
+ g_free(out_real_path);
68
if (!blk_new_backing) {
69
error_reportf_err(local_err,
70
"Could not open new backing file '%s': ",
71
--
42
--
72
2.17.1
43
2.26.2
73
44
74
45
diff view generated by jsdifflib
1
Currently, qemu-io basically always returns success when it gets to
1
From: John Snow <jsnow@redhat.com>
2
interactive mode (so once the whole command line has been parsed; even
3
before the commands on the command line are interpreted). That is not
4
very useful.
5
2
6
This patch makes qemu-io return failure when any of the executed
3
Mark the verify functions as "private" with a leading underscore, to
7
commands failed.
4
discourage their use. Update type signatures while we're here.
8
5
9
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1519617
6
(Also, make pending patches not yet using the new entry points fail in a
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
very obvious way.)
11
Reviewed-by: Eric Blake <eblake@redhat.com>
8
12
Message-id: 20180509194302.21585-4-mreitz@redhat.com
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>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
14
---
15
qemu-io.c | 28 ++++++++++++++++++++++------
15
tests/qemu-iotests/iotests.py | 23 +++++++++++++----------
16
1 file changed, 22 insertions(+), 6 deletions(-)
16
1 file changed, 13 insertions(+), 10 deletions(-)
17
17
18
diff --git a/qemu-io.c b/qemu-io.c
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qemu-io.c
20
--- a/tests/qemu-iotests/iotests.py
21
+++ b/qemu-io.c
21
+++ b/tests/qemu-iotests/iotests.py
22
@@ -XXX,XX +XXX,XX @@ static void prep_fetchline(void *opaque)
22
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
23
*fetchable= 1;
23
open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
24
}
24
' [case not run] ' + reason + '\n')
25
25
26
-static void command_loop(void)
26
-def verify_image_format(supported_fmts=(), unsupported_fmts=()):
27
+static int command_loop(void)
27
+def _verify_image_format(supported_fmts: Sequence[str] = (),
28
{
28
+ unsupported_fmts: Sequence[str] = ()) -> None:
29
int i, fetchable = 0, prompted = 0;
29
assert not (supported_fmts and unsupported_fmts)
30
+ int ret, last_error = 0;
30
31
char *input;
31
if 'generic' in supported_fmts and \
32
32
@@ -XXX,XX +XXX,XX @@ def verify_image_format(supported_fmts=(), unsupported_fmts=()):
33
for (i = 0; !quit_qemu_io && i < ncmdline; i++) {
33
if not_sup or (imgfmt in unsupported_fmts):
34
- qemuio_command(qemuio_blk, cmdline[i]);
34
notrun('not suitable for this image format: %s' % imgfmt)
35
+ ret = qemuio_command(qemuio_blk, cmdline[i]);
35
36
+ if (ret < 0) {
36
-def verify_protocol(supported=(), unsupported=()):
37
+ last_error = ret;
37
+def _verify_protocol(supported: Sequence[str] = (),
38
+ }
38
+ unsupported: Sequence[str] = ()) -> None:
39
}
39
assert not (supported and unsupported)
40
if (cmdline) {
40
41
g_free(cmdline);
41
if 'generic' in supported:
42
- return;
42
@@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=(), unsupported=()):
43
+ return last_error;
43
if not_sup or (imgproto in unsupported):
44
}
44
notrun('not suitable for this protocol: %s' % imgproto)
45
45
46
while (!quit_qemu_io) {
46
-def verify_platform(supported=(), unsupported=()):
47
@@ -XXX,XX +XXX,XX @@ static void command_loop(void)
47
+def _verify_platform(supported: Sequence[str] = (),
48
if (input == NULL) {
48
+ unsupported: Sequence[str] = ()) -> None:
49
break;
49
if any((sys.platform.startswith(x) for x in unsupported)):
50
}
50
notrun('not suitable for this OS: %s' % sys.platform)
51
- qemuio_command(qemuio_blk, input);
51
52
+ ret = qemuio_command(qemuio_blk, input);
52
@@ -XXX,XX +XXX,XX @@ def verify_platform(supported=(), unsupported=()):
53
g_free(input);
53
if not any((sys.platform.startswith(x) for x in supported)):
54
54
notrun('not suitable for this OS: %s' % sys.platform)
55
+ if (ret < 0) {
55
56
+ last_error = ret;
56
-def verify_cache_mode(supported_cache_modes=()):
57
+ }
57
+def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
58
+
58
if supported_cache_modes and (cachemode not in supported_cache_modes):
59
prompted = 0;
59
notrun('not suitable for this cache mode: %s' % cachemode)
60
fetchable = 0;
60
61
}
61
-def verify_aio_mode(supported_aio_modes=()):
62
qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
62
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
63
+
63
if supported_aio_modes and (aiomode not in supported_aio_modes):
64
+ return last_error;
64
notrun('not suitable for this aio mode: %s' % aiomode)
65
}
65
66
66
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
67
static void add_user_command(char *optarg)
67
sys.stderr.write('Please run this test via the "check" script\n')
68
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
68
sys.exit(os.EX_USAGE)
69
int c;
69
70
int opt_index = 0;
70
- verify_image_format(supported_fmts, unsupported_fmts)
71
int flags = BDRV_O_UNMAP;
71
- verify_protocol(supported_protocols, unsupported_protocols)
72
+ int ret;
72
- verify_platform(supported=supported_platforms)
73
bool writethrough = true;
73
- verify_cache_mode(supported_cache_modes)
74
Error *local_error = NULL;
74
- verify_aio_mode(supported_aio_modes)
75
QDict *opts = NULL;
75
+ _verify_image_format(supported_fmts, unsupported_fmts)
76
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
76
+ _verify_protocol(supported_protocols, unsupported_protocols)
77
}
77
+ _verify_platform(supported=supported_platforms)
78
}
78
+ _verify_cache_mode(supported_cache_modes)
79
}
79
+ _verify_aio_mode(supported_aio_modes)
80
- command_loop();
80
81
+ ret = command_loop();
81
debug = '-d' in sys.argv
82
82
if debug:
83
/*
84
* Make sure all outstanding requests complete before the program exits.
85
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
86
87
blk_unref(qemuio_blk);
88
g_free(readline_state);
89
- return 0;
90
+
91
+ if (ret < 0) {
92
+ return 1;
93
+ } else {
94
+ return 0;
95
+ }
96
}
97
--
83
--
98
2.17.1
84
2.26.2
99
85
100
86
diff view generated by jsdifflib
1
This is basically what everything else in the qemu code base does, so we
1
From: John Snow <jsnow@redhat.com>
2
can do it here, too.
2
3
3
We can turn logging on/off globally instead of per-function.
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Remove use_log from run_job, and use python logging to turn on
6
Message-id: 20180509194302.21585-3-mreitz@redhat.com
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>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
43
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
44
---
9
include/qemu-io.h | 9 +-
45
tests/qemu-iotests/030 | 4 +--
10
qemu-io-cmds.c | 346 +++++++++++++++++++++++++++-------------------
46
tests/qemu-iotests/155 | 2 +-
11
qemu-io.c | 34 +++--
47
tests/qemu-iotests/245 | 1 +
12
3 files changed, 232 insertions(+), 157 deletions(-)
48
tests/qemu-iotests/245.out | 10 +++----
13
49
tests/qemu-iotests/iotests.py | 53 ++++++++++++++++++++---------------
14
diff --git a/include/qemu-io.h b/include/qemu-io.h
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
15
index XXXXXXX..XXXXXXX 100644
92
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu-io.h
93
--- a/tests/qemu-iotests/245.out
17
+++ b/include/qemu-io.h
94
+++ b/tests/qemu-iotests/245.out
18
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
19
96
-.....................
20
#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
97
-----------------------------------------------------------------------
21
98
-Ran 21 tests
22
-typedef void (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
99
-
23
+/* Implement a qemu-io command.
100
-OK
24
+ * Operate on @blk using @argc/@argv as the command's arguments, and
101
{"execute": "job-finalize", "arguments": {"id": "commit0"}}
25
+ * return 0 on success or negative errno on failure.
102
{"return": {}}
26
+ */
103
{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
27
+typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
104
@@ -XXX,XX +XXX,XX @@ OK
28
+
105
{"return": {}}
29
typedef void (*helpfunc_t)(void);
106
{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
30
107
{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
31
typedef struct cmdinfo {
108
+.....................
32
@@ -XXX,XX +XXX,XX @@ typedef struct cmdinfo {
109
+----------------------------------------------------------------------
33
110
+Ran 21 tests
34
extern bool qemuio_misalign;
111
+
35
112
+OK
36
-void qemuio_command(BlockBackend *blk, const char *cmd);
113
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
37
+int qemuio_command(BlockBackend *blk, const char *cmd);
38
39
void qemuio_add_command(const cmdinfo_t *ci);
40
void qemuio_command_usage(const cmdinfo_t *ci);
41
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
42
index XXXXXXX..XXXXXXX 100644
114
index XXXXXXX..XXXXXXX 100644
43
--- a/qemu-io-cmds.c
115
--- a/tests/qemu-iotests/iotests.py
44
+++ b/qemu-io-cmds.c
116
+++ b/tests/qemu-iotests/iotests.py
45
@@ -XXX,XX +XXX,XX @@ static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
117
@@ -XXX,XX +XXX,XX @@ assert sys.version_info >= (3, 6)
46
return 1;
118
QMPResponse = Dict[str, Any]
47
}
119
48
120
49
-static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
121
+# Use this logger for logging messages directly from the iotests module
50
- char **argv)
122
+logger = logging.getLogger('qemu.iotests')
51
+static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
123
+logger.addHandler(logging.NullHandler())
52
+ char **argv)
124
+
53
{
125
+# Use this logger for messages that ought to be used for diff output.
54
char *cmd = argv[0];
126
+test_logger = logging.getLogger('qemu.iotests.diff_io')
55
127
+
56
if (!init_check_command(blk, ct)) {
128
+
57
- return;
129
faulthandler.enable()
58
+ return -EINVAL;
130
59
}
131
# This will not work if arguments contain spaces but is necessary if we
60
132
@@ -XXX,XX +XXX,XX @@ def log(msg: Msg,
61
if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
133
if isinstance(msg, (dict, list)):
62
@@ -XXX,XX +XXX,XX @@ static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
134
# Don't sort if it's already sorted
63
"bad argument count %d to %s, expected between %d and %d arguments\n",
135
do_sort = not isinstance(msg, OrderedDict)
64
argc-1, cmd, ct->argmin, ct->argmax);
136
- print(json.dumps(msg, sort_keys=do_sort, indent=indent))
65
}
137
+ test_logger.info(json.dumps(msg, sort_keys=do_sort, indent=indent))
66
- return;
138
else:
67
+ return -EINVAL;
139
- print(msg)
68
}
140
+ test_logger.info(msg)
69
141
70
/* Request additional permissions if necessary for this command. The caller
142
class Timeout:
71
@@ -XXX,XX +XXX,XX @@ static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
143
def __init__(self, seconds, errmsg="Timeout"):
72
ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
144
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
73
if (ret < 0) {
145
74
error_report_err(local_err);
146
# Returns None on success, and an error string on failure
75
- return;
147
def run_job(self, job, auto_finalize=True, auto_dismiss=False,
76
+ return ret;
148
- pre_finalize=None, cancel=False, use_log=True, wait=60.0):
77
}
149
+ pre_finalize=None, cancel=False, wait=60.0):
78
}
150
"""
79
}
151
run_job moves a job from creation through to dismissal.
80
152
81
optind = 0;
153
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
82
- ct->cfunc(blk, argc, argv);
154
invoked prior to issuing job-finalize, if any.
83
+ return ct->cfunc(blk, argc, argv);
155
:param cancel: Bool. When true, cancels the job after the pre_finalize
84
}
156
callback.
85
157
- :param use_log: Bool. When false, does not log QMP messages.
86
static const cmdinfo_t *find_command(const char *cmd)
158
:param wait: Float. Timeout value specifying how long to wait for any
87
@@ -XXX,XX +XXX,XX @@ static void read_help(void)
159
event, in seconds. Defaults to 60.0.
88
"\n");
160
"""
89
}
161
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
90
162
while True:
91
-static void read_f(BlockBackend *blk, int argc, char **argv);
163
ev = filter_qmp_event(self.events_wait(events, timeout=wait))
92
+static int read_f(BlockBackend *blk, int argc, char **argv);
164
if ev['event'] != 'JOB_STATUS_CHANGE':
93
165
- if use_log:
94
static const cmdinfo_t read_cmd = {
166
- log(ev)
95
.name = "read",
167
+ log(ev)
96
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t read_cmd = {
168
continue
97
.help = read_help,
169
status = ev['data']['status']
98
};
170
if status == 'aborting':
99
171
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
100
-static void read_f(BlockBackend *blk, int argc, char **argv)
172
for j in result['return']:
101
+static int read_f(BlockBackend *blk, int argc, char **argv)
173
if j['id'] == job:
102
{
174
error = j['error']
103
struct timeval t1, t2;
175
- if use_log:
104
bool Cflag = false, qflag = false, vflag = false;
176
- log('Job failed: %s' % (j['error']))
105
bool Pflag = false, sflag = false, lflag = false, bflag = false;
177
+ log('Job failed: %s' % (j['error']))
106
- int c, cnt;
178
elif status == 'ready':
107
+ int c, cnt, ret;
179
- if use_log:
108
char *buf;
180
- self.qmp_log('job-complete', id=job)
109
int64_t offset;
181
- else:
110
int64_t count;
182
- self.qmp('job-complete', id=job)
111
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
183
+ self.qmp_log('job-complete', id=job)
112
pattern_count = cvtnum(optarg);
184
elif status == 'pending' and not auto_finalize:
113
if (pattern_count < 0) {
185
if pre_finalize:
114
print_cvtnum_err(pattern_count, optarg);
186
pre_finalize()
115
- return;
187
- if cancel and use_log:
116
+ return pattern_count;
188
+ if cancel:
117
}
189
self.qmp_log('job-cancel', id=job)
118
break;
190
- elif cancel:
119
case 'p':
191
- self.qmp('job-cancel', id=job)
120
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
192
- elif use_log:
121
Pflag = true;
193
- self.qmp_log('job-finalize', id=job)
122
pattern = parse_pattern(optarg);
194
else:
123
if (pattern < 0) {
195
- self.qmp('job-finalize', id=job)
124
- return;
196
+ self.qmp_log('job-finalize', id=job)
125
+ return -EINVAL;
197
elif status == 'concluded' and not auto_dismiss:
126
}
198
- if use_log:
127
break;
199
- self.qmp_log('job-dismiss', id=job)
128
case 'q':
200
- else:
129
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
201
- self.qmp('job-dismiss', id=job)
130
pattern_offset = cvtnum(optarg);
202
+ self.qmp_log('job-dismiss', id=job)
131
if (pattern_offset < 0) {
203
elif status == 'null':
132
print_cvtnum_err(pattern_offset, optarg);
204
return error
133
- return;
205
134
+ return pattern_offset;
206
@@ -XXX,XX +XXX,XX @@ def notrun(reason):
135
}
207
seq = os.path.basename(sys.argv[0])
136
break;
208
137
case 'v':
209
open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
138
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
210
- print('%s not run: %s' % (seq, reason))
139
break;
211
+ logger.warning("%s not run: %s", seq, reason)
140
default:
212
sys.exit(0)
141
qemuio_command_usage(&read_cmd);
213
142
- return;
214
def case_notrun(reason):
143
+ return -EINVAL;
215
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
144
}
216
if debug:
145
}
217
sys.argv.remove('-d')
146
218
logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
147
if (optind != argc - 2) {
219
+ logger.debug("iotests debugging messages active")
148
qemuio_command_usage(&read_cmd);
220
149
- return;
221
return debug
150
+ return -EINVAL;
222
151
}
223
@@ -XXX,XX +XXX,XX @@ def execute_test(*args, test_function=None, **kwargs):
152
224
else:
153
offset = cvtnum(argv[optind]);
225
test_function()
154
if (offset < 0) {
226
155
print_cvtnum_err(offset, argv[optind]);
227
+def activate_logging():
156
- return;
228
+ """Activate iotests.log() output to stdout for script-style tests."""
157
+ return offset;
229
+ handler = logging.StreamHandler(stream=sys.stdout)
158
}
230
+ formatter = logging.Formatter('%(message)s')
159
231
+ handler.setFormatter(formatter)
160
optind++;
232
+ test_logger.addHandler(handler)
161
count = cvtnum(argv[optind]);
233
+ test_logger.setLevel(logging.INFO)
162
if (count < 0) {
234
+ test_logger.propagate = False
163
print_cvtnum_err(count, argv[optind]);
235
+
164
- return;
236
# This is called from script-style iotests without a single point of entry
165
+ return count;
237
def script_initialize(*args, **kwargs):
166
} else if (count > BDRV_REQUEST_MAX_BYTES) {
238
"""Initialize script-style tests without running any tests."""
167
printf("length cannot exceed %" PRIu64 ", given %s\n",
239
+ activate_logging()
168
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
240
execute_setup_common(*args, **kwargs)
169
- return;
241
170
+ return -EINVAL;
242
# This is called from script-style iotests with a single point of entry
171
}
243
def script_main(test_function, *args, **kwargs):
172
244
"""Run script-style tests outside of the unittest framework"""
173
if (!Pflag && (lflag || sflag)) {
245
+ activate_logging()
174
qemuio_command_usage(&read_cmd);
246
execute_test(*args, test_function=test_function, **kwargs)
175
- return;
247
176
+ return -EINVAL;
248
# This is called from unittest style iotests
177
}
178
179
if (!lflag) {
180
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
181
182
if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
183
printf("pattern verification range exceeds end of read data\n");
184
- return;
185
+ return -EINVAL;
186
}
187
188
if (bflag) {
189
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
190
printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
191
offset);
192
- return;
193
+ return -EINVAL;
194
}
195
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
196
printf("%"PRId64" is not a sector-aligned value for 'count'\n",
197
count);
198
- return;
199
+ return -EINVAL;
200
}
201
}
202
203
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
204
205
gettimeofday(&t1, NULL);
206
if (bflag) {
207
- cnt = do_load_vmstate(blk, buf, offset, count, &total);
208
+ ret = do_load_vmstate(blk, buf, offset, count, &total);
209
} else {
210
- cnt = do_pread(blk, buf, offset, count, &total);
211
+ ret = do_pread(blk, buf, offset, count, &total);
212
}
213
gettimeofday(&t2, NULL);
214
215
- if (cnt < 0) {
216
- printf("read failed: %s\n", strerror(-cnt));
217
+ if (ret < 0) {
218
+ printf("read failed: %s\n", strerror(-ret));
219
goto out;
220
}
221
+ cnt = ret;
222
+
223
+ ret = 0;
224
225
if (Pflag) {
226
void *cmp_buf = g_malloc(pattern_count);
227
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
228
printf("Pattern verification failed at offset %"
229
PRId64 ", %"PRId64" bytes\n",
230
offset + pattern_offset, pattern_count);
231
+ ret = -EINVAL;
232
}
233
g_free(cmp_buf);
234
}
235
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
236
237
out:
238
qemu_io_free(buf);
239
+ return ret;
240
}
241
242
static void readv_help(void)
243
@@ -XXX,XX +XXX,XX @@ static void readv_help(void)
244
"\n");
245
}
246
247
-static void readv_f(BlockBackend *blk, int argc, char **argv);
248
+static int readv_f(BlockBackend *blk, int argc, char **argv);
249
250
static const cmdinfo_t readv_cmd = {
251
.name = "readv",
252
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t readv_cmd = {
253
.help = readv_help,
254
};
255
256
-static void readv_f(BlockBackend *blk, int argc, char **argv)
257
+static int readv_f(BlockBackend *blk, int argc, char **argv)
258
{
259
struct timeval t1, t2;
260
bool Cflag = false, qflag = false, vflag = false;
261
- int c, cnt;
262
+ int c, cnt, ret;
263
char *buf;
264
int64_t offset;
265
/* Some compilers get confused and warn if this is not initialized. */
266
@@ -XXX,XX +XXX,XX @@ static void readv_f(BlockBackend *blk, int argc, char **argv)
267
Pflag = true;
268
pattern = parse_pattern(optarg);
269
if (pattern < 0) {
270
- return;
271
+ return -EINVAL;
272
}
273
break;
274
case 'q':
275
@@ -XXX,XX +XXX,XX @@ static void readv_f(BlockBackend *blk, int argc, char **argv)
276
break;
277
default:
278
qemuio_command_usage(&readv_cmd);
279
- return;
280
+ return -EINVAL;
281
}
282
}
283
284
if (optind > argc - 2) {
285
qemuio_command_usage(&readv_cmd);
286
- return;
287
+ return -EINVAL;
288
}
289
290
291
offset = cvtnum(argv[optind]);
292
if (offset < 0) {
293
print_cvtnum_err(offset, argv[optind]);
294
- return;
295
+ return offset;
296
}
297
optind++;
298
299
nr_iov = argc - optind;
300
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
301
if (buf == NULL) {
302
- return;
303
+ return -EINVAL;
304
}
305
306
gettimeofday(&t1, NULL);
307
- cnt = do_aio_readv(blk, &qiov, offset, &total);
308
+ ret = do_aio_readv(blk, &qiov, offset, &total);
309
gettimeofday(&t2, NULL);
310
311
- if (cnt < 0) {
312
- printf("readv failed: %s\n", strerror(-cnt));
313
+ if (ret < 0) {
314
+ printf("readv failed: %s\n", strerror(-ret));
315
goto out;
316
}
317
+ cnt = ret;
318
+
319
+ ret = 0;
320
321
if (Pflag) {
322
void *cmp_buf = g_malloc(qiov.size);
323
@@ -XXX,XX +XXX,XX @@ static void readv_f(BlockBackend *blk, int argc, char **argv)
324
if (memcmp(buf, cmp_buf, qiov.size)) {
325
printf("Pattern verification failed at offset %"
326
PRId64 ", %zd bytes\n", offset, qiov.size);
327
+ ret = -EINVAL;
328
}
329
g_free(cmp_buf);
330
}
331
@@ -XXX,XX +XXX,XX @@ static void readv_f(BlockBackend *blk, int argc, char **argv)
332
out:
333
qemu_iovec_destroy(&qiov);
334
qemu_io_free(buf);
335
+ return ret;
336
}
337
338
static void write_help(void)
339
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
340
"\n");
341
}
342
343
-static void write_f(BlockBackend *blk, int argc, char **argv);
344
+static int write_f(BlockBackend *blk, int argc, char **argv);
345
346
static const cmdinfo_t write_cmd = {
347
.name = "write",
348
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = {
349
.help = write_help,
350
};
351
352
-static void write_f(BlockBackend *blk, int argc, char **argv)
353
+static int write_f(BlockBackend *blk, int argc, char **argv)
354
{
355
struct timeval t1, t2;
356
bool Cflag = false, qflag = false, bflag = false;
357
bool Pflag = false, zflag = false, cflag = false;
358
int flags = 0;
359
- int c, cnt;
360
+ int c, cnt, ret;
361
char *buf = NULL;
362
int64_t offset;
363
int64_t count;
364
@@ -XXX,XX +XXX,XX @@ static void write_f(BlockBackend *blk, int argc, char **argv)
365
Pflag = true;
366
pattern = parse_pattern(optarg);
367
if (pattern < 0) {
368
- return;
369
+ return -EINVAL;
370
}
371
break;
372
case 'q':
373
@@ -XXX,XX +XXX,XX @@ static void write_f(BlockBackend *blk, int argc, char **argv)
374
break;
375
default:
376
qemuio_command_usage(&write_cmd);
377
- return;
378
+ return -EINVAL;
379
}
380
}
381
382
if (optind != argc - 2) {
383
qemuio_command_usage(&write_cmd);
384
- return;
385
+ return -EINVAL;
386
}
387
388
if (bflag && zflag) {
389
printf("-b and -z cannot be specified at the same time\n");
390
- return;
391
+ return -EINVAL;
392
}
393
394
if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
395
printf("-f and -b or -c cannot be specified at the same time\n");
396
- return;
397
+ return -EINVAL;
398
}
399
400
if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
401
printf("-u requires -z to be specified\n");
402
- return;
403
+ return -EINVAL;
404
}
405
406
if (zflag && Pflag) {
407
printf("-z and -P cannot be specified at the same time\n");
408
- return;
409
+ return -EINVAL;
410
}
411
412
offset = cvtnum(argv[optind]);
413
if (offset < 0) {
414
print_cvtnum_err(offset, argv[optind]);
415
- return;
416
+ return offset;
417
}
418
419
optind++;
420
count = cvtnum(argv[optind]);
421
if (count < 0) {
422
print_cvtnum_err(count, argv[optind]);
423
- return;
424
+ return count;
425
} else if (count > BDRV_REQUEST_MAX_BYTES) {
426
printf("length cannot exceed %" PRIu64 ", given %s\n",
427
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
428
- return;
429
+ return -EINVAL;
430
}
431
432
if (bflag || cflag) {
433
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
434
printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
435
offset);
436
- return;
437
+ return -EINVAL;
438
}
439
440
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
441
printf("%"PRId64" is not a sector-aligned value for 'count'\n",
442
count);
443
- return;
444
+ return -EINVAL;
445
}
446
}
447
448
@@ -XXX,XX +XXX,XX @@ static void write_f(BlockBackend *blk, int argc, char **argv)
449
450
gettimeofday(&t1, NULL);
451
if (bflag) {
452
- cnt = do_save_vmstate(blk, buf, offset, count, &total);
453
+ ret = do_save_vmstate(blk, buf, offset, count, &total);
454
} else if (zflag) {
455
- cnt = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
456
+ ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
457
} else if (cflag) {
458
- cnt = do_write_compressed(blk, buf, offset, count, &total);
459
+ ret = do_write_compressed(blk, buf, offset, count, &total);
460
} else {
461
- cnt = do_pwrite(blk, buf, offset, count, flags, &total);
462
+ ret = do_pwrite(blk, buf, offset, count, flags, &total);
463
}
464
gettimeofday(&t2, NULL);
465
466
- if (cnt < 0) {
467
- printf("write failed: %s\n", strerror(-cnt));
468
+ if (ret < 0) {
469
+ printf("write failed: %s\n", strerror(-ret));
470
goto out;
471
}
472
+ cnt = ret;
473
+
474
+ ret = 0;
475
476
if (qflag) {
477
goto out;
478
@@ -XXX,XX +XXX,XX @@ out:
479
if (!zflag) {
480
qemu_io_free(buf);
481
}
482
+ return ret;
483
}
484
485
static void
486
@@ -XXX,XX +XXX,XX @@ writev_help(void)
487
"\n");
488
}
489
490
-static void writev_f(BlockBackend *blk, int argc, char **argv);
491
+static int writev_f(BlockBackend *blk, int argc, char **argv);
492
493
static const cmdinfo_t writev_cmd = {
494
.name = "writev",
495
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t writev_cmd = {
496
.help = writev_help,
497
};
498
499
-static void writev_f(BlockBackend *blk, int argc, char **argv)
500
+static int writev_f(BlockBackend *blk, int argc, char **argv)
501
{
502
struct timeval t1, t2;
503
bool Cflag = false, qflag = false;
504
int flags = 0;
505
- int c, cnt;
506
+ int c, cnt, ret;
507
char *buf;
508
int64_t offset;
509
/* Some compilers get confused and warn if this is not initialized. */
510
@@ -XXX,XX +XXX,XX @@ static void writev_f(BlockBackend *blk, int argc, char **argv)
511
case 'P':
512
pattern = parse_pattern(optarg);
513
if (pattern < 0) {
514
- return;
515
+ return -EINVAL;
516
}
517
break;
518
default:
519
qemuio_command_usage(&writev_cmd);
520
- return;
521
+ return -EINVAL;
522
}
523
}
524
525
if (optind > argc - 2) {
526
qemuio_command_usage(&writev_cmd);
527
- return;
528
+ return -EINVAL;
529
}
530
531
offset = cvtnum(argv[optind]);
532
if (offset < 0) {
533
print_cvtnum_err(offset, argv[optind]);
534
- return;
535
+ return offset;
536
}
537
optind++;
538
539
nr_iov = argc - optind;
540
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
541
if (buf == NULL) {
542
- return;
543
+ return -EINVAL;
544
}
545
546
gettimeofday(&t1, NULL);
547
- cnt = do_aio_writev(blk, &qiov, offset, flags, &total);
548
+ ret = do_aio_writev(blk, &qiov, offset, flags, &total);
549
gettimeofday(&t2, NULL);
550
551
- if (cnt < 0) {
552
- printf("writev failed: %s\n", strerror(-cnt));
553
+ if (ret < 0) {
554
+ printf("writev failed: %s\n", strerror(-ret));
555
goto out;
556
}
557
+ cnt = ret;
558
+
559
+ ret = 0;
560
561
if (qflag) {
562
goto out;
563
@@ -XXX,XX +XXX,XX @@ static void writev_f(BlockBackend *blk, int argc, char **argv)
564
out:
565
qemu_iovec_destroy(&qiov);
566
qemu_io_free(buf);
567
+ return ret;
568
}
569
570
struct aio_ctx {
571
@@ -XXX,XX +XXX,XX @@ static void aio_read_help(void)
572
" standard output stream (with -v option) for subsequent inspection.\n"
573
" The read is performed asynchronously and the aio_flush command must be\n"
574
" used to ensure all outstanding aio requests have been completed.\n"
575
+" Note that due to its asynchronous nature, this command will be\n"
576
+" considered successful once the request is submitted, independently\n"
577
+" of potential I/O errors or pattern mismatches.\n"
578
" -C, -- report statistics in a machine parsable format\n"
579
" -P, -- use a pattern to verify read data\n"
580
" -i, -- treat request as invalid, for exercising stats\n"
581
@@ -XXX,XX +XXX,XX @@ static void aio_read_help(void)
582
"\n");
583
}
584
585
-static void aio_read_f(BlockBackend *blk, int argc, char **argv);
586
+static int aio_read_f(BlockBackend *blk, int argc, char **argv);
587
588
static const cmdinfo_t aio_read_cmd = {
589
.name = "aio_read",
590
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_read_cmd = {
591
.help = aio_read_help,
592
};
593
594
-static void aio_read_f(BlockBackend *blk, int argc, char **argv)
595
+static int aio_read_f(BlockBackend *blk, int argc, char **argv)
596
{
597
int nr_iov, c;
598
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
599
@@ -XXX,XX +XXX,XX @@ static void aio_read_f(BlockBackend *blk, int argc, char **argv)
600
ctx->pattern = parse_pattern(optarg);
601
if (ctx->pattern < 0) {
602
g_free(ctx);
603
- return;
604
+ return -EINVAL;
605
}
606
break;
607
case 'i':
608
printf("injecting invalid read request\n");
609
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
610
g_free(ctx);
611
- return;
612
+ return 0;
613
case 'q':
614
ctx->qflag = true;
615
break;
616
@@ -XXX,XX +XXX,XX @@ static void aio_read_f(BlockBackend *blk, int argc, char **argv)
617
default:
618
g_free(ctx);
619
qemuio_command_usage(&aio_read_cmd);
620
- return;
621
+ return -EINVAL;
622
}
623
}
624
625
if (optind > argc - 2) {
626
g_free(ctx);
627
qemuio_command_usage(&aio_read_cmd);
628
- return;
629
+ return -EINVAL;
630
}
631
632
ctx->offset = cvtnum(argv[optind]);
633
if (ctx->offset < 0) {
634
- print_cvtnum_err(ctx->offset, argv[optind]);
635
+ int ret = ctx->offset;
636
+ print_cvtnum_err(ret, argv[optind]);
637
g_free(ctx);
638
- return;
639
+ return ret;
640
}
641
optind++;
642
643
@@ -XXX,XX +XXX,XX @@ static void aio_read_f(BlockBackend *blk, int argc, char **argv)
644
if (ctx->buf == NULL) {
645
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
646
g_free(ctx);
647
- return;
648
+ return -EINVAL;
649
}
650
651
gettimeofday(&ctx->t1, NULL);
652
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
653
BLOCK_ACCT_READ);
654
blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
655
+ return 0;
656
}
657
658
static void aio_write_help(void)
659
@@ -XXX,XX +XXX,XX @@ static void aio_write_help(void)
660
" filled with a set pattern (0xcdcdcdcd).\n"
661
" The write is performed asynchronously and the aio_flush command must be\n"
662
" used to ensure all outstanding aio requests have been completed.\n"
663
+" Note that due to its asynchronous nature, this command will be\n"
664
+" considered successful once the request is submitted, independently\n"
665
+" of potential I/O errors or pattern mismatches.\n"
666
" -P, -- use different pattern to fill file\n"
667
" -C, -- report statistics in a machine parsable format\n"
668
" -f, -- use Force Unit Access semantics\n"
669
@@ -XXX,XX +XXX,XX @@ static void aio_write_help(void)
670
"\n");
671
}
672
673
-static void aio_write_f(BlockBackend *blk, int argc, char **argv);
674
+static int aio_write_f(BlockBackend *blk, int argc, char **argv);
675
676
static const cmdinfo_t aio_write_cmd = {
677
.name = "aio_write",
678
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_write_cmd = {
679
.help = aio_write_help,
680
};
681
682
-static void aio_write_f(BlockBackend *blk, int argc, char **argv)
683
+static int aio_write_f(BlockBackend *blk, int argc, char **argv)
684
{
685
int nr_iov, c;
686
int pattern = 0xcd;
687
@@ -XXX,XX +XXX,XX @@ static void aio_write_f(BlockBackend *blk, int argc, char **argv)
688
pattern = parse_pattern(optarg);
689
if (pattern < 0) {
690
g_free(ctx);
691
- return;
692
+ return -EINVAL;
693
}
694
break;
695
case 'i':
696
printf("injecting invalid write request\n");
697
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
698
g_free(ctx);
699
- return;
700
+ return 0;
701
case 'z':
702
ctx->zflag = true;
703
break;
704
default:
705
g_free(ctx);
706
qemuio_command_usage(&aio_write_cmd);
707
- return;
708
+ return -EINVAL;
709
}
710
}
711
712
if (optind > argc - 2) {
713
g_free(ctx);
714
qemuio_command_usage(&aio_write_cmd);
715
- return;
716
+ return -EINVAL;
717
}
718
719
if (ctx->zflag && optind != argc - 2) {
720
printf("-z supports only a single length parameter\n");
721
g_free(ctx);
722
- return;
723
+ return -EINVAL;
724
}
725
726
if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
727
printf("-u requires -z to be specified\n");
728
g_free(ctx);
729
- return;
730
+ return -EINVAL;
731
}
732
733
if (ctx->zflag && ctx->Pflag) {
734
printf("-z and -P cannot be specified at the same time\n");
735
g_free(ctx);
736
- return;
737
+ return -EINVAL;
738
}
739
740
ctx->offset = cvtnum(argv[optind]);
741
if (ctx->offset < 0) {
742
- print_cvtnum_err(ctx->offset, argv[optind]);
743
+ int ret = ctx->offset;
744
+ print_cvtnum_err(ret, argv[optind]);
745
g_free(ctx);
746
- return;
747
+ return ret;
748
}
749
optind++;
750
751
@@ -XXX,XX +XXX,XX @@ static void aio_write_f(BlockBackend *blk, int argc, char **argv)
752
if (count < 0) {
753
print_cvtnum_err(count, argv[optind]);
754
g_free(ctx);
755
- return;
756
+ return count;
757
}
758
759
ctx->qiov.size = count;
760
@@ -XXX,XX +XXX,XX @@ static void aio_write_f(BlockBackend *blk, int argc, char **argv)
761
if (ctx->buf == NULL) {
762
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
763
g_free(ctx);
764
- return;
765
+ return -EINVAL;
766
}
767
768
gettimeofday(&ctx->t1, NULL);
769
@@ -XXX,XX +XXX,XX @@ static void aio_write_f(BlockBackend *blk, int argc, char **argv)
770
blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
771
ctx);
772
}
773
+
774
+ return 0;
775
}
776
777
-static void aio_flush_f(BlockBackend *blk, int argc, char **argv)
778
+static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
779
{
780
BlockAcctCookie cookie;
781
block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
782
blk_drain_all();
783
block_acct_done(blk_get_stats(blk), &cookie);
784
+ return 0;
785
}
786
787
static const cmdinfo_t aio_flush_cmd = {
788
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_flush_cmd = {
789
.oneline = "completes all outstanding aio requests"
790
};
791
792
-static void flush_f(BlockBackend *blk, int argc, char **argv)
793
+static int flush_f(BlockBackend *blk, int argc, char **argv)
794
{
795
- blk_flush(blk);
796
+ return blk_flush(blk);
797
}
798
799
static const cmdinfo_t flush_cmd = {
800
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t flush_cmd = {
801
.oneline = "flush all in-core file state to disk",
802
};
803
804
-static void truncate_f(BlockBackend *blk, int argc, char **argv)
805
+static int truncate_f(BlockBackend *blk, int argc, char **argv)
806
{
807
Error *local_err = NULL;
808
int64_t offset;
809
@@ -XXX,XX +XXX,XX @@ static void truncate_f(BlockBackend *blk, int argc, char **argv)
810
offset = cvtnum(argv[1]);
811
if (offset < 0) {
812
print_cvtnum_err(offset, argv[1]);
813
- return;
814
+ return offset;
815
}
816
817
ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
818
if (ret < 0) {
819
error_report_err(local_err);
820
- return;
821
+ return ret;
822
}
823
+
824
+ return 0;
825
}
826
827
static const cmdinfo_t truncate_cmd = {
828
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t truncate_cmd = {
829
.oneline = "truncates the current file at the given offset",
830
};
831
832
-static void length_f(BlockBackend *blk, int argc, char **argv)
833
+static int length_f(BlockBackend *blk, int argc, char **argv)
834
{
835
int64_t size;
836
char s1[64];
837
@@ -XXX,XX +XXX,XX @@ static void length_f(BlockBackend *blk, int argc, char **argv)
838
size = blk_getlength(blk);
839
if (size < 0) {
840
printf("getlength: %s\n", strerror(-size));
841
- return;
842
+ return size;
843
}
844
845
cvtstr(size, s1, sizeof(s1));
846
printf("%s\n", s1);
847
+ return 0;
848
}
849
850
851
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t length_cmd = {
852
};
853
854
855
-static void info_f(BlockBackend *blk, int argc, char **argv)
856
+static int info_f(BlockBackend *blk, int argc, char **argv)
857
{
858
BlockDriverState *bs = blk_bs(blk);
859
BlockDriverInfo bdi;
860
@@ -XXX,XX +XXX,XX @@ static void info_f(BlockBackend *blk, int argc, char **argv)
861
862
ret = bdrv_get_info(bs, &bdi);
863
if (ret) {
864
- return;
865
+ return ret;
866
}
867
868
cvtstr(bdi.cluster_size, s1, sizeof(s1));
869
@@ -XXX,XX +XXX,XX @@ static void info_f(BlockBackend *blk, int argc, char **argv)
870
bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
871
qapi_free_ImageInfoSpecific(spec_info);
872
}
873
+
874
+ return 0;
875
}
876
877
878
@@ -XXX,XX +XXX,XX @@ static void discard_help(void)
879
"\n");
880
}
881
882
-static void discard_f(BlockBackend *blk, int argc, char **argv);
883
+static int discard_f(BlockBackend *blk, int argc, char **argv);
884
885
static const cmdinfo_t discard_cmd = {
886
.name = "discard",
887
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t discard_cmd = {
888
.help = discard_help,
889
};
890
891
-static void discard_f(BlockBackend *blk, int argc, char **argv)
892
+static int discard_f(BlockBackend *blk, int argc, char **argv)
893
{
894
struct timeval t1, t2;
895
bool Cflag = false, qflag = false;
896
@@ -XXX,XX +XXX,XX @@ static void discard_f(BlockBackend *blk, int argc, char **argv)
897
break;
898
default:
899
qemuio_command_usage(&discard_cmd);
900
- return;
901
+ return -EINVAL;
902
}
903
}
904
905
if (optind != argc - 2) {
906
qemuio_command_usage(&discard_cmd);
907
- return;
908
+ return -EINVAL;
909
}
910
911
offset = cvtnum(argv[optind]);
912
if (offset < 0) {
913
print_cvtnum_err(offset, argv[optind]);
914
- return;
915
+ return offset;
916
}
917
918
optind++;
919
bytes = cvtnum(argv[optind]);
920
if (bytes < 0) {
921
print_cvtnum_err(bytes, argv[optind]);
922
- return;
923
+ return bytes;
924
} else if (bytes >> BDRV_SECTOR_BITS > BDRV_REQUEST_MAX_SECTORS) {
925
printf("length cannot exceed %"PRIu64", given %s\n",
926
(uint64_t)BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS,
927
argv[optind]);
928
- return;
929
+ return -EINVAL;
930
}
931
932
gettimeofday(&t1, NULL);
933
@@ -XXX,XX +XXX,XX @@ static void discard_f(BlockBackend *blk, int argc, char **argv)
934
935
if (ret < 0) {
936
printf("discard failed: %s\n", strerror(-ret));
937
- return;
938
+ return ret;
939
}
940
941
/* Finally, report back -- -C gives a parsable format */
942
@@ -XXX,XX +XXX,XX @@ static void discard_f(BlockBackend *blk, int argc, char **argv)
943
t2 = tsub(t2, t1);
944
print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
945
}
946
+
947
+ return 0;
948
}
949
950
-static void alloc_f(BlockBackend *blk, int argc, char **argv)
951
+static int alloc_f(BlockBackend *blk, int argc, char **argv)
952
{
953
BlockDriverState *bs = blk_bs(blk);
954
int64_t offset, start, remaining, count;
955
@@ -XXX,XX +XXX,XX @@ static void alloc_f(BlockBackend *blk, int argc, char **argv)
956
start = offset = cvtnum(argv[1]);
957
if (offset < 0) {
958
print_cvtnum_err(offset, argv[1]);
959
- return;
960
+ return offset;
961
}
962
963
if (argc == 3) {
964
count = cvtnum(argv[2]);
965
if (count < 0) {
966
print_cvtnum_err(count, argv[2]);
967
- return;
968
+ return count;
969
}
970
} else {
971
count = BDRV_SECTOR_SIZE;
972
@@ -XXX,XX +XXX,XX @@ static void alloc_f(BlockBackend *blk, int argc, char **argv)
973
ret = bdrv_is_allocated(bs, offset, remaining, &num);
974
if (ret < 0) {
975
printf("is_allocated failed: %s\n", strerror(-ret));
976
- return;
977
+ return ret;
978
}
979
offset += num;
980
remaining -= num;
981
@@ -XXX,XX +XXX,XX @@ static void alloc_f(BlockBackend *blk, int argc, char **argv)
982
983
printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
984
sum_alloc, count, s1);
985
+ return 0;
986
}
987
988
static const cmdinfo_t alloc_cmd = {
989
@@ -XXX,XX +XXX,XX @@ static int map_is_allocated(BlockDriverState *bs, int64_t offset,
990
return firstret;
991
}
992
993
-static void map_f(BlockBackend *blk, int argc, char **argv)
994
+static int map_f(BlockBackend *blk, int argc, char **argv)
995
{
996
int64_t offset, bytes;
997
char s1[64], s2[64];
998
@@ -XXX,XX +XXX,XX @@ static void map_f(BlockBackend *blk, int argc, char **argv)
999
bytes = blk_getlength(blk);
1000
if (bytes < 0) {
1001
error_report("Failed to query image length: %s", strerror(-bytes));
1002
- return;
1003
+ return bytes;
1004
}
1005
1006
while (bytes) {
1007
ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
1008
if (ret < 0) {
1009
error_report("Failed to get allocation status: %s", strerror(-ret));
1010
- return;
1011
+ return ret;
1012
} else if (!num) {
1013
error_report("Unexpected end of image");
1014
- return;
1015
+ return -EIO;
1016
}
1017
1018
retstr = ret ? " allocated" : "not allocated";
1019
@@ -XXX,XX +XXX,XX @@ static void map_f(BlockBackend *blk, int argc, char **argv)
1020
offset += num;
1021
bytes -= num;
1022
}
1023
+
1024
+ return 0;
1025
}
1026
1027
static const cmdinfo_t map_cmd = {
1028
@@ -XXX,XX +XXX,XX @@ static void reopen_help(void)
1029
"\n");
1030
}
1031
1032
-static void reopen_f(BlockBackend *blk, int argc, char **argv);
1033
+static int reopen_f(BlockBackend *blk, int argc, char **argv);
1034
1035
static QemuOptsList reopen_opts = {
1036
.name = "reopen",
1037
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t reopen_cmd = {
1038
.help = reopen_help,
1039
};
1040
1041
-static void reopen_f(BlockBackend *blk, int argc, char **argv)
1042
+static int reopen_f(BlockBackend *blk, int argc, char **argv)
1043
{
1044
BlockDriverState *bs = blk_bs(blk);
1045
QemuOpts *qopts;
1046
@@ -XXX,XX +XXX,XX @@ static void reopen_f(BlockBackend *blk, int argc, char **argv)
1047
case 'c':
1048
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
1049
error_report("Invalid cache option: %s", optarg);
1050
- return;
1051
+ return -EINVAL;
1052
}
1053
break;
1054
case 'o':
1055
if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
1056
qemu_opts_reset(&reopen_opts);
1057
- return;
1058
+ return -EINVAL;
1059
}
1060
break;
1061
case 'r':
1062
if (has_rw_option) {
1063
error_report("Only one -r/-w option may be given");
1064
- return;
1065
+ return -EINVAL;
1066
}
1067
flags &= ~BDRV_O_RDWR;
1068
has_rw_option = true;
1069
@@ -XXX,XX +XXX,XX @@ static void reopen_f(BlockBackend *blk, int argc, char **argv)
1070
case 'w':
1071
if (has_rw_option) {
1072
error_report("Only one -r/-w option may be given");
1073
- return;
1074
+ return -EINVAL;
1075
}
1076
flags |= BDRV_O_RDWR;
1077
has_rw_option = true;
1078
@@ -XXX,XX +XXX,XX @@ static void reopen_f(BlockBackend *blk, int argc, char **argv)
1079
default:
1080
qemu_opts_reset(&reopen_opts);
1081
qemuio_command_usage(&reopen_cmd);
1082
- return;
1083
+ return -EINVAL;
1084
}
1085
}
1086
1087
if (optind != argc) {
1088
qemu_opts_reset(&reopen_opts);
1089
qemuio_command_usage(&reopen_cmd);
1090
- return;
1091
+ return -EINVAL;
1092
}
1093
1094
if (writethrough != blk_enable_write_cache(blk) &&
1095
@@ -XXX,XX +XXX,XX @@ static void reopen_f(BlockBackend *blk, int argc, char **argv)
1096
{
1097
error_report("Cannot change cache.writeback: Device attached");
1098
qemu_opts_reset(&reopen_opts);
1099
- return;
1100
+ return -EBUSY;
1101
}
1102
1103
if (!(flags & BDRV_O_RDWR)) {
1104
@@ -XXX,XX +XXX,XX @@ static void reopen_f(BlockBackend *blk, int argc, char **argv)
1105
1106
if (local_err) {
1107
error_report_err(local_err);
1108
- } else {
1109
- blk_set_enable_write_cache(blk, !writethrough);
1110
+ return -EINVAL;
1111
}
1112
+
1113
+ blk_set_enable_write_cache(blk, !writethrough);
1114
+ return 0;
1115
}
1116
1117
-static void break_f(BlockBackend *blk, int argc, char **argv)
1118
+static int break_f(BlockBackend *blk, int argc, char **argv)
1119
{
1120
int ret;
1121
1122
ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
1123
if (ret < 0) {
1124
printf("Could not set breakpoint: %s\n", strerror(-ret));
1125
+ return ret;
1126
}
1127
+
1128
+ return 0;
1129
}
1130
1131
-static void remove_break_f(BlockBackend *blk, int argc, char **argv)
1132
+static int remove_break_f(BlockBackend *blk, int argc, char **argv)
1133
{
1134
int ret;
1135
1136
ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
1137
if (ret < 0) {
1138
printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1139
+ return ret;
1140
}
1141
+
1142
+ return 0;
1143
}
1144
1145
static const cmdinfo_t break_cmd = {
1146
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t remove_break_cmd = {
1147
.oneline = "remove a breakpoint by tag",
1148
};
1149
1150
-static void resume_f(BlockBackend *blk, int argc, char **argv)
1151
+static int resume_f(BlockBackend *blk, int argc, char **argv)
1152
{
1153
int ret;
1154
1155
ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
1156
if (ret < 0) {
1157
printf("Could not resume request: %s\n", strerror(-ret));
1158
+ return ret;
1159
}
1160
+
1161
+ return 0;
1162
}
1163
1164
static const cmdinfo_t resume_cmd = {
1165
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t resume_cmd = {
1166
.oneline = "resumes the request tagged as tag",
1167
};
1168
1169
-static void wait_break_f(BlockBackend *blk, int argc, char **argv)
1170
+static int wait_break_f(BlockBackend *blk, int argc, char **argv)
1171
{
1172
while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
1173
aio_poll(blk_get_aio_context(blk), true);
1174
}
1175
+ return 0;
1176
}
1177
1178
static const cmdinfo_t wait_break_cmd = {
1179
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t wait_break_cmd = {
1180
.oneline = "waits for the suspension of a request",
1181
};
1182
1183
-static void abort_f(BlockBackend *blk, int argc, char **argv)
1184
+static int abort_f(BlockBackend *blk, int argc, char **argv)
1185
{
1186
abort();
1187
}
1188
@@ -XXX,XX +XXX,XX @@ static void sigraise_help(void)
1189
"\n", SIGTERM);
1190
}
1191
1192
-static void sigraise_f(BlockBackend *blk, int argc, char **argv);
1193
+static int sigraise_f(BlockBackend *blk, int argc, char **argv);
1194
1195
static const cmdinfo_t sigraise_cmd = {
1196
.name = "sigraise",
1197
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t sigraise_cmd = {
1198
.help = sigraise_help,
1199
};
1200
1201
-static void sigraise_f(BlockBackend *blk, int argc, char **argv)
1202
+static int sigraise_f(BlockBackend *blk, int argc, char **argv)
1203
{
1204
int64_t sig = cvtnum(argv[1]);
1205
if (sig < 0) {
1206
print_cvtnum_err(sig, argv[1]);
1207
- return;
1208
+ return sig;
1209
} else if (sig > NSIG) {
1210
printf("signal argument '%s' is too large to be a valid signal\n",
1211
argv[1]);
1212
- return;
1213
+ return -EINVAL;
1214
}
1215
1216
/* Using raise() to kill this process does not necessarily flush all open
1217
@@ -XXX,XX +XXX,XX @@ static void sigraise_f(BlockBackend *blk, int argc, char **argv)
1218
fflush(stderr);
1219
1220
raise(sig);
1221
+
1222
+ return 0;
1223
}
1224
1225
static void sleep_cb(void *opaque)
1226
@@ -XXX,XX +XXX,XX @@ static void sleep_cb(void *opaque)
1227
*expired = true;
1228
}
1229
1230
-static void sleep_f(BlockBackend *blk, int argc, char **argv)
1231
+static int sleep_f(BlockBackend *blk, int argc, char **argv)
1232
{
1233
char *endptr;
1234
long ms;
1235
@@ -XXX,XX +XXX,XX @@ static void sleep_f(BlockBackend *blk, int argc, char **argv)
1236
ms = strtol(argv[1], &endptr, 0);
1237
if (ms < 0 || *endptr != '\0') {
1238
printf("%s is not a valid number\n", argv[1]);
1239
- return;
1240
+ return -EINVAL;
1241
}
1242
1243
timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
1244
@@ -XXX,XX +XXX,XX @@ static void sleep_f(BlockBackend *blk, int argc, char **argv)
1245
}
1246
1247
timer_free(timer);
1248
+ return 0;
1249
}
1250
1251
static const cmdinfo_t sleep_cmd = {
1252
@@ -XXX,XX +XXX,XX @@ static void help_all(void)
1253
printf("\nUse 'help commandname' for extended help.\n");
1254
}
1255
1256
-static void help_f(BlockBackend *blk, int argc, char **argv)
1257
+static int help_f(BlockBackend *blk, int argc, char **argv)
1258
{
1259
const cmdinfo_t *ct;
1260
1261
if (argc == 1) {
1262
help_all();
1263
- return;
1264
+ return 0;
1265
}
1266
1267
ct = find_command(argv[1]);
1268
if (ct == NULL) {
1269
printf("command %s not found\n", argv[1]);
1270
- return;
1271
+ return -EINVAL;
1272
}
1273
1274
help_onecmd(argv[1], ct);
1275
+ return 0;
1276
}
1277
1278
static const cmdinfo_t help_cmd = {
1279
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t help_cmd = {
1280
.oneline = "help for one or all commands",
1281
};
1282
1283
-void qemuio_command(BlockBackend *blk, const char *cmd)
1284
+int qemuio_command(BlockBackend *blk, const char *cmd)
1285
{
1286
AioContext *ctx;
1287
char *input;
1288
const cmdinfo_t *ct;
1289
char **v;
1290
int c;
1291
+ int ret = 0;
1292
1293
input = g_strdup(cmd);
1294
v = breakline(input, &c);
1295
@@ -XXX,XX +XXX,XX @@ void qemuio_command(BlockBackend *blk, const char *cmd)
1296
if (ct) {
1297
ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
1298
aio_context_acquire(ctx);
1299
- command(blk, ct, c, v);
1300
+ ret = command(blk, ct, c, v);
1301
aio_context_release(ctx);
1302
} else {
1303
fprintf(stderr, "command \"%s\" not found\n", v[0]);
1304
+ ret = -EINVAL;
1305
}
1306
}
1307
g_free(input);
1308
g_free(v);
1309
+
1310
+ return ret;
1311
}
1312
1313
static void __attribute((constructor)) init_qemuio_commands(void)
1314
diff --git a/qemu-io.c b/qemu-io.c
1315
index XXXXXXX..XXXXXXX 100644
1316
--- a/qemu-io.c
1317
+++ b/qemu-io.c
1318
@@ -XXX,XX +XXX,XX @@ static int get_eof_char(void)
1319
#endif
1320
}
1321
1322
-static void close_f(BlockBackend *blk, int argc, char **argv)
1323
+static int close_f(BlockBackend *blk, int argc, char **argv)
1324
{
1325
blk_unref(qemuio_blk);
1326
qemuio_blk = NULL;
1327
+ return 0;
1328
}
1329
1330
static const cmdinfo_t close_cmd = {
1331
@@ -XXX,XX +XXX,XX @@ static void open_help(void)
1332
"\n");
1333
}
1334
1335
-static void open_f(BlockBackend *blk, int argc, char **argv);
1336
+static int open_f(BlockBackend *blk, int argc, char **argv);
1337
1338
static const cmdinfo_t open_cmd = {
1339
.name = "open",
1340
@@ -XXX,XX +XXX,XX @@ static QemuOptsList empty_opts = {
1341
},
1342
};
1343
1344
-static void open_f(BlockBackend *blk, int argc, char **argv)
1345
+static int open_f(BlockBackend *blk, int argc, char **argv)
1346
{
1347
int flags = BDRV_O_UNMAP;
1348
int readonly = 0;
1349
bool writethrough = true;
1350
int c;
1351
+ int ret;
1352
QemuOpts *qopts;
1353
QDict *opts;
1354
bool force_share = false;
1355
@@ -XXX,XX +XXX,XX @@ static void open_f(BlockBackend *blk, int argc, char **argv)
1356
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
1357
error_report("Invalid cache option: %s", optarg);
1358
qemu_opts_reset(&empty_opts);
1359
- return;
1360
+ return -EINVAL;
1361
}
1362
break;
1363
case 'd':
1364
if (bdrv_parse_discard_flags(optarg, &flags) < 0) {
1365
error_report("Invalid discard option: %s", optarg);
1366
qemu_opts_reset(&empty_opts);
1367
- return;
1368
+ return -EINVAL;
1369
}
1370
break;
1371
case 'o':
1372
if (imageOpts) {
1373
printf("--image-opts and 'open -o' are mutually exclusive\n");
1374
qemu_opts_reset(&empty_opts);
1375
- return;
1376
+ return -EINVAL;
1377
}
1378
if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) {
1379
qemu_opts_reset(&empty_opts);
1380
- return;
1381
+ return -EINVAL;
1382
}
1383
break;
1384
case 'U':
1385
@@ -XXX,XX +XXX,XX @@ static void open_f(BlockBackend *blk, int argc, char **argv)
1386
default:
1387
qemu_opts_reset(&empty_opts);
1388
qemuio_command_usage(&open_cmd);
1389
- return;
1390
+ return -EINVAL;
1391
}
1392
}
1393
1394
@@ -XXX,XX +XXX,XX @@ static void open_f(BlockBackend *blk, int argc, char **argv)
1395
if (imageOpts && (optind == argc - 1)) {
1396
if (!qemu_opts_parse_noisily(&empty_opts, argv[optind], false)) {
1397
qemu_opts_reset(&empty_opts);
1398
- return;
1399
+ return -EINVAL;
1400
}
1401
optind++;
1402
}
1403
@@ -XXX,XX +XXX,XX @@ static void open_f(BlockBackend *blk, int argc, char **argv)
1404
qemu_opts_reset(&empty_opts);
1405
1406
if (optind == argc - 1) {
1407
- openfile(argv[optind], flags, writethrough, force_share, opts);
1408
+ ret = openfile(argv[optind], flags, writethrough, force_share, opts);
1409
} else if (optind == argc) {
1410
- openfile(NULL, flags, writethrough, force_share, opts);
1411
+ ret = openfile(NULL, flags, writethrough, force_share, opts);
1412
} else {
1413
qobject_unref(opts);
1414
qemuio_command_usage(&open_cmd);
1415
+ return -EINVAL;
1416
+ }
1417
+
1418
+ if (ret) {
1419
+ return -EINVAL;
1420
}
1421
+
1422
+ return 0;
1423
}
1424
1425
-static void quit_f(BlockBackend *blk, int argc, char **argv)
1426
+static int quit_f(BlockBackend *blk, int argc, char **argv)
1427
{
1428
quit_qemu_io = true;
1429
+ return 0;
1430
}
1431
1432
static const cmdinfo_t quit_cmd = {
1433
--
249
--
1434
2.17.1
250
2.26.2
1435
251
1436
252
diff view generated by jsdifflib
1
This is a useful function for the whole block layer, so make it public.
1
From: Eric Blake <eblake@redhat.com>
2
At the same time, users outside of block.c probably do not need to make
2
3
use of the reopen functionality, so rename the current function to
3
There are several callers that need to create a new block backend from
4
bdrv_is_writable_after_reopen() create a new bdrv_is_writable() function
4
an existing BDS; make the task slightly easier with a common helper
5
that just passes NULL to it for the reopen queue.
5
routine.
6
6
7
Cc: qemu-stable@nongnu.org
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]
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20180606193702.7113-2-mreitz@redhat.com
13
Message-Id: <20200428192648.749066-2-eblake@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Jeff Cody <jcody@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
15
---
14
include/block/block.h | 1 +
16
include/sysemu/block-backend.h | 2 ++
15
block.c | 17 ++++++++++++++---
17
block/block-backend.c | 23 +++++++++++++++++++++++
16
2 files changed, 15 insertions(+), 3 deletions(-)
18
block/crypto.c | 9 ++++-----
17
19
block/parallels.c | 8 ++++----
18
diff --git a/include/block/block.h b/include/block/block.h
20
block/qcow.c | 8 ++++----
19
index XXXXXXX..XXXXXXX 100644
21
block/qcow2.c | 18 ++++++++----------
20
--- a/include/block/block.h
22
block/qed.c | 8 ++++----
21
+++ b/include/block/block.h
23
block/sheepdog.c | 10 +++++-----
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs);
24
block/vdi.c | 8 ++++----
23
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
25
block/vhdx.c | 8 ++++----
24
bool ignore_allow_rdw, Error **errp);
26
block/vmdk.c | 9 ++++-----
25
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
27
block/vpc.c | 8 ++++----
26
+bool bdrv_is_writable(BlockDriverState *bs);
28
blockdev.c | 8 +++-----
27
bool bdrv_is_sg(BlockDriverState *bs);
29
blockjob.c | 7 ++-----
28
bool bdrv_is_inserted(BlockDriverState *bs);
30
14 files changed, 75 insertions(+), 59 deletions(-)
29
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
31
30
diff --git a/block.c b/block.c
32
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
31
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
34
--- a/include/sysemu/block-backend.h
33
+++ b/block.c
35
+++ b/include/sysemu/block-backend.h
34
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs)
36
@@ -XXX,XX +XXX,XX @@ typedef struct BlockBackendPublic {
35
37
} BlockBackendPublic;
36
/* Returns whether the image file can be written to after the reopen queue @q
38
37
* has been successfully applied, or right now if @q is NULL. */
39
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm);
38
-static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q)
40
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
39
+static bool bdrv_is_writable_after_reopen(BlockDriverState *bs,
41
+ uint64_t shared_perm, Error **errp);
40
+ BlockReopenQueue *q)
42
BlockBackend *blk_new_open(const char *filename, const char *reference,
41
{
43
QDict *options, int flags, Error **errp);
42
int flags = bdrv_reopen_get_flags(q, bs);
44
int blk_get_refcnt(BlockBackend *blk);
43
45
diff --git a/block/block-backend.c b/block/block-backend.c
44
return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR;
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;
45
}
51
}
46
52
47
+/*
53
+/*
48
+ * Return whether the BDS can be written to. This is not necessarily
54
+ * Create a new BlockBackend connected to an existing BlockDriverState.
49
+ * the same as !bdrv_is_read_only(bs), as inactivated images may not
55
+ *
50
+ * be written to but do not count as read-only images.
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.
51
+ */
63
+ */
52
+bool bdrv_is_writable(BlockDriverState *bs)
64
+BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
65
+ uint64_t shared_perm, Error **errp)
53
+{
66
+{
54
+ return bdrv_is_writable_after_reopen(bs, NULL);
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;
55
+}
74
+}
56
+
75
+
57
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
76
/*
58
BdrvChild *c, const BdrvChildRole *role,
77
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
59
BlockReopenQueue *reopen_queue,
78
* The new BlockBackend is in the main AioContext.
60
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
79
diff --git a/block/crypto.c b/block/crypto.c
61
80
index XXXXXXX..XXXXXXX 100644
62
/* Write permissions never work with read-only images */
81
--- a/block/crypto.c
63
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
82
+++ b/block/crypto.c
64
- !bdrv_is_writable(bs, q))
83
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
+ !bdrv_is_writable_after_reopen(bs, q))
84
QCryptoBlock *crypto = NULL;
66
{
85
struct BlockCryptoCreateData data;
67
error_setg(errp, "Block node is read-only");
86
68
return -EPERM;
87
- blk = blk_new(bdrv_get_aio_context(bs),
69
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
88
- BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
70
&perm, &shared);
89
-
71
90
- ret = blk_insert_bs(blk, bs, errp);
72
/* Format drivers may touch metadata even if the guest doesn't write */
91
- if (ret < 0) {
73
- if (bdrv_is_writable(bs, reopen_queue)) {
92
+ blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
74
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
93
+ errp);
75
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
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;
76
}
170
}
77
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
78
--
344
--
79
2.17.1
345
2.26.2
80
346
81
347
diff view generated by jsdifflib
1
Looking at the qcow2 code that is riddled with error_report() calls,
1
From: Eric Blake <eblake@redhat.com>
2
this is really how it should have been from the start.
2
3
3
We originally refused to allow resize of images with internal
4
Along the way, turn the target_version/current_version comparisons at
4
snapshots because the v2 image format did not require the tracking of
5
the beginning of qcow2_downgrade() into assertions (the caller has to
5
snapshot size, making it impossible to safely revert to a snapshot
6
make sure these conditions are met), and rephrase the error message on
6
with a different size than the current view of the image. But the
7
using compat=1.1 to get refcount widths other than 16 bits.
7
snapshot size tracking was rectified in v3, and our recent fixes to
8
8
qemu-img amend (see 0a85af35) guarantee that we always have a valid
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
snapshot size. Thus, we no longer need to artificially limit image
10
Message-id: 20180509210023.20283-3-mreitz@redhat.com
10
resizes, but it does become one more thing that would prevent a
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
downgrade back to v2. And now that we support different-sized
12
Reviewed-by: John Snow <jsnow@redhat.com>
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>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
37
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
38
---
15
include/block/block.h | 3 +-
39
block/qcow2-snapshot.c | 20 ++++++++++++++++----
16
include/block/block_int.h | 3 +-
40
block/qcow2.c | 25 ++++++++++++++++++++++---
17
block.c | 8 +++--
41
tests/qemu-iotests/061 | 35 +++++++++++++++++++++++++++++++++++
18
block/qcow2.c | 72 ++++++++++++++++++++++----------------
42
tests/qemu-iotests/061.out | 28 ++++++++++++++++++++++++++++
19
qemu-img.c | 4 +--
43
4 files changed, 101 insertions(+), 7 deletions(-)
20
tests/qemu-iotests/060.out | 4 +--
44
21
tests/qemu-iotests/061.out | 7 ----
45
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
22
tests/qemu-iotests/080.out | 4 +--
23
tests/qemu-iotests/112.out | 5 +--
24
9 files changed, 58 insertions(+), 52 deletions(-)
25
26
diff --git a/include/block/block.h b/include/block/block.h
27
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
28
--- a/include/block/block.h
47
--- a/block/qcow2-snapshot.c
29
+++ b/include/block/block.h
48
+++ b/block/qcow2-snapshot.c
30
@@ -XXX,XX +XXX,XX @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
49
@@ -XXX,XX +XXX,XX @@
31
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
50
*/
32
int64_t total_work_size, void *opaque);
51
33
int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
52
#include "qemu/osdep.h"
34
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque);
53
+#include "sysemu/block-backend.h"
35
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
54
#include "qapi/error.h"
36
+ Error **errp);
55
#include "qcow2.h"
37
56
#include "qemu/bswap.h"
38
/* external snapshots */
57
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
39
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
58
}
40
diff --git a/include/block/block_int.h b/include/block/block_int.h
59
41
index XXXXXXX..XXXXXXX 100644
60
if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
42
--- a/include/block/block_int.h
61
- error_report("qcow2: Loading snapshots with different disk "
43
+++ b/include/block/block_int.h
62
- "size is not implemented");
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
63
- ret = -ENOTSUP;
45
64
- goto fail;
46
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
65
+ BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
47
BlockDriverAmendStatusCB *status_cb,
66
+ &local_err);
48
- void *cb_opaque);
67
+ if (!blk) {
49
+ void *cb_opaque,
68
+ error_report_err(local_err);
50
+ Error **errp);
69
+ ret = -ENOTSUP;
51
70
+ goto fail;
52
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
71
+ }
53
72
+
54
diff --git a/block.c b/block.c
73
+ ret = blk_truncate(blk, sn->disk_size, true, PREALLOC_MODE_OFF, 0,
55
index XXXXXXX..XXXXXXX 100644
74
+ &local_err);
56
--- a/block.c
75
+ blk_unref(blk);
57
+++ b/block.c
76
+ if (ret < 0) {
58
@@ -XXX,XX +XXX,XX @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
77
+ error_report_err(local_err);
59
}
78
+ goto fail;
60
79
+ }
61
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
80
}
62
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
81
63
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
82
/*
64
+ Error **errp)
65
{
66
if (!bs->drv) {
67
+ error_setg(errp, "Node is ejected");
68
return -ENOMEDIUM;
69
}
70
if (!bs->drv->bdrv_amend_options) {
71
+ error_setg(errp, "Block driver '%s' does not support option amendment",
72
+ bs->drv->format_name);
73
return -ENOTSUP;
74
}
75
- return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque);
76
+ return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque, errp);
77
}
78
79
/* This function will be called by the bdrv_recurse_is_first_non_filter method
80
diff --git a/block/qcow2.c b/block/qcow2.c
83
diff --git a/block/qcow2.c b/block/qcow2.c
81
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
82
--- a/block/qcow2.c
85
--- a/block/qcow2.c
83
+++ b/block/qcow2.c
86
+++ b/block/qcow2.c
84
@@ -XXX,XX +XXX,XX @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
85
* have to be removed.
88
86
*/
89
qemu_co_mutex_lock(&s->lock);
87
static int qcow2_downgrade(BlockDriverState *bs, int target_version,
90
88
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
91
- /* cannot proceed if image has snapshots */
89
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
92
- if (s->nb_snapshots) {
90
+ Error **errp)
93
- error_setg(errp, "Can't resize an image which has snapshots");
91
{
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,
92
BDRVQcow2State *s = bs->opaque;
104
BDRVQcow2State *s = bs->opaque;
93
int current_version = s->qcow_version;
105
int current_version = s->qcow_version;
94
int ret;
106
int ret;
95
107
+ int i;
96
- if (target_version == current_version) {
108
97
- return 0;
109
/* This is qcow2_downgrade(), not qcow2_upgrade() */
98
- } else if (target_version > current_version) {
110
assert(target_version < current_version);
99
- return -EINVAL;
111
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
100
- } else if (target_version != 2) {
101
- return -EINVAL;
102
- }
103
+ /* This is qcow2_downgrade(), not qcow2_upgrade() */
104
+ assert(target_version < current_version);
105
+
106
+ /* There are no other versions (now) that you can downgrade to */
107
+ assert(target_version == 2);
108
109
if (s->refcount_order != 4) {
110
- error_report("compat=0.10 requires refcount_bits=16");
111
+ error_setg(errp, "compat=0.10 requires refcount_bits=16");
112
return -ENOTSUP;
112
return -ENOTSUP;
113
}
113
}
114
114
115
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
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 */
116
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
131
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
117
ret = qcow2_mark_clean(bs);
132
ret = qcow2_mark_clean(bs);
118
if (ret < 0) {
133
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
119
+ error_setg_errno(errp, -ret, "Failed to make the image clean");
134
index XXXXXXX..XXXXXXX 100755
120
return ret;
135
--- a/tests/qemu-iotests/061
121
}
136
+++ b/tests/qemu-iotests/061
122
}
137
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" dump-header
123
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
138
$QEMU_IO -c "read -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
124
* best thing to do anyway */
139
_check_test_img
125
140
126
if (s->incompatible_features) {
141
+echo
127
+ error_setg(errp, "Cannot downgrade an image with incompatible features "
142
+echo "=== Testing resize with snapshots ==="
128
+ "%#" PRIx64 " set", s->incompatible_features);
143
+echo
129
return -ENOTSUP;
144
+_make_test_img -o "compat=0.10" 32M
130
}
145
+$QEMU_IO -c "write -P 0x2a 24M 64k" "$TEST_IMG" | _filter_qemu_io
131
146
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
132
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
147
+$QEMU_IMG resize "$TEST_IMG" 64M &&
133
148
+ echo "unexpected pass"
134
ret = qcow2_expand_zero_clusters(bs, status_cb, cb_opaque);
149
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
135
if (ret < 0) {
150
+
136
+ error_setg_errno(errp, -ret, "Failed to turn zero into data clusters");
151
+$QEMU_IMG amend -o "compat=1.1,size=128M" "$TEST_IMG" ||
137
return ret;
152
+ echo "unexpected fail"
138
}
153
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
139
154
+
140
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
155
+$QEMU_IMG snapshot -c bar "$TEST_IMG"
141
ret = qcow2_update_header(bs);
156
+$QEMU_IMG resize --shrink "$TEST_IMG" 64M ||
142
if (ret < 0) {
157
+ echo "unexpected fail"
143
s->qcow_version = current_version;
158
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
144
+ error_setg_errno(errp, -ret, "Failed to update the image header");
159
+
145
return ret;
160
+$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" &&
146
}
161
+ echo "unexpected pass"
147
return 0;
162
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
148
@@ -XXX,XX +XXX,XX @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
163
+
149
164
+$QEMU_IMG snapshot -a bar "$TEST_IMG" ||
150
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
165
+ echo "unexpected fail"
151
BlockDriverAmendStatusCB *status_cb,
166
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
152
- void *cb_opaque)
167
+
153
+ void *cb_opaque,
168
+$QEMU_IMG snapshot -d bar "$TEST_IMG"
154
+ Error **errp)
169
+$QEMU_IMG amend -o "compat=0.10,size=32M" "$TEST_IMG" ||
155
{
170
+ echo "unexpected fail"
156
BDRVQcow2State *s = bs->opaque;
171
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep '^\(version\|size\|nb_snap\)'
157
int old_version = s->qcow_version, new_version = old_version;
172
+
158
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
173
+_check_test_img
159
bool encrypt;
174
+
160
int encformat;
175
+
161
int refcount_bits = s->refcount_bits;
176
echo
162
- Error *local_err = NULL;
177
echo "=== Testing dirty lazy_refcounts=off ==="
163
int ret;
178
echo
164
QemuOptDesc *desc = opts->list->desc;
165
Qcow2AmendHelperCBInfo helper_cb_info;
166
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
167
} else if (!strcmp(compat, "1.1")) {
168
new_version = 3;
169
} else {
170
- error_report("Unknown compatibility level %s", compat);
171
+ error_setg(errp, "Unknown compatibility level %s", compat);
172
return -EINVAL;
173
}
174
} else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {
175
- error_report("Cannot change preallocation mode");
176
+ error_setg(errp, "Cannot change preallocation mode");
177
return -ENOTSUP;
178
} else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
179
new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
180
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
181
!!s->crypto);
182
183
if (encrypt != !!s->crypto) {
184
- error_report("Changing the encryption flag is not supported");
185
+ error_setg(errp,
186
+ "Changing the encryption flag is not supported");
187
return -ENOTSUP;
188
}
189
} else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) {
190
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
191
qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT));
192
193
if (encformat != s->crypt_method_header) {
194
- error_report("Changing the encryption format is not supported");
195
+ error_setg(errp,
196
+ "Changing the encryption format is not supported");
197
return -ENOTSUP;
198
}
199
} else if (g_str_has_prefix(desc->name, "encrypt.")) {
200
- error_report("Changing the encryption parameters is not supported");
201
+ error_setg(errp,
202
+ "Changing the encryption parameters is not supported");
203
return -ENOTSUP;
204
} else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
205
cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
206
cluster_size);
207
if (cluster_size != s->cluster_size) {
208
- error_report("Changing the cluster size is not supported");
209
+ error_setg(errp, "Changing the cluster size is not supported");
210
return -ENOTSUP;
211
}
212
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
213
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
214
if (refcount_bits <= 0 || refcount_bits > 64 ||
215
!is_power_of_2(refcount_bits))
216
{
217
- error_report("Refcount width must be a power of two and may "
218
- "not exceed 64 bits");
219
+ error_setg(errp, "Refcount width must be a power of two and "
220
+ "may not exceed 64 bits");
221
return -EINVAL;
222
}
223
} else {
224
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
225
ret = qcow2_update_header(bs);
226
if (ret < 0) {
227
s->qcow_version = old_version;
228
+ error_setg_errno(errp, -ret, "Failed to update the image header");
229
return ret;
230
}
231
}
232
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
233
int refcount_order = ctz32(refcount_bits);
234
235
if (new_version < 3 && refcount_bits != 16) {
236
- error_report("Different refcount widths than 16 bits require "
237
- "compatibility level 1.1 or above (use compat=1.1 or "
238
- "greater)");
239
+ error_setg(errp, "Refcount widths other than 16 bits require "
240
+ "compatibility level 1.1 or above (use compat=1.1 or "
241
+ "greater)");
242
return -EINVAL;
243
}
244
245
helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
246
ret = qcow2_change_refcount_order(bs, refcount_order,
247
&qcow2_amend_helper_cb,
248
- &helper_cb_info, &local_err);
249
+ &helper_cb_info, errp);
250
if (ret < 0) {
251
- error_report_err(local_err);
252
return ret;
253
}
254
}
255
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
256
backing_file ?: s->image_backing_file,
257
backing_format ?: s->image_backing_format);
258
if (ret < 0) {
259
+ error_setg_errno(errp, -ret, "Failed to change the backing file");
260
return ret;
261
}
262
}
263
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
264
if (s->use_lazy_refcounts != lazy_refcounts) {
265
if (lazy_refcounts) {
266
if (new_version < 3) {
267
- error_report("Lazy refcounts only supported with compatibility "
268
- "level 1.1 and above (use compat=1.1 or greater)");
269
+ error_setg(errp, "Lazy refcounts only supported with "
270
+ "compatibility level 1.1 and above (use compat=1.1 "
271
+ "or greater)");
272
return -EINVAL;
273
}
274
s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;
275
ret = qcow2_update_header(bs);
276
if (ret < 0) {
277
s->compatible_features &= ~QCOW2_COMPAT_LAZY_REFCOUNTS;
278
+ error_setg_errno(errp, -ret, "Failed to update the image header");
279
return ret;
280
}
281
s->use_lazy_refcounts = true;
282
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
283
/* make image clean first */
284
ret = qcow2_mark_clean(bs);
285
if (ret < 0) {
286
+ error_setg_errno(errp, -ret, "Failed to make the image clean");
287
return ret;
288
}
289
/* now disallow lazy refcounts */
290
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
291
ret = qcow2_update_header(bs);
292
if (ret < 0) {
293
s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;
294
+ error_setg_errno(errp, -ret, "Failed to update the image header");
295
return ret;
296
}
297
s->use_lazy_refcounts = false;
298
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
299
300
if (new_size) {
301
BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
302
- ret = blk_insert_bs(blk, bs, &local_err);
303
+ ret = blk_insert_bs(blk, bs, errp);
304
if (ret < 0) {
305
- error_report_err(local_err);
306
blk_unref(blk);
307
return ret;
308
}
309
310
- ret = blk_truncate(blk, new_size, PREALLOC_MODE_OFF, &local_err);
311
+ ret = blk_truncate(blk, new_size, PREALLOC_MODE_OFF, errp);
312
blk_unref(blk);
313
if (ret < 0) {
314
- error_report_err(local_err);
315
return ret;
316
}
317
}
318
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
319
if (new_version < old_version) {
320
helper_cb_info.current_operation = QCOW2_DOWNGRADING;
321
ret = qcow2_downgrade(bs, new_version, &qcow2_amend_helper_cb,
322
- &helper_cb_info);
323
+ &helper_cb_info, errp);
324
if (ret < 0) {
325
return ret;
326
}
327
diff --git a/qemu-img.c b/qemu-img.c
328
index XXXXXXX..XXXXXXX 100644
329
--- a/qemu-img.c
330
+++ b/qemu-img.c
331
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
332
333
/* In case the driver does not call amend_status_cb() */
334
qemu_progress_print(0.f, 0);
335
- ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL);
336
+ ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, &err);
337
qemu_progress_print(100.f, 0);
338
if (ret < 0) {
339
- error_report("Error while amending options: %s", strerror(-ret));
340
+ error_report_err(err);
341
goto out;
342
}
343
344
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
345
index XXXXXXX..XXXXXXX 100644
346
--- a/tests/qemu-iotests/060.out
347
+++ b/tests/qemu-iotests/060.out
348
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
349
wrote 65536/65536 bytes at offset 0
350
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
351
qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed
352
-qemu-img: Error while amending options: Input/output error
353
+qemu-img: Failed to turn zero into data clusters: Input/output error
354
355
=== Testing unaligned L2 entry ===
356
357
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
358
wrote 65536/65536 bytes at offset 0
359
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
qcow2: Marking image as corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
361
-qemu-img: Error while amending options: Input/output error
362
+qemu-img: Failed to turn zero into data clusters: Input/output error
363
364
=== Testing unaligned reftable entry ===
365
366
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
179
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
367
index XXXXXXX..XXXXXXX 100644
180
index XXXXXXX..XXXXXXX 100644
368
--- a/tests/qemu-iotests/061.out
181
--- a/tests/qemu-iotests/061.out
369
+++ b/tests/qemu-iotests/061.out
182
+++ b/tests/qemu-iotests/061.out
370
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
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 ===
371
216
372
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
217
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
373
qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
374
-qemu-img: Error while amending options: Invalid argument
375
qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
376
-qemu-img: Error while amending options: Invalid argument
377
qemu-img: Unknown compatibility level 0.42
378
-qemu-img: Error while amending options: Invalid argument
379
qemu-img: Invalid parameter 'foo'
380
qemu-img: Changing the cluster size is not supported
381
-qemu-img: Error while amending options: Operation not supported
382
qemu-img: Changing the encryption flag is not supported
383
-qemu-img: Error while amending options: Operation not supported
384
qemu-img: Cannot change preallocation mode
385
-qemu-img: Error while amending options: Operation not supported
386
387
=== Testing correct handling of unset value ===
388
389
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
390
Should work:
391
Should not work:
392
qemu-img: Changing the cluster size is not supported
393
-qemu-img: Error while amending options: Operation not supported
394
395
=== Testing zero expansion on inactive clusters ===
396
397
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
398
index XXXXXXX..XXXXXXX 100644
399
--- a/tests/qemu-iotests/080.out
400
+++ b/tests/qemu-iotests/080.out
401
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 0
402
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid
404
qemu-img: Snapshot L1 table offset invalid
405
-qemu-img: Error while amending options: Invalid argument
406
+qemu-img: Failed to turn zero into data clusters: Invalid argument
407
Failed to flush the refcount block cache: Invalid argument
408
write failed: Invalid argument
409
qemu-img: Snapshot L1 table offset invalid
410
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 0
411
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
412
qemu-img: Failed to load snapshot: Snapshot L1 table too large
413
qemu-img: Snapshot L1 table too large
414
-qemu-img: Error while amending options: File too large
415
+qemu-img: Failed to turn zero into data clusters: File too large
416
Failed to flush the refcount block cache: File too large
417
write failed: File too large
418
qemu-img: Snapshot L1 table too large
419
diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out
420
index XXXXXXX..XXXXXXX 100644
421
--- a/tests/qemu-iotests/112.out
422
+++ b/tests/qemu-iotests/112.out
423
@@ -XXX,XX +XXX,XX @@ refcount bits: 64
424
=== Amend to compat=0.10 ===
425
426
qemu-img: compat=0.10 requires refcount_bits=16
427
-qemu-img: Error while amending options: Operation not supported
428
refcount bits: 64
429
No errors were found on the image.
430
refcount bits: 16
431
refcount bits: 16
432
-qemu-img: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater)
433
-qemu-img: Error while amending options: Invalid argument
434
+qemu-img: Refcount widths other than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater)
435
refcount bits: 16
436
437
=== Amend with snapshot ===
438
@@ -XXX,XX +XXX,XX @@ refcount bits: 16
439
wrote 16777216/16777216 bytes at offset 0
440
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
441
qemu-img: Cannot decrease refcount entry width to 1 bits: Cluster at offset 0x50000 has a refcount of 2
442
-qemu-img: Error while amending options: Invalid argument
443
No errors were found on the image.
444
refcount bits: 16
445
No errors were found on the image.
446
--
218
--
447
2.17.1
219
2.26.2
448
220
449
221
diff view generated by jsdifflib
1
When signaling a corruption on a read-only image, qcow2 already makes
1
From: Eric Blake <eblake@redhat.com>
2
fatal events non-fatal (i.e., they will not result in the image being
3
closed, and the image header's corrupt flag will not be set). This is
4
necessary because we cannot set the corrupt flag on read-only images,
5
and it is possible because further corruption of read-only images is
6
impossible.
7
2
8
Inactive images are effectively read-only, too, so we should do the same
3
Our comment did not actually match the code. Rewrite the comment to
9
for them. bdrv_is_writable() can tell us whether an image can actually
4
be less sensitive to any future changes to qcow2-bitmap.c that might
10
be written to, so use its result instead of !bs->read_only.
5
implement scenarios that we currently reject.
11
6
12
(Otherwise, the assert(!(bs->open_flags & BDRV_O_INACTIVE)) in
7
Signed-off-by: Eric Blake <eblake@redhat.com>
13
bdrv_co_pwritev() will fail, crashing qemu.)
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
9
Message-Id: <20200428192648.749066-4-eblake@redhat.com>
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Message-id: 20180606193702.7113-3-mreitz@redhat.com
18
Reviewed-by: John Snow <jsnow@redhat.com>
19
Reviewed-by: Jeff Cody <jcody@redhat.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
11
---
22
block/qcow2.c | 2 +-
12
block/qcow2.c | 2 +-
23
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
24
14
25
diff --git a/block/qcow2.c b/block/qcow2.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2.c
17
--- a/block/qcow2.c
28
+++ b/block/qcow2.c
18
+++ b/block/qcow2.c
29
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
30
char *message;
20
goto fail;
31
va_list ap;
21
}
32
22
33
- fatal = fatal && !bs->read_only;
23
- /* cannot proceed if image has bitmaps */
34
+ fatal = fatal && bdrv_is_writable(bs);
24
+ /* See qcow2-bitmap.c for which bitmap scenarios prevent a resize. */
35
25
if (qcow2_truncate_bitmaps_check(bs, errp)) {
36
if (s->signaled_corruption &&
26
ret = -ENOTSUP;
37
(!fatal || (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT)))
27
goto fail;
38
--
28
--
39
2.17.1
29
2.26.2
40
30
41
31
diff view generated by jsdifflib
1
Repairing OFLAG_COPIED is usually safe because it is done after the
1
From: Eric Blake <eblake@redhat.com>
2
refcounts have been repaired. Therefore, it we did not find anyone else
3
referencing a data or L2 cluster, it makes no sense to not set
4
OFLAG_COPIED -- and the other direction (clearing OFLAG_COPIED) is
5
always safe, anyway, it may just induce leaks.
6
2
7
Furthermore, if OFLAG_COPIED is actually consistent with a wrong (leaky)
3
It's been a while since we got rid of the sector-based bdrv_read and
8
refcount, we will decrement the refcount with -r leaks, but OFLAG_COPIED
4
bdrv_write (commit 2e11d756); let's finish the job on a few remaining
9
will then be wrong. qemu-img check should not produce images that are
5
comments.
10
more corrupted afterwards then they were before.
11
6
12
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527085
7
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200428213807.776655-1-eblake@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Message-id: 20180509200059.31125-2-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
11
---
18
block/qcow2-refcount.c | 25 +++++++++++++++++--------
12
block/io.c | 3 ++-
19
1 file changed, 17 insertions(+), 8 deletions(-)
13
block/qcow2-refcount.c | 2 +-
14
block/vvfat.c | 10 +++++-----
15
tests/qemu-iotests/001 | 2 +-
16
tests/qemu-iotests/052 | 2 +-
17
tests/qemu-iotests/134 | 2 +-
18
tests/qemu-iotests/188 | 2 +-
19
7 files changed, 12 insertions(+), 11 deletions(-)
20
20
21
diff --git a/block/io.c b/block/io.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/io.c
24
+++ b/block/io.c
25
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
26
* flags are passed through to bdrv_pwrite_zeroes (e.g. BDRV_REQ_MAY_UNMAP,
27
* BDRV_REQ_FUA).
28
*
29
- * Returns < 0 on error, 0 on success. For error codes see bdrv_write().
30
+ * Returns < 0 on error, 0 on success. For error codes see bdrv_pwrite().
31
*/
32
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
33
{
34
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
35
}
36
}
37
38
+/* return < 0 if error. See bdrv_pwrite() for the return codes */
39
int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
40
{
41
int ret;
21
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
42
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
22
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-refcount.c
44
--- a/block/qcow2-refcount.c
24
+++ b/block/qcow2-refcount.c
45
+++ b/block/qcow2-refcount.c
25
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
46
@@ -XXX,XX +XXX,XX @@ fail:
26
int ret;
47
* - 0 if writing to this offset will not affect the mentioned metadata
27
uint64_t refcount;
48
* - a positive QCow2MetadataOverlap value indicating one overlapping section
28
int i, j;
49
* - a negative value (-errno) indicating an error while performing a check,
29
+ bool repair;
50
- * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
30
+
51
+ * e.g. when bdrv_pread failed on QCOW2_OL_INACTIVE_L2
31
+ if (fix & BDRV_FIX_ERRORS) {
52
*/
32
+ /* Always repair */
53
int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
33
+ repair = true;
54
int64_t size)
34
+ } else if (fix & BDRV_FIX_LEAKS) {
55
diff --git a/block/vvfat.c b/block/vvfat.c
35
+ /* Repair only if that seems safe: This function is always
56
index XXXXXXX..XXXXXXX 100644
36
+ * called after the refcounts have been fixed, so the refcount
57
--- a/block/vvfat.c
37
+ * is accurate if that repair was successful */
58
+++ b/block/vvfat.c
38
+ repair = !res->check_errors && !res->corruptions && !res->leaks;
59
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
39
+ } else {
60
* - get modified FAT
40
+ repair = false;
61
* - compare the two FATs (TODO)
41
+ }
62
* - get buffer for marking used clusters
42
63
- * - recurse direntries from root (using bs->bdrv_read to make
43
for (i = 0; i < s->l1_size; i++) {
64
+ * - recurse direntries from root (using bs->bdrv_pread to make
44
uint64_t l1_entry = s->l1_table[i];
65
* sure to get the new data)
45
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
66
* - check that the FAT agrees with the size
46
if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {
67
* - count the number of clusters occupied by this directory and
47
fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "
68
@@ -XXX,XX +XXX,XX @@ static int handle_deletes(BDRVVVFATState* s)
48
"l1_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
69
/*
49
- fix & BDRV_FIX_ERRORS ? "Repairing" :
70
* synchronize mapping with new state:
50
- "ERROR",
71
*
51
- i, l1_entry, refcount);
72
- * - copy FAT (with bdrv_read)
52
- if (fix & BDRV_FIX_ERRORS) {
73
+ * - copy FAT (with bdrv_pread)
53
+ repair ? "Repairing" : "ERROR", i, l1_entry, refcount);
74
* - mark all filenames corresponding to mappings as deleted
54
+ if (repair) {
75
- * - recurse direntries from root (using bs->bdrv_read)
55
s->l1_table[i] = refcount == 1
76
+ * - recurse direntries from root (using bs->bdrv_pread)
56
? l1_entry | QCOW_OFLAG_COPIED
77
* - delete files corresponding to mappings marked as deleted
57
: l1_entry & ~QCOW_OFLAG_COPIED;
78
*/
58
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
79
static int do_commit(BDRVVVFATState* s)
59
if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {
80
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
60
fprintf(stderr, "%s OFLAG_COPIED data cluster: "
81
return ret;
61
"l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
82
}
62
- fix & BDRV_FIX_ERRORS ? "Repairing" :
83
63
- "ERROR",
84
- /* copy FAT (with bdrv_read) */
64
- l2_entry, refcount);
85
+ /* copy FAT (with bdrv_pread) */
65
- if (fix & BDRV_FIX_ERRORS) {
86
memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
66
+ repair ? "Repairing" : "ERROR", l2_entry, refcount);
87
67
+ if (repair) {
88
- /* recurse direntries from root (using bs->bdrv_read) */
68
l2_table[j] = cpu_to_be64(refcount == 1
89
+ /* recurse direntries from root (using bs->bdrv_pread) */
69
? l2_entry | QCOW_OFLAG_COPIED
90
ret = commit_direntries(s, 0, -1);
70
: l2_entry & ~QCOW_OFLAG_COPIED);
91
if (ret) {
92
fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
93
diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001
94
index XXXXXXX..XXXXXXX 100755
95
--- a/tests/qemu-iotests/001
96
+++ b/tests/qemu-iotests/001
97
@@ -XXX,XX +XXX,XX @@
98
#!/usr/bin/env bash
99
#
100
-# Test simple read/write using plain bdrv_read/bdrv_write
101
+# Test simple read/write using plain bdrv_pread/bdrv_pwrite
102
#
103
# Copyright (C) 2009 Red Hat, Inc.
104
#
105
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
106
index XXXXXXX..XXXXXXX 100755
107
--- a/tests/qemu-iotests/052
108
+++ b/tests/qemu-iotests/052
109
@@ -XXX,XX +XXX,XX @@
110
#!/usr/bin/env bash
111
#
112
-# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT
113
+# Test bdrv_pread/bdrv_pwrite using BDRV_O_SNAPSHOT
114
#
115
# Copyright (C) 2013 Red Hat, Inc.
116
#
117
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
118
index XXXXXXX..XXXXXXX 100755
119
--- a/tests/qemu-iotests/134
120
+++ b/tests/qemu-iotests/134
121
@@ -XXX,XX +XXX,XX @@
122
#!/usr/bin/env bash
123
#
124
-# Test encrypted read/write using plain bdrv_read/bdrv_write
125
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
126
#
127
# Copyright (C) 2015 Red Hat, Inc.
128
#
129
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
130
index XXXXXXX..XXXXXXX 100755
131
--- a/tests/qemu-iotests/188
132
+++ b/tests/qemu-iotests/188
133
@@ -XXX,XX +XXX,XX @@
134
#!/usr/bin/env bash
135
#
136
-# Test encrypted read/write using plain bdrv_read/bdrv_write
137
+# Test encrypted read/write using plain bdrv_pread/bdrv_pwrite
138
#
139
# Copyright (C) 2017 Red Hat, Inc.
140
#
71
--
141
--
72
2.17.1
142
2.26.2
73
143
74
144
diff view generated by jsdifflib
1
This patch adds a test case to 153 which tries to overwrite an image
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
(using qemu-img create) while it is in use. Without the original user
3
explicitly sharing the necessary permissions (writing and truncation),
4
this should not be allowed.
5
2
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Commit f62514b3def5fb2acbef64d0e053c0c31fa45aff made qemu-img reject -o "" but this test uses it.
7
Reviewed-by: Fam Zheng <famz@redhat.com>
4
Since this test only tries to do a dry-run run of qemu-img amend,
8
Message-id: 20180509215336.31304-4-mreitz@redhat.com
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>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
12
---
11
tests/qemu-iotests/153 | 18 ++++++++++++++++++
13
tests/qemu-iotests/153 | 2 +-
12
tests/qemu-iotests/153.out | 13 +++++++++++++
14
tests/qemu-iotests/153.out | 12 ++++++------
13
2 files changed, 31 insertions(+)
15
2 files changed, 7 insertions(+), 7 deletions(-)
14
16
15
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
17
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
16
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/153
19
--- a/tests/qemu-iotests/153
18
+++ b/tests/qemu-iotests/153
20
+++ b/tests/qemu-iotests/153
19
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
21
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
20
_run_cmd $QEMU_IMG dd $L if="${TEST_IMG}" of="${TEST_IMG}.convert" bs=512 count=1
22
_run_cmd $QEMU_IMG check $L "${TEST_IMG}"
21
_run_cmd $QEMU_IMG bench $L -c 1 "${TEST_IMG}"
23
_run_cmd $QEMU_IMG compare $L "${TEST_IMG}" "${TEST_IMG}"
22
_run_cmd $QEMU_IMG bench $L -w -c 1 "${TEST_IMG}"
24
_run_cmd $QEMU_IMG map $L "${TEST_IMG}"
23
+
25
- _run_cmd $QEMU_IMG amend -o "" $L "${TEST_IMG}"
24
+ # qemu-img create does not support -U
26
+ _run_cmd $QEMU_IMG amend -o "size=$size" $L "${TEST_IMG}"
25
+ if [ -z "$L" ]; then
27
_run_cmd $QEMU_IMG commit $L "${TEST_IMG}"
26
+ _run_cmd $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" \
28
_run_cmd $QEMU_IMG resize $L "${TEST_IMG}" $size
27
+ -b ${TEST_IMG}.base
29
_run_cmd $QEMU_IMG rebase $L "${TEST_IMG}" -b "${TEST_IMG}.base"
28
+ # Read the file format. It used to be the case that
29
+ # file-posix simply truncated the file, but the qcow2
30
+ # driver then failed to format it because it was unable
31
+ # to acquire the necessary WRITE permission. However, the
32
+ # truncation was already wrong, and the whole process
33
+ # resulted in the file being completely empty and thus its
34
+ # format would be detected to be raw.
35
+ # So we read it here to see that creation either completed
36
+ # successfully (thus the format is qcow2) or it aborted
37
+ # before the file was changed at all (thus the format stays
38
+ # qcow2).
39
+ _img_info -U | grep 'file format'
40
+ fi
41
done
42
_send_qemu_cmd $h "{ 'execute': 'quit', }" ""
43
echo
44
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
30
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
45
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
46
--- a/tests/qemu-iotests/153.out
32
--- a/tests/qemu-iotests/153.out
47
+++ b/tests/qemu-iotests/153.out
33
+++ b/tests/qemu-iotests/153.out
48
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
34
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper map TEST_DIR/t.qcow2
35
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
36
Is another process using the image [TEST_DIR/t.qcow2]?
37
38
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
39
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
49
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
40
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
50
Is another process using the image?
41
Is another process using the image [TEST_DIR/t.qcow2]?
51
42
52
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
43
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
53
+qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
44
54
+Is another process using the image?
45
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
55
+file format: IMGFMT
46
56
+
47
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
57
== Running utility commands -U ==
48
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
58
49
qemu-img: unrecognized option '-U'
59
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
50
Try 'qemu-img --help' for more information
60
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
51
52
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
53
54
_qemu_img_wrapper map TEST_DIR/t.qcow2
55
56
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
57
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
61
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
58
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
62
Is another process using the image?
59
Is another process using the image [TEST_DIR/t.qcow2]?
63
60
64
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
61
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
65
+qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
62
66
+Is another process using the image?
63
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
67
+file format: IMGFMT
64
68
+
65
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
69
== Running utility commands -U ==
66
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
70
67
qemu-img: unrecognized option '-U'
71
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
68
Try 'qemu-img --help' for more information
72
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
69
73
70
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
74
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
71
75
72
_qemu_img_wrapper map TEST_DIR/t.qcow2
76
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
73
77
+file format: IMGFMT
74
-_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
78
+
75
+_qemu_img_wrapper amend -o size=32M TEST_DIR/t.qcow2
79
== Running utility commands -U ==
76
80
77
_qemu_img_wrapper commit TEST_DIR/t.qcow2
81
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
78
79
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper compare -U TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
80
81
_qemu_img_wrapper map -U TEST_DIR/t.qcow2
82
83
-_qemu_img_wrapper amend -o -U TEST_DIR/t.qcow2
84
+_qemu_img_wrapper amend -o size=32M -U TEST_DIR/t.qcow2
85
qemu-img: unrecognized option '-U'
86
Try 'qemu-img --help' for more information
87
82
--
88
--
83
2.17.1
89
2.26.2
84
90
85
91
diff view generated by jsdifflib
1
Currently, qemu-img convert writes zeroes when it reads zeroes.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Sometimes it does not because the target is initialized to zeroes
2
3
anyway, so we do not need to overwrite (and thus potentially allocate)
3
We are going to use aio-task-pool API and extend in-flight request
4
it. This is never the case for targets with backing files, though. But
4
structure to be a successor of AioTask, so rename things appropriately.
5
even they may have an area that is initialized to zeroes, and that is
5
6
the area past the end of the backing file (if that is shorter than the
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
overlay).
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
8
Message-Id: <20200429130847.28124-2-vsementsov@virtuozzo.com>
9
So if the target format's unallocated blocks are zero and there is a gap
10
between the target's backing file's end and the target's end, we do not
11
have to explicitly write zeroes there.
12
13
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527898
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20180501165750.19242-2-mreitz@redhat.com
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
10
---
19
qemu-img.c | 26 +++++++++++++++++++++++++-
11
block/block-copy.c | 98 +++++++++++++++++++++++-----------------------
20
1 file changed, 25 insertions(+), 1 deletion(-)
12
1 file changed, 48 insertions(+), 50 deletions(-)
21
13
22
diff --git a/qemu-img.c b/qemu-img.c
14
diff --git a/block/block-copy.c b/block/block-copy.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-img.c
16
--- a/block/block-copy.c
25
+++ b/qemu-img.c
17
+++ b/block/block-copy.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct ImgConvertState {
18
@@ -XXX,XX +XXX,XX @@
27
BlockBackend *target;
19
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
28
bool has_zero_init;
20
#define BLOCK_COPY_MAX_MEM (128 * MiB)
29
bool compressed;
21
30
+ bool unallocated_blocks_are_zero;
22
-typedef struct BlockCopyInFlightReq {
31
bool target_has_backing;
23
+typedef struct BlockCopyTask {
32
+ int64_t target_backing_sectors; /* negative if unknown */
24
int64_t offset;
33
bool wr_in_order;
25
int64_t bytes;
34
bool copy_range;
26
- QLIST_ENTRY(BlockCopyInFlightReq) list;
35
int min_sparse;
27
- CoQueue wait_queue; /* coroutines blocked on this request */
36
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
28
-} BlockCopyInFlightReq;
37
{
29
+ QLIST_ENTRY(BlockCopyTask) list;
38
int64_t src_cur_offset;
30
+ CoQueue wait_queue; /* coroutines blocked on this task */
39
int ret, n, src_cur;
31
+} BlockCopyTask;
40
+ bool post_backing_zero = false;
32
41
33
typedef struct BlockCopyState {
42
convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
34
/*
43
35
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
44
assert(s->total_sectors > sector_num);
36
bool use_copy_range;
45
n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
37
int64_t copy_size;
46
38
uint64_t len;
47
+ if (s->target_backing_sectors >= 0) {
39
- QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;
48
+ if (sector_num >= s->target_backing_sectors) {
40
+ QLIST_HEAD(, BlockCopyTask) tasks;
49
+ post_backing_zero = s->unallocated_blocks_are_zero;
41
50
+ } else if (sector_num + n > s->target_backing_sectors) {
42
BdrvRequestFlags write_flags;
51
+ /* Split requests around target_backing_sectors (because
43
52
+ * starting from there, zeros are handled differently) */
44
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
53
+ n = s->target_backing_sectors - sector_num;
45
SharedResource *mem;
54
+ }
46
} BlockCopyState;
55
+ }
47
56
+
48
-static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
57
if (s->sector_next_status <= sector_num) {
49
- int64_t offset,
58
int64_t count = n * BDRV_SECTOR_SIZE;
50
- int64_t bytes)
59
51
+static BlockCopyTask *find_conflicting_task(BlockCopyState *s,
60
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
52
+ int64_t offset, int64_t bytes)
61
n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
53
{
62
54
- BlockCopyInFlightReq *req;
63
if (ret & BDRV_BLOCK_ZERO) {
55
+ BlockCopyTask *t;
64
- s->status = BLK_ZERO;
56
65
+ s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO;
57
- QLIST_FOREACH(req, &s->inflight_reqs, list) {
66
} else if (ret & BDRV_BLOCK_DATA) {
58
- if (offset + bytes > req->offset && offset < req->offset + req->bytes) {
67
s->status = BLK_DATA;
59
- return req;
68
} else {
60
+ QLIST_FOREACH(t, &s->tasks, list) {
69
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
61
+ if (offset + bytes > t->offset && offset < t->offset + t->bytes) {
62
+ return t;
70
}
63
}
71
}
64
}
72
65
73
+ if (s.target_has_backing) {
66
@@ -XXX,XX +XXX,XX @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
74
+ /* Errors are treated as "backing length unknown" (which means
67
}
75
+ * s.target_backing_sectors has to be negative, which it will
68
76
+ * be automatically). The backing file length is used only
69
/*
77
+ * for optimizations, so such a case is not fatal. */
70
- * If there are no intersecting requests return false. Otherwise, wait for the
78
+ s.target_backing_sectors = bdrv_nb_sectors(out_bs->backing->bs);
71
- * first found intersecting request to finish and return true.
79
+ } else {
72
+ * If there are no intersecting tasks return false. Otherwise, wait for the
80
+ s.target_backing_sectors = -1;
73
+ * first found intersecting tasks to finish and return true.
81
+ }
74
*/
82
+
75
static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
83
ret = bdrv_get_info(out_bs, &bdi);
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;
84
if (ret < 0) {
160
if (ret < 0) {
85
if (s.compressed) {
161
- bdrv_set_dirty_bitmap(s->copy_bitmap, req->offset, req->bytes);
86
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
162
+ bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes);
87
} else {
163
}
88
s.compressed = s.compressed || bdi.needs_compressed_writes;
164
- QLIST_REMOVE(req, list);
89
s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
165
- qemu_co_queue_restart_all(&req->wait_queue);
90
+ s.unallocated_blocks_are_zero = bdi.unallocated_blocks_are_zero;
166
+ QLIST_REMOVE(task, list);
91
}
167
+ qemu_co_queue_restart_all(&task->wait_queue);
92
168
}
93
ret = convert_do_copy(&s);
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
}
94
--
216
--
95
2.17.1
217
2.26.2
96
218
97
219
diff view generated by jsdifflib
1
For qemu-io, a function returns an integer with two possible values: 0
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
for "qemu-io may continue execution", or 1 for "qemu-io should exit".
3
However, there is only a single command that returns 1, and that is
4
"quit".
5
2
6
So let's turn this case into a global variable instead so we can make
3
We are going to use aio-task-pool API, so tasks will be handled in
7
better use of the return value in a later patch.
4
parallel. We need therefore separate allocated task on each iteration.
5
Introduce this logic now.
8
6
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20180509194302.21585-2-mreitz@redhat.com
9
Message-Id: <20200429130847.28124-3-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
11
---
14
include/qemu-io.h | 6 +-
12
block/block-copy.c | 18 +++++++++++-------
15
qemu-io-cmds.c | 294 +++++++++++++++++++++-------------------------
13
1 file changed, 11 insertions(+), 7 deletions(-)
16
qemu-io.c | 36 +++---
17
3 files changed, 157 insertions(+), 179 deletions(-)
18
14
19
diff --git a/include/qemu-io.h b/include/qemu-io.h
15
diff --git a/block/block-copy.c b/block/block-copy.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qemu-io.h
17
--- a/block/block-copy.c
22
+++ b/include/qemu-io.h
18
+++ b/block/block-copy.c
23
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
24
25
#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
26
27
-typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
28
+typedef void (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
29
typedef void (*helpfunc_t)(void);
30
31
typedef struct cmdinfo {
32
@@ -XXX,XX +XXX,XX @@ typedef struct cmdinfo {
33
34
extern bool qemuio_misalign;
35
36
-bool qemuio_command(BlockBackend *blk, const char *cmd);
37
+void qemuio_command(BlockBackend *blk, const char *cmd);
38
39
void qemuio_add_command(const cmdinfo_t *ci);
40
-int qemuio_command_usage(const cmdinfo_t *ci);
41
+void qemuio_command_usage(const cmdinfo_t *ci);
42
void qemuio_complete_command(const char *input,
43
void (*fn)(const char *cmd, void *opaque),
44
void *opaque);
45
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/qemu-io-cmds.c
48
+++ b/qemu-io-cmds.c
49
@@ -XXX,XX +XXX,XX @@ void qemuio_add_command(const cmdinfo_t *ci)
50
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
51
}
20
}
52
21
53
-int qemuio_command_usage(const cmdinfo_t *ci)
22
/* Called only on full-dirty region */
54
+void qemuio_command_usage(const cmdinfo_t *ci)
23
-static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
24
- int64_t offset, int64_t bytes)
25
+static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
26
+ int64_t offset, int64_t bytes)
55
{
27
{
56
printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
28
+ BlockCopyTask *task = g_new(BlockCopyTask, 1);
57
- return 0;
29
+
30
assert(!find_conflicting_task(s, offset, bytes));
31
32
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
33
@@ -XXX,XX +XXX,XX @@ static void block_copy_task_begin(BlockCopyState *s, BlockCopyTask *task,
34
task->bytes = bytes;
35
qemu_co_queue_init(&task->wait_queue);
36
QLIST_INSERT_HEAD(&s->tasks, task, list);
37
+
38
+ return task;
58
}
39
}
59
40
60
static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
41
/*
61
@@ -XXX,XX +XXX,XX @@ static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
62
return 1;
43
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
63
}
44
64
45
while (bytes) {
65
-static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
46
- BlockCopyTask task;
66
- char **argv)
47
+ g_autofree BlockCopyTask *task = NULL;
67
+static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
48
int64_t next_zero, cur_bytes, status_bytes;
68
+ char **argv)
49
69
{
50
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
70
char *cmd = argv[0];
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
71
52
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
72
if (!init_check_command(blk, ct)) {
53
cur_bytes = next_zero - offset;
73
- return 0;
74
+ return;
75
}
76
77
if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
78
@@ -XXX,XX +XXX,XX @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
79
"bad argument count %d to %s, expected between %d and %d arguments\n",
80
argc-1, cmd, ct->argmin, ct->argmax);
81
}
54
}
82
- return 0;
55
- block_copy_task_begin(s, &task, offset, cur_bytes);
83
+ return;
56
+ task = block_copy_task_create(s, offset, cur_bytes);
84
}
57
85
58
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
86
/* Request additional permissions if necessary for this command. The caller
59
assert(ret >= 0); /* never fail */
87
@@ -XXX,XX +XXX,XX @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
60
cur_bytes = MIN(cur_bytes, status_bytes);
88
ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
61
- block_copy_task_shrink(s, &task, cur_bytes);
89
if (ret < 0) {
62
+ block_copy_task_shrink(s, task, cur_bytes);
90
error_report_err(local_err);
63
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
91
- return 0;
64
- block_copy_task_end(s, &task, 0);
92
+ return;
65
+ block_copy_task_end(s, task, 0);
93
}
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;
94
}
77
}
95
}
96
97
optind = 0;
98
- return ct->cfunc(blk, argc, argv);
99
+ ct->cfunc(blk, argc, argv);
100
}
101
102
static const cmdinfo_t *find_command(const char *cmd)
103
@@ -XXX,XX +XXX,XX @@ static void read_help(void)
104
"\n");
105
}
106
107
-static int read_f(BlockBackend *blk, int argc, char **argv);
108
+static void read_f(BlockBackend *blk, int argc, char **argv);
109
110
static const cmdinfo_t read_cmd = {
111
.name = "read",
112
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t read_cmd = {
113
.help = read_help,
114
};
115
116
-static int read_f(BlockBackend *blk, int argc, char **argv)
117
+static void read_f(BlockBackend *blk, int argc, char **argv)
118
{
119
struct timeval t1, t2;
120
bool Cflag = false, qflag = false, vflag = false;
121
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
122
pattern_count = cvtnum(optarg);
123
if (pattern_count < 0) {
124
print_cvtnum_err(pattern_count, optarg);
125
- return 0;
126
+ return;
127
}
128
break;
129
case 'p':
130
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
131
Pflag = true;
132
pattern = parse_pattern(optarg);
133
if (pattern < 0) {
134
- return 0;
135
+ return;
136
}
137
break;
138
case 'q':
139
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
140
pattern_offset = cvtnum(optarg);
141
if (pattern_offset < 0) {
142
print_cvtnum_err(pattern_offset, optarg);
143
- return 0;
144
+ return;
145
}
146
break;
147
case 'v':
148
vflag = true;
149
break;
150
default:
151
- return qemuio_command_usage(&read_cmd);
152
+ qemuio_command_usage(&read_cmd);
153
+ return;
154
}
155
}
156
157
if (optind != argc - 2) {
158
- return qemuio_command_usage(&read_cmd);
159
+ qemuio_command_usage(&read_cmd);
160
+ return;
161
}
162
163
offset = cvtnum(argv[optind]);
164
if (offset < 0) {
165
print_cvtnum_err(offset, argv[optind]);
166
- return 0;
167
+ return;
168
}
169
170
optind++;
171
count = cvtnum(argv[optind]);
172
if (count < 0) {
173
print_cvtnum_err(count, argv[optind]);
174
- return 0;
175
+ return;
176
} else if (count > BDRV_REQUEST_MAX_BYTES) {
177
printf("length cannot exceed %" PRIu64 ", given %s\n",
178
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
179
- return 0;
180
+ return;
181
}
182
183
if (!Pflag && (lflag || sflag)) {
184
- return qemuio_command_usage(&read_cmd);
185
+ qemuio_command_usage(&read_cmd);
186
+ return;
187
}
188
189
if (!lflag) {
190
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
191
192
if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
193
printf("pattern verification range exceeds end of read data\n");
194
- return 0;
195
+ return;
196
}
197
198
if (bflag) {
199
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
200
printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
201
offset);
202
- return 0;
203
+ return;
204
}
205
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
206
printf("%"PRId64" is not a sector-aligned value for 'count'\n",
207
count);
208
- return 0;
209
+ return;
210
}
211
}
212
213
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
214
215
out:
216
qemu_io_free(buf);
217
-
218
- return 0;
219
}
220
221
static void readv_help(void)
222
@@ -XXX,XX +XXX,XX @@ static void readv_help(void)
223
"\n");
224
}
225
226
-static int readv_f(BlockBackend *blk, int argc, char **argv);
227
+static void readv_f(BlockBackend *blk, int argc, char **argv);
228
229
static const cmdinfo_t readv_cmd = {
230
.name = "readv",
231
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t readv_cmd = {
232
.help = readv_help,
233
};
234
235
-static int readv_f(BlockBackend *blk, int argc, char **argv)
236
+static void readv_f(BlockBackend *blk, int argc, char **argv)
237
{
238
struct timeval t1, t2;
239
bool Cflag = false, qflag = false, vflag = false;
240
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
241
Pflag = true;
242
pattern = parse_pattern(optarg);
243
if (pattern < 0) {
244
- return 0;
245
+ return;
246
}
247
break;
248
case 'q':
249
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
250
vflag = true;
251
break;
252
default:
253
- return qemuio_command_usage(&readv_cmd);
254
+ qemuio_command_usage(&readv_cmd);
255
+ return;
256
}
257
}
258
259
if (optind > argc - 2) {
260
- return qemuio_command_usage(&readv_cmd);
261
+ qemuio_command_usage(&readv_cmd);
262
+ return;
263
}
264
265
266
offset = cvtnum(argv[optind]);
267
if (offset < 0) {
268
print_cvtnum_err(offset, argv[optind]);
269
- return 0;
270
+ return;
271
}
272
optind++;
273
274
nr_iov = argc - optind;
275
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
276
if (buf == NULL) {
277
- return 0;
278
+ return;
279
}
280
281
gettimeofday(&t1, NULL);
282
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
283
out:
284
qemu_iovec_destroy(&qiov);
285
qemu_io_free(buf);
286
- return 0;
287
}
288
289
static void write_help(void)
290
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
291
"\n");
292
}
293
294
-static int write_f(BlockBackend *blk, int argc, char **argv);
295
+static void write_f(BlockBackend *blk, int argc, char **argv);
296
297
static const cmdinfo_t write_cmd = {
298
.name = "write",
299
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = {
300
.help = write_help,
301
};
302
303
-static int write_f(BlockBackend *blk, int argc, char **argv)
304
+static void write_f(BlockBackend *blk, int argc, char **argv)
305
{
306
struct timeval t1, t2;
307
bool Cflag = false, qflag = false, bflag = false;
308
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
309
Pflag = true;
310
pattern = parse_pattern(optarg);
311
if (pattern < 0) {
312
- return 0;
313
+ return;
314
}
315
break;
316
case 'q':
317
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
318
zflag = true;
319
break;
320
default:
321
- return qemuio_command_usage(&write_cmd);
322
+ qemuio_command_usage(&write_cmd);
323
+ return;
324
}
325
}
326
327
if (optind != argc - 2) {
328
- return qemuio_command_usage(&write_cmd);
329
+ qemuio_command_usage(&write_cmd);
330
+ return;
331
}
332
333
if (bflag && zflag) {
334
printf("-b and -z cannot be specified at the same time\n");
335
- return 0;
336
+ return;
337
}
338
339
if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
340
printf("-f and -b or -c cannot be specified at the same time\n");
341
- return 0;
342
+ return;
343
}
344
345
if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
346
printf("-u requires -z to be specified\n");
347
- return 0;
348
+ return;
349
}
350
351
if (zflag && Pflag) {
352
printf("-z and -P cannot be specified at the same time\n");
353
- return 0;
354
+ return;
355
}
356
357
offset = cvtnum(argv[optind]);
358
if (offset < 0) {
359
print_cvtnum_err(offset, argv[optind]);
360
- return 0;
361
+ return;
362
}
363
364
optind++;
365
count = cvtnum(argv[optind]);
366
if (count < 0) {
367
print_cvtnum_err(count, argv[optind]);
368
- return 0;
369
+ return;
370
} else if (count > BDRV_REQUEST_MAX_BYTES) {
371
printf("length cannot exceed %" PRIu64 ", given %s\n",
372
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
373
- return 0;
374
+ return;
375
}
376
377
if (bflag || cflag) {
378
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
379
printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
380
offset);
381
- return 0;
382
+ return;
383
}
384
385
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
386
printf("%"PRId64" is not a sector-aligned value for 'count'\n",
387
count);
388
- return 0;
389
+ return;
390
}
391
}
392
393
@@ -XXX,XX +XXX,XX @@ out:
394
if (!zflag) {
395
qemu_io_free(buf);
396
}
397
-
398
- return 0;
399
}
400
401
static void
402
@@ -XXX,XX +XXX,XX @@ writev_help(void)
403
"\n");
404
}
405
406
-static int writev_f(BlockBackend *blk, int argc, char **argv);
407
+static void writev_f(BlockBackend *blk, int argc, char **argv);
408
409
static const cmdinfo_t writev_cmd = {
410
.name = "writev",
411
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t writev_cmd = {
412
.help = writev_help,
413
};
414
415
-static int writev_f(BlockBackend *blk, int argc, char **argv)
416
+static void writev_f(BlockBackend *blk, int argc, char **argv)
417
{
418
struct timeval t1, t2;
419
bool Cflag = false, qflag = false;
420
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
421
case 'P':
422
pattern = parse_pattern(optarg);
423
if (pattern < 0) {
424
- return 0;
425
+ return;
426
}
427
break;
428
default:
429
- return qemuio_command_usage(&writev_cmd);
430
+ qemuio_command_usage(&writev_cmd);
431
+ return;
432
}
433
}
434
435
if (optind > argc - 2) {
436
- return qemuio_command_usage(&writev_cmd);
437
+ qemuio_command_usage(&writev_cmd);
438
+ return;
439
}
440
441
offset = cvtnum(argv[optind]);
442
if (offset < 0) {
443
print_cvtnum_err(offset, argv[optind]);
444
- return 0;
445
+ return;
446
}
447
optind++;
448
449
nr_iov = argc - optind;
450
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
451
if (buf == NULL) {
452
- return 0;
453
+ return;
454
}
455
456
gettimeofday(&t1, NULL);
457
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
458
out:
459
qemu_iovec_destroy(&qiov);
460
qemu_io_free(buf);
461
- return 0;
462
}
463
464
struct aio_ctx {
465
@@ -XXX,XX +XXX,XX @@ static void aio_read_help(void)
466
"\n");
467
}
468
469
-static int aio_read_f(BlockBackend *blk, int argc, char **argv);
470
+static void aio_read_f(BlockBackend *blk, int argc, char **argv);
471
472
static const cmdinfo_t aio_read_cmd = {
473
.name = "aio_read",
474
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_read_cmd = {
475
.help = aio_read_help,
476
};
477
478
-static int aio_read_f(BlockBackend *blk, int argc, char **argv)
479
+static void aio_read_f(BlockBackend *blk, int argc, char **argv)
480
{
481
int nr_iov, c;
482
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
483
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
484
ctx->pattern = parse_pattern(optarg);
485
if (ctx->pattern < 0) {
486
g_free(ctx);
487
- return 0;
488
+ return;
489
}
490
break;
491
case 'i':
492
printf("injecting invalid read request\n");
493
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
494
g_free(ctx);
495
- return 0;
496
+ return;
497
case 'q':
498
ctx->qflag = true;
499
break;
500
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
501
break;
502
default:
503
g_free(ctx);
504
- return qemuio_command_usage(&aio_read_cmd);
505
+ qemuio_command_usage(&aio_read_cmd);
506
+ return;
507
}
508
}
509
510
if (optind > argc - 2) {
511
g_free(ctx);
512
- return qemuio_command_usage(&aio_read_cmd);
513
+ qemuio_command_usage(&aio_read_cmd);
514
+ return;
515
}
516
517
ctx->offset = cvtnum(argv[optind]);
518
if (ctx->offset < 0) {
519
print_cvtnum_err(ctx->offset, argv[optind]);
520
g_free(ctx);
521
- return 0;
522
+ return;
523
}
524
optind++;
525
526
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
527
if (ctx->buf == NULL) {
528
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
529
g_free(ctx);
530
- return 0;
531
+ return;
532
}
533
534
gettimeofday(&ctx->t1, NULL);
535
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
536
BLOCK_ACCT_READ);
537
blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
538
- return 0;
539
}
540
541
static void aio_write_help(void)
542
@@ -XXX,XX +XXX,XX @@ static void aio_write_help(void)
543
"\n");
544
}
545
546
-static int aio_write_f(BlockBackend *blk, int argc, char **argv);
547
+static void aio_write_f(BlockBackend *blk, int argc, char **argv);
548
549
static const cmdinfo_t aio_write_cmd = {
550
.name = "aio_write",
551
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_write_cmd = {
552
.help = aio_write_help,
553
};
554
555
-static int aio_write_f(BlockBackend *blk, int argc, char **argv)
556
+static void aio_write_f(BlockBackend *blk, int argc, char **argv)
557
{
558
int nr_iov, c;
559
int pattern = 0xcd;
560
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
561
pattern = parse_pattern(optarg);
562
if (pattern < 0) {
563
g_free(ctx);
564
- return 0;
565
+ return;
566
}
567
break;
568
case 'i':
569
printf("injecting invalid write request\n");
570
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
571
g_free(ctx);
572
- return 0;
573
+ return;
574
case 'z':
575
ctx->zflag = true;
576
break;
577
default:
578
g_free(ctx);
579
- return qemuio_command_usage(&aio_write_cmd);
580
+ qemuio_command_usage(&aio_write_cmd);
581
+ return;
582
}
583
}
584
585
if (optind > argc - 2) {
586
g_free(ctx);
587
- return qemuio_command_usage(&aio_write_cmd);
588
+ qemuio_command_usage(&aio_write_cmd);
589
+ return;
590
}
591
592
if (ctx->zflag && optind != argc - 2) {
593
printf("-z supports only a single length parameter\n");
594
g_free(ctx);
595
- return 0;
596
+ return;
597
}
598
599
if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
600
printf("-u requires -z to be specified\n");
601
g_free(ctx);
602
- return 0;
603
+ return;
604
}
605
606
if (ctx->zflag && ctx->Pflag) {
607
printf("-z and -P cannot be specified at the same time\n");
608
g_free(ctx);
609
- return 0;
610
+ return;
611
}
612
613
ctx->offset = cvtnum(argv[optind]);
614
if (ctx->offset < 0) {
615
print_cvtnum_err(ctx->offset, argv[optind]);
616
g_free(ctx);
617
- return 0;
618
+ return;
619
}
620
optind++;
621
622
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
623
if (count < 0) {
624
print_cvtnum_err(count, argv[optind]);
625
g_free(ctx);
626
- return 0;
627
+ return;
628
}
629
630
ctx->qiov.size = count;
631
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
632
if (ctx->buf == NULL) {
633
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
634
g_free(ctx);
635
- return 0;
636
+ return;
637
}
638
639
gettimeofday(&ctx->t1, NULL);
640
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
641
blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
642
ctx);
643
}
644
- return 0;
645
}
646
647
-static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
648
+static void aio_flush_f(BlockBackend *blk, int argc, char **argv)
649
{
650
BlockAcctCookie cookie;
651
block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
652
blk_drain_all();
653
block_acct_done(blk_get_stats(blk), &cookie);
654
- return 0;
655
}
656
657
static const cmdinfo_t aio_flush_cmd = {
658
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_flush_cmd = {
659
.oneline = "completes all outstanding aio requests"
660
};
661
662
-static int flush_f(BlockBackend *blk, int argc, char **argv)
663
+static void flush_f(BlockBackend *blk, int argc, char **argv)
664
{
665
blk_flush(blk);
666
- return 0;
667
}
668
669
static const cmdinfo_t flush_cmd = {
670
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t flush_cmd = {
671
.oneline = "flush all in-core file state to disk",
672
};
673
674
-static int truncate_f(BlockBackend *blk, int argc, char **argv)
675
+static void truncate_f(BlockBackend *blk, int argc, char **argv)
676
{
677
Error *local_err = NULL;
678
int64_t offset;
679
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
680
offset = cvtnum(argv[1]);
681
if (offset < 0) {
682
print_cvtnum_err(offset, argv[1]);
683
- return 0;
684
+ return;
685
}
686
687
ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
688
if (ret < 0) {
689
error_report_err(local_err);
690
- return 0;
691
+ return;
692
}
693
-
694
- return 0;
695
}
696
697
static const cmdinfo_t truncate_cmd = {
698
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t truncate_cmd = {
699
.oneline = "truncates the current file at the given offset",
700
};
701
702
-static int length_f(BlockBackend *blk, int argc, char **argv)
703
+static void length_f(BlockBackend *blk, int argc, char **argv)
704
{
705
int64_t size;
706
char s1[64];
707
@@ -XXX,XX +XXX,XX @@ static int length_f(BlockBackend *blk, int argc, char **argv)
708
size = blk_getlength(blk);
709
if (size < 0) {
710
printf("getlength: %s\n", strerror(-size));
711
- return 0;
712
+ return;
713
}
714
715
cvtstr(size, s1, sizeof(s1));
716
printf("%s\n", s1);
717
- return 0;
718
}
719
720
721
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t length_cmd = {
722
};
723
724
725
-static int info_f(BlockBackend *blk, int argc, char **argv)
726
+static void info_f(BlockBackend *blk, int argc, char **argv)
727
{
728
BlockDriverState *bs = blk_bs(blk);
729
BlockDriverInfo bdi;
730
@@ -XXX,XX +XXX,XX @@ static int info_f(BlockBackend *blk, int argc, char **argv)
731
732
ret = bdrv_get_info(bs, &bdi);
733
if (ret) {
734
- return 0;
735
+ return;
736
}
737
738
cvtstr(bdi.cluster_size, s1, sizeof(s1));
739
@@ -XXX,XX +XXX,XX @@ static int info_f(BlockBackend *blk, int argc, char **argv)
740
bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
741
qapi_free_ImageInfoSpecific(spec_info);
742
}
743
-
744
- return 0;
745
}
746
747
748
@@ -XXX,XX +XXX,XX @@ static void discard_help(void)
749
"\n");
750
}
751
752
-static int discard_f(BlockBackend *blk, int argc, char **argv);
753
+static void discard_f(BlockBackend *blk, int argc, char **argv);
754
755
static const cmdinfo_t discard_cmd = {
756
.name = "discard",
757
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t discard_cmd = {
758
.help = discard_help,
759
};
760
761
-static int discard_f(BlockBackend *blk, int argc, char **argv)
762
+static void discard_f(BlockBackend *blk, int argc, char **argv)
763
{
764
struct timeval t1, t2;
765
bool Cflag = false, qflag = false;
766
@@ -XXX,XX +XXX,XX @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
767
qflag = true;
768
break;
769
default:
770
- return qemuio_command_usage(&discard_cmd);
771
+ qemuio_command_usage(&discard_cmd);
772
+ return;
773
}
774
}
775
776
if (optind != argc - 2) {
777
- return qemuio_command_usage(&discard_cmd);
778
+ qemuio_command_usage(&discard_cmd);
779
+ return;
780
}
781
782
offset = cvtnum(argv[optind]);
783
if (offset < 0) {
784
print_cvtnum_err(offset, argv[optind]);
785
- return 0;
786
+ return;
787
}
788
789
optind++;
790
bytes = cvtnum(argv[optind]);
791
if (bytes < 0) {
792
print_cvtnum_err(bytes, argv[optind]);
793
- return 0;
794
+ return;
795
} else if (bytes >> BDRV_SECTOR_BITS > BDRV_REQUEST_MAX_SECTORS) {
796
printf("length cannot exceed %"PRIu64", given %s\n",
797
(uint64_t)BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS,
798
argv[optind]);
799
- return 0;
800
+ return;
801
}
802
803
gettimeofday(&t1, NULL);
804
@@ -XXX,XX +XXX,XX @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
805
806
if (ret < 0) {
807
printf("discard failed: %s\n", strerror(-ret));
808
- goto out;
809
+ return;
810
}
811
812
/* Finally, report back -- -C gives a parsable format */
813
@@ -XXX,XX +XXX,XX @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
814
t2 = tsub(t2, t1);
815
print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
816
}
817
-
818
-out:
819
- return 0;
820
}
821
822
-static int alloc_f(BlockBackend *blk, int argc, char **argv)
823
+static void alloc_f(BlockBackend *blk, int argc, char **argv)
824
{
825
BlockDriverState *bs = blk_bs(blk);
826
int64_t offset, start, remaining, count;
827
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
828
start = offset = cvtnum(argv[1]);
829
if (offset < 0) {
830
print_cvtnum_err(offset, argv[1]);
831
- return 0;
832
+ return;
833
}
834
835
if (argc == 3) {
836
count = cvtnum(argv[2]);
837
if (count < 0) {
838
print_cvtnum_err(count, argv[2]);
839
- return 0;
840
+ return;
841
}
842
} else {
843
count = BDRV_SECTOR_SIZE;
844
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
845
ret = bdrv_is_allocated(bs, offset, remaining, &num);
846
if (ret < 0) {
847
printf("is_allocated failed: %s\n", strerror(-ret));
848
- return 0;
849
+ return;
850
}
851
offset += num;
852
remaining -= num;
853
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
854
855
printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
856
sum_alloc, count, s1);
857
- return 0;
858
}
859
860
static const cmdinfo_t alloc_cmd = {
861
@@ -XXX,XX +XXX,XX @@ static int map_is_allocated(BlockDriverState *bs, int64_t offset,
862
return firstret;
863
}
864
865
-static int map_f(BlockBackend *blk, int argc, char **argv)
866
+static void map_f(BlockBackend *blk, int argc, char **argv)
867
{
868
int64_t offset, bytes;
869
char s1[64], s2[64];
870
@@ -XXX,XX +XXX,XX @@ static int map_f(BlockBackend *blk, int argc, char **argv)
871
bytes = blk_getlength(blk);
872
if (bytes < 0) {
873
error_report("Failed to query image length: %s", strerror(-bytes));
874
- return 0;
875
+ return;
876
}
877
878
while (bytes) {
879
ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
880
if (ret < 0) {
881
error_report("Failed to get allocation status: %s", strerror(-ret));
882
- return 0;
883
+ return;
884
} else if (!num) {
885
error_report("Unexpected end of image");
886
- return 0;
887
+ return;
888
}
889
890
retstr = ret ? " allocated" : "not allocated";
891
@@ -XXX,XX +XXX,XX @@ static int map_f(BlockBackend *blk, int argc, char **argv)
892
offset += num;
893
bytes -= num;
894
}
895
-
896
- return 0;
897
}
898
899
static const cmdinfo_t map_cmd = {
900
@@ -XXX,XX +XXX,XX @@ static void reopen_help(void)
901
"\n");
902
}
903
904
-static int reopen_f(BlockBackend *blk, int argc, char **argv);
905
+static void reopen_f(BlockBackend *blk, int argc, char **argv);
906
907
static QemuOptsList reopen_opts = {
908
.name = "reopen",
909
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t reopen_cmd = {
910
.help = reopen_help,
911
};
912
913
-static int reopen_f(BlockBackend *blk, int argc, char **argv)
914
+static void reopen_f(BlockBackend *blk, int argc, char **argv)
915
{
916
BlockDriverState *bs = blk_bs(blk);
917
QemuOpts *qopts;
918
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
919
case 'c':
920
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
921
error_report("Invalid cache option: %s", optarg);
922
- return 0;
923
+ return;
924
}
925
break;
926
case 'o':
927
if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
928
qemu_opts_reset(&reopen_opts);
929
- return 0;
930
+ return;
931
}
932
break;
933
case 'r':
934
if (has_rw_option) {
935
error_report("Only one -r/-w option may be given");
936
- return 0;
937
+ return;
938
}
939
flags &= ~BDRV_O_RDWR;
940
has_rw_option = true;
941
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
942
case 'w':
943
if (has_rw_option) {
944
error_report("Only one -r/-w option may be given");
945
- return 0;
946
+ return;
947
}
948
flags |= BDRV_O_RDWR;
949
has_rw_option = true;
950
break;
951
default:
952
qemu_opts_reset(&reopen_opts);
953
- return qemuio_command_usage(&reopen_cmd);
954
+ qemuio_command_usage(&reopen_cmd);
955
+ return;
956
}
957
}
958
959
if (optind != argc) {
960
qemu_opts_reset(&reopen_opts);
961
- return qemuio_command_usage(&reopen_cmd);
962
+ qemuio_command_usage(&reopen_cmd);
963
+ return;
964
}
965
966
if (writethrough != blk_enable_write_cache(blk) &&
967
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
968
{
969
error_report("Cannot change cache.writeback: Device attached");
970
qemu_opts_reset(&reopen_opts);
971
- return 0;
972
+ return;
973
}
974
975
if (!(flags & BDRV_O_RDWR)) {
976
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
977
} else {
978
blk_set_enable_write_cache(blk, !writethrough);
979
}
980
-
981
- return 0;
982
}
983
984
-static int break_f(BlockBackend *blk, int argc, char **argv)
985
+static void break_f(BlockBackend *blk, int argc, char **argv)
986
{
987
int ret;
988
989
@@ -XXX,XX +XXX,XX @@ static int break_f(BlockBackend *blk, int argc, char **argv)
990
if (ret < 0) {
991
printf("Could not set breakpoint: %s\n", strerror(-ret));
992
}
993
-
994
- return 0;
995
}
996
997
-static int remove_break_f(BlockBackend *blk, int argc, char **argv)
998
+static void remove_break_f(BlockBackend *blk, int argc, char **argv)
999
{
1000
int ret;
1001
1002
@@ -XXX,XX +XXX,XX @@ static int remove_break_f(BlockBackend *blk, int argc, char **argv)
1003
if (ret < 0) {
1004
printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1005
}
1006
-
1007
- return 0;
1008
}
1009
1010
static const cmdinfo_t break_cmd = {
1011
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t remove_break_cmd = {
1012
.oneline = "remove a breakpoint by tag",
1013
};
1014
1015
-static int resume_f(BlockBackend *blk, int argc, char **argv)
1016
+static void resume_f(BlockBackend *blk, int argc, char **argv)
1017
{
1018
int ret;
1019
1020
@@ -XXX,XX +XXX,XX @@ static int resume_f(BlockBackend *blk, int argc, char **argv)
1021
if (ret < 0) {
1022
printf("Could not resume request: %s\n", strerror(-ret));
1023
}
1024
-
1025
- return 0;
1026
}
1027
1028
static const cmdinfo_t resume_cmd = {
1029
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t resume_cmd = {
1030
.oneline = "resumes the request tagged as tag",
1031
};
1032
1033
-static int wait_break_f(BlockBackend *blk, int argc, char **argv)
1034
+static void wait_break_f(BlockBackend *blk, int argc, char **argv)
1035
{
1036
while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
1037
aio_poll(blk_get_aio_context(blk), true);
1038
}
1039
-
1040
- return 0;
1041
}
1042
1043
static const cmdinfo_t wait_break_cmd = {
1044
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t wait_break_cmd = {
1045
.oneline = "waits for the suspension of a request",
1046
};
1047
1048
-static int abort_f(BlockBackend *blk, int argc, char **argv)
1049
+static void abort_f(BlockBackend *blk, int argc, char **argv)
1050
{
1051
abort();
1052
}
1053
@@ -XXX,XX +XXX,XX @@ static void sigraise_help(void)
1054
"\n", SIGTERM);
1055
}
1056
1057
-static int sigraise_f(BlockBackend *blk, int argc, char **argv);
1058
+static void sigraise_f(BlockBackend *blk, int argc, char **argv);
1059
1060
static const cmdinfo_t sigraise_cmd = {
1061
.name = "sigraise",
1062
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t sigraise_cmd = {
1063
.help = sigraise_help,
1064
};
1065
1066
-static int sigraise_f(BlockBackend *blk, int argc, char **argv)
1067
+static void sigraise_f(BlockBackend *blk, int argc, char **argv)
1068
{
1069
int64_t sig = cvtnum(argv[1]);
1070
if (sig < 0) {
1071
print_cvtnum_err(sig, argv[1]);
1072
- return 0;
1073
+ return;
1074
} else if (sig > NSIG) {
1075
printf("signal argument '%s' is too large to be a valid signal\n",
1076
argv[1]);
1077
- return 0;
1078
+ return;
1079
}
1080
1081
/* Using raise() to kill this process does not necessarily flush all open
1082
@@ -XXX,XX +XXX,XX @@ static int sigraise_f(BlockBackend *blk, int argc, char **argv)
1083
fflush(stderr);
1084
1085
raise(sig);
1086
- return 0;
1087
}
1088
1089
static void sleep_cb(void *opaque)
1090
@@ -XXX,XX +XXX,XX @@ static void sleep_cb(void *opaque)
1091
*expired = true;
1092
}
1093
1094
-static int sleep_f(BlockBackend *blk, int argc, char **argv)
1095
+static void sleep_f(BlockBackend *blk, int argc, char **argv)
1096
{
1097
char *endptr;
1098
long ms;
1099
@@ -XXX,XX +XXX,XX @@ static int sleep_f(BlockBackend *blk, int argc, char **argv)
1100
ms = strtol(argv[1], &endptr, 0);
1101
if (ms < 0 || *endptr != '\0') {
1102
printf("%s is not a valid number\n", argv[1]);
1103
- return 0;
1104
+ return;
1105
}
1106
1107
timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
1108
@@ -XXX,XX +XXX,XX @@ static int sleep_f(BlockBackend *blk, int argc, char **argv)
1109
}
1110
1111
timer_free(timer);
1112
-
1113
- return 0;
1114
}
1115
1116
static const cmdinfo_t sleep_cmd = {
1117
@@ -XXX,XX +XXX,XX @@ static void help_all(void)
1118
printf("\nUse 'help commandname' for extended help.\n");
1119
}
1120
1121
-static int help_f(BlockBackend *blk, int argc, char **argv)
1122
+static void help_f(BlockBackend *blk, int argc, char **argv)
1123
{
1124
const cmdinfo_t *ct;
1125
1126
if (argc == 1) {
1127
help_all();
1128
- return 0;
1129
+ return;
1130
}
1131
1132
ct = find_command(argv[1]);
1133
if (ct == NULL) {
1134
printf("command %s not found\n", argv[1]);
1135
- return 0;
1136
+ return;
1137
}
1138
1139
help_onecmd(argv[1], ct);
1140
- return 0;
1141
}
1142
1143
static const cmdinfo_t help_cmd = {
1144
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t help_cmd = {
1145
.oneline = "help for one or all commands",
1146
};
1147
1148
-bool qemuio_command(BlockBackend *blk, const char *cmd)
1149
+void qemuio_command(BlockBackend *blk, const char *cmd)
1150
{
1151
AioContext *ctx;
1152
char *input;
1153
const cmdinfo_t *ct;
1154
char **v;
1155
int c;
1156
- bool done = false;
1157
1158
input = g_strdup(cmd);
1159
v = breakline(input, &c);
1160
@@ -XXX,XX +XXX,XX @@ bool qemuio_command(BlockBackend *blk, const char *cmd)
1161
if (ct) {
1162
ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
1163
aio_context_acquire(ctx);
1164
- done = command(blk, ct, c, v);
1165
+ command(blk, ct, c, v);
1166
aio_context_release(ctx);
1167
} else {
1168
fprintf(stderr, "command \"%s\" not found\n", v[0]);
1169
@@ -XXX,XX +XXX,XX @@ bool qemuio_command(BlockBackend *blk, const char *cmd)
1170
}
1171
g_free(input);
1172
g_free(v);
1173
-
1174
- return done;
1175
}
1176
1177
static void __attribute((constructor)) init_qemuio_commands(void)
1178
diff --git a/qemu-io.c b/qemu-io.c
1179
index XXXXXXX..XXXXXXX 100644
1180
--- a/qemu-io.c
1181
+++ b/qemu-io.c
1182
@@ -XXX,XX +XXX,XX @@
1183
static char *progname;
1184
1185
static BlockBackend *qemuio_blk;
1186
+static bool quit_qemu_io;
1187
1188
/* qemu-io commands passed using -c */
1189
static int ncmdline;
1190
@@ -XXX,XX +XXX,XX @@ static int get_eof_char(void)
1191
#endif
1192
}
1193
1194
-static int close_f(BlockBackend *blk, int argc, char **argv)
1195
+static void close_f(BlockBackend *blk, int argc, char **argv)
1196
{
1197
blk_unref(qemuio_blk);
1198
qemuio_blk = NULL;
1199
- return 0;
1200
}
1201
1202
static const cmdinfo_t close_cmd = {
1203
@@ -XXX,XX +XXX,XX @@ static void open_help(void)
1204
"\n");
1205
}
1206
1207
-static int open_f(BlockBackend *blk, int argc, char **argv);
1208
+static void open_f(BlockBackend *blk, int argc, char **argv);
1209
1210
static const cmdinfo_t open_cmd = {
1211
.name = "open",
1212
@@ -XXX,XX +XXX,XX @@ static QemuOptsList empty_opts = {
1213
},
1214
};
1215
1216
-static int open_f(BlockBackend *blk, int argc, char **argv)
1217
+static void open_f(BlockBackend *blk, int argc, char **argv)
1218
{
1219
int flags = BDRV_O_UNMAP;
1220
int readonly = 0;
1221
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
1222
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
1223
error_report("Invalid cache option: %s", optarg);
1224
qemu_opts_reset(&empty_opts);
1225
- return 0;
1226
+ return;
1227
}
1228
break;
1229
case 'd':
1230
if (bdrv_parse_discard_flags(optarg, &flags) < 0) {
1231
error_report("Invalid discard option: %s", optarg);
1232
qemu_opts_reset(&empty_opts);
1233
- return 0;
1234
+ return;
1235
}
1236
break;
1237
case 'o':
1238
if (imageOpts) {
1239
printf("--image-opts and 'open -o' are mutually exclusive\n");
1240
qemu_opts_reset(&empty_opts);
1241
- return 0;
1242
+ return;
1243
}
1244
if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) {
1245
qemu_opts_reset(&empty_opts);
1246
- return 0;
1247
+ return;
1248
}
1249
break;
1250
case 'U':
1251
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
1252
break;
1253
default:
1254
qemu_opts_reset(&empty_opts);
1255
- return qemuio_command_usage(&open_cmd);
1256
+ qemuio_command_usage(&open_cmd);
1257
+ return;
1258
}
1259
}
1260
1261
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
1262
if (imageOpts && (optind == argc - 1)) {
1263
if (!qemu_opts_parse_noisily(&empty_opts, argv[optind], false)) {
1264
qemu_opts_reset(&empty_opts);
1265
- return 0;
1266
+ return;
1267
}
1268
optind++;
1269
}
1270
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
1271
qobject_unref(opts);
1272
qemuio_command_usage(&open_cmd);
1273
}
1274
- return 0;
1275
}
1276
1277
-static int quit_f(BlockBackend *blk, int argc, char **argv)
1278
+static void quit_f(BlockBackend *blk, int argc, char **argv)
1279
{
1280
- return 1;
1281
+ quit_qemu_io = true;
1282
}
1283
1284
static const cmdinfo_t quit_cmd = {
1285
@@ -XXX,XX +XXX,XX @@ static void prep_fetchline(void *opaque)
1286
1287
static void command_loop(void)
1288
{
1289
- int i, done = 0, fetchable = 0, prompted = 0;
1290
+ int i, fetchable = 0, prompted = 0;
1291
char *input;
1292
1293
- for (i = 0; !done && i < ncmdline; i++) {
1294
- done = qemuio_command(qemuio_blk, cmdline[i]);
1295
+ for (i = 0; !quit_qemu_io && i < ncmdline; i++) {
1296
+ qemuio_command(qemuio_blk, cmdline[i]);
1297
}
1298
if (cmdline) {
1299
g_free(cmdline);
1300
return;
1301
}
1302
1303
- while (!done) {
1304
+ while (!quit_qemu_io) {
1305
if (!prompted) {
1306
printf("%s", get_prompt());
1307
fflush(stdout);
1308
@@ -XXX,XX +XXX,XX @@ static void command_loop(void)
1309
if (input == NULL) {
1310
break;
1311
}
1312
- done = qemuio_command(qemuio_blk, input);
1313
+ qemuio_command(qemuio_blk, input);
1314
g_free(input);
1315
1316
prompted = 0;
1317
--
78
--
1318
2.17.1
79
2.26.2
1319
80
1320
81
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
This assert may fail, because bitmap_table is not initialized. Just
3
We are going to use aio-task-pool API, so we'll need state pointer in
4
drop it, as it's obvious, that bitmap_table_load sets bitmap_table
4
BlockCopyTask anyway. Add it now and use where possible.
5
parameter only when returning zero.
6
5
7
Reported-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-id: 20180608101225.2575-1-vsementsov@virtuozzo.com
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200429130847.28124-4-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
10
---
12
block/qcow2-bitmap.c | 1 -
11
block/block-copy.c | 28 +++++++++++++++-------------
13
1 file changed, 1 deletion(-)
12
1 file changed, 15 insertions(+), 13 deletions(-)
14
13
15
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
14
diff --git a/block/block-copy.c b/block/block-copy.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2-bitmap.c
16
--- a/block/block-copy.c
18
+++ b/block/qcow2-bitmap.c
17
+++ b/block/block-copy.c
19
@@ -XXX,XX +XXX,XX @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
18
@@ -XXX,XX +XXX,XX @@
20
19
#define BLOCK_COPY_MAX_MEM (128 * MiB)
21
ret = bitmap_table_load(bs, tb, &bitmap_table);
20
21
typedef struct BlockCopyTask {
22
+ BlockCopyState *s;
23
int64_t offset;
24
int64_t bytes;
25
QLIST_ENTRY(BlockCopyTask) list;
26
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
27
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
28
s->in_flight_bytes += bytes;
29
30
- task->offset = offset;
31
- task->bytes = bytes;
32
+ *task = (BlockCopyTask) {
33
+ .s = s,
34
+ .offset = offset,
35
+ .bytes = bytes,
36
+ };
37
qemu_co_queue_init(&task->wait_queue);
38
QLIST_INSERT_HEAD(&s->tasks, task, list);
39
40
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
41
* wake up all tasks waiting for us (may be some of them are not intersecting
42
* with shrunk task)
43
*/
44
-static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
45
- BlockCopyTask *task,
46
+static void coroutine_fn block_copy_task_shrink(BlockCopyTask *task,
47
int64_t new_bytes)
48
{
49
if (new_bytes == task->bytes) {
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_shrink(BlockCopyState *s,
51
52
assert(new_bytes > 0 && new_bytes < task->bytes);
53
54
- s->in_flight_bytes -= task->bytes - new_bytes;
55
- bdrv_set_dirty_bitmap(s->copy_bitmap,
56
+ task->s->in_flight_bytes -= task->bytes - new_bytes;
57
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap,
58
task->offset + new_bytes, task->bytes - new_bytes);
59
60
task->bytes = new_bytes;
61
qemu_co_queue_restart_all(&task->wait_queue);
62
}
63
64
-static void coroutine_fn block_copy_task_end(BlockCopyState *s,
65
- BlockCopyTask *task, int ret)
66
+static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
67
{
68
- s->in_flight_bytes -= task->bytes;
69
+ task->s->in_flight_bytes -= task->bytes;
22
if (ret < 0) {
70
if (ret < 0) {
23
- assert(bitmap_table == NULL);
71
- bdrv_set_dirty_bitmap(s->copy_bitmap, task->offset, task->bytes);
24
return ret;
72
+ bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
25
}
73
}
26
74
QLIST_REMOVE(task, list);
75
qemu_co_queue_restart_all(&task->wait_queue);
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
77
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
78
assert(ret >= 0); /* never fail */
79
cur_bytes = MIN(cur_bytes, status_bytes);
80
- block_copy_task_shrink(s, task, cur_bytes);
81
+ block_copy_task_shrink(task, cur_bytes);
82
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
83
- block_copy_task_end(s, task, 0);
84
+ block_copy_task_end(task, 0);
85
progress_set_remaining(s->progress,
86
bdrv_get_dirty_count(s->copy_bitmap) +
87
s->in_flight_bytes);
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
89
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
90
error_is_read);
91
co_put_to_shres(s->mem, cur_bytes);
92
- block_copy_task_end(s, task, ret);
93
+ block_copy_task_end(task, ret);
94
if (ret < 0) {
95
return ret;
96
}
27
--
97
--
28
2.17.1
98
2.26.2
29
99
30
100
diff view generated by jsdifflib
1
When creating a file, we should take the WRITE and RESIZE permissions.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
We do not need either for the creation itself, but we do need them for
3
clearing and resizing it. So we can take the proper permissions by
4
replacing O_TRUNC with an explicit truncation to 0, and by taking the
5
appropriate file locks between those two steps.
6
2
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Instead of just relying on the comment "Called only on full-dirty
8
Message-id: 20180509215336.31304-3-mreitz@redhat.com
4
region" in block_copy_task_create() let's move initial dirty area
9
Reviewed-by: Fam Zheng <famz@redhat.com>
5
search directly to block_copy_task_create(). Let's also use effective
6
bdrv_dirty_bitmap_next_dirty_area instead of looping through all
7
non-dirty clusters.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200429130847.28124-5-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
13
---
12
block/file-posix.c | 37 +++++++++++++++++++++++++++++++++++--
14
block/block-copy.c | 80 ++++++++++++++++++++++++++--------------------
13
1 file changed, 35 insertions(+), 2 deletions(-)
15
1 file changed, 46 insertions(+), 34 deletions(-)
14
16
15
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/block/block-copy.c b/block/block-copy.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
19
--- a/block/block-copy.c
18
+++ b/block/file-posix.c
20
+++ b/block/block-copy.c
19
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyTask {
22
CoQueue wait_queue; /* coroutines blocked on this task */
23
} BlockCopyTask;
24
25
+static int64_t task_end(BlockCopyTask *task)
26
+{
27
+ return task->offset + task->bytes;
28
+}
29
+
30
typedef struct BlockCopyState {
31
/*
32
* BdrvChild objects are not owned or managed by block-copy. They are
33
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
34
return true;
35
}
36
37
-/* Called only on full-dirty region */
38
+/*
39
+ * Search for the first dirty area in offset/bytes range and create task at
40
+ * the beginning of it.
41
+ */
42
static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
43
int64_t offset, int64_t bytes)
20
{
44
{
21
BlockdevCreateOptionsFile *file_opts;
45
- BlockCopyTask *task = g_new(BlockCopyTask, 1);
22
int fd;
46
+ BlockCopyTask *task;
23
+ int perm, shared;
47
24
int result = 0;
48
+ if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap,
25
49
+ offset, offset + bytes,
26
/* Validate options and set default values */
50
+ s->copy_size, &offset, &bytes))
27
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
51
+ {
28
}
52
+ return NULL;
29
30
/* Create file */
31
- fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
32
- 0644);
33
+ fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644);
34
if (fd < 0) {
35
result = -errno;
36
error_setg_errno(errp, -result, "Could not create file");
37
goto out;
38
}
39
40
+ /* Take permissions: We want to discard everything, so we need
41
+ * BLK_PERM_WRITE; and truncation to the desired size requires
42
+ * BLK_PERM_RESIZE.
43
+ * On the other hand, we cannot share the RESIZE permission
44
+ * because we promise that after this function, the file has the
45
+ * size given in the options. If someone else were to resize it
46
+ * concurrently, we could not guarantee that.
47
+ * Note that after this function, we can no longer guarantee that
48
+ * the file is not touched by a third party, so it may be resized
49
+ * then. */
50
+ perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
51
+ shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
52
+
53
+ /* Step one: Take locks */
54
+ result = raw_apply_lock_bytes(fd, perm, shared, false, errp);
55
+ if (result < 0) {
56
+ goto out_close;
57
+ }
53
+ }
58
+
54
+
59
+ /* Step two: Check that nobody else has taken conflicting locks */
55
+ /* region is dirty, so no existent tasks possible in it */
60
+ result = raw_check_lock_bytes(fd, perm, shared, errp);
56
assert(!find_conflicting_task(s, offset, bytes));
61
+ if (result < 0) {
57
62
+ goto out_close;
58
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
63
+ }
59
s->in_flight_bytes += bytes;
64
+
60
65
+ /* Clear the file by truncating it to 0 */
61
+ task = g_new(BlockCopyTask, 1);
66
+ result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
62
*task = (BlockCopyTask) {
67
+ if (result < 0) {
63
.s = s,
68
+ goto out_close;
64
.offset = offset,
69
+ }
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
70
+
66
{
71
if (file_opts->nocow) {
67
int ret = 0;
72
#ifdef __linux__
68
bool found_dirty = false;
73
/* Set NOCOW flag to solve performance issue on fs like btrfs.
69
+ int64_t end = offset + bytes;
74
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
70
75
#endif
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;
76
}
155
}
77
156
78
+ /* Resize and potentially preallocate the file to the desired
157
return found_dirty;
79
+ * final size */
80
result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
81
errp);
82
if (result < 0) {
83
--
158
--
84
2.17.1
159
2.26.2
85
160
86
161
diff view generated by jsdifflib
Deleted patch
1
Instead of checking whether a driver has a non-NULL create_opts we
2
should check whether it supports image amendment in the first place. If
3
it does, it must have create_opts.
4
1
5
On the other hand, if it does not have create_opts (so it does not
6
support amendment either), the error message "does not support any
7
options" is a bit useless. Stating clearly that the driver has no
8
amendment support whatsoever is probably better.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Message-id: 20180509210023.20283-2-mreitz@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
qemu-img.c | 7 +++++--
17
1 file changed, 5 insertions(+), 2 deletions(-)
18
19
diff --git a/qemu-img.c b/qemu-img.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/qemu-img.c
22
+++ b/qemu-img.c
23
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
24
goto out;
25
}
26
27
- if (!bs->drv->create_opts) {
28
- error_report("Format driver '%s' does not support any options to amend",
29
+ if (!bs->drv->bdrv_amend_options) {
30
+ error_report("Format driver '%s' does not support option amendment",
31
fmt);
32
ret = -1;
33
goto out;
34
}
35
36
+ /* Every driver supporting amendment must have create_opts */
37
+ assert(bs->drv->create_opts);
38
+
39
create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
40
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
41
qemu_opts_do_parse(opts, options, NULL, &err);
42
--
43
2.17.1
44
45
diff view generated by jsdifflib
Deleted patch
1
It really is up to the caller to decide what this list of options means.
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: John Snow <jsnow@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-id: 20180509210023.20283-4-mreitz@redhat.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
qemu-img.c | 1 +
10
util/qemu-option.c | 1 -
11
2 files changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/qemu-img.c b/qemu-img.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/qemu-img.c
16
+++ b/qemu-img.c
17
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
18
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
19
}
20
21
+ printf("Supported options:\n");
22
qemu_opts_print_help(create_opts);
23
qemu_opts_free(create_opts);
24
return 0;
25
diff --git a/util/qemu-option.c b/util/qemu-option.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/util/qemu-option.c
28
+++ b/util/qemu-option.c
29
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
30
31
assert(list);
32
desc = list->desc;
33
- printf("Supported options:\n");
34
while (desc && desc->name) {
35
printf("%-16s %s\n", desc->name,
36
desc->help ? desc->help : "No description available");
37
--
38
2.17.1
39
40
diff view generated by jsdifflib
1
The more generic print_block_option_help() function is not really
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
suitable for qemu-img amend, for a couple of reasons:
2
3
(1) We do not need to append the protocol-level options, as amendment
3
Run block_copy iterations in parallel in aio tasks.
4
happens only on one node and does not descend downwards to its
4
5
children.
5
Changes:
6
(2) print_block_option_help() says those options are "supported". For
6
- BlockCopyTask becomes aio task structure. Add zeroes field to pass
7
option amendment, we do not really know that. So this new function
7
it to block_copy_do_copy
8
explicitly says that those options are the creation options, and not
8
- add call state - it's a state of one call of block_copy(), shared
9
all of them may be supported.
9
between parallel tasks. For now used only to keep information about
10
(3) If the driver does not support option amendment, we should not print
10
first error: is it read or not.
11
anything (except for an error message that amendment is not
11
- convert block_copy_dirty_clusters to aio-task loop.
12
supported).
12
13
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1537956
14
Message-Id: <20200429130847.28124-6-vsementsov@virtuozzo.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: John Snow <jsnow@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
18
Message-id: 20180509210023.20283-5-mreitz@redhat.com
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
16
---
21
qemu-img.c | 30 ++++++++++++++++++++++++--
17
block/block-copy.c | 119 ++++++++++++++++++++++++++++++++++++++++-----
22
tests/qemu-iotests/082.out | 44 +++++++++++++++++++++++---------------
18
1 file changed, 106 insertions(+), 13 deletions(-)
23
2 files changed, 55 insertions(+), 19 deletions(-)
19
24
20
diff --git a/block/block-copy.c b/block/block-copy.c
25
diff --git a/qemu-img.c b/qemu-img.c
26
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
22
--- a/block/block-copy.c
28
+++ b/qemu-img.c
23
+++ b/block/block-copy.c
29
@@ -XXX,XX +XXX,XX @@ static void amend_status_cb(BlockDriverState *bs,
24
@@ -XXX,XX +XXX,XX @@
30
qemu_progress_print(100.f * offset / total_work_size, 0);
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;
31
}
74
}
32
75
33
+static int print_amend_option_help(const char *format)
76
+/*
77
+ * Takes ownership of @task
78
+ *
79
+ * If pool is NULL directly run the task, otherwise schedule it into the pool.
80
+ *
81
+ * Returns: task.func return code if pool is NULL
82
+ * otherwise -ECANCELED if pool status is bad
83
+ * otherwise 0 (successfully scheduled)
84
+ */
85
+static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
86
+ BlockCopyTask *task)
34
+{
87
+{
35
+ BlockDriver *drv;
88
+ if (!pool) {
36
+
89
+ int ret = task->task.func(&task->task);
37
+ /* Find driver and parse its options */
90
+
38
+ drv = bdrv_find_format(format);
91
+ g_free(task);
39
+ if (!drv) {
92
+ return ret;
40
+ error_report("Unknown file format '%s'", format);
93
+ }
41
+ return 1;
94
+
42
+ }
95
+ aio_task_pool_wait_slot(pool);
43
+
96
+ if (aio_task_pool_status(pool) < 0) {
44
+ if (!drv->bdrv_amend_options) {
97
+ co_put_to_shres(task->s->mem, task->bytes);
45
+ error_report("Format driver '%s' does not support option amendment",
98
+ block_copy_task_end(task, -ECANCELED);
46
+ format);
99
+ g_free(task);
47
+ return 1;
100
+ return -ECANCELED;
48
+ }
101
+ }
49
+
102
+
50
+ /* Every driver supporting amendment must have create_opts */
103
+ aio_task_pool_start_task(pool, &task->task);
51
+ assert(drv->create_opts);
104
+
52
+
53
+ printf("Creation options for '%s':\n", format);
54
+ qemu_opts_print_help(drv->create_opts);
55
+ printf("\nNote that not all of these options may be amendable.\n");
56
+ return 0;
105
+ return 0;
57
+}
106
+}
58
+
107
+
59
static int img_amend(int argc, char **argv)
108
/*
109
* block_copy_do_copy
110
*
111
@@ -XXX,XX +XXX,XX @@ out:
112
return ret;
113
}
114
115
+static coroutine_fn int block_copy_task_entry(AioTask *task)
116
+{
117
+ BlockCopyTask *t = container_of(task, BlockCopyTask, task);
118
+ bool error_is_read;
119
+ int ret;
120
+
121
+ ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
122
+ &error_is_read);
123
+ if (ret < 0 && !t->call_state->failed) {
124
+ t->call_state->failed = true;
125
+ t->call_state->error_is_read = error_is_read;
126
+ } else {
127
+ progress_work_done(t->s->progress, t->bytes);
128
+ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
129
+ }
130
+ co_put_to_shres(t->s->mem, t->bytes);
131
+ block_copy_task_end(t, ret);
132
+
133
+ return ret;
134
+}
135
+
136
static int block_copy_block_status(BlockCopyState *s, int64_t offset,
137
int64_t bytes, int64_t *pnum)
60
{
138
{
61
Error *err = NULL;
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
62
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
140
int ret = 0;
63
if (fmt && has_help_option(options)) {
141
bool found_dirty = false;
64
/* If a format is explicitly specified (and possibly no filename is
142
int64_t end = offset + bytes;
65
* given), print option help here */
143
+ AioTaskPool *aio = NULL;
66
- ret = print_block_option_help(filename, fmt);
144
+ BlockCopyCallState call_state = {false, false};
67
+ ret = print_amend_option_help(fmt);
145
68
goto out;
146
/*
147
* block_copy() user is responsible for keeping source and target in same
148
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
149
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
150
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
151
152
- while (bytes) {
153
- g_autofree BlockCopyTask *task = NULL;
154
+ while (bytes && aio_task_pool_status(aio) == 0) {
155
+ BlockCopyTask *task;
156
int64_t status_bytes;
157
158
- task = block_copy_task_create(s, offset, bytes);
159
+ task = block_copy_task_create(s, &call_state, offset, bytes);
160
if (!task) {
161
/* No more dirty bits in the bitmap */
162
trace_block_copy_skip_range(s, offset, bytes);
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
164
}
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;
69
}
220
}
70
221
71
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
222
- return found_dirty;
72
223
+ return ret < 0 ? ret : found_dirty;
73
if (has_help_option(options)) {
224
}
74
/* If the format was auto-detected, print option help here */
225
75
- ret = print_block_option_help(filename, fmt);
226
/*
76
+ ret = print_amend_option_help(fmt);
77
goto out;
78
}
79
80
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
81
index XXXXXXX..XXXXXXX 100644
82
--- a/tests/qemu-iotests/082.out
83
+++ b/tests/qemu-iotests/082.out
84
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
85
=== amend: help for -o ===
86
87
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
88
-Supported options:
89
+Creation options for 'qcow2':
90
size Virtual disk size
91
compat Compatibility level (0.10 or 1.1)
92
backing_file File name of a base image
93
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
94
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
95
lazy_refcounts Postpone refcount updates
96
refcount_bits Width of a reference count entry in bits
97
-nocow Turn off copy-on-write (valid only on btrfs)
98
+
99
+Note that not all of these options may be amendable.
100
101
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
102
-Supported options:
103
+Creation options for 'qcow2':
104
size Virtual disk size
105
compat Compatibility level (0.10 or 1.1)
106
backing_file File name of a base image
107
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
108
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
109
lazy_refcounts Postpone refcount updates
110
refcount_bits Width of a reference count entry in bits
111
-nocow Turn off copy-on-write (valid only on btrfs)
112
+
113
+Note that not all of these options may be amendable.
114
115
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
116
-Supported options:
117
+Creation options for 'qcow2':
118
size Virtual disk size
119
compat Compatibility level (0.10 or 1.1)
120
backing_file File name of a base image
121
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
122
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
123
lazy_refcounts Postpone refcount updates
124
refcount_bits Width of a reference count entry in bits
125
-nocow Turn off copy-on-write (valid only on btrfs)
126
+
127
+Note that not all of these options may be amendable.
128
129
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
130
-Supported options:
131
+Creation options for 'qcow2':
132
size Virtual disk size
133
compat Compatibility level (0.10 or 1.1)
134
backing_file File name of a base image
135
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
136
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
137
lazy_refcounts Postpone refcount updates
138
refcount_bits Width of a reference count entry in bits
139
-nocow Turn off copy-on-write (valid only on btrfs)
140
+
141
+Note that not all of these options may be amendable.
142
143
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
144
-Supported options:
145
+Creation options for 'qcow2':
146
size Virtual disk size
147
compat Compatibility level (0.10 or 1.1)
148
backing_file File name of a base image
149
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
150
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
151
lazy_refcounts Postpone refcount updates
152
refcount_bits Width of a reference count entry in bits
153
-nocow Turn off copy-on-write (valid only on btrfs)
154
+
155
+Note that not all of these options may be amendable.
156
157
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
158
-Supported options:
159
+Creation options for 'qcow2':
160
size Virtual disk size
161
compat Compatibility level (0.10 or 1.1)
162
backing_file File name of a base image
163
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
164
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
165
lazy_refcounts Postpone refcount updates
166
refcount_bits Width of a reference count entry in bits
167
-nocow Turn off copy-on-write (valid only on btrfs)
168
+
169
+Note that not all of these options may be amendable.
170
171
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
172
-Supported options:
173
+Creation options for 'qcow2':
174
size Virtual disk size
175
compat Compatibility level (0.10 or 1.1)
176
backing_file File name of a base image
177
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
178
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
179
lazy_refcounts Postpone refcount updates
180
refcount_bits Width of a reference count entry in bits
181
-nocow Turn off copy-on-write (valid only on btrfs)
182
+
183
+Note that not all of these options may be amendable.
184
185
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
186
-Supported options:
187
+Creation options for 'qcow2':
188
size Virtual disk size
189
compat Compatibility level (0.10 or 1.1)
190
backing_file File name of a base image
191
@@ -XXX,XX +XXX,XX @@ cluster_size qcow2 cluster size
192
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
193
lazy_refcounts Postpone refcount updates
194
refcount_bits Width of a reference count entry in bits
195
-nocow Turn off copy-on-write (valid only on btrfs)
196
+
197
+Note that not all of these options may be amendable.
198
199
Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
200
201
@@ -XXX,XX +XXX,XX @@ Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2 -o ,, -o help TEST_DIR/
202
qemu-img: Invalid option list: ,,
203
204
Testing: amend -f qcow2 -o help
205
-Supported options:
206
+Creation options for 'qcow2':
207
size Virtual disk size
208
compat Compatibility level (0.10 or 1.1)
209
backing_file File name of a base image
210
@@ -XXX,XX +XXX,XX @@ preallocation Preallocation mode (allowed values: off, metadata, falloc, full
211
lazy_refcounts Postpone refcount updates
212
refcount_bits Width of a reference count entry in bits
213
214
+Note that not all of these options may be amendable.
215
+
216
Testing: convert -o help
217
Supported options:
218
size Virtual disk size
219
--
227
--
220
2.17.1
228
2.26.2
221
229
222
230
diff view generated by jsdifflib
Deleted patch
1
This adds test cases to 082 for qemu-img create/convert/amend "-o help"
2
on formats that do not support creation or amendment, respectively.
3
1
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-id: 20180509210023.20283-7-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/082 | 9 +++++++++
11
tests/qemu-iotests/082.out | 9 +++++++++
12
2 files changed, 18 insertions(+)
13
14
diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/082
17
+++ b/tests/qemu-iotests/082
18
@@ -XXX,XX +XXX,XX @@ run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG" -o ,, -o help "$TEST_
19
run_qemu_img create -f $IMGFMT -o help
20
run_qemu_img create -o help
21
22
+# Try help option for a format that does not support creation
23
+run_qemu_img create -f bochs -o help
24
+
25
echo
26
echo === convert: Options specified more than once ===
27
28
@@ -XXX,XX +XXX,XX @@ run_qemu_img convert -O $IMGFMT -o backing_file="$TEST_IMG" -o ,, -o help "$TEST
29
run_qemu_img convert -O $IMGFMT -o help
30
run_qemu_img convert -o help
31
32
+# Try help option for a format that does not support creation
33
+run_qemu_img convert -O bochs -o help
34
+
35
echo
36
echo === amend: Options specified more than once ===
37
38
@@ -XXX,XX +XXX,XX @@ run_qemu_img amend -f $IMGFMT -o backing_file="$TEST_IMG" -o ,, -o help "$TEST_I
39
run_qemu_img amend -f $IMGFMT -o help
40
run_qemu_img convert -o help
41
42
+# Try help option for a format that does not support amendment
43
+run_qemu_img amend -f bochs -o help
44
+
45
# success, all done
46
echo "*** done"
47
rm -f $seq.full
48
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
49
index XXXXXXX..XXXXXXX 100644
50
--- a/tests/qemu-iotests/082.out
51
+++ b/tests/qemu-iotests/082.out
52
@@ -XXX,XX +XXX,XX @@ Testing: create -o help
53
Supported options:
54
size Virtual disk size
55
56
+Testing: create -f bochs -o help
57
+qemu-img: Format driver 'bochs' does not support image creation
58
+
59
=== convert: Options specified more than once ===
60
61
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
62
@@ -XXX,XX +XXX,XX @@ Testing: convert -o help
63
Supported options:
64
size Virtual disk size
65
66
+Testing: convert -O bochs -o help
67
+qemu-img: Format driver 'bochs' does not support image creation
68
+
69
=== amend: Options specified more than once ===
70
71
Testing: amend -f foo -f qcow2 -o lazy_refcounts=on TEST_DIR/t.qcow2
72
@@ -XXX,XX +XXX,XX @@ Note that not all of these options may be amendable.
73
Testing: convert -o help
74
Supported options:
75
size Virtual disk size
76
+
77
+Testing: amend -f bochs -o help
78
+qemu-img: Format driver 'bochs' does not support option amendment
79
*** done
80
--
81
2.17.1
82
83
diff view generated by jsdifflib
Deleted patch
1
This test case has been broken since 398e6ad014df261d (roughly half a
2
year). qemu-img amend requires its output image to be R/W, so it opens
3
it as such; the node is then turned into an read-only node automatically
4
which is now accompanied by a warning, however. This warning has not
5
been part of the reference output.
6
1
7
For one thing, this warning shows that we cannot keep the test case as
8
it is. We would need a format that has no create_opts but that does
9
have write support -- we do not have such a format, though.
10
11
Another thing is that qemu now actually checks whether an image format
12
supports amendment instead of whether it has create_opts (since the
13
former always implies the latter). So we can now use any format that
14
does not support amendment (even if it supports creation) and thus test
15
the same code path.
16
17
The reason nobody has noticed the breakage until now of course is the
18
fact that nobody runs the iotests for nbd+bochs. There actually was
19
never any reason to set the protocol to "nbd" but because that was
20
technically correct; functionally it made no difference. So that is the
21
first thing we are going to change: Make the protocol "file" instead so
22
that people might actually notice breakage here.
23
24
Secondly, now that bochs no longer works for the amend test case, we
25
have to change the format there anyway. Set let us just bend the truth
26
a bit, declare this test a raw test. In fact, that does not even
27
concern the bochs test cases, other than the output now reading 'bochs'
28
instead of 'IMGFMT'.
29
30
So with this test now being a raw test, we can rework the amend test
31
case to use raw instead.
32
33
Signed-off-by: Max Reitz <mreitz@redhat.com>
34
Reviewed-by: John Snow <jsnow@redhat.com>
35
Message-id: 20180509210023.20283-8-mreitz@redhat.com
36
Signed-off-by: Max Reitz <mreitz@redhat.com>
37
---
38
tests/qemu-iotests/113 | 19 +++++++++----------
39
tests/qemu-iotests/113.out | 7 ++++---
40
2 files changed, 13 insertions(+), 13 deletions(-)
41
42
diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/113
45
+++ b/tests/qemu-iotests/113
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
47
. ./common.rc
48
. ./common.filter
49
50
-# We can only test one format here because we need its sample file
51
-_supported_fmt bochs
52
-_supported_proto nbd
53
+# Some of these test cases use bochs, but others do use raw, so this
54
+# is only half a lie.
55
+_supported_fmt raw
56
+_supported_proto file
57
_supported_os Linux
58
59
echo
60
echo '=== Unsupported image creation in qemu-img create ==='
61
echo
62
63
-$QEMU_IMG create -f $IMGFMT nbd://example.com 2>&1 64M | _filter_imgfmt
64
+$QEMU_IMG create -f bochs nbd://example.com 2>&1 64M
65
66
echo
67
echo '=== Unsupported image creation in qemu-img convert ==='
68
@@ -XXX,XX +XXX,XX @@ echo
69
# We could use any input image format here, but this is a bochs test, so just
70
# use the bochs image
71
_use_sample_img empty.bochs.bz2
72
-$QEMU_IMG convert -f $IMGFMT -O $IMGFMT "$TEST_IMG" nbd://example.com 2>&1 \
73
- | _filter_imgfmt
74
+$QEMU_IMG convert -f bochs -O bochs "$TEST_IMG" nbd://example.com
75
76
echo
77
echo '=== Unsupported format in qemu-img amend ==='
78
echo
79
80
-# The protocol does not matter here
81
-_use_sample_img empty.bochs.bz2
82
-$QEMU_IMG amend -f $IMGFMT -o foo=bar "$TEST_IMG" 2>&1 | _filter_imgfmt
83
-
84
+TEST_IMG="$TEST_DIR/t.$IMGFMT"
85
+_make_test_img 1M
86
+$QEMU_IMG amend -f $IMGFMT -o size=2M "$TEST_IMG" 2>&1 | _filter_imgfmt
87
88
# success, all done
89
echo
90
diff --git a/tests/qemu-iotests/113.out b/tests/qemu-iotests/113.out
91
index XXXXXXX..XXXXXXX 100644
92
--- a/tests/qemu-iotests/113.out
93
+++ b/tests/qemu-iotests/113.out
94
@@ -XXX,XX +XXX,XX @@ QA output created by 113
95
96
=== Unsupported image creation in qemu-img create ===
97
98
-qemu-img: nbd://example.com: Format driver 'IMGFMT' does not support image creation
99
+qemu-img: nbd://example.com: Format driver 'bochs' does not support image creation
100
101
=== Unsupported image creation in qemu-img convert ===
102
103
-qemu-img: Format driver 'IMGFMT' does not support image creation
104
+qemu-img: Format driver 'bochs' does not support image creation
105
106
=== Unsupported format in qemu-img amend ===
107
108
-qemu-img: Format driver 'IMGFMT' does not support any options to amend
109
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
110
+qemu-img: Format driver 'IMGFMT' does not support option amendment
111
112
*** done
113
--
114
2.17.1
115
116
diff view generated by jsdifflib