1
The following changes since commit 9f55925b8f50a962d1d08d815044db7767ae3838:
1
The following changes since commit 99fc08366b06282614daeda989d2fde6ab8a707f:
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 tag 'seabios-20211203-pull-request' of git://git.kraxel.org/qemu into staging (2021-12-03 05:26:40 -0800)
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://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to c50abd175a88cd41c2c08339de91f6f6e4a7b162:
9
for you to fetch changes up to 5b807181c27a940a3a7ad1f221a2e76a132cbdc0:
10
10
11
iotests: Add case for a corrupted inactive image (2018-06-11 16:18:45 +0200)
11
virtio-blk: Fix clean up of host notifiers for single MR transaction. (2021-12-06 14:21:14 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Various bug fixes
16
- Removal of qemu-img convert's deprecated -s option
17
- qemu-io now exits with an error when a command failed
18
15
19
----------------------------------------------------------------
16
----------------------------------------------------------------
20
Alberto Garcia (1):
21
throttle: Fix crash on reopen
22
17
23
Max Reitz (25):
18
Mark Mielke (1):
24
block/file-posix: Pass FD to locking helpers
19
virtio-blk: Fix clean up of host notifiers for single MR transaction.
25
block/file-posix: File locking during creation
26
iotests: Add creation test to 153
27
qemu-img: Amendment support implies create_opts
28
block: Add Error parameter to bdrv_amend_options
29
qemu-option: Pull out "Supported options" print
30
qemu-img: Add print_amend_option_help()
31
qemu-img: Recognize no creation support in -o help
32
iotests: Test help option for unsupporting formats
33
iotests: Rework 113
34
qcow2: Repair OFLAG_COPIED when fixing leaks
35
iotests: Repairing error during snapshot deletion
36
qemu-io: Drop command functions' return values
37
qemu-io: Let command functions return error code
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
20
50
Thomas Huth (1):
21
hw/block/dataplane/virtio-blk.c | 2 +-
51
qemu-img: Remove deprecated -s snapshot_id_or_name option
22
1 file changed, 1 insertion(+), 1 deletion(-)
52
53
Vladimir Sementsov-Ogievskiy (2):
54
iotests: improve pause_job
55
block/qcow2-bitmap: fix free_bitmap_clusters
56
57
include/block/block.h | 4 +-
58
include/block/block_int.h | 3 +-
59
include/qemu-io.h | 9 +-
60
block.c | 25 ++-
61
block/file-posix.c | 64 ++++++--
62
block/qcow2-bitmap.c | 1 -
63
block/qcow2-refcount.c | 25 ++-
64
block/qcow2.c | 74 +++++----
65
block/throttle.c | 54 ++++---
66
qemu-img.c | 108 +++++++++++--
67
qemu-io-cmds.c | 276 +++++++++++++++++++---------------
68
qemu-io.c | 62 +++++---
69
util/qemu-option.c | 1 -
70
qemu-doc.texi | 7 -
71
qemu-img-cmds.hx | 4 +-
72
qemu-img.texi | 7 +-
73
tests/qemu-iotests/024 | 82 +++++++++-
74
tests/qemu-iotests/024.out | 30 ++++
75
tests/qemu-iotests/029 | 2 +-
76
tests/qemu-iotests/060 | 30 ++++
77
tests/qemu-iotests/060.out | 18 ++-
78
tests/qemu-iotests/061.out | 7 -
79
tests/qemu-iotests/080 | 4 +-
80
tests/qemu-iotests/080.out | 4 +-
81
tests/qemu-iotests/082 | 9 ++
82
tests/qemu-iotests/082.out | 53 ++++---
83
tests/qemu-iotests/112.out | 5 +-
84
tests/qemu-iotests/113 | 19 ++-
85
tests/qemu-iotests/113.out | 7 +-
86
tests/qemu-iotests/122 | 42 ++++++
87
tests/qemu-iotests/122.out | 18 +++
88
tests/qemu-iotests/153 | 18 +++
89
tests/qemu-iotests/153.out | 13 ++
90
tests/qemu-iotests/216 | 23 +--
91
tests/qemu-iotests/216.out | 17 +--
92
tests/qemu-iotests/217 | 90 +++++++++++
93
tests/qemu-iotests/217.out | 42 ++++++
94
tests/qemu-iotests/219 | 26 +++-
95
tests/qemu-iotests/219.out | 10 +-
96
tests/qemu-iotests/group | 1 +
97
tests/qemu-iotests/iotests.py | 18 ++-
98
41 files changed, 970 insertions(+), 342 deletions(-)
99
create mode 100755 tests/qemu-iotests/217
100
create mode 100644 tests/qemu-iotests/217.out
101
23
102
--
24
--
103
2.17.1
25
2.33.1
104
26
105
27
28
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
Deleted patch
1
When creating a file, we should take the WRITE and RESIZE permissions.
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
1
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20180509215336.31304-3-mreitz@redhat.com
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/file-posix.c | 37 +++++++++++++++++++++++++++++++++++--
13
1 file changed, 35 insertions(+), 2 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 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
20
{
21
BlockdevCreateOptionsFile *file_opts;
22
int fd;
23
+ int perm, shared;
24
int result = 0;
25
26
/* Validate options and set default values */
27
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
28
}
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
+ }
58
+
59
+ /* Step two: Check that nobody else has taken conflicting locks */
60
+ result = raw_check_lock_bytes(fd, perm, shared, errp);
61
+ if (result < 0) {
62
+ goto out_close;
63
+ }
64
+
65
+ /* Clear the file by truncating it to 0 */
66
+ result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
67
+ if (result < 0) {
68
+ goto out_close;
69
+ }
70
+
71
if (file_opts->nocow) {
72
#ifdef __linux__
73
/* Set NOCOW flag to solve performance issue on fs like btrfs.
74
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
75
#endif
76
}
77
78
+ /* Resize and potentially preallocate the file to the desired
79
+ * final size */
80
result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
81
errp);
82
if (result < 0) {
83
--
84
2.17.1
85
86
diff view generated by jsdifflib
Deleted patch
1
This patch adds a test case to 153 which tries to overwrite an image
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
1
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Message-id: 20180509215336.31304-4-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/153 | 18 ++++++++++++++++++
12
tests/qemu-iotests/153.out | 13 +++++++++++++
13
2 files changed, 31 insertions(+)
14
15
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/153
18
+++ b/tests/qemu-iotests/153
19
@@ -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
21
_run_cmd $QEMU_IMG bench $L -c 1 "${TEST_IMG}"
22
_run_cmd $QEMU_IMG bench $L -w -c 1 "${TEST_IMG}"
23
+
24
+ # qemu-img create does not support -U
25
+ if [ -z "$L" ]; then
26
+ _run_cmd $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" \
27
+ -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
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tests/qemu-iotests/153.out
47
+++ b/tests/qemu-iotests/153.out
48
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
49
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
50
Is another process using the image?
51
52
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
53
+qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
54
+Is another process using the image?
55
+file format: IMGFMT
56
+
57
== Running utility commands -U ==
58
59
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
60
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
61
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
62
Is another process using the image?
63
64
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
65
+qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
66
+Is another process using the image?
67
+file format: IMGFMT
68
+
69
== Running utility commands -U ==
70
71
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
72
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
73
74
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
75
76
+_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
77
+file format: IMGFMT
78
+
79
== Running utility commands -U ==
80
81
_qemu_io_wrapper -U -c read 0 512 TEST_DIR/t.qcow2
82
--
83
2.17.1
84
85
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
Looking at the qcow2 code that is riddled with error_report() calls,
2
this is really how it should have been from the start.
3
1
4
Along the way, turn the target_version/current_version comparisons at
5
the beginning of qcow2_downgrade() into assertions (the caller has to
6
make sure these conditions are met), and rephrase the error message on
7
using compat=1.1 to get refcount widths other than 16 bits.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20180509210023.20283-3-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
include/block/block.h | 3 +-
16
include/block/block_int.h | 3 +-
17
block.c | 8 +++--
18
block/qcow2.c | 72 ++++++++++++++++++++++----------------
19
qemu-img.c | 4 +--
20
tests/qemu-iotests/060.out | 4 +--
21
tests/qemu-iotests/061.out | 7 ----
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
28
--- a/include/block/block.h
29
+++ b/include/block/block.h
30
@@ -XXX,XX +XXX,XX @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
31
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
32
int64_t total_work_size, void *opaque);
33
int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
34
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque);
35
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
36
+ Error **errp);
37
38
/* external snapshots */
39
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
40
diff --git a/include/block/block_int.h b/include/block/block_int.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int.h
43
+++ b/include/block/block_int.h
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
45
46
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
47
BlockDriverAmendStatusCB *status_cb,
48
- void *cb_opaque);
49
+ void *cb_opaque,
50
+ Error **errp);
51
52
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
53
54
diff --git a/block.c b/block.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block.c
57
+++ b/block.c
58
@@ -XXX,XX +XXX,XX @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
59
}
60
61
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
62
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
63
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
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
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/qcow2.c
83
+++ b/block/qcow2.c
84
@@ -XXX,XX +XXX,XX @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
85
* have to be removed.
86
*/
87
static int qcow2_downgrade(BlockDriverState *bs, int target_version,
88
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
89
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
90
+ Error **errp)
91
{
92
BDRVQcow2State *s = bs->opaque;
93
int current_version = s->qcow_version;
94
int ret;
95
96
- if (target_version == current_version) {
97
- return 0;
98
- } else if (target_version > current_version) {
99
- return -EINVAL;
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;
113
}
114
115
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
116
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
117
ret = qcow2_mark_clean(bs);
118
if (ret < 0) {
119
+ error_setg_errno(errp, -ret, "Failed to make the image clean");
120
return ret;
121
}
122
}
123
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
124
* best thing to do anyway */
125
126
if (s->incompatible_features) {
127
+ error_setg(errp, "Cannot downgrade an image with incompatible features "
128
+ "%#" PRIx64 " set", s->incompatible_features);
129
return -ENOTSUP;
130
}
131
132
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
133
134
ret = qcow2_expand_zero_clusters(bs, status_cb, cb_opaque);
135
if (ret < 0) {
136
+ error_setg_errno(errp, -ret, "Failed to turn zero into data clusters");
137
return ret;
138
}
139
140
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
141
ret = qcow2_update_header(bs);
142
if (ret < 0) {
143
s->qcow_version = current_version;
144
+ error_setg_errno(errp, -ret, "Failed to update the image header");
145
return ret;
146
}
147
return 0;
148
@@ -XXX,XX +XXX,XX @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
149
150
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
151
BlockDriverAmendStatusCB *status_cb,
152
- void *cb_opaque)
153
+ void *cb_opaque,
154
+ Error **errp)
155
{
156
BDRVQcow2State *s = bs->opaque;
157
int old_version = s->qcow_version, new_version = old_version;
158
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
159
bool encrypt;
160
int encformat;
161
int refcount_bits = s->refcount_bits;
162
- Error *local_err = NULL;
163
int ret;
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
367
index XXXXXXX..XXXXXXX 100644
368
--- a/tests/qemu-iotests/061.out
369
+++ b/tests/qemu-iotests/061.out
370
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
371
372
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
--
447
2.17.1
448
449
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
Deleted patch
1
The more generic print_block_option_help() function is not really
2
suitable for qemu-img amend, for a couple of reasons:
3
(1) We do not need to append the protocol-level options, as amendment
4
happens only on one node and does not descend downwards to its
5
children.
6
(2) print_block_option_help() says those options are "supported". For
7
option amendment, we do not really know that. So this new function
8
explicitly says that those options are the creation options, and not
9
all of them may be supported.
10
(3) If the driver does not support option amendment, we should not print
11
anything (except for an error message that amendment is not
12
supported).
13
1
14
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1537956
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>
20
---
21
qemu-img.c | 30 ++++++++++++++++++++++++--
22
tests/qemu-iotests/082.out | 44 +++++++++++++++++++++++---------------
23
2 files changed, 55 insertions(+), 19 deletions(-)
24
25
diff --git a/qemu-img.c b/qemu-img.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
28
+++ b/qemu-img.c
29
@@ -XXX,XX +XXX,XX @@ static void amend_status_cb(BlockDriverState *bs,
30
qemu_progress_print(100.f * offset / total_work_size, 0);
31
}
32
33
+static int print_amend_option_help(const char *format)
34
+{
35
+ BlockDriver *drv;
36
+
37
+ /* Find driver and parse its options */
38
+ drv = bdrv_find_format(format);
39
+ if (!drv) {
40
+ error_report("Unknown file format '%s'", format);
41
+ return 1;
42
+ }
43
+
44
+ if (!drv->bdrv_amend_options) {
45
+ error_report("Format driver '%s' does not support option amendment",
46
+ format);
47
+ return 1;
48
+ }
49
+
50
+ /* Every driver supporting amendment must have create_opts */
51
+ assert(drv->create_opts);
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;
57
+}
58
+
59
static int img_amend(int argc, char **argv)
60
{
61
Error *err = NULL;
62
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
63
if (fmt && has_help_option(options)) {
64
/* If a format is explicitly specified (and possibly no filename is
65
* given), print option help here */
66
- ret = print_block_option_help(filename, fmt);
67
+ ret = print_amend_option_help(fmt);
68
goto out;
69
}
70
71
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
72
73
if (has_help_option(options)) {
74
/* If the format was auto-detected, print option help here */
75
- ret = print_block_option_help(filename, fmt);
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
--
220
2.17.1
221
222
diff view generated by jsdifflib
Deleted patch
1
The only users of print_block_option_help() are qemu-img create and
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
1
6
So if image creation is not supported by either the format or the
7
protocol, there is no need to print any option description, because the
8
user cannot create an image like this anyway.
9
10
This also fixes an assertion failure:
11
12
$ qemu-img create -f bochs -o help
13
Supported options:
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>
23
---
24
qemu-img.c | 10 ++++++++++
25
1 file changed, 10 insertions(+)
26
27
diff --git a/qemu-img.c b/qemu-img.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/qemu-img.c
30
+++ b/qemu-img.c
31
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
32
return 1;
33
}
34
35
+ if (!drv->create_opts) {
36
+ error_report("Format driver '%s' does not support image creation", fmt);
37
+ return 1;
38
+ }
39
+
40
create_opts = qemu_opts_append(create_opts, drv->create_opts);
41
if (filename) {
42
proto_drv = bdrv_find_protocol(filename, true, &local_err);
43
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
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
55
--
56
2.17.1
57
58
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
Deleted patch
1
Repairing OFLAG_COPIED is usually safe because it is done after the
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
1
7
Furthermore, if OFLAG_COPIED is actually consistent with a wrong (leaky)
8
refcount, we will decrement the refcount with -r leaks, but OFLAG_COPIED
9
will then be wrong. qemu-img check should not produce images that are
10
more corrupted afterwards then they were before.
11
12
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527085
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Message-id: 20180509200059.31125-2-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/qcow2-refcount.c | 25 +++++++++++++++++--------
19
1 file changed, 17 insertions(+), 8 deletions(-)
20
21
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-refcount.c
24
+++ b/block/qcow2-refcount.c
25
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
26
int ret;
27
uint64_t refcount;
28
int i, j;
29
+ bool repair;
30
+
31
+ if (fix & BDRV_FIX_ERRORS) {
32
+ /* Always repair */
33
+ repair = true;
34
+ } else if (fix & BDRV_FIX_LEAKS) {
35
+ /* Repair only if that seems safe: This function is always
36
+ * called after the refcounts have been fixed, so the refcount
37
+ * is accurate if that repair was successful */
38
+ repair = !res->check_errors && !res->corruptions && !res->leaks;
39
+ } else {
40
+ repair = false;
41
+ }
42
43
for (i = 0; i < s->l1_size; i++) {
44
uint64_t l1_entry = s->l1_table[i];
45
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
46
if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {
47
fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "
48
"l1_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
49
- fix & BDRV_FIX_ERRORS ? "Repairing" :
50
- "ERROR",
51
- i, l1_entry, refcount);
52
- if (fix & BDRV_FIX_ERRORS) {
53
+ repair ? "Repairing" : "ERROR", i, l1_entry, refcount);
54
+ if (repair) {
55
s->l1_table[i] = refcount == 1
56
? l1_entry | QCOW_OFLAG_COPIED
57
: l1_entry & ~QCOW_OFLAG_COPIED;
58
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
59
if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {
60
fprintf(stderr, "%s OFLAG_COPIED data cluster: "
61
"l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
62
- fix & BDRV_FIX_ERRORS ? "Repairing" :
63
- "ERROR",
64
- l2_entry, refcount);
65
- if (fix & BDRV_FIX_ERRORS) {
66
+ repair ? "Repairing" : "ERROR", l2_entry, refcount);
67
+ if (repair) {
68
l2_table[j] = cpu_to_be64(refcount == 1
69
? l2_entry | QCOW_OFLAG_COPIED
70
: l2_entry & ~QCOW_OFLAG_COPIED);
71
--
72
2.17.1
73
74
diff view generated by jsdifflib
Deleted patch
1
This adds a test for an I/O error during snapshot deletion, and maybe
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
1
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-id: 20180509200059.31125-3-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/217 | 90 ++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/217.out | 42 ++++++++++++++++++
14
tests/qemu-iotests/group | 1 +
15
3 files changed, 133 insertions(+)
16
create mode 100755 tests/qemu-iotests/217
17
create mode 100644 tests/qemu-iotests/217.out
18
19
diff --git a/tests/qemu-iotests/217 b/tests/qemu-iotests/217
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
117
index XXXXXXX..XXXXXXX
118
--- /dev/null
119
+++ b/tests/qemu-iotests/217.out
120
@@ -XXX,XX +XXX,XX @@
121
+QA output created by 217
122
+
123
+=== Simulating an I/O error during snapshot deletion ===
124
+
125
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
126
+wrote 65536/65536 bytes at offset 0
127
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
128
+
129
+Snapshot list:
130
+(Snapshot filtered)
131
+
132
+qcow2_free_clusters failed: Input/output error
133
+qemu-img: Could not delete snapshot 'foo': Failed to free the cluster and L1 table: Input/output error
134
+
135
+--- Checking test image ---
136
+Leaked cluster 4 refcount=2 reference=1
137
+Leaked cluster 5 refcount=2 reference=1
138
+Leaked cluster 6 refcount=1 reference=0
139
+Leaked cluster 7 refcount=1 reference=0
140
+
141
+4 leaked clusters were found on the image.
142
+This means waste of disk space, but no harm to data.
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
--
175
2.17.1
176
177
diff view generated by jsdifflib
Deleted patch
1
For qemu-io, a function returns an integer with two possible values: 0
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
1
6
So let's turn this case into a global variable instead so we can make
7
better use of the return value in a later patch.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20180509194302.21585-2-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
include/qemu-io.h | 6 +-
15
qemu-io-cmds.c | 294 +++++++++++++++++++++-------------------------
16
qemu-io.c | 36 +++---
17
3 files changed, 157 insertions(+), 179 deletions(-)
18
19
diff --git a/include/qemu-io.h b/include/qemu-io.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qemu-io.h
22
+++ b/include/qemu-io.h
23
@@ -XXX,XX +XXX,XX @@
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
}
52
53
-int qemuio_command_usage(const cmdinfo_t *ci)
54
+void qemuio_command_usage(const cmdinfo_t *ci)
55
{
56
printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
57
- return 0;
58
}
59
60
static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
61
@@ -XXX,XX +XXX,XX @@ static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
62
return 1;
63
}
64
65
-static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
66
- char **argv)
67
+static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
68
+ char **argv)
69
{
70
char *cmd = argv[0];
71
72
if (!init_check_command(blk, ct)) {
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
}
82
- return 0;
83
+ return;
84
}
85
86
/* Request additional permissions if necessary for this command. The caller
87
@@ -XXX,XX +XXX,XX @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
88
ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
89
if (ret < 0) {
90
error_report_err(local_err);
91
- return 0;
92
+ return;
93
}
94
}
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
--
1318
2.17.1
1319
1320
diff view generated by jsdifflib
Deleted patch
1
This is basically what everything else in the qemu code base does, so we
2
can do it here, too.
3
1
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-id: 20180509194302.21585-3-mreitz@redhat.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
include/qemu-io.h | 9 +-
10
qemu-io-cmds.c | 346 +++++++++++++++++++++++++++-------------------
11
qemu-io.c | 34 +++--
12
3 files changed, 232 insertions(+), 157 deletions(-)
13
14
diff --git a/include/qemu-io.h b/include/qemu-io.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu-io.h
17
+++ b/include/qemu-io.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
21
22
-typedef void (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
23
+/* Implement a qemu-io command.
24
+ * Operate on @blk using @argc/@argv as the command's arguments, and
25
+ * return 0 on success or negative errno on failure.
26
+ */
27
+typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
28
+
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
-void qemuio_command(BlockBackend *blk, const char *cmd);
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
43
--- a/qemu-io-cmds.c
44
+++ b/qemu-io-cmds.c
45
@@ -XXX,XX +XXX,XX @@ static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
46
return 1;
47
}
48
49
-static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
50
- char **argv)
51
+static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
52
+ char **argv)
53
{
54
char *cmd = argv[0];
55
56
if (!init_check_command(blk, ct)) {
57
- return;
58
+ return -EINVAL;
59
}
60
61
if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
62
@@ -XXX,XX +XXX,XX @@ static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
63
"bad argument count %d to %s, expected between %d and %d arguments\n",
64
argc-1, cmd, ct->argmin, ct->argmax);
65
}
66
- return;
67
+ return -EINVAL;
68
}
69
70
/* Request additional permissions if necessary for this command. The caller
71
@@ -XXX,XX +XXX,XX @@ static void command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
72
ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
73
if (ret < 0) {
74
error_report_err(local_err);
75
- return;
76
+ return ret;
77
}
78
}
79
}
80
81
optind = 0;
82
- ct->cfunc(blk, argc, argv);
83
+ return ct->cfunc(blk, argc, argv);
84
}
85
86
static const cmdinfo_t *find_command(const char *cmd)
87
@@ -XXX,XX +XXX,XX @@ static void read_help(void)
88
"\n");
89
}
90
91
-static void read_f(BlockBackend *blk, int argc, char **argv);
92
+static int read_f(BlockBackend *blk, int argc, char **argv);
93
94
static const cmdinfo_t read_cmd = {
95
.name = "read",
96
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t read_cmd = {
97
.help = read_help,
98
};
99
100
-static void read_f(BlockBackend *blk, int argc, char **argv)
101
+static int read_f(BlockBackend *blk, int argc, char **argv)
102
{
103
struct timeval t1, t2;
104
bool Cflag = false, qflag = false, vflag = false;
105
bool Pflag = false, sflag = false, lflag = false, bflag = false;
106
- int c, cnt;
107
+ int c, cnt, ret;
108
char *buf;
109
int64_t offset;
110
int64_t count;
111
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
112
pattern_count = cvtnum(optarg);
113
if (pattern_count < 0) {
114
print_cvtnum_err(pattern_count, optarg);
115
- return;
116
+ return pattern_count;
117
}
118
break;
119
case 'p':
120
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
121
Pflag = true;
122
pattern = parse_pattern(optarg);
123
if (pattern < 0) {
124
- return;
125
+ return -EINVAL;
126
}
127
break;
128
case 'q':
129
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
130
pattern_offset = cvtnum(optarg);
131
if (pattern_offset < 0) {
132
print_cvtnum_err(pattern_offset, optarg);
133
- return;
134
+ return pattern_offset;
135
}
136
break;
137
case 'v':
138
@@ -XXX,XX +XXX,XX @@ static void read_f(BlockBackend *blk, int argc, char **argv)
139
break;
140
default:
141
qemuio_command_usage(&read_cmd);
142
- return;
143
+ return -EINVAL;
144
}
145
}
146
147
if (optind != argc - 2) {
148
qemuio_command_usage(&read_cmd);
149
- return;
150
+ return -EINVAL;
151
}
152
153
offset = cvtnum(argv[optind]);
154
if (offset < 0) {
155
print_cvtnum_err(offset, argv[optind]);
156
- return;
157
+ return offset;
158
}
159
160
optind++;
161
count = cvtnum(argv[optind]);
162
if (count < 0) {
163
print_cvtnum_err(count, argv[optind]);
164
- return;
165
+ return count;
166
} else if (count > BDRV_REQUEST_MAX_BYTES) {
167
printf("length cannot exceed %" PRIu64 ", given %s\n",
168
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
169
- return;
170
+ return -EINVAL;
171
}
172
173
if (!Pflag && (lflag || sflag)) {
174
qemuio_command_usage(&read_cmd);
175
- return;
176
+ return -EINVAL;
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
--
1434
2.17.1
1435
1436
diff view generated by jsdifflib
Deleted patch
1
Currently, qemu-io basically always returns success when it gets to
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
1
6
This patch makes qemu-io return failure when any of the executed
7
commands failed.
8
9
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1519617
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Message-id: 20180509194302.21585-4-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
qemu-io.c | 28 ++++++++++++++++++++++------
16
1 file changed, 22 insertions(+), 6 deletions(-)
17
18
diff --git a/qemu-io.c b/qemu-io.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qemu-io.c
21
+++ b/qemu-io.c
22
@@ -XXX,XX +XXX,XX @@ static void prep_fetchline(void *opaque)
23
*fetchable= 1;
24
}
25
26
-static void command_loop(void)
27
+static int command_loop(void)
28
{
29
int i, fetchable = 0, prompted = 0;
30
+ int ret, last_error = 0;
31
char *input;
32
33
for (i = 0; !quit_qemu_io && i < ncmdline; i++) {
34
- qemuio_command(qemuio_blk, cmdline[i]);
35
+ ret = qemuio_command(qemuio_blk, cmdline[i]);
36
+ if (ret < 0) {
37
+ last_error = ret;
38
+ }
39
}
40
if (cmdline) {
41
g_free(cmdline);
42
- return;
43
+ return last_error;
44
}
45
46
while (!quit_qemu_io) {
47
@@ -XXX,XX +XXX,XX @@ static void command_loop(void)
48
if (input == NULL) {
49
break;
50
}
51
- qemuio_command(qemuio_blk, input);
52
+ ret = qemuio_command(qemuio_blk, input);
53
g_free(input);
54
55
+ if (ret < 0) {
56
+ last_error = ret;
57
+ }
58
+
59
prompted = 0;
60
fetchable = 0;
61
}
62
qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
63
+
64
+ return last_error;
65
}
66
67
static void add_user_command(char *optarg)
68
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
69
int c;
70
int opt_index = 0;
71
int flags = BDRV_O_UNMAP;
72
+ int ret;
73
bool writethrough = true;
74
Error *local_error = NULL;
75
QDict *opts = NULL;
76
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
77
}
78
}
79
}
80
- command_loop();
81
+ ret = command_loop();
82
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
--
98
2.17.1
99
100
diff view generated by jsdifflib
Deleted patch
1
With qemu-io now returning a useful exit code, some tests may find it
2
sufficient to just query that instead of logging (and filtering) the
3
whole output.
4
1
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-id: 20180509194302.21585-5-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/iotests.py | 9 +++++++++
11
1 file changed, 9 insertions(+)
12
13
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/iotests.py
16
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args):
18
sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
19
return subp.communicate()[0]
20
21
+def qemu_io_silent(*args):
22
+ '''Run qemu-io and return the exit code, suppressing stdout'''
23
+ args = qemu_io_args + list(args)
24
+ exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
25
+ if exitcode < 0:
26
+ sys.stderr.write('qemu-io received signal %i: %s\n' %
27
+ (-exitcode, ' '.join(args)))
28
+ return exitcode
29
+
30
31
class QemuIoInteractive:
32
def __init__(self, *args):
33
--
34
2.17.1
35
36
diff view generated by jsdifflib
Deleted patch
1
As a showcase of how you can use qemu-io's exit code to determine
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
1
6
One real advantage of this is that in case of an error, you get a
7
backtrace that helps you locate the issue in the test file quickly.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20180509194302.21585-6-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/216 | 23 ++++++++++++-----------
15
tests/qemu-iotests/216.out | 17 ++---------------
16
2 files changed, 14 insertions(+), 26 deletions(-)
17
18
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/216
21
+++ b/tests/qemu-iotests/216
22
@@ -XXX,XX +XXX,XX @@
23
# Creator/Owner: Max Reitz <mreitz@redhat.com>
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
29
# Need backing file support
30
iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
31
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
32
log('--- Setting up images ---')
33
log('')
34
35
- qemu_img_pipe('create', '-f', iotests.imgfmt, base_img_path, '64M')
36
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
37
+ assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
38
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
39
+ top_img_path) == 0
40
+ assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
41
42
- log(filter_qemu_io(qemu_io(base_img_path, '-c', 'write -P 1 0M 1M')))
43
-
44
- qemu_img_pipe('create', '-f', iotests.imgfmt, '-b', base_img_path,
45
- top_img_path)
46
-
47
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'write -P 2 1M 1M')))
48
+ log('Done')
49
50
log('')
51
log('--- Doing COR ---')
52
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
53
log('--- Checking COR result ---')
54
log('')
55
56
- log(filter_qemu_io(qemu_io(base_img_path, '-c', 'discard 0 64M')))
57
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 1 0M 1M')))
58
- log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 2 1M 1M')))
59
+ assert qemu_io_silent(base_img_path, '-c', 'discard 0 64M') == 0
60
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 1 0M 1M') == 0
61
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
62
+
63
+ log('Done')
64
diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out
65
index XXXXXXX..XXXXXXX 100644
66
--- a/tests/qemu-iotests/216.out
67
+++ b/tests/qemu-iotests/216.out
68
@@ -XXX,XX +XXX,XX @@
69
70
--- Setting up images ---
71
72
-wrote 1048576/1048576 bytes at offset 0
73
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
74
-
75
-wrote 1048576/1048576 bytes at offset 1048576
76
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
77
-
78
+Done
79
80
--- Doing COR ---
81
82
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 1048576
83
84
--- Checking COR result ---
85
86
-discard 67108864/67108864 bytes at offset 0
87
-64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
88
-
89
-read 1048576/1048576 bytes at offset 0
90
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
91
-
92
-read 1048576/1048576 bytes at offset 1048576
93
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
94
-
95
+Done
96
--
97
2.17.1
98
99
diff view generated by jsdifflib
Deleted patch
1
Currently, rebase interprets a relative path for the new backing image
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
1
8
If the overlay is not in qemu-img's working directory, both will be
9
different interpretations, which may either lead to an error somewhere
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
16
Fix this by interpreting the target backing path as relative to the
17
overlay, like qemu-img does everywhere else.
18
19
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1569835
20
Cc: qemu-stable@nongnu.org
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>
25
---
26
qemu-img.c | 23 ++++++++++++++++++++++-
27
1 file changed, 22 insertions(+), 1 deletion(-)
28
29
diff --git a/qemu-img.c b/qemu-img.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/qemu-img.c
32
+++ b/qemu-img.c
33
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
34
}
35
36
if (out_baseimg[0]) {
37
+ const char *overlay_filename;
38
+ char *out_real_path;
39
+
40
options = qdict_new();
41
if (out_basefmt) {
42
qdict_put_str(options, "driver", out_basefmt);
43
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
44
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
45
}
46
47
- blk_new_backing = blk_new_open(out_baseimg, NULL,
48
+ overlay_filename = bs->exact_filename[0] ? bs->exact_filename
49
+ : bs->filename;
50
+ out_real_path = g_malloc(PATH_MAX);
51
+
52
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
53
+ out_baseimg,
54
+ out_real_path,
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
--
72
2.17.1
73
74
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
Message-id: 20180509182002.8044-3-mreitz@redhat.com
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
6
tests/qemu-iotests/024 | 82 ++++++++++++++++++++++++++++++++++++--
7
tests/qemu-iotests/024.out | 30 ++++++++++++++
8
2 files changed, 109 insertions(+), 3 deletions(-)
9
1
10
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
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
112
--- a/tests/qemu-iotests/024.out
113
+++ b/tests/qemu-iotests/024.out
114
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 917504
115
=== IO: pattern 0x00
116
read 65536/65536 bytes at offset 983040
117
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
118
+
119
+=== Test rebase in a subdirectory of the working directory ===
120
+
121
+Formatting 'TEST_DIR/subdir/t.IMGFMT.base_old', fmt=IMGFMT size=1048576
122
+Formatting 'TEST_DIR/subdir/t.IMGFMT.base_new', fmt=IMGFMT size=1048576
123
+Formatting 'TEST_DIR/subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base_old
124
+
125
+wrote 131072/131072 bytes at offset 0
126
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
127
+wrote 65536/65536 bytes at offset 196608
128
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
129
+wrote 131072/131072 bytes at offset 65536
130
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
131
+wrote 65536/65536 bytes at offset 196608
132
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
133
+
134
+backing file: t.IMGFMT.base_new (actual path: TEST_DIR/subdir/t.IMGFMT.base_new)
135
+
136
+read 65536/65536 bytes at offset 0
137
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
138
+read 65536/65536 bytes at offset 65536
139
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
140
+read 65536/65536 bytes at offset 131072
141
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
142
+read 65536/65536 bytes at offset 196608
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
--
150
2.17.1
151
152
diff view generated by jsdifflib
Deleted patch
1
Currently, qemu-img convert writes zeroes when it reads zeroes.
2
Sometimes it does not because the target is initialized to zeroes
3
anyway, so we do not need to overwrite (and thus potentially allocate)
4
it. This is never the case for targets with backing files, though. But
5
even they may have an area that is initialized to zeroes, and that is
6
the area past the end of the backing file (if that is shorter than the
7
overlay).
8
1
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>
18
---
19
qemu-img.c | 26 +++++++++++++++++++++++++-
20
1 file changed, 25 insertions(+), 1 deletion(-)
21
22
diff --git a/qemu-img.c b/qemu-img.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-img.c
25
+++ b/qemu-img.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct ImgConvertState {
27
BlockBackend *target;
28
bool has_zero_init;
29
bool compressed;
30
+ bool unallocated_blocks_are_zero;
31
bool target_has_backing;
32
+ int64_t target_backing_sectors; /* negative if unknown */
33
bool wr_in_order;
34
bool copy_range;
35
int min_sparse;
36
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
37
{
38
int64_t src_cur_offset;
39
int ret, n, src_cur;
40
+ bool post_backing_zero = false;
41
42
convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
43
44
assert(s->total_sectors > sector_num);
45
n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
46
47
+ if (s->target_backing_sectors >= 0) {
48
+ if (sector_num >= s->target_backing_sectors) {
49
+ post_backing_zero = s->unallocated_blocks_are_zero;
50
+ } else if (sector_num + n > s->target_backing_sectors) {
51
+ /* Split requests around target_backing_sectors (because
52
+ * starting from there, zeros are handled differently) */
53
+ n = s->target_backing_sectors - sector_num;
54
+ }
55
+ }
56
+
57
if (s->sector_next_status <= sector_num) {
58
int64_t count = n * BDRV_SECTOR_SIZE;
59
60
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
61
n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
62
63
if (ret & BDRV_BLOCK_ZERO) {
64
- s->status = BLK_ZERO;
65
+ s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO;
66
} else if (ret & BDRV_BLOCK_DATA) {
67
s->status = BLK_DATA;
68
} else {
69
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
70
}
71
}
72
73
+ if (s.target_has_backing) {
74
+ /* Errors are treated as "backing length unknown" (which means
75
+ * s.target_backing_sectors has to be negative, which it will
76
+ * be automatically). The backing file length is used only
77
+ * for optimizations, so such a case is not fatal. */
78
+ s.target_backing_sectors = bdrv_nb_sectors(out_bs->backing->bs);
79
+ } else {
80
+ s.target_backing_sectors = -1;
81
+ }
82
+
83
ret = bdrv_get_info(out_bs, &bdi);
84
if (ret < 0) {
85
if (s.compressed) {
86
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
87
} else {
88
s.compressed = s.compressed || bdi.needs_compressed_writes;
89
s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
90
+ s.unallocated_blocks_are_zero = bdi.unallocated_blocks_are_zero;
91
}
92
93
ret = convert_do_copy(&s);
94
--
95
2.17.1
96
97
diff view generated by jsdifflib
Deleted patch
1
This adds a test case to 122 for what happens when you convert to a
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
1
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180501165750.19242-3-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/122 | 42 ++++++++++++++++++++++++++++++++++++++
12
tests/qemu-iotests/122.out | 18 ++++++++++++++++
13
2 files changed, 60 insertions(+)
14
15
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/122
18
+++ b/tests/qemu-iotests/122
19
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base "$TEST_IMG" "$TEST_IMG".orig
20
$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir
21
22
23
+echo
24
+echo "=== Converting to an overlay larger than its backing file ==="
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
+
64
+
65
echo
66
echo "=== Concatenate multiple source images ==="
67
echo
68
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
69
index XXXXXXX..XXXXXXX 100644
70
--- a/tests/qemu-iotests/122.out
71
+++ b/tests/qemu-iotests/122.out
72
@@ -XXX,XX +XXX,XX @@ read 3145728/3145728 bytes at offset 0
73
read 3145728/3145728 bytes at offset 0
74
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
76
+=== Converting to an overlay larger than its backing file ===
77
+
78
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=268435456
79
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=805306368 backing_file=TEST_DIR/t.IMGFMT.base
80
+Offset Length File
81
+
82
+wrote 1048576/1048576 bytes at offset 267386880
83
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
84
+wrote 1048576/1048576 bytes at offset 629145600
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
+
94
=== Concatenate multiple source images ===
95
96
Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=4194304
97
--
98
2.17.1
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
It's possible, that job was finished during waiting. In this case we
4
will see error message "Timeout waiting for job to pause" which is not
5
very informative. So, let's check during waiting iteration that the job
6
exists.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-id: 20180601115923.17159-1-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 9 +++++++--
13
1 file changed, 7 insertions(+), 2 deletions(-)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
20
with Timeout(1, "Timeout waiting for job to pause"):
21
while True:
22
result = self.vm.qmp('query-block-jobs')
23
+ found = False
24
for job in result['return']:
25
- if job['device'] == job_id and job['paused'] == True and job['busy'] == False:
26
- return job
27
+ if job['device'] == job_id:
28
+ found = True
29
+ if job['paused'] == True and job['busy'] == False:
30
+ return job
31
+ break
32
+ assert found
33
34
def pause_job(self, job_id='job0', wait=True):
35
result = self.vm.qmp('block-job-pause', device=job_id)
36
--
37
2.17.1
38
39
diff view generated by jsdifflib
Deleted patch
1
219 has two issues that may lead to sporadic failure, both of which are
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
1
6
First, query-jobs is issued right after the job has been created.
7
Besides its current progress possibly being in any random state (which
8
has already been taken care of), its total progress too is basically
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
15
Secondly, query-jobs is issued right after a job has been resumed. The
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
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Message-id: 20180606190628.8170-1-mreitz@redhat.com
23
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
tests/qemu-iotests/219 | 26 ++++++++++++++++++++------
27
tests/qemu-iotests/219.out | 10 +++++-----
28
2 files changed, 25 insertions(+), 11 deletions(-)
29
30
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
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
81
--- a/tests/qemu-iotests/219.out
82
+++ b/tests/qemu-iotests/219.out
83
@@ -XXX,XX +XXX,XX @@ Launching VM...
84
85
Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True)
86
{u'return': {}}
87
-{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]}
88
+{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'mirror'}]}
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'}
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
128
--
129
2.17.1
130
131
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
It has been marked as deprecated since QEMU v2.0 already, so it
4
is time now to finally remove it.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 1528288551-31641-1-git-send-email-thuth@redhat.com
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
qemu-img.c | 7 +------
12
qemu-doc.texi | 7 -------
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
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 void QEMU_NORETURN help(void)
24
" 'snapshot_param' is param used for internal snapshot, format\n"
25
" is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
26
" '[ID_OR_NAME]'\n"
27
- " 'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
28
- " instead\n"
29
" '-c' indicates that target image must be compressed (qcow format only)\n"
30
" '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
31
" new backing file match exactly. The image doesn't need a working\n"
32
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
33
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
34
{0, 0, 0, 0}
35
};
36
- c = getopt_long(argc, argv, ":hf:O:B:co:s:l:S:pt:T:qnm:WU",
37
+ c = getopt_long(argc, argv, ":hf:O:B:co:l:S:pt:T:qnm:WU",
38
long_options, NULL);
39
if (c == -1) {
40
break;
41
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
42
g_free(old_options);
43
}
44
break;
45
- case 's':
46
- snapshot_name = optarg;
47
- break;
48
case 'l':
49
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
50
sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
51
diff --git a/qemu-doc.texi b/qemu-doc.texi
52
index XXXXXXX..XXXXXXX 100644
53
--- a/qemu-doc.texi
54
+++ b/qemu-doc.texi
55
@@ -XXX,XX +XXX,XX @@ Option @option{-virtioconsole} has been replaced by
56
The @code{-clock} option is ignored since QEMU version 1.7.0. There is no
57
replacement since it is not needed anymore.
58
59
-@section qemu-img command line arguments
60
-
61
-@subsection convert -s (since 2.0.0)
62
-
63
-The ``convert -s snapshot_id_or_name'' argument is obsoleted
64
-by the ``convert -l snapshot_param'' argument instead.
65
-
66
@section QEMU Machine Protocol (QMP) commands
67
68
@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
69
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
70
index XXXXXXX..XXXXXXX 100644
71
--- a/qemu-img-cmds.hx
72
+++ b/qemu-img-cmds.hx
73
@@ -XXX,XX +XXX,XX @@ STEXI
74
ETEXI
75
76
DEF("convert", img_convert,
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")
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")
79
STEXI
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}
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}
82
ETEXI
83
84
DEF("create", img_create,
85
diff --git a/qemu-img.texi b/qemu-img.texi
86
index XXXXXXX..XXXXXXX 100644
87
--- a/qemu-img.texi
88
+++ b/qemu-img.texi
89
@@ -XXX,XX +XXX,XX @@ by the used format or see the format descriptions below for details.
90
is param used for internal snapshot, format is
91
'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'
92
93
-@item snapshot_id_or_name
94
-is deprecated, use snapshot_param instead
95
-
96
@end table
97
98
@table @option
99
@@ -XXX,XX +XXX,XX @@ Error on reading data
100
101
@end table
102
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}
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}
105
106
-Convert the disk image @var{filename} or a snapshot @var{snapshot_param}(@var{snapshot_id_or_name} is deprecated)
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
--
147
2.17.1
148
149
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This assert may fail, because bitmap_table is not initialized. Just
4
drop it, as it's obvious, that bitmap_table_load sets bitmap_table
5
parameter only when returning zero.
6
7
Reported-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-id: 20180608101225.2575-1-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2-bitmap.c | 1 -
13
1 file changed, 1 deletion(-)
14
15
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2-bitmap.c
18
+++ b/block/qcow2-bitmap.c
19
@@ -XXX,XX +XXX,XX @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
20
21
ret = bitmap_table_load(bs, tb, &bitmap_table);
22
if (ret < 0) {
23
- assert(bitmap_table == NULL);
24
return ret;
25
}
26
27
--
28
2.17.1
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The throttle block filter can be reopened, and with this it is
4
possible to change the throttle group that the filter belongs to.
5
6
The way the code does that is the following:
7
8
- On throttle_reopen_prepare(): create a new ThrottleGroupMember
9
and attach it to the new throttle group.
10
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>
36
---
37
block/throttle.c | 54 +++++++++++++++++++++++++++++-------------------
38
1 file changed, 33 insertions(+), 21 deletions(-)
39
40
diff --git a/block/throttle.c b/block/throttle.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/throttle.c
43
+++ b/block/throttle.c
44
@@ -XXX,XX +XXX,XX @@ static QemuOptsList throttle_opts = {
45
},
46
};
47
48
-static int throttle_configure_tgm(BlockDriverState *bs,
49
- ThrottleGroupMember *tgm,
50
- QDict *options, Error **errp)
51
+/*
52
+ * If this function succeeds then the throttle group name is stored in
53
+ * @group and must be freed by the caller.
54
+ * If there's an error then @group remains unmodified.
55
+ */
56
+static int throttle_parse_options(QDict *options, char **group, Error **errp)
57
{
58
int ret;
59
const char *group_name;
60
@@ -XXX,XX +XXX,XX @@ static int throttle_configure_tgm(BlockDriverState *bs,
61
goto fin;
62
}
63
64
- /* Register membership to group with name group_name */
65
- throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
66
+ *group = g_strdup(group_name);
67
ret = 0;
68
fin:
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
--
148
2.17.1
149
150
diff view generated by jsdifflib
Deleted patch
1
This is a useful function for the whole block layer, so make it public.
2
At the same time, users outside of block.c probably do not need to make
3
use of the reopen functionality, so rename the current function to
4
bdrv_is_writable_after_reopen() create a new bdrv_is_writable() function
5
that just passes NULL to it for the reopen queue.
6
1
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20180606193702.7113-2-mreitz@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>
13
---
14
include/block/block.h | 1 +
15
block.c | 17 ++++++++++++++---
16
2 files changed, 15 insertions(+), 3 deletions(-)
17
18
diff --git a/include/block/block.h b/include/block/block.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block.h
21
+++ b/include/block/block.h
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs);
23
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
24
bool ignore_allow_rdw, Error **errp);
25
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
26
+bool bdrv_is_writable(BlockDriverState *bs);
27
bool bdrv_is_sg(BlockDriverState *bs);
28
bool bdrv_is_inserted(BlockDriverState *bs);
29
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs)
35
36
/* Returns whether the image file can be written to after the reopen queue @q
37
* has been successfully applied, or right now if @q is NULL. */
38
-static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q)
39
+static bool bdrv_is_writable_after_reopen(BlockDriverState *bs,
40
+ BlockReopenQueue *q)
41
{
42
int flags = bdrv_reopen_get_flags(q, bs);
43
44
return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR;
45
}
46
47
+/*
48
+ * Return whether the BDS can be written to. This is not necessarily
49
+ * the same as !bdrv_is_read_only(bs), as inactivated images may not
50
+ * be written to but do not count as read-only images.
51
+ */
52
+bool bdrv_is_writable(BlockDriverState *bs)
53
+{
54
+ return bdrv_is_writable_after_reopen(bs, NULL);
55
+}
56
+
57
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
58
BdrvChild *c, const BdrvChildRole *role,
59
BlockReopenQueue *reopen_queue,
60
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
61
62
/* Write permissions never work with read-only images */
63
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
64
- !bdrv_is_writable(bs, q))
65
+ !bdrv_is_writable_after_reopen(bs, q))
66
{
67
error_setg(errp, "Block node is read-only");
68
return -EPERM;
69
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
70
&perm, &shared);
71
72
/* Format drivers may touch metadata even if the guest doesn't write */
73
- if (bdrv_is_writable(bs, reopen_queue)) {
74
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
75
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
76
}
77
78
--
79
2.17.1
80
81
diff view generated by jsdifflib
1
When signaling a corruption on a read-only image, qcow2 already makes
1
From: Mark Mielke <mark.mielke@gmail.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
The code that introduced "virtio-blk: Configure all host notifiers in
9
for them. bdrv_is_writable() can tell us whether an image can actually
4
a single MR transaction" introduced a second loop variable to perform
10
be written to, so use its result instead of !bs->read_only.
5
cleanup in second loop, but mistakenly still refers to the first
6
loop variable within the second loop body.
11
7
12
(Otherwise, the assert(!(bs->open_flags & BDRV_O_INACTIVE)) in
8
Fixes: d0267da61489 ("virtio-blk: Configure all host notifiers in a single MR transaction")
13
bdrv_co_pwritev() will fail, crashing qemu.)
9
Signed-off-by: Mark Mielke <mark.mielke@gmail.com>
14
10
Message-id: CALm7yL08qarOu0dnQkTN+pa=BSRC92g31YpQQNDeAiT4yLZWQQ@mail.gmail.com
15
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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>
21
---
12
---
22
block/qcow2.c | 2 +-
13
hw/block/dataplane/virtio-blk.c | 2 +-
23
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
24
15
25
diff --git a/block/qcow2.c b/block/qcow2.c
16
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2.c
18
--- a/hw/block/dataplane/virtio-blk.c
28
+++ b/block/qcow2.c
19
+++ b/hw/block/dataplane/virtio-blk.c
29
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
20
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
30
char *message;
21
memory_region_transaction_commit();
31
va_list ap;
22
32
23
while (j--) {
33
- fatal = fatal && !bs->read_only;
24
- virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
34
+ fatal = fatal && bdrv_is_writable(bs);
25
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
35
26
}
36
if (s->signaled_corruption &&
27
goto fail_host_notifiers;
37
(!fatal || (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT)))
28
}
38
--
29
--
39
2.17.1
30
2.33.1
40
31
41
32
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: John Snow <jsnow@redhat.com>
2
Tested-by: Jeff Cody <jcody@redhat.com>
3
Reviewed-by: Jeff Cody <jcody@redhat.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Message-id: 20180606193702.7113-4-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/060 | 30 ++++++++++++++++++++++++++++++
9
tests/qemu-iotests/060.out | 14 ++++++++++++++
10
2 files changed, 44 insertions(+)
11
1
12
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/060
15
+++ b/tests/qemu-iotests/060
16
@@ -XXX,XX +XXX,XX @@ echo "{'execute': 'qmp_capabilities'}
17
-drive if=none,node-name=drive,file="$TEST_IMG",driver=qcow2 \
18
| _filter_qmp | _filter_qemu_io
19
20
+echo
21
+echo "=== Testing incoming inactive corrupted image ==="
22
+echo
23
+
24
+_make_test_img 64M
25
+# Create an unaligned L1 entry, so qemu will signal a corruption when
26
+# reading from the covered area
27
+poke_file "$TEST_IMG" "$l1_offset" "\x00\x00\x00\x00\x2a\x2a\x2a\x2a"
28
+
29
+# Inactive images are effectively read-only images, so this should be a
30
+# non-fatal corruption (which does not modify the image)
31
+echo "{'execute': 'qmp_capabilities'}
32
+ {'execute': 'human-monitor-command',
33
+ 'arguments': {'command-line': 'qemu-io drive \"read 0 512\"'}}
34
+ {'execute': 'quit'}" \
35
+ | $QEMU -qmp stdio -nographic -nodefaults \
36
+ -blockdev "{'node-name': 'drive',
37
+ 'driver': 'qcow2',
38
+ 'file': {
39
+ 'driver': 'file',
40
+ 'filename': '$TEST_IMG'
41
+ }}" \
42
+ -incoming exec:'cat /dev/null' \
43
+ 2>&1 \
44
+ | _filter_qmp | _filter_qemu_io
45
+
46
+echo
47
+# Image should not have been marked corrupt
48
+_img_info --format-specific | grep 'corrupt:'
49
+
50
# success, all done
51
echo "*** done"
52
rm -f $seq.full
53
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tests/qemu-iotests/060.out
56
+++ b/tests/qemu-iotests/060.out
57
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
58
{"return": ""}
59
{"return": {}}
60
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
61
+
62
+=== Testing incoming inactive corrupted image ===
63
+
64
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
65
+QMP_VERSION
66
+{"return": {}}
67
+qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
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}}
69
+read failed: Input/output error
70
+{"return": ""}
71
+{"return": {}}
72
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
73
+
74
+ corrupt: false
75
*** done
76
--
77
2.17.1
78
79
diff view generated by jsdifflib