1
The following changes since commit ba29883206d92a29ad5a466e679ccfc2ee6132ef:
1
The following changes since commit dfaecc04c46d298e9ee81bd0ca96d8754f1c27ed:
2
2
3
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20200310' into staging (2020-03-10 16:50:28 +0000)
3
Merge tag 'pull-riscv-to-apply-20250407-1' of https://github.com/alistair23/qemu into staging (2025-04-07 09:18:33 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 8bb3b023f2055054ee119cb45b42d2b14be7fc8a:
9
for you to fetch changes up to f8222bfba3409a3ce09c191941127a8cf2c7e623:
10
10
11
qemu-iotests: adding LUKS cleanup for non-UTF8 secret error (2020-03-11 15:54:38 +0100)
11
test-bdrv-drain: Fix data races (2025-04-08 15:00:01 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Relax restrictions for blockdev-snapshot (allows libvirt to do live
16
- scsi-disk: Apply error policy for host_status errors again
17
storage migration with blockdev-mirror)
17
- qcow2: Fix qemu-img info crash with missing crypto header
18
- luks: Delete created files when block_crypto_co_create_opts_luks fails
18
- qemu-img bench: Fix division by zero for zero-sized images
19
- Fix memleaks in qmp_object_add
19
- test-bdrv-drain: Fix data races
20
20
21
----------------------------------------------------------------
21
----------------------------------------------------------------
22
Daniel Henrique Barboza (4):
22
Denis Rastyogin (1):
23
block: introducing 'bdrv_co_delete_file' interface
23
qemu-img: fix division by zero in bench_cb() for zero-sized images
24
block.c: adding bdrv_co_delete_file
25
crypto.c: cleanup created file when block_crypto_co_create_opts_luks fails
26
qemu-iotests: adding LUKS cleanup for non-UTF8 secret error
27
24
28
Kevin Wolf (6):
25
Kevin Wolf (2):
29
block: Make bdrv_get_cumulative_perm() public
26
qcow2: Don't crash qemu-img info with missing crypto header
30
block: Relax restrictions for blockdev-snapshot
27
scsi-disk: Apply error policy for host_status errors again
31
iotests: Fix run_job() with use_log=False
32
iotests: Test mirror with temporarily disabled target backing file
33
block: Fix cross-AioContext blockdev-snapshot
34
iotests: Add iothread cases to 155
35
28
36
Pan Nengyuan (1):
29
Vitalii Mordan (1):
37
qom-qmp-cmds: fix two memleaks in qmp_object_add
30
test-bdrv-drain: Fix data races
38
31
39
Peter Krempa (1):
32
include/qemu/job.h | 3 ++
40
qapi: Add '@allow-write-only-overlay' feature for 'blockdev-snapshot'
33
block/qcow2.c | 4 +-
41
34
hw/scsi/scsi-disk.c | 39 +++++++++-----
42
Philippe Mathieu-Daudé (1):
35
job.c | 6 +++
43
tests/qemu-iotests: Fix socket_scm_helper build path
36
qemu-img.c | 6 ++-
44
37
tests/unit/test-bdrv-drain.c | 32 +++++++-----
45
qapi/block-core.json | 9 ++++-
38
tests/qemu-iotests/tests/qcow2-encryption | 75 +++++++++++++++++++++++++++
46
include/block/block.h | 1 +
39
tests/qemu-iotests/tests/qcow2-encryption.out | 32 ++++++++++++
47
include/block/block_int.h | 7 ++++
40
8 files changed, 167 insertions(+), 30 deletions(-)
48
block.c | 33 ++++++++++++++--
41
create mode 100755 tests/qemu-iotests/tests/qcow2-encryption
49
block/crypto.c | 18 +++++++++
42
create mode 100644 tests/qemu-iotests/tests/qcow2-encryption.out
50
block/file-posix.c | 23 +++++++++++
51
blockdev.c | 30 ++++-----------
52
qom/qom-qmp-cmds.c | 16 +++-----
53
tests/qemu-iotests/iotests.py | 5 ++-
54
tests/Makefile.include | 1 +
55
tests/qemu-iotests/085.out | 4 +-
56
tests/qemu-iotests/155 | 88 ++++++++++++++++++++++++++++++++++++-------
57
tests/qemu-iotests/155.out | 4 +-
58
tests/qemu-iotests/282 | 67 ++++++++++++++++++++++++++++++++
59
tests/qemu-iotests/282.out | 11 ++++++
60
tests/qemu-iotests/group | 1 +
61
tests/qtest/Makefile.include | 1 -
62
17 files changed, 262 insertions(+), 57 deletions(-)
63
create mode 100755 tests/qemu-iotests/282
64
create mode 100644 tests/qemu-iotests/282.out
65
66
diff view generated by jsdifflib
Deleted patch
1
From: Pan Nengyuan <pannengyuan@huawei.com>
2
1
3
'type/id' forgot to free in qmp_object_add, this patch fix that.
4
5
The leak stack:
6
Direct leak of 84 byte(s) in 6 object(s) allocated from:
7
#0 0x7fe2a5ebf768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768)
8
#1 0x7fe2a5044445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445)
9
#2 0x7fe2a505dd92 in g_strdup (/lib64/libglib-2.0.so.0+0x6bd92)
10
#3 0x56344954e692 in qmp_object_add /mnt/sdb/qemu-new/qemu_test/qemu/qom/qom-qmp-cmds.c:258
11
#4 0x563449960f5a in do_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:132
12
#5 0x563449960f5a in qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:175
13
#6 0x563449498a30 in monitor_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:145
14
#7 0x56344949a64f in monitor_qmp_bh_dispatcher /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:234
15
#8 0x563449a92a3a in aio_bh_call /mnt/sdb/qemu-new/qemu_test/qemu/util/async.c:136
16
17
Direct leak of 54 byte(s) in 6 object(s) allocated from:
18
#0 0x7fe2a5ebf768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768)
19
#1 0x7fe2a5044445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445)
20
#2 0x7fe2a505dd92 in g_strdup (/lib64/libglib-2.0.so.0+0x6bd92)
21
#3 0x56344954e6c4 in qmp_object_add /mnt/sdb/qemu-new/qemu_test/qemu/qom/qom-qmp-cmds.c:267
22
#4 0x563449960f5a in do_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:132
23
#5 0x563449960f5a in qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:175
24
#6 0x563449498a30 in monitor_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:145
25
#7 0x56344949a64f in monitor_qmp_bh_dispatcher /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:234
26
#8 0x563449a92a3a in aio_bh_call /mnt/sdb/qemu-new/qemu_test/qemu/util/async.c:136
27
28
Fixes: 5f07c4d60d091320186e7b0edaf9ed2cc16b2d1e
29
Reported-by: Euler Robot <euler.robot@huawei.com>
30
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
31
Message-Id: <20200310064640.5059-1-pannengyuan@huawei.com>
32
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
33
Acked-by: Igor Mammedov <imammedo@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
36
qom/qom-qmp-cmds.c | 16 ++++++----------
37
1 file changed, 6 insertions(+), 10 deletions(-)
38
39
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/qom/qom-qmp-cmds.c
42
+++ b/qom/qom-qmp-cmds.c
43
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
44
QDict *pdict;
45
Visitor *v;
46
Object *obj;
47
- const char *type;
48
- const char *id;
49
+ g_autofree char *type = NULL;
50
+ g_autofree char *id = NULL;
51
52
- type = qdict_get_try_str(qdict, "qom-type");
53
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
54
if (!type) {
55
error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
56
return;
57
- } else {
58
- type = g_strdup(type);
59
- qdict_del(qdict, "qom-type");
60
}
61
+ qdict_del(qdict, "qom-type");
62
63
- id = qdict_get_try_str(qdict, "id");
64
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
65
if (!id) {
66
error_setg(errp, QERR_MISSING_PARAMETER, "id");
67
return;
68
- } else {
69
- id = g_strdup(id);
70
- qdict_del(qdict, "id");
71
}
72
+ qdict_del(qdict, "id");
73
74
props = qdict_get(qdict, "props");
75
if (props) {
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Message-Id: <20200310113831.27293-2-kwolf@redhat.com>
3
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
include/block/block_int.h | 3 +++
7
block.c | 6 ++----
8
2 files changed, 5 insertions(+), 4 deletions(-)
9
1
10
diff --git a/include/block/block_int.h b/include/block/block_int.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/block/block_int.h
13
+++ b/include/block/block_int.h
14
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
15
void *opaque, Error **errp);
16
void bdrv_root_unref_child(BdrvChild *child);
17
18
+void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
19
+ uint64_t *shared_perm);
20
+
21
/**
22
* Sets a BdrvChild's permissions. Avoid if the parent is a BDS; use
23
* bdrv_child_refresh_perms() instead and make the parent's
24
diff --git a/block.c b/block.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
27
+++ b/block.c
28
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
29
bool *tighten_restrictions, Error **errp);
30
static void bdrv_child_abort_perm_update(BdrvChild *c);
31
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
32
-static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
33
- uint64_t *shared_perm);
34
35
typedef struct BlockReopenQueueEntry {
36
bool prepared;
37
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
38
}
39
}
40
41
-static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
42
- uint64_t *shared_perm)
43
+void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
44
+ uint64_t *shared_perm)
45
{
46
BdrvChild *c;
47
uint64_t cumulative_perms = 0;
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
Deleted patch
1
blockdev-snapshot returned an error if the overlay was already in use,
2
which it defined as having any BlockBackend parent. This is in fact both
3
too strict (some parents can tolerate the change of visible data caused
4
by attaching a backing file) and too loose (some non-BlockBackend
5
parents may not be happy with it).
6
1
7
One important use case that is prevented by the too strict check is live
8
storage migration with blockdev-mirror. Here, the target node is
9
usually opened without a backing file so that the active layer is
10
mirrored while its backing chain can be copied in the background.
11
12
The backing chain should be attached to the mirror target node when
13
finalising the job, just before switching the users of the source node
14
to the new copy (at which point the mirror job still has a reference to
15
the node). drive-mirror did this automatically, but with blockdev-mirror
16
this is the job of the QMP client, so it needs a way to do this.
17
18
blockdev-snapshot is the obvious way, so this patch makes it work in
19
this scenario. The new condition is that no parent uses CONSISTENT_READ
20
permissions. This will ensure that the operation will still be blocked
21
when the node is attached to the guest device, so blockdev-snapshot
22
remains safe.
23
24
(For the sake of completeness, x-blockdev-reopen can be used to achieve
25
the same, however it is a big hammer, performs the graph change
26
completely unchecked and is still experimental. So even with the option
27
of using x-blockdev-reopen, there are reasons why blockdev-snapshot
28
should be able to perform this operation.)
29
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Message-Id: <20200310113831.27293-3-kwolf@redhat.com>
32
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
33
Tested-by: Peter Krempa <pkrempa@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
36
blockdev.c | 14 ++++++++------
37
tests/qemu-iotests/085.out | 4 ++--
38
2 files changed, 10 insertions(+), 8 deletions(-)
39
40
diff --git a/blockdev.c b/blockdev.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/blockdev.c
43
+++ b/blockdev.c
44
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
45
TransactionAction *action = common->action;
46
AioContext *aio_context;
47
AioContext *old_context;
48
+ uint64_t perm, shared;
49
int ret;
50
51
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
52
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
53
goto out;
54
}
55
56
- if (bdrv_has_blk(state->new_bs)) {
57
+ /*
58
+ * Allow attaching a backing file to an overlay that's already in use only
59
+ * if the parents don't assume that they are already seeing a valid image.
60
+ * (Specifically, allow it as a mirror target, which is write-only access.)
61
+ */
62
+ bdrv_get_cumulative_perm(state->new_bs, &perm, &shared);
63
+ if (perm & BLK_PERM_CONSISTENT_READ) {
64
error_setg(errp, "The overlay is already in use");
65
goto out;
66
}
67
68
- if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
69
- errp)) {
70
- goto out;
71
- }
72
-
73
if (state->new_bs->backing != NULL) {
74
error_setg(errp, "The overlay already has a backing image");
75
goto out;
76
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/qemu-iotests/085.out
79
+++ b/tests/qemu-iotests/085.out
80
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f
81
=== Invalid command - cannot create a snapshot using a file BDS ===
82
83
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } }
84
-{"error": {"class": "GenericError", "desc": "The overlay does not support backing images"}}
85
+{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
86
87
=== Invalid command - snapshot node used as active layer ===
88
89
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f
90
=== Invalid command - snapshot node used as backing hd ===
91
92
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
93
-{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'snap_12'"}}
94
+{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
95
96
=== Invalid command - snapshot node has a backing image ===
97
98
--
99
2.20.1
100
101
diff view generated by jsdifflib
Deleted patch
1
The 'job-complete' QMP command should be run with qmp() rather than
2
qmp_log() if use_log=False is passed.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20200310113831.27293-4-kwolf@redhat.com>
6
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/iotests.py | 5 ++++-
10
1 file changed, 4 insertions(+), 1 deletion(-)
11
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/iotests.py
16
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
17
if use_log:
18
log('Job failed: %s' % (j['error']))
19
elif status == 'ready':
20
- self.qmp_log('job-complete', id=job)
21
+ if use_log:
22
+ self.qmp_log('job-complete', id=job)
23
+ else:
24
+ self.qmp('job-complete', id=job)
25
elif status == 'pending' and not auto_finalize:
26
if pre_finalize:
27
pre_finalize()
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
The newly tested scenario is a common live storage migration scenario:
2
The target node is opened without a backing file so that the active
3
layer is mirrored while its backing chain can be copied in the
4
background.
5
1
6
The backing chain should be attached to the mirror target node when
7
finalising the job, just before switching the users of the source node
8
to the new copy (at which point the mirror job still has a reference to
9
the node). drive-mirror did this automatically, but with blockdev-mirror
10
this is the job of the QMP client.
11
12
This patch adds test cases for two ways to achieve the desired result,
13
using either x-blockdev-reopen or blockdev-snapshot.
14
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Message-Id: <20200310113831.27293-5-kwolf@redhat.com>
17
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
tests/qemu-iotests/155 | 56 ++++++++++++++++++++++++++++++++++----
21
tests/qemu-iotests/155.out | 4 +--
22
2 files changed, 53 insertions(+), 7 deletions(-)
23
24
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/155
27
+++ b/tests/qemu-iotests/155
28
@@ -XXX,XX +XXX,XX @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt)
29
# image during runtime, only makes sense if
30
# target_blockdev_backing is not None
31
# (None: same as target_backing)
32
+# target_open_with_backing: If True, the target image is added with its backing
33
+# chain opened right away. If False, blockdev-add
34
+# opens it without a backing file and job completion
35
+# is supposed to open the backing chain.
36
37
class BaseClass(iotests.QMPTestCase):
38
target_blockdev_backing = None
39
target_real_backing = None
40
+ target_open_with_backing = True
41
42
def setUp(self):
43
qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K')
44
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
45
options = { 'node-name': 'target',
46
'driver': iotests.imgfmt,
47
'file': { 'driver': 'file',
48
+ 'node-name': 'target-file',
49
'filename': target_img } }
50
- if self.target_blockdev_backing:
51
- options['backing'] = self.target_blockdev_backing
52
+
53
+ if not self.target_open_with_backing:
54
+ options['backing'] = None
55
+ elif self.target_blockdev_backing:
56
+ options['backing'] = self.target_blockdev_backing
57
58
result = self.vm.qmp('blockdev-add', **options)
59
self.assert_qmp(result, 'return', {})
60
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
61
# cmd: Mirroring command to execute, either drive-mirror or blockdev-mirror
62
63
class MirrorBaseClass(BaseClass):
64
+ def openBacking(self):
65
+ pass
66
+
67
def runMirror(self, sync):
68
if self.cmd == 'blockdev-mirror':
69
result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source',
70
- sync=sync, target='target')
71
+ sync=sync, target='target',
72
+ auto_finalize=False)
73
else:
74
if self.existing:
75
mode = 'existing'
76
@@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass):
77
result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source',
78
sync=sync, target=target_img,
79
format=iotests.imgfmt, mode=mode,
80
- node_name='target')
81
+ node_name='target', auto_finalize=False)
82
83
self.assert_qmp(result, 'return', {})
84
85
- self.complete_and_wait('mirror-job')
86
+ self.vm.run_job('mirror-job', use_log=False, auto_finalize=False,
87
+ pre_finalize=self.openBacking, auto_dismiss=True)
88
89
def testFull(self):
90
self.runMirror('full')
91
@@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorForcedBacking(MirrorBaseClass):
92
target_blockdev_backing = { 'driver': 'null-co' }
93
target_real_backing = 'null-co://'
94
95
+# Attach the backing chain only during completion, with blockdev-reopen
96
+class TestBlockdevMirrorReopen(MirrorBaseClass):
97
+ cmd = 'blockdev-mirror'
98
+ existing = True
99
+ target_backing = 'null-co://'
100
+ target_open_with_backing = False
101
+
102
+ def openBacking(self):
103
+ if not self.target_open_with_backing:
104
+ result = self.vm.qmp('blockdev-add', node_name="backing",
105
+ driver="null-co")
106
+ self.assert_qmp(result, 'return', {})
107
+ result = self.vm.qmp('x-blockdev-reopen', node_name="target",
108
+ driver=iotests.imgfmt, file="target-file",
109
+ backing="backing")
110
+ self.assert_qmp(result, 'return', {})
111
+
112
+# Attach the backing chain only during completion, with blockdev-snapshot
113
+class TestBlockdevMirrorSnapshot(MirrorBaseClass):
114
+ cmd = 'blockdev-mirror'
115
+ existing = True
116
+ target_backing = 'null-co://'
117
+ target_open_with_backing = False
118
+
119
+ def openBacking(self):
120
+ if not self.target_open_with_backing:
121
+ result = self.vm.qmp('blockdev-add', node_name="backing",
122
+ driver="null-co")
123
+ self.assert_qmp(result, 'return', {})
124
+ result = self.vm.qmp('blockdev-snapshot', node="backing",
125
+ overlay="target")
126
+ self.assert_qmp(result, 'return', {})
127
128
class TestCommit(BaseClass):
129
existing = False
130
diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out
131
index XXXXXXX..XXXXXXX 100644
132
--- a/tests/qemu-iotests/155.out
133
+++ b/tests/qemu-iotests/155.out
134
@@ -XXX,XX +XXX,XX @@
135
-...................
136
+.........................
137
----------------------------------------------------------------------
138
-Ran 19 tests
139
+Ran 25 tests
140
141
OK
142
--
143
2.20.1
144
145
diff view generated by jsdifflib
Deleted patch
1
external_snapshot_prepare() tries to move the overlay to the AioContext
2
of the backing file (the snapshotted node). However, it's possible that
3
this doesn't work, but the backing file can instead be moved to the
4
overlay's AioContext (e.g. opening the backing chain for a mirror
5
target).
6
1
7
bdrv_append() already indirectly uses bdrv_attach_node(), which takes
8
care to move nodes to make sure they use the same AioContext and which
9
tries both directions.
10
11
So the problem has a simple fix: Just delete the unnecessary extra
12
bdrv_try_set_aio_context() call in external_snapshot_prepare() and
13
instead assert in bdrv_append() that both nodes were indeed moved to the
14
same AioContext.
15
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20200310113831.27293-6-kwolf@redhat.com>
18
Tested-by: Peter Krempa <pkrempa@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block.c | 1 +
22
blockdev.c | 16 ----------------
23
2 files changed, 1 insertion(+), 16 deletions(-)
24
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
30
bdrv_ref(from);
31
32
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
33
+ assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to));
34
bdrv_drained_begin(from);
35
36
/* Put all parents into @list and calculate their cumulative permissions */
37
diff --git a/blockdev.c b/blockdev.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/blockdev.c
40
+++ b/blockdev.c
41
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
42
DO_UPCAST(ExternalSnapshotState, common, common);
43
TransactionAction *action = common->action;
44
AioContext *aio_context;
45
- AioContext *old_context;
46
uint64_t perm, shared;
47
- int ret;
48
49
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
50
* purpose but a different set of parameters */
51
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
52
goto out;
53
}
54
55
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
56
- old_context = bdrv_get_aio_context(state->new_bs);
57
- aio_context_release(aio_context);
58
- aio_context_acquire(old_context);
59
-
60
- ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
61
-
62
- aio_context_release(old_context);
63
- aio_context_acquire(aio_context);
64
-
65
- if (ret < 0) {
66
- goto out;
67
- }
68
-
69
/* This removes our old bs and adds the new bs. This is an operation that
70
* can fail, so we need to do it in .prepare; undoing it for abort is
71
* always possible. */
72
--
73
2.20.1
74
75
diff view generated by jsdifflib
Deleted patch
1
This patch adds test cases for attaching the backing chain to a mirror
2
job target right before finalising the job, where the image is in a
3
non-mainloop AioContext (i.e. the backing chain needs to be moved to the
4
AioContext of the mirror target).
5
1
6
This requires switching the test case from virtio-blk to virtio-scsi
7
because virtio-blk only actually starts using the iothreads when the
8
guest driver initialises the device (which never happens in a test case
9
without a guest OS). virtio-scsi always keeps its block nodes in the
10
AioContext of the the requested iothread without guest interaction.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20200310113831.27293-7-kwolf@redhat.com>
14
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
tests/qemu-iotests/155 | 32 +++++++++++++++++++++++---------
18
tests/qemu-iotests/155.out | 4 ++--
19
2 files changed, 25 insertions(+), 11 deletions(-)
20
21
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/155
24
+++ b/tests/qemu-iotests/155
25
@@ -XXX,XX +XXX,XX @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt)
26
# chain opened right away. If False, blockdev-add
27
# opens it without a backing file and job completion
28
# is supposed to open the backing chain.
29
+# use_iothread: If True, an iothread is configured for the virtio-blk device
30
+# that uses the image being mirrored
31
32
class BaseClass(iotests.QMPTestCase):
33
target_blockdev_backing = None
34
target_real_backing = None
35
target_open_with_backing = True
36
+ use_iothread = False
37
38
def setUp(self):
39
qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K')
40
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
41
'file': {'driver': 'file',
42
'filename': source_img}}
43
self.vm.add_blockdev(self.vm.qmp_to_opts(blockdev))
44
- self.vm.add_device('virtio-blk,id=qdev0,drive=source')
45
+
46
+ if self.use_iothread:
47
+ self.vm.add_object('iothread,id=iothread0')
48
+ iothread = ",iothread=iothread0"
49
+ else:
50
+ iothread = ""
51
+
52
+ self.vm.add_device('virtio-scsi%s' % iothread)
53
+ self.vm.add_device('scsi-hd,id=qdev0,drive=source')
54
+
55
self.vm.launch()
56
57
self.assertIntactSourceBackingChain()
58
@@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass):
59
def testFull(self):
60
self.runMirror('full')
61
62
- node = self.findBlockNode('target',
63
- '/machine/peripheral/qdev0/virtio-backend')
64
+ node = self.findBlockNode('target', 'qdev0')
65
self.assertCorrectBackingImage(node, None)
66
self.assertIntactSourceBackingChain()
67
68
def testTop(self):
69
self.runMirror('top')
70
71
- node = self.findBlockNode('target',
72
- '/machine/peripheral/qdev0/virtio-backend')
73
+ node = self.findBlockNode('target', 'qdev0')
74
self.assertCorrectBackingImage(node, back2_img)
75
self.assertIntactSourceBackingChain()
76
77
def testNone(self):
78
self.runMirror('none')
79
80
- node = self.findBlockNode('target',
81
- '/machine/peripheral/qdev0/virtio-backend')
82
+ node = self.findBlockNode('target', 'qdev0')
83
self.assertCorrectBackingImage(node, source_img)
84
self.assertIntactSourceBackingChain()
85
86
@@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorReopen(MirrorBaseClass):
87
backing="backing")
88
self.assert_qmp(result, 'return', {})
89
90
+class TestBlockdevMirrorReopenIothread(TestBlockdevMirrorReopen):
91
+ use_iothread = True
92
+
93
# Attach the backing chain only during completion, with blockdev-snapshot
94
class TestBlockdevMirrorSnapshot(MirrorBaseClass):
95
cmd = 'blockdev-mirror'
96
@@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorSnapshot(MirrorBaseClass):
97
overlay="target")
98
self.assert_qmp(result, 'return', {})
99
100
+class TestBlockdevMirrorSnapshotIothread(TestBlockdevMirrorSnapshot):
101
+ use_iothread = True
102
+
103
class TestCommit(BaseClass):
104
existing = False
105
106
@@ -XXX,XX +XXX,XX @@ class TestCommit(BaseClass):
107
108
self.vm.event_wait('BLOCK_JOB_COMPLETED')
109
110
- node = self.findBlockNode(None,
111
- '/machine/peripheral/qdev0/virtio-backend')
112
+ node = self.findBlockNode(None, 'qdev0')
113
self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename',
114
back1_img)
115
self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename',
116
diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out
117
index XXXXXXX..XXXXXXX 100644
118
--- a/tests/qemu-iotests/155.out
119
+++ b/tests/qemu-iotests/155.out
120
@@ -XXX,XX +XXX,XX @@
121
-.........................
122
+...............................
123
----------------------------------------------------------------------
124
-Ran 25 tests
125
+Ran 31 tests
126
127
OK
128
--
129
2.20.1
130
131
diff view generated by jsdifflib
Deleted patch
1
From: Peter Krempa <pkrempa@redhat.com>
2
1
3
Anounce that 'blockdev-snapshot' command's permissions allow changing
4
of the backing file if the 'consistent_read' permission is not required.
5
6
This is useful for libvirt to allow late opening of the backing chain
7
during a blockdev-mirror.
8
9
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20200310113831.27293-8-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
qapi/block-core.json | 9 ++++++++-
15
1 file changed, 8 insertions(+), 1 deletion(-)
16
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
19
--- a/qapi/block-core.json
20
+++ b/qapi/block-core.json
21
@@ -XXX,XX +XXX,XX @@
22
#
23
# For the arguments, see the documentation of BlockdevSnapshot.
24
#
25
+# Features:
26
+# @allow-write-only-overlay: If present, the check whether this operation is safe
27
+# was relaxed so that it can be used to change
28
+# backing file of a destination of a blockdev-mirror.
29
+# (since 5.0)
30
+#
31
# Since: 2.5
32
#
33
# Example:
34
@@ -XXX,XX +XXX,XX @@
35
#
36
##
37
{ 'command': 'blockdev-snapshot',
38
- 'data': 'BlockdevSnapshot' }
39
+ 'data': 'BlockdevSnapshot',
40
+ 'features': [ 'allow-write-only-overlay' ] }
41
42
##
43
# @change-backing-file:
44
--
45
2.20.1
46
47
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
The socket_scm_helper path got corrupted during the mechanical
4
refactor moving the qtests files into their own sub-directory.
5
6
Fixes: 1e8a1fae7 ("test: Move qtests to a separate directory")
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-Id: <20200306165751.18986-1-philmd@redhat.com>
9
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
tests/Makefile.include | 1 +
13
tests/qtest/Makefile.include | 1 -
14
2 files changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/Makefile.include
19
+++ b/tests/Makefile.include
20
@@ -XXX,XX +XXX,XX @@ include $(SRC_PATH)/tests/qtest/Makefile.include
21
tests/test-qga$(EXESUF): qemu-ga$(EXESUF)
22
tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y)
23
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a
24
+tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
25
26
SPEED = quick
27
28
diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qtest/Makefile.include
31
+++ b/tests/qtest/Makefile.include
32
@@ -XXX,XX +XXX,XX @@ tests/qtest/usb-hcd-ehci-test$(EXESUF): tests/qtest/usb-hcd-ehci-test.o $(libqos
33
tests/qtest/usb-hcd-xhci-test$(EXESUF): tests/qtest/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
34
tests/qtest/cpu-plug-test$(EXESUF): tests/qtest/cpu-plug-test.o
35
tests/qtest/migration-test$(EXESUF): tests/qtest/migration-test.o tests/qtest/migration-helpers.o
36
-tests/qtest/qemu-iotests/qtest/socket_scm_helper$(EXESUF): tests/qtest/qemu-iotests/qtest/socket_scm_helper.o
37
tests/qtest/test-netfilter$(EXESUF): tests/qtest/test-netfilter.o $(qtest-obj-y)
38
tests/qtest/test-filter-mirror$(EXESUF): tests/qtest/test-filter-mirror.o $(qtest-obj-y)
39
tests/qtest/test-filter-redirector$(EXESUF): tests/qtest/test-filter-redirector.o $(qtest-obj-y)
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Denis Rastyogin <gerben@altlinux.org>
2
2
3
When using a non-UTF8 secret to create a volume using qemu-img, the
3
This error was discovered by fuzzing qemu-img.
4
following error happens:
5
4
6
$ qemu-img create -f luks --object secret,id=vol_1_encrypt0,file=vol_resize_pool.vol_1.secret.qzVQrI -o key-secret=vol_1_encrypt0 /var/tmp/pool_target/vol_1 10240K
5
This commit fixes a division by zero error in the bench_cb() function
6
that occurs when using the bench command with a zero-sized image.
7
7
8
Formatting '/var/tmp/pool_target/vol_1', fmt=luks size=10485760 key-secret=vol_1_encrypt0
8
The issue arises because b->image_size can be zero, leading to a
9
qemu-img: /var/tmp/pool_target/vol_1: Data from secret vol_1_encrypt0 is not valid UTF-8
9
division by zero in the modulo operation (b->offset %= b->image_size).
10
This patch adds a check for b->image_size == 0 and resets b->offset
11
to 0 in such cases, preventing the error.
10
12
11
However, the created file '/var/tmp/pool_target/vol_1' is left behind in the
13
Signed-off-by: Denis Rastyogin <gerben@altlinux.org>
12
file system after the failure. This behavior can be observed when creating
14
Message-ID: <20250318101933.255617-1-gerben@altlinux.org>
13
the volume using Libvirt, via 'virsh vol-create', and then getting "volume
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
target path already exist" errors when trying to re-create the volume.
15
16
The volume file is created inside block_crypto_co_create_opts_luks(), in
17
block/crypto.c. If the bdrv_create_file() call is successful but any
18
succeeding step fails*, the existing 'fail' label does not take into
19
account the created file, leaving it behind.
20
21
This patch changes block_crypto_co_create_opts_luks() to delete
22
'filename' in case of failure. A failure in this point means that
23
the volume is now truncated/corrupted, so even if 'filename' was an
24
existing volume before calling qemu-img, it is now unusable. Deleting
25
the file it is not much worse than leaving it in the filesystem in
26
this scenario, and we don't have to deal with checking the file
27
pre-existence in the code.
28
29
* in our case, block_crypto_co_create_generic calls qcrypto_block_create,
30
which calls qcrypto_block_luks_create, and this function fails when
31
calling qcrypto_secret_lookup_as_utf8.
32
33
Reported-by: Srikanth Aithal <bssrikanth@in.ibm.com>
34
Suggested-by: Kevin Wolf <kwolf@redhat.com>
35
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
36
Message-Id: <20200130213907.2830642-4-danielhb413@gmail.com>
37
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
---
17
---
39
block/crypto.c | 18 ++++++++++++++++++
18
qemu-img.c | 6 +++++-
40
1 file changed, 18 insertions(+)
19
1 file changed, 5 insertions(+), 1 deletion(-)
41
20
42
diff --git a/block/crypto.c b/block/crypto.c
21
diff --git a/qemu-img.c b/qemu-img.c
43
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
44
--- a/block/crypto.c
23
--- a/qemu-img.c
45
+++ b/block/crypto.c
24
+++ b/qemu-img.c
46
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void bench_cb(void *opaque, int ret)
47
#include "qapi/error.h"
26
*/
48
#include "qemu/module.h"
27
b->in_flight++;
49
#include "qemu/option.h"
28
b->offset += b->step;
50
+#include "qemu/cutils.h"
29
- b->offset %= b->image_size;
51
#include "crypto.h"
30
+ if (b->image_size == 0) {
52
31
+ b->offset = 0;
53
typedef struct BlockCrypto BlockCrypto;
32
+ } else {
54
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
33
+ b->offset %= b->image_size;
55
56
ret = 0;
57
fail:
58
+ /*
59
+ * If an error occurred, delete 'filename'. Even if the file existed
60
+ * beforehand, it has been truncated and corrupted in the process.
61
+ */
62
+ if (ret && bs) {
63
+ Error *local_delete_err = NULL;
64
+ int r_del = bdrv_co_delete_file(bs, &local_delete_err);
65
+ /*
66
+ * ENOTSUP will happen if the block driver doesn't support
67
+ * the 'bdrv_co_delete_file' interface. This is a predictable
68
+ * scenario and shouldn't be reported back to the user.
69
+ */
70
+ if ((r_del < 0) && (r_del != -ENOTSUP)) {
71
+ error_report_err(local_delete_err);
72
+ }
34
+ }
73
+ }
35
if (b->write) {
74
+
36
acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
75
bdrv_unref(bs);
37
} else {
76
qapi_free_QCryptoBlockCreateOptions(create_opts);
77
qobject_unref(cryptoopts);
78
--
38
--
79
2.20.1
39
2.49.0
80
81
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
qcow2_refresh_limits() assumes that s->crypto is non-NULL whenever
2
bs->encrypted is true. This is actually not the case: qcow2_do_open()
3
allows to open an image with a missing crypto header for BDRV_O_NO_IO,
4
and then bs->encrypted is true, but s->crypto is still NULL.
2
5
3
This patch adds a new test file to exercise the case where
6
It doesn't make sense to open an invalid image, so remove the exception
4
qemu-img fails to complete for the LUKS format when a non-UTF8
7
for BDRV_O_NO_IO. This catches the problem early and any code that makes
5
secret is used.
8
the same assumption is safe now.
6
9
7
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
10
At the same time, in the name of defensive programming, we shouldn't
8
Message-Id: <20200130213907.2830642-5-danielhb413@gmail.com>
11
make the assumption in the first place. Let qcow2_refresh_limits() check
12
s->crypto rather than bs->encrypted. If s->crypto is NULL, it also can't
13
make any requirement on request alignment.
14
15
Finally, start a qcow2-encryption test case that only serves as a
16
regression test for this crash for now.
17
18
Reported-by: Leonid Reviakin <L.reviakin@fobos-nt.ru>
19
Reported-by: Denis Rastyogin <gerben@altlinux.org>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Message-ID: <20250318201143.70657-1-kwolf@redhat.com>
22
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
24
---
11
tests/qemu-iotests/282 | 67 ++++++++++++++++++++++++++++++++++++++
25
block/qcow2.c | 4 +-
12
tests/qemu-iotests/282.out | 11 +++++++
26
tests/qemu-iotests/tests/qcow2-encryption | 75 +++++++++++++++++++
13
tests/qemu-iotests/group | 1 +
27
tests/qemu-iotests/tests/qcow2-encryption.out | 32 ++++++++
14
3 files changed, 79 insertions(+)
28
3 files changed, 109 insertions(+), 2 deletions(-)
15
create mode 100755 tests/qemu-iotests/282
29
create mode 100755 tests/qemu-iotests/tests/qcow2-encryption
16
create mode 100644 tests/qemu-iotests/282.out
30
create mode 100644 tests/qemu-iotests/tests/qcow2-encryption.out
17
31
18
diff --git a/tests/qemu-iotests/282 b/tests/qemu-iotests/282
32
diff --git a/block/qcow2.c b/block/qcow2.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/qcow2.c
35
+++ b/block/qcow2.c
36
@@ -XXX,XX +XXX,XX @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
37
ret = -EINVAL;
38
goto fail;
39
}
40
- } else if (!(flags & BDRV_O_NO_IO)) {
41
+ } else {
42
error_setg(errp, "Missing CRYPTO header for crypt method %d",
43
s->crypt_method_header);
44
ret = -EINVAL;
45
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
46
{
47
BDRVQcow2State *s = bs->opaque;
48
49
- if (bs->encrypted) {
50
+ if (s->crypto) {
51
/* Encryption works on a sector granularity */
52
bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
53
}
54
diff --git a/tests/qemu-iotests/tests/qcow2-encryption b/tests/qemu-iotests/tests/qcow2-encryption
19
new file mode 100755
55
new file mode 100755
20
index XXXXXXX..XXXXXXX
56
index XXXXXXX..XXXXXXX
21
--- /dev/null
57
--- /dev/null
22
+++ b/tests/qemu-iotests/282
58
+++ b/tests/qemu-iotests/tests/qcow2-encryption
23
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
24
+#!/usr/bin/env bash
60
+#!/usr/bin/env bash
61
+# group: rw quick
25
+#
62
+#
26
+# Test qemu-img file cleanup for LUKS when using a non-UTF8 secret
63
+# Test case for encryption support in qcow2
27
+#
64
+#
28
+# Copyright (C) 2020, IBM Corporation.
65
+# Copyright (C) 2025 Red Hat, Inc.
29
+#
66
+#
30
+# This program is free software; you can redistribute it and/or modify
67
+# This program is free software; you can redistribute it and/or modify
31
+# it under the terms of the GNU General Public License as published by
68
+# it under the terms of the GNU General Public License as published by
32
+# the Free Software Foundation; either version 2 of the License, or
69
+# the Free Software Foundation; either version 2 of the License, or
33
+# (at your option) any later version.
70
+# (at your option) any later version.
...
...
39
+#
76
+#
40
+# You should have received a copy of the GNU General Public License
77
+# You should have received a copy of the GNU General Public License
41
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
78
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
42
+#
79
+#
43
+
80
+
44
+seq=`basename $0`
81
+# creator
82
+owner=kwolf@redhat.com
83
+
84
+seq="$(basename $0)"
45
+echo "QA output created by $seq"
85
+echo "QA output created by $seq"
46
+
86
+
47
+status=1    # failure is the default!
87
+status=1    # failure is the default!
48
+TEST_IMAGE_FILE='vol.img'
49
+
88
+
50
+_cleanup()
89
+_cleanup()
51
+{
90
+{
52
+ _cleanup_test_img
91
+    _cleanup_test_img
53
+ rm non_utf8_secret
54
+ rm -f $TEST_IMAGE_FILE
55
+}
92
+}
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
93
+trap "_cleanup; exit \$status" 0 1 2 3 15
57
+
94
+
58
+# get standard environment, filters and checks
95
+# get standard environment, filters and checks
59
+. ./common.rc
96
+. ../common.rc
60
+. ./common.filter
97
+. ../common.filter
61
+
98
+
62
+_supported_fmt luks
99
+# This tests qcow2-specific low-level functionality
63
+_supported_proto generic
100
+_supported_fmt qcow2
64
+_unsupported_proto vxhs
101
+_supported_proto file
102
+_require_working_luks
65
+
103
+
66
+echo "== Create non-UTF8 secret =="
104
+IMG_SIZE=64M
67
+echo -n -e '\x3a\x3c\x3b\xff' > non_utf8_secret
68
+SECRET="secret,id=sec0,file=non_utf8_secret"
69
+
105
+
70
+echo "== Throws an error because of invalid UTF-8 secret =="
106
+echo
71
+$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M
107
+echo "=== Create an encrypted image ==="
108
+echo
72
+
109
+
73
+echo "== Image file should not exist after the error =="
110
+_make_test_img --object secret,id=sec0,data=123456 -o encrypt.format=luks,encrypt.key-secret=sec0 $IMG_SIZE
74
+if test -f "$TEST_IMAGE_FILE"; then
111
+$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts
75
+ exit 1
112
+_img_info
76
+fi
113
+$QEMU_IMG check \
114
+ --object secret,id=sec0,data=123456 \
115
+ --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 \
116
+ | _filter_qemu_img_check
77
+
117
+
78
+echo "== Create a stub image file and run qemu-img again =="
118
+echo
79
+touch $TEST_IMAGE_FILE
119
+echo "=== Remove the header extension ==="
80
+$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M
120
+echo
81
+
121
+
82
+echo "== Pre-existing image file should also be deleted after the error =="
122
+$PYTHON ../qcow2.py "$TEST_IMG" del-header-ext 0x0537be77
83
+if test -f "$TEST_IMAGE_FILE"; then
123
+$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts
84
+ exit 1
124
+_img_info
85
+fi
125
+$QEMU_IMG check \
126
+ --object secret,id=sec0,data=123456 \
127
+ --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 2>&1 \
128
+ | _filter_qemu_img_check \
129
+ | _filter_testdir
86
+
130
+
87
+# success, all done
131
+# success, all done
88
+echo "*** done"
132
+echo "*** done"
89
+rm -f $seq.full
133
+rm -f $seq.full
90
+status=0
134
+status=0
91
diff --git a/tests/qemu-iotests/282.out b/tests/qemu-iotests/282.out
135
diff --git a/tests/qemu-iotests/tests/qcow2-encryption.out b/tests/qemu-iotests/tests/qcow2-encryption.out
92
new file mode 100644
136
new file mode 100644
93
index XXXXXXX..XXXXXXX
137
index XXXXXXX..XXXXXXX
94
--- /dev/null
138
--- /dev/null
95
+++ b/tests/qemu-iotests/282.out
139
+++ b/tests/qemu-iotests/tests/qcow2-encryption.out
96
@@ -XXX,XX +XXX,XX @@
140
@@ -XXX,XX +XXX,XX @@
97
+QA output created by 282
141
+QA output created by qcow2-encryption
98
+== Create non-UTF8 secret ==
142
+
99
+== Throws an error because of invalid UTF-8 secret ==
143
+=== Create an encrypted image ===
100
+qemu-img: vol.img: Data from secret sec0 is not valid UTF-8
144
+
101
+Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0
145
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
102
+== Image file should not exist after the error ==
146
+Header extension:
103
+== Create a stub image file and run qemu-img again ==
147
+magic 0x537be77 (Crypto header)
104
+qemu-img: vol.img: Data from secret sec0 is not valid UTF-8
148
+length 16
105
+Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0
149
+data <binary>
106
+== Pre-existing image file should also be deleted after the error ==
150
+
107
+ *** done
151
+Header extension:
108
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
152
+magic 0x6803f857 (Feature table)
109
index XXXXXXX..XXXXXXX 100644
153
+length 384
110
--- a/tests/qemu-iotests/group
154
+data <binary>
111
+++ b/tests/qemu-iotests/group
155
+
112
@@ -XXX,XX +XXX,XX @@
156
+image: TEST_DIR/t.IMGFMT
113
279 rw backing quick
157
+file format: IMGFMT
114
280 rw migration quick
158
+virtual size: 64 MiB (67108864 bytes)
115
281 rw quick
159
+encrypted: yes
116
+282 rw img quick
160
+cluster_size: 65536
117
283 auto quick
161
+No errors were found on the image.
118
284 rw
162
+
119
286 rw quick
163
+=== Remove the header extension ===
164
+
165
+Header extension:
166
+magic 0x6803f857 (Feature table)
167
+length 384
168
+data <binary>
169
+
170
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Missing CRYPTO header for crypt method 2
171
+qemu-img: Could not open 'file.filename=TEST_DIR/t.qcow2,encrypt.key-secret=sec0': Missing CRYPTO header for crypt method 2
172
+*** done
120
--
173
--
121
2.20.1
174
2.49.0
122
175
123
176
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
Originally, all failed SG_IO requests called scsi_handle_rw_error() to
2
apply the configured error policy. However, commit f3126d65, which was
3
supposed to be a mere refactoring for scsi-disk.c, broke this and
4
accidentally completed the SCSI request without considering the error
5
policy any more if the error was signalled in the host_status field.
2
6
3
Using the new 'bdrv_co_delete_file' interface, a pure co_routine function
7
Apart from the commit message not describing the change as intended,
4
'bdrv_co_delete_file' inside block.c can can be used in a way similar of
8
errors indicated in host_status are also obviously backend errors and
5
the existing bdrv_create_file to to clean up a created file.
9
not something the guest must deal with independently of the error
10
policy.
6
11
7
We're creating a pure co_routine because the only caller of
12
This behaviour means that some recoverable errors (such as a path error
8
'bdrv_co_delete_file' will be already in co_routine context, thus there
13
in multipath configurations) were reported to the guest anyway, which
9
is no need to add all the machinery to check for qemu_in_coroutine() and
14
might not expect it and might consider its disk broken.
10
create a separated co_routine to do the job.
11
15
12
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
16
Make sure that we apply the error policy again for host_status errors,
13
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
17
too. This addresses an existing FIXME comment and allows us to remove
14
Message-Id: <20200130213907.2830642-3-danielhb413@gmail.com>
18
some comments warning that callbacks weren't always called. With this
19
fix, they are called in all cases again.
20
21
The return value passed to the request callback doesn't have more free
22
values that could be used to indicate host_status errors as well as SAM
23
status codes and negative errno. Store the value in the host_status
24
field of the SCSIRequest instead and use -ENODEV as the return value (if
25
a path hasn't been reachable for a while, blk_aio_ioctl() will return
26
-ENODEV instead of just setting host_status, so just reuse it here -
27
it's not necessarily entirely accurate, but it's as good as any errno).
28
29
Cc: qemu-stable@nongnu.org
30
Fixes: f3126d65b393 ('scsi: move host_status handling into SCSI drivers')
31
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
Message-ID: <20250407155949.44736-1-kwolf@redhat.com>
33
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
34
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
36
---
17
include/block/block.h | 1 +
37
hw/scsi/scsi-disk.c | 39 +++++++++++++++++++++++++--------------
18
block.c | 26 ++++++++++++++++++++++++++
38
1 file changed, 25 insertions(+), 14 deletions(-)
19
2 files changed, 27 insertions(+)
20
39
21
diff --git a/include/block/block.h b/include/block/block.h
40
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
22
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block.h
42
--- a/hw/scsi/scsi-disk.c
24
+++ b/include/block/block.h
43
+++ b/hw/scsi/scsi-disk.c
25
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
44
@@ -XXX,XX +XXX,XX @@ struct SCSIDiskClass {
26
int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
45
SCSIDeviceClass parent_class;
27
Error **errp);
46
/*
28
void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
47
* Callbacks receive ret == 0 for success. Errors are represented either as
29
+int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
48
- * negative errno values, or as positive SAM status codes.
30
49
- *
31
50
- * Beware: For errors returned in host_status, the function may directly
32
typedef struct BdrvCheckResult {
51
- * complete the request and never call the callback.
33
diff --git a/block.c b/block.c
52
+ * negative errno values, or as positive SAM status codes. For host_status
34
index XXXXXXX..XXXXXXX 100644
53
+ * errors, the function passes ret == -ENODEV and sets the host_status field
35
--- a/block.c
54
+ * of the SCSIRequest.
36
+++ b/block.c
55
*/
37
@@ -XXX,XX +XXX,XX @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
56
DMAIOFunc *dma_readv;
38
}
57
DMAIOFunc *dma_writev;
39
}
58
@@ -XXX,XX +XXX,XX @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
40
59
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
41
+int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
60
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
42
+{
61
SCSISense sense = SENSE_CODE(NO_SENSE);
43
+ Error *local_err = NULL;
62
+ int16_t host_status;
44
+ int ret;
63
int error;
45
+
64
bool req_has_sense = false;
46
+ assert(bs != NULL);
65
BlockErrorAction action;
47
+
66
int status;
48
+ if (!bs->drv) {
67
49
+ error_setg(errp, "Block node '%s' is not opened", bs->filename);
68
+ /*
50
+ return -ENOMEDIUM;
69
+ * host_status should only be set for SG_IO requests that came back with a
70
+ * host_status error in scsi_block_sgio_complete(). This error path passes
71
+ * -ENODEV as the return value.
72
+ *
73
+ * Reset host_status in the request because we may still want to complete
74
+ * the request successfully with the 'stop' or 'ignore' error policy.
75
+ */
76
+ host_status = r->req.host_status;
77
+ if (host_status != -1) {
78
+ assert(ret == -ENODEV);
79
+ r->req.host_status = -1;
51
+ }
80
+ }
52
+
81
+
53
+ if (!bs->drv->bdrv_co_delete_file) {
82
if (ret < 0) {
54
+ error_setg(errp, "Driver '%s' does not support image deletion",
83
status = scsi_sense_from_errno(-ret, &sense);
55
+ bs->drv->format_name);
84
error = -ret;
56
+ return -ENOTSUP;
85
@@ -XXX,XX +XXX,XX @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
57
+ }
86
if (acct_failed) {
58
+
87
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
59
+ ret = bs->drv->bdrv_co_delete_file(bs, &local_err);
88
}
60
+ if (ret < 0) {
89
+ if (host_status != -1) {
61
+ error_propagate(errp, local_err);
90
+ scsi_req_complete_failed(&r->req, host_status);
62
+ }
91
+ return true;
63
+
92
+ }
64
+ return ret;
93
if (req_has_sense) {
65
+}
94
sdc->update_sense(&r->req);
66
+
95
} else if (status == CHECK_CONDITION) {
67
/**
96
@@ -XXX,XX +XXX,XX @@ done:
68
* Try to get @bs's logical and physical block size.
97
scsi_req_unref(&r->req);
69
* On success, store them in @bsz struct and return 0.
98
}
99
100
-/* May not be called in all error cases, don't rely on cleanup here */
101
static void scsi_dma_complete(void *opaque, int ret)
102
{
103
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
104
@@ -XXX,XX +XXX,XX @@ done:
105
scsi_req_unref(&r->req);
106
}
107
108
-/* May not be called in all error cases, don't rely on cleanup here */
109
static void scsi_read_complete(void *opaque, int ret)
110
{
111
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
112
@@ -XXX,XX +XXX,XX @@ done:
113
scsi_req_unref(&r->req);
114
}
115
116
-/* May not be called in all error cases, don't rely on cleanup here */
117
static void scsi_write_complete(void * opaque, int ret)
118
{
119
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
120
@@ -XXX,XX +XXX,XX @@ static void scsi_block_sgio_complete(void *opaque, int ret)
121
sg_io_hdr_t *io_hdr = &req->io_header;
122
123
if (ret == 0) {
124
- /* FIXME This skips calling req->cb() and any cleanup in it */
125
if (io_hdr->host_status != SCSI_HOST_OK) {
126
- scsi_req_complete_failed(&r->req, io_hdr->host_status);
127
- scsi_req_unref(&r->req);
128
- return;
129
- }
130
-
131
- if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
132
+ r->req.host_status = io_hdr->host_status;
133
+ ret = -ENODEV;
134
+ } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
135
ret = BUSY;
136
} else {
137
ret = io_hdr->status;
70
--
138
--
71
2.20.1
139
2.49.0
72
73
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Vitalii Mordan <mordan@ispras.ru>
2
2
3
Adding to Block Drivers the capability of being able to clean up
3
This patch addresses potential data races involving access to Job fields
4
its created files can be useful in certain situations. For the
4
in the test-bdrv-drain test.
5
LUKS driver, for instance, a failure in one of its authentication
6
steps can leave files in the host that weren't there before.
7
5
8
This patch adds the 'bdrv_co_delete_file' interface to block
6
Fixes: 7253220de4 ("test-bdrv-drain: Test drain vs. block jobs")
9
drivers and add it to the 'file' driver in file-posix.c. The
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2900
10
implementation is given by 'raw_co_delete_file'.
8
Signed-off-by: Vitalii Mordan <mordan@ispras.ru>
11
9
Message-ID: <20250402102119.3345626-1-mordan@ispras.ru>
12
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
10
[kwolf: Fixed up coding style and one missing atomic access]
13
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20200130213907.2830642-2-danielhb413@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
13
---
17
include/block/block_int.h | 4 ++++
14
include/qemu/job.h | 3 +++
18
block/file-posix.c | 23 +++++++++++++++++++++++
15
job.c | 6 ++++++
19
2 files changed, 27 insertions(+)
16
tests/unit/test-bdrv-drain.c | 32 +++++++++++++++++++-------------
17
3 files changed, 28 insertions(+), 13 deletions(-)
20
18
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
19
diff --git a/include/qemu/job.h b/include/qemu/job.h
22
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
21
--- a/include/qemu/job.h
24
+++ b/include/block/block_int.h
22
+++ b/include/qemu/job.h
25
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
23
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job);
26
*/
24
/* Same as job_is_ready(), but called with job lock held. */
27
int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
25
bool job_is_ready_locked(Job *job);
28
26
29
+ /* Delete a created file. */
27
+/** Returns whether the job is paused. Called with job_mutex *not* held. */
30
+ int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
28
+bool job_is_paused(Job *job);
31
+ Error **errp);
32
+
29
+
33
/*
30
/**
34
* Flushes all data that was already written to the OS all the way down to
31
* Request @job to pause at the next pause point. Must be paired with
35
* the disk (for example file-posix.c calls fsync()).
32
* job_resume(). If the job is supposed to be resumed by user action, call
36
diff --git a/block/file-posix.c b/block/file-posix.c
33
diff --git a/job.c b/job.c
37
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
38
--- a/block/file-posix.c
35
--- a/job.c
39
+++ b/block/file-posix.c
36
+++ b/job.c
40
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
37
@@ -XXX,XX +XXX,XX @@ bool job_is_cancelled_locked(Job *job)
41
return raw_co_create(&options, errp);
38
return job->force_cancel;
42
}
39
}
43
40
44
+static int coroutine_fn raw_co_delete_file(BlockDriverState *bs,
41
+bool job_is_paused(Job *job)
45
+ Error **errp)
46
+{
42
+{
47
+ struct stat st;
43
+ JOB_LOCK_GUARD();
48
+ int ret;
44
+ return job->paused;
49
+
50
+ if (!(stat(bs->filename, &st) == 0) || !S_ISREG(st.st_mode)) {
51
+ error_setg_errno(errp, ENOENT, "%s is not a regular file",
52
+ bs->filename);
53
+ return -ENOENT;
54
+ }
55
+
56
+ ret = unlink(bs->filename);
57
+ if (ret < 0) {
58
+ ret = -errno;
59
+ error_setg_errno(errp, -ret, "Error when deleting file %s",
60
+ bs->filename);
61
+ }
62
+
63
+ return ret;
64
+}
45
+}
65
+
46
+
66
/*
47
bool job_is_cancelled(Job *job)
67
* Find allocation range in @bs around offset @start.
48
{
68
* May change underlying file descriptor's file offset.
49
JOB_LOCK_GUARD();
69
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
50
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
70
.bdrv_co_block_status = raw_co_block_status,
51
index XXXXXXX..XXXXXXX 100644
71
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
52
--- a/tests/unit/test-bdrv-drain.c
72
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
53
+++ b/tests/unit/test-bdrv-drain.c
73
+ .bdrv_co_delete_file = raw_co_delete_file,
54
@@ -XXX,XX +XXX,XX @@ typedef struct TestBlockJob {
74
55
BlockDriverState *bs;
75
.bdrv_co_preadv = raw_co_preadv,
56
int run_ret;
76
.bdrv_co_pwritev = raw_co_pwritev,
57
int prepare_ret;
58
+
59
+ /* Accessed with atomics */
60
bool running;
61
bool should_complete;
62
} TestBlockJob;
63
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_job_run(Job *job, Error **errp)
64
65
/* We are running the actual job code past the pause point in
66
* job_co_entry(). */
67
- s->running = true;
68
+ qatomic_set(&s->running, true);
69
70
job_transition_to_ready(&s->common.job);
71
- while (!s->should_complete) {
72
+ while (!qatomic_read(&s->should_complete)) {
73
/* Avoid job_sleep_ns() because it marks the job as !busy. We want to
74
* emulate some actual activity (probably some I/O) here so that drain
75
* has to wait for this activity to stop. */
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_job_run(Job *job, Error **errp)
77
static void test_job_complete(Job *job, Error **errp)
78
{
79
TestBlockJob *s = container_of(job, TestBlockJob, common.job);
80
- s->should_complete = true;
81
+ qatomic_set(&s->should_complete, true);
82
}
83
84
BlockJobDriver test_job_driver = {
85
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
86
/* job_co_entry() is run in the I/O thread, wait for the actual job
87
* code to start (we don't want to catch the job in the pause point in
88
* job_co_entry(). */
89
- while (!tjob->running) {
90
+ while (!qatomic_read(&tjob->running)) {
91
aio_poll(qemu_get_aio_context(), false);
92
}
93
}
94
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
95
WITH_JOB_LOCK_GUARD() {
96
g_assert_cmpint(job->job.pause_count, ==, 0);
97
g_assert_false(job->job.paused);
98
- g_assert_true(tjob->running);
99
+ g_assert_true(qatomic_read(&tjob->running));
100
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
104
*
105
* paused is reset in the I/O thread, wait for it
106
*/
107
- while (job->job.paused) {
108
+ while (job_is_paused(&job->job)) {
109
aio_poll(qemu_get_aio_context(), false);
110
}
111
}
112
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
113
*
114
* paused is reset in the I/O thread, wait for it
115
*/
116
- while (job->job.paused) {
117
+ while (job_is_paused(&job->job)) {
118
aio_poll(qemu_get_aio_context(), false);
119
}
120
}
121
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
122
123
typedef struct TestDropBackingBlockJob {
124
BlockJob common;
125
- bool should_complete;
126
bool *did_complete;
127
BlockDriverState *detach_also;
128
BlockDriverState *bs;
129
+
130
+ /* Accessed with atomics */
131
+ bool should_complete;
132
} TestDropBackingBlockJob;
133
134
static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp)
135
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp)
136
TestDropBackingBlockJob *s =
137
container_of(job, TestDropBackingBlockJob, common.job);
138
139
- while (!s->should_complete) {
140
+ while (!qatomic_read(&s->should_complete)) {
141
job_sleep_ns(job, 0);
142
}
143
144
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_commit_by_drained_end(void)
145
146
job_start(&job->common.job);
147
148
- job->should_complete = true;
149
+ qatomic_set(&job->should_complete, true);
150
bdrv_drained_begin(bs_child);
151
g_assert(!job_has_completed);
152
bdrv_drained_end(bs_child);
153
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_commit_by_drained_end(void)
154
155
typedef struct TestSimpleBlockJob {
156
BlockJob common;
157
- bool should_complete;
158
bool *did_complete;
159
+
160
+ /* Accessed with atomics */
161
+ bool should_complete;
162
} TestSimpleBlockJob;
163
164
static int coroutine_fn test_simple_job_run(Job *job, Error **errp)
165
{
166
TestSimpleBlockJob *s = container_of(job, TestSimpleBlockJob, common.job);
167
168
- while (!s->should_complete) {
169
+ while (!qatomic_read(&s->should_complete)) {
170
job_sleep_ns(job, 0);
171
}
172
173
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
174
job->did_complete = &job_has_completed;
175
176
job_start(&job->common.job);
177
- job->should_complete = true;
178
+ qatomic_set(&job->should_complete, true);
179
180
g_assert(!job_has_completed);
181
ret = bdrv_drop_intermediate(chain[1], chain[0], NULL, false);
77
--
182
--
78
2.20.1
183
2.49.0
79
80
diff view generated by jsdifflib