1
The following changes since commit b98a66201dbc7cf3b962f4bb260f66100cc75578:
1
The following changes since commit dd2db39d78431ab5a0b78777afaab3d61e94533e:
2
2
3
Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-4.0-rc0-2' into staging (2019-03-19 12:55:02 +0000)
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2021-06-01 21:23:26 +0100)
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
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 59fba0aaee7438002d9803a86c888f21a1070cc8:
9
for you to fetch changes up to b317006a3f1f04191a7981cef83417cb2477213b:
10
10
11
qemu-iotests: Treat custom TEST_DIR in 051 (2019-03-19 15:51:31 +0100)
11
docs/secure-coding-practices: Describe how to use 'null-co' block driver (2021-06-02 14:29:14 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- mirror: Fix early return from drain (could cause deadlocks)
16
- NBD server: Fix crashes related to switching between AioContexts
17
- vmdk: Fixed probing for version 3 images
17
- file-posix: Workaround for discard/write_zeroes on buggy filesystems
18
- vl: Fix to create migration object before block backends again (fixes
18
- Follow-up fixes for the reopen vs. permission changes
19
segfault for block drivers that set migration blockers)
19
- quorum: Fix error handling for flush
20
- Several minor fixes, documentation and test case improvements
20
- block-copy: Refactor copy_range handling
21
- docs: Describe how to use 'null-co' block driver
21
22
22
----------------------------------------------------------------
23
----------------------------------------------------------------
23
Alberto Garcia (1):
24
Lukas Straub (1):
24
block: Make bdrv_{copy_on_read,crypto_luks,replication} static
25
block/quorum: Provide .bdrv_co_flush instead of .bdrv_co_flush_to_disk
25
26
26
Kevin Wolf (3):
27
Philippe Mathieu-Daudé (1):
27
qcow2: Fix data file error condition in qcow2_co_create()
28
docs/secure-coding-practices: Describe how to use 'null-co' block driver
28
block: Silence Coverity in bdrv_drop_intermediate()
29
qemu-iotests: Fix 232 for non-qcow2
30
31
Lukáš Doktor (1):
32
qemu-iotests: Treat custom TEST_DIR in 051
33
34
Markus Armbruster (1):
35
vl: Fix to create migration object before block backends again
36
37
Max Reitz (1):
38
blockdev: Check @replaces in blockdev_mirror_common
39
40
Sam Eiderman (1):
41
vmdk: Support version=3 in VMDK descriptor files
42
29
43
Sergio Lopez (2):
30
Sergio Lopez (2):
44
mirror: Confirm we're quiesced only if the job is paused or cancelled
31
block-backend: add drained_poll
45
iotests: 153: Wait for an answer to QMP commands
32
nbd/server: Use drained block ops to quiesce the server
46
33
47
Vladimir Sementsov-Ogievskiy (2):
34
Thomas Huth (2):
48
qapi: fix block-latency-histogram-set description and examples
35
block/file-posix: Fix problem with fallocate(PUNCH_HOLE) on GPFS
49
blockjob: fix user pause in block_job_error_action
36
block/file-posix: Try other fallbacks after invalid FALLOC_FL_ZERO_RANGE
50
37
51
qapi/block-core.json | 10 +++---
38
Vladimir Sementsov-Ogievskiy (14):
52
block.c | 7 ++--
39
qemu-io-cmds: assert that we don't have .perm requested in no-blk case
53
block/copy-on-read.c | 2 +-
40
block/vvfat: child_vvfat_qcow: add .get_parent_aio_context, fix crash
54
block/crypto.c | 2 +-
41
block/vvfat: fix vvfat_child_perm crash
55
block/mirror.c | 16 ++++++++++
42
block: consistently use bdrv_is_read_only()
56
block/qcow2.c | 2 +-
43
block: drop BlockDriverState::read_only
57
block/replication.c | 2 +-
44
block: drop BlockBackendRootState::read_only
58
block/vmdk.c | 6 ++--
45
block: document child argument of bdrv_attach_child_common()
59
blockdev.c | 55 +++++++++++++++++++-------------
46
block-backend: improve blk_root_get_parent_desc()
60
blockjob.c | 8 +++--
47
block: improve bdrv_child_get_parent_desc()
61
vl.c | 15 +++++----
48
block/vvfat: inherit child_vvfat_qcow from child_of_bds
62
tests/qemu-iotests/051 | 2 +-
49
block: simplify bdrv_child_user_desc()
63
tests/qemu-iotests/153 | 12 +++----
50
block: improve permission conflict error message
64
tests/qemu-iotests/153.out | 6 ++++
51
block-copy: fix block_copy_task_entry() progress update
65
tests/qemu-iotests/232 | 30 ------------------
52
block-copy: refactor copy_range handling
66
tests/qemu-iotests/232.out | 20 ------------
67
tests/qemu-iotests/247 | 79 ++++++++++++++++++++++++++++++++++++++++++++++
68
tests/qemu-iotests/247.out | 22 +++++++++++++
69
tests/qemu-iotests/group | 1 +
70
19 files changed, 193 insertions(+), 104 deletions(-)
71
create mode 100755 tests/qemu-iotests/247
72
create mode 100644 tests/qemu-iotests/247.out
73
53
54
docs/devel/secure-coding-practices.rst | 9 ++++
55
include/block/block.h | 1 +
56
include/block/block_int.h | 2 -
57
include/sysemu/block-backend.h | 4 ++
58
block.c | 82 ++++++++++++++++++++--------------
59
block/block-backend.c | 26 +++++------
60
block/block-copy.c | 80 ++++++++++++++++++++++-----------
61
block/commit.c | 2 +-
62
block/file-posix.c | 29 ++++++++----
63
block/io.c | 4 +-
64
block/qapi.c | 2 +-
65
block/qcow2-snapshot.c | 2 +-
66
block/qcow2.c | 5 +--
67
block/quorum.c | 2 +-
68
block/snapshot.c | 2 +-
69
block/vhdx-log.c | 2 +-
70
block/vvfat.c | 14 +++---
71
blockdev.c | 3 +-
72
nbd/server.c | 82 +++++++++++++++++++++++++---------
73
qemu-io-cmds.c | 14 +++++-
74
tests/unit/test-block-iothread.c | 6 ---
75
tests/qemu-iotests/283.out | 2 +-
76
tests/qemu-iotests/307.out | 2 +-
77
tests/qemu-iotests/tests/qsd-jobs.out | 2 +-
78
24 files changed, 241 insertions(+), 138 deletions(-)
79
80
diff view generated by jsdifflib
1
From: Lukáš Doktor <ldoktor@redhat.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
When custom TEST_DIR is specified the output includes it without leading
3
The quorum block driver uses a custom flush callback to handle the
4
'/':
4
case when some children return io errors. In that case it still
5
returns success if enough children are healthy.
6
However, it provides it as the .bdrv_co_flush_to_disk callback, not
7
as .bdrv_co_flush. This causes the block layer to do it's own
8
generic flushing for the children instead, which doesn't handle
9
errors properly.
5
10
6
$ TEST_DIR=/var/tmp ./check -file -qcow2 051
11
Fix this by providing .bdrv_co_flush instead of
7
....
12
.bdrv_co_flush_to_disk so the block layer uses the custom flush
8
-drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file":
13
callback.
9
{"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2",
10
"file": {"driver": "file", "filename": SNAPSHOT_PATH}} (qcow2,
11
read-only)
12
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file":
13
{"driver": "file", "filename": "TEST_DIR/t.qcow2"}}, "driver": "qcow2",
14
"file": {"driver": "file", "filename": "TEST_DIR/vl.ziHfeP"}} (qcow2,
15
read-only)
16
14
17
Let's remove it from the sed regexp.
15
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
18
16
Reported-by: Minghao Yuan <meeho@qq.com>
19
Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
17
Message-Id: <20210518134214.11ccf05f@gecko.fritz.box>
18
Tested-by: Zhang Chen <chen.zhang@intel.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
20
---
22
tests/qemu-iotests/051 | 2 +-
21
block/quorum.c | 2 +-
23
1 file changed, 1 insertion(+), 1 deletion(-)
22
1 file changed, 1 insertion(+), 1 deletion(-)
24
23
25
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
24
diff --git a/block/quorum.c b/block/quorum.c
26
index XXXXXXX..XXXXXXX 100755
25
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/qemu-iotests/051
26
--- a/block/quorum.c
28
+++ b/tests/qemu-iotests/051
27
+++ b/block/quorum.c
29
@@ -XXX,XX +XXX,XX @@ TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
28
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
30
echo "info block" |
29
.bdrv_dirname = quorum_dirname,
31
run_qemu -drive file="$TEST_IMG",snapshot=on,read-only=on,if=none,id=$device_id |
30
.bdrv_co_block_status = quorum_co_block_status,
32
_filter_qemu_io |
31
33
- sed -e 's#"/[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g'
32
- .bdrv_co_flush_to_disk = quorum_co_flush,
34
+ sed -e 's#"[^"]*/vl\.[A-Za-z0-9]\{6\}"#SNAPSHOT_PATH#g'
33
+ .bdrv_co_flush = quorum_co_flush,
35
34
36
35
.bdrv_getlength = quorum_getlength,
37
# success, all done
36
38
--
37
--
39
2.20.1
38
2.30.2
40
39
41
40
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Coverity thinks blk may be NULL. It's a false-positive, as described in
4
a new comment.
5
6
Fixes: Coverity CID 1453194
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210519090532.3753-1-vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
qemu-io-cmds.c | 14 ++++++++++++--
12
1 file changed, 12 insertions(+), 2 deletions(-)
13
14
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-io-cmds.c
17
+++ b/qemu-io-cmds.c
18
@@ -XXX,XX +XXX,XX @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
19
return -EINVAL;
20
}
21
22
- /* Request additional permissions if necessary for this command. The caller
23
+ /*
24
+ * Request additional permissions if necessary for this command. The caller
25
* is responsible for restoring the original permissions afterwards if this
26
- * is what it wants. */
27
+ * is what it wants.
28
+ *
29
+ * Coverity thinks that blk may be NULL in the following if condition. It's
30
+ * not so: in init_check_command() we fail if blk is NULL for command with
31
+ * both CMD_FLAG_GLOBAL and CMD_NOFILE_OK flags unset. And in
32
+ * qemuio_add_command() we assert that command with non-zero .perm field
33
+ * doesn't set this flags. So, the following assertion is to silence
34
+ * Coverity:
35
+ */
36
+ assert(blk || !ct->perm);
37
if (ct->perm && blk_is_available(blk)) {
38
uint64_t orig_perm, orig_shared_perm;
39
blk_get_perm(blk, &orig_perm, &orig_shared_perm);
40
--
41
2.30.2
42
43
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Commit 3ca1f3225727419ba573673b744edac10904276f
4
"block: BdrvChildClass: add .get_parent_aio_context handler" introduced
5
new handler and commit 228ca37e12f97788e05bd0c92f89b3e5e4019607
6
"block: drop ctx argument from bdrv_root_attach_child" made a generic
7
use of it. But 3ca1f3225727419ba573673b744edac10904276f didn't update
8
child_vvfat_qcow. Fix that.
9
10
Before that fix the command
11
12
./build/qemu-system-x86_64 -usb -device usb-storage,drive=fat16 \
13
-drive file=fat:rw:fat-type=16:"<path of a host folder>",id=fat16,format=raw,if=none
14
15
crashes:
16
17
1 bdrv_child_get_parent_aio_context (c=0x559d62426d20)
18
at ../block.c:1440
19
2 bdrv_attach_child_common
20
(child_bs=0x559d62468190, child_name=0x559d606f9e3d "write-target",
21
child_class=0x559d60c58d20 <child_vvfat_qcow>, child_role=3,
22
perm=3, shared_perm=4, opaque=0x559d62445690,
23
child=0x7ffc74c2acc8, tran=0x559d6246ddd0, errp=0x7ffc74c2ae60)
24
at ../block.c:2795
25
3 bdrv_attach_child_noperm
26
(parent_bs=0x559d62445690, child_bs=0x559d62468190,
27
child_name=0x559d606f9e3d "write-target",
28
child_class=0x559d60c58d20 <child_vvfat_qcow>, child_role=3,
29
child=0x7ffc74c2acc8, tran=0x559d6246ddd0, errp=0x7ffc74c2ae60) at
30
../block.c:2855
31
4 bdrv_attach_child
32
(parent_bs=0x559d62445690, child_bs=0x559d62468190,
33
child_name=0x559d606f9e3d "write-target",
34
child_class=0x559d60c58d20 <child_vvfat_qcow>, child_role=3,
35
errp=0x7ffc74c2ae60) at ../block.c:2953
36
5 bdrv_open_child
37
(filename=0x559d62464b80 "/var/tmp/vl.h3TIS4",
38
options=0x559d6246ec20, bdref_key=0x559d606f9e3d "write-target",
39
parent=0x559d62445690, child_class=0x559d60c58d20
40
<child_vvfat_qcow>, child_role=3, allow_none=false,
41
errp=0x7ffc74c2ae60) at ../block.c:3351
42
6 enable_write_target (bs=0x559d62445690, errp=0x7ffc74c2ae60) at
43
../block/vvfat.c:3176
44
7 vvfat_open (bs=0x559d62445690, options=0x559d6244adb0, flags=155650,
45
errp=0x7ffc74c2ae60) at ../block/vvfat.c:1236
46
8 bdrv_open_driver (bs=0x559d62445690, drv=0x559d60d4f7e0
47
<bdrv_vvfat>, node_name=0x0,
48
options=0x559d6244adb0, open_flags=155650,
49
errp=0x7ffc74c2af70) at ../block.c:1557
50
9 bdrv_open_common (bs=0x559d62445690, file=0x0,
51
options=0x559d6244adb0, errp=0x7ffc74c2af70) at
52
...
53
54
(gdb) fr 1
55
#1 0x0000559d603ea3bf in bdrv_child_get_parent_aio_context
56
(c=0x559d62426d20) at ../block.c:1440
57
1440 return c->klass->get_parent_aio_context(c);
58
(gdb) p c->klass
59
$1 = (const BdrvChildClass *) 0x559d60c58d20 <child_vvfat_qcow>
60
(gdb) p c->klass->get_parent_aio_context
61
$2 = (AioContext *(*)(BdrvChild *)) 0x0
62
63
Fixes: 3ca1f3225727419ba573673b744edac10904276f
64
Fixes: 228ca37e12f97788e05bd0c92f89b3e5e4019607
65
Reported-by: John Arbuckle <programmingkidx@gmail.com>
66
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
67
Message-Id: <20210524101257.119377-2-vsementsov@virtuozzo.com>
68
Tested-by: John Arbuckle <programmingkidx@gmail.com>
69
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
70
---
71
include/block/block.h | 1 +
72
block.c | 4 ++--
73
block/vvfat.c | 1 +
74
3 files changed, 4 insertions(+), 2 deletions(-)
75
76
diff --git a/include/block/block.h b/include/block/block.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/block/block.h
79
+++ b/include/block/block.h
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
81
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
82
GSList **ignore, Error **errp);
83
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
84
+AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
85
86
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
87
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
88
diff --git a/block.c b/block.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block.c
91
+++ b/block.c
92
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
93
return 0;
94
}
95
96
-static AioContext *bdrv_child_cb_get_parent_aio_context(BdrvChild *c)
97
+AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c)
98
{
99
BlockDriverState *bs = c->opaque;
100
101
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
102
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
103
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
104
.update_filename = bdrv_child_cb_update_filename,
105
- .get_parent_aio_context = bdrv_child_cb_get_parent_aio_context,
106
+ .get_parent_aio_context = child_of_bds_get_parent_aio_context,
107
};
108
109
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c)
110
diff --git a/block/vvfat.c b/block/vvfat.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/vvfat.c
113
+++ b/block/vvfat.c
114
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
115
static const BdrvChildClass child_vvfat_qcow = {
116
.parent_is_bds = true,
117
.inherit_options = vvfat_qcow_options,
118
+ .get_parent_aio_context = child_of_bds_get_parent_aio_context,
119
};
120
121
static int enable_write_target(BlockDriverState *bs, Error **errp)
122
--
123
2.30.2
124
125
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
It's wrong to rely on s->qcow in vvfat_child_perm, as on permission
4
update during bdrv_open_child() call this field is not set yet.
5
6
Still prior to aa5a04c7db27eea6b36de32f241b155f0d9ce34d, it didn't
7
crash, as bdrv_open_child passed NULL as child to bdrv_child_perm(),
8
and NULL was equal to NULL in assertion (still, it was bad guarantee
9
for child being s->qcow, not backing :).
10
11
Since aa5a04c7db27eea6b36de32f241b155f0d9ce34d
12
"add bdrv_attach_child_noperm" bdrv_refresh_perms called on parent node
13
when attaching child, and new correct child pointer is passed to
14
.bdrv_child_perm. Still, s->qcow is NULL at the moment. Let's rely only
15
on role instead.
16
17
Without that fix,
18
./build/qemu-system-x86_64 -usb -device usb-storage,drive=fat16 \
19
-drive \
20
file=fat:rw:fat-type=16:"<path of a host folder>",id=fat16,format=raw,if=none
21
22
crashes:
23
(gdb) bt
24
0 raise () at /lib64/libc.so.6
25
1 abort () at /lib64/libc.so.6
26
2 _nl_load_domain.cold () at /lib64/libc.so.6
27
3 annobin_assert.c_end () at /lib64/libc.so.6
28
4 vvfat_child_perm (bs=0x559186f3d690, c=0x559186f1ed20, role=3,
29
reopen_queue=0x0, perm=0, shared=31,
30
nperm=0x7ffe56f28298, nshared=0x7ffe56f282a0) at
31
../block/vvfat.c:3214
32
5 bdrv_child_perm (bs=0x559186f3d690, child_bs=0x559186f60190,
33
c=0x559186f1ed20, role=3, reopen_queue=0x0,
34
parent_perm=0, parent_shared=31,
35
nperm=0x7ffe56f28298, nshared=0x7ffe56f282a0)
36
at ../block.c:2094
37
6 bdrv_node_refresh_perm (bs=0x559186f3d690, q=0x0,
38
tran=0x559186f65850, errp=0x7ffe56f28530) at
39
../block.c:2336
40
7 bdrv_list_refresh_perms (list=0x559186db5b90 = {...}, q=0x0,
41
tran=0x559186f65850, errp=0x7ffe56f28530)
42
at ../block.c:2358
43
8 bdrv_refresh_perms (bs=0x559186f3d690, errp=0x7ffe56f28530) at
44
../block.c:2419
45
9 bdrv_attach_child
46
(parent_bs=0x559186f3d690, child_bs=0x559186f60190,
47
child_name=0x559184d83e3d "write-target",
48
child_class=0x5591852f3b00 <child_vvfat_qcow>, child_role=3,
49
errp=0x7ffe56f28530) at ../block.c:2959
50
10 bdrv_open_child
51
(filename=0x559186f5cb80 "/var/tmp/vl.7WYmFU",
52
options=0x559186f66c20, bdref_key=0x559184d83e3d "write-target",
53
parent=0x559186f3d690, child_class=0x5591852f3b00
54
<child_vvfat_qcow>, child_role=3, allow_none=false,
55
errp=0x7ffe56f28530) at ../block.c:3351
56
11 enable_write_target (bs=0x559186f3d690, errp=0x7ffe56f28530) at
57
../block/vvfat.c:3177
58
12 vvfat_open (bs=0x559186f3d690, options=0x559186f42db0, flags=155650,
59
errp=0x7ffe56f28530) at ../block/vvfat.c:1236
60
13 bdrv_open_driver (bs=0x559186f3d690, drv=0x5591853d97e0
61
<bdrv_vvfat>, node_name=0x0,
62
options=0x559186f42db0, open_flags=155650,
63
errp=0x7ffe56f28640) at ../block.c:1557
64
14 bdrv_open_common (bs=0x559186f3d690, file=0x0,
65
options=0x559186f42db0, errp=0x7ffe56f28640) at
66
../block.c:1833
67
...
68
69
(gdb) fr 4
70
#4 vvfat_child_perm (bs=0x559186f3d690, c=0x559186f1ed20, role=3,
71
reopen_queue=0x0, perm=0, shared=31,
72
nperm=0x7ffe56f28298, nshared=0x7ffe56f282a0) at
73
../block/vvfat.c:3214
74
3214 assert(c == s->qcow || (role & BDRV_CHILD_COW));
75
(gdb) p role
76
$1 = 3 # BDRV_CHILD_DATA | BDRV_CHILD_METADATA
77
(gdb) p *c
78
$2 = {bs = 0x559186f60190, name = 0x559186f669d0 "write-target", klass
79
= 0x5591852f3b00 <child_vvfat_qcow>, role = 3, opaque =
80
0x559186f3d690, perm = 3, shared_perm = 4, frozen = false,
81
parent_quiesce_counter = 0, next = {le_next = 0x0, le_prev =
82
0x559186f41818}, next_parent = {le_next = 0x0, le_prev =
83
0x559186f64320}}
84
(gdb) p s->qcow
85
$3 = (BdrvChild *) 0x0
86
87
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
88
Message-Id: <20210524101257.119377-3-vsementsov@virtuozzo.com>
89
Tested-by: John Arbuckle <programmingkidx@gmail.com>
90
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
91
---
92
block/vvfat.c | 7 ++-----
93
1 file changed, 2 insertions(+), 5 deletions(-)
94
95
diff --git a/block/vvfat.c b/block/vvfat.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/block/vvfat.c
98
+++ b/block/vvfat.c
99
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
100
uint64_t perm, uint64_t shared,
101
uint64_t *nperm, uint64_t *nshared)
102
{
103
- BDRVVVFATState *s = bs->opaque;
104
-
105
- assert(c == s->qcow || (role & BDRV_CHILD_COW));
106
-
107
- if (c == s->qcow) {
108
+ if (role & BDRV_CHILD_DATA) {
109
/* This is a private node, nobody should try to attach to it */
110
*nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
111
*nshared = BLK_PERM_WRITE_UNCHANGED;
112
} else {
113
+ assert(role & BDRV_CHILD_COW);
114
/* The backing file is there so 'commit' can use it. vvfat doesn't
115
* access it in any way. */
116
*nperm = 0;
117
--
118
2.30.2
119
120
diff view generated by jsdifflib
1
We were trying to check whether bdrv_open_blockdev_ref() returned
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
success, but accidentally checked the wrong variable. Spotted by
3
Coverity (CID 1399703).
4
2
3
It's better to use accessor function instead of bs->read_only directly.
4
In some places use bdrv_is_writable() instead of
5
checking both BDRV_O_RDWR set and BDRV_O_INACTIVE not set.
6
7
In bdrv_open_common() it's a bit strange to add one more variable, but
8
we are going to drop bs->read_only in the next patch, so new ro local
9
variable substitutes it here.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-Id: <20210527154056.70294-2-vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
8
---
14
---
9
block/qcow2.c | 2 +-
15
block.c | 11 +++++++----
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
block/block-backend.c | 2 +-
17
block/commit.c | 2 +-
18
block/io.c | 4 ++--
19
block/qapi.c | 2 +-
20
block/qcow2-snapshot.c | 2 +-
21
block/qcow2.c | 5 ++---
22
block/snapshot.c | 2 +-
23
block/vhdx-log.c | 2 +-
24
9 files changed, 17 insertions(+), 15 deletions(-)
11
25
26
diff --git a/block.c b/block.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block.c
29
+++ b/block.c
30
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
31
QemuOpts *opts;
32
BlockDriver *drv;
33
Error *local_err = NULL;
34
+ bool ro;
35
36
assert(bs->file == NULL);
37
assert(options != NULL && bs->options != options);
38
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
39
40
bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
41
42
- if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
43
- if (!bs->read_only && bdrv_is_whitelisted(drv, true)) {
44
+ ro = bdrv_is_read_only(bs);
45
+
46
+ if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, ro)) {
47
+ if (!ro && bdrv_is_whitelisted(drv, true)) {
48
ret = bdrv_apply_auto_read_only(bs, NULL, NULL);
49
} else {
50
ret = -ENOTSUP;
51
}
52
if (ret < 0) {
53
error_setg(errp,
54
- !bs->read_only && bdrv_is_whitelisted(drv, true)
55
+ !ro && bdrv_is_whitelisted(drv, true)
56
? "Driver '%s' can only be used for read-only devices"
57
: "Driver '%s' is not whitelisted",
58
drv->format_name);
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
60
assert(qatomic_read(&bs->copy_on_read) == 0);
61
62
if (bs->open_flags & BDRV_O_COPY_ON_READ) {
63
- if (!bs->read_only) {
64
+ if (!ro) {
65
bdrv_enable_copy_on_read(bs);
66
} else {
67
error_setg(errp, "Can't use copy-on-read on read-only device");
68
diff --git a/block/block-backend.c b/block/block-backend.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/block-backend.c
71
+++ b/block/block-backend.c
72
@@ -XXX,XX +XXX,XX @@ void blk_update_root_state(BlockBackend *blk)
73
assert(blk->root);
74
75
blk->root_state.open_flags = blk->root->bs->open_flags;
76
- blk->root_state.read_only = blk->root->bs->read_only;
77
+ blk->root_state.read_only = bdrv_is_read_only(blk->root->bs);
78
blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
79
}
80
81
diff --git a/block/commit.c b/block/commit.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/block/commit.c
84
+++ b/block/commit.c
85
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
86
return -EBUSY;
87
}
88
89
- ro = backing_file_bs->read_only;
90
+ ro = bdrv_is_read_only(backing_file_bs);
91
92
if (ro) {
93
if (bdrv_reopen_set_read_only(backing_file_bs, false, NULL)) {
94
diff --git a/block/io.c b/block/io.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/io.c
97
+++ b/block/io.c
98
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
99
100
bdrv_check_request(offset, bytes, &error_abort);
101
102
- if (bs->read_only) {
103
+ if (bdrv_is_read_only(bs)) {
104
return -EPERM;
105
}
106
107
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
108
if (new_bytes) {
109
bdrv_make_request_serialising(&req, 1);
110
}
111
- if (bs->read_only) {
112
+ if (bdrv_is_read_only(bs)) {
113
error_setg(errp, "Image is read-only");
114
ret = -EACCES;
115
goto out;
116
diff --git a/block/qapi.c b/block/qapi.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/qapi.c
119
+++ b/block/qapi.c
120
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
121
122
info = g_malloc0(sizeof(*info));
123
info->file = g_strdup(bs->filename);
124
- info->ro = bs->read_only;
125
+ info->ro = bdrv_is_read_only(bs);
126
info->drv = g_strdup(bs->drv->format_name);
127
info->encrypted = bs->encrypted;
128
129
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/qcow2-snapshot.c
132
+++ b/block/qcow2-snapshot.c
133
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
134
int new_l1_bytes;
135
int ret;
136
137
- assert(bs->read_only);
138
+ assert(bdrv_is_read_only(bs));
139
140
/* Search the snapshot */
141
snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
12
diff --git a/block/qcow2.c b/block/qcow2.c
142
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
144
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
145
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
146
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
17
goto out;
147
18
}
148
/* Clear unknown autoclear feature bits */
19
data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp);
149
update_header |= s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK;
20
- if (bs == NULL) {
150
- update_header =
21
+ if (data_bs == NULL) {
151
- update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE);
22
ret = -EIO;
152
+ update_header = update_header && bdrv_is_writable(bs);
23
goto out;
153
if (update_header) {
24
}
154
s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
155
}
156
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
157
bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
158
159
/* Repair image if dirty */
160
- if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
161
+ if (!(flags & BDRV_O_CHECK) && bdrv_is_writable(bs) &&
162
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
163
BdrvCheckResult result = {0};
164
165
diff --git a/block/snapshot.c b/block/snapshot.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/snapshot.c
168
+++ b/block/snapshot.c
169
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
170
error_setg(errp, "snapshot_id and name are both NULL");
171
return -EINVAL;
172
}
173
- if (!bs->read_only) {
174
+ if (!bdrv_is_read_only(bs)) {
175
error_setg(errp, "Device is not readonly");
176
return -EINVAL;
177
}
178
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/vhdx-log.c
181
+++ b/block/vhdx-log.c
182
@@ -XXX,XX +XXX,XX @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
183
}
184
185
if (logs.valid) {
186
- if (bs->read_only) {
187
+ if (bdrv_is_read_only(bs)) {
188
bdrv_refresh_filename(bs);
189
ret = -EPERM;
190
error_setg(errp,
25
--
191
--
26
2.20.1
192
2.30.2
27
193
28
194
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Recent commit cda4aa9a5a0 moved block backend creation before machine
3
This variable is just a cache for !(bs->open_flags & BDRV_O_RDWR),
4
property evaluation. This broke qemu-iotests 055. Turns out we need
4
which we have to synchronize everywhere. Let's just drop it and
5
to create the migration object before block backends, so block
5
consistently use bdrv_is_read_only().
6
backends can add migration blockers. Fix by calling
7
migration_object_init() earlier, right before configure_blockdev().
8
6
9
Fixes: cda4aa9a5a08777cf13e164c0543bd4888b8adce
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reported-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20210527154056.70294-3-vsementsov@virtuozzo.com>
11
Signed-off-by: Markus Armbruster <armbru@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
vl.c | 15 ++++++++-------
11
include/block/block_int.h | 1 -
15
1 file changed, 8 insertions(+), 7 deletions(-)
12
block.c | 7 +------
13
tests/unit/test-block-iothread.c | 6 ------
14
3 files changed, 1 insertion(+), 13 deletions(-)
16
15
17
diff --git a/vl.c b/vl.c
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/vl.c
18
--- a/include/block/block_int.h
20
+++ b/vl.c
19
+++ b/include/block/block_int.h
21
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
20
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
22
exit(0);
21
* locking needed during I/O...
22
*/
23
int open_flags; /* flags used to open the file, re-used for re-open */
24
- bool read_only; /* if true, the media is read only */
25
bool encrypted; /* if true, the media is encrypted */
26
bool sg; /* if true, the device is a /dev/sg* */
27
bool probed; /* if true, format was probed rather than specified */
28
diff --git a/block.c b/block.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block.c
31
+++ b/block.c
32
@@ -XXX,XX +XXX,XX @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
33
* image is inactivated. */
34
bool bdrv_is_read_only(BlockDriverState *bs)
35
{
36
- return bs->read_only;
37
+ return !(bs->open_flags & BDRV_O_RDWR);
38
}
39
40
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
41
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
42
goto fail;
23
}
43
}
24
44
25
+ /*
45
- bs->read_only = true;
26
+ * Migration object can only be created after global properties
46
bs->open_flags &= ~BDRV_O_RDWR;
27
+ * are applied correctly.
47
28
+ */
48
return 0;
29
+ migration_object_init();
49
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
30
+
31
/*
32
* Note: we need to create block backends before
33
* machine_set_property(), so machine properties can refer to
34
- * them.
35
+ * them, and after migration_object_init(), so we can create
36
+ * migration blockers.
37
*/
38
configure_blockdev(&bdo_queue, machine_class, snapshot);
39
40
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
41
machine_class->name, machine_class->deprecation_reason);
42
}
50
}
43
51
44
- /*
52
bs->drv = drv;
45
- * Migration object can only be created after global properties
53
- bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
46
- * are applied correctly.
54
bs->opaque = g_malloc0(drv->instance_size);
47
- */
55
48
- migration_object_init();
56
if (drv->bdrv_file_open) {
57
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
58
trace_bdrv_open_common(bs, filename ?: "", bs->open_flags,
59
drv->format_name);
60
61
- bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
49
-
62
-
50
if (qtest_chrdev) {
63
ro = bdrv_is_read_only(bs);
51
qtest_init(qtest_chrdev, qtest_log, &error_fatal);
64
52
}
65
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, ro)) {
66
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
67
bs->explicit_options = reopen_state->explicit_options;
68
bs->options = reopen_state->options;
69
bs->open_flags = reopen_state->flags;
70
- bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
71
bs->detect_zeroes = reopen_state->detect_zeroes;
72
73
if (reopen_state->replace_backing_bs) {
74
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/tests/unit/test-block-iothread.c
77
+++ b/tests/unit/test-block-iothread.c
78
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
79
g_assert_cmpint(ret, ==, -EINVAL);
80
81
/* Error: Read-only image */
82
- c->bs->read_only = true;
83
c->bs->open_flags &= ~BDRV_O_RDWR;
84
85
ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
86
g_assert_cmpint(ret, ==, -EACCES);
87
88
- c->bs->read_only = false;
89
c->bs->open_flags |= BDRV_O_RDWR;
90
}
91
92
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_flush(BdrvChild *c)
93
g_assert_cmpint(ret, ==, 0);
94
95
/* Early success: Read-only image */
96
- c->bs->read_only = true;
97
c->bs->open_flags &= ~BDRV_O_RDWR;
98
99
ret = bdrv_flush(c->bs);
100
g_assert_cmpint(ret, ==, 0);
101
102
- c->bs->read_only = false;
103
c->bs->open_flags |= BDRV_O_RDWR;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_flush(BlockBackend *blk)
107
g_assert_cmpint(ret, ==, 0);
108
109
/* Early success: Read-only image */
110
- bs->read_only = true;
111
bs->open_flags &= ~BDRV_O_RDWR;
112
113
ret = blk_flush(blk);
114
g_assert_cmpint(ret, ==, 0);
115
116
- bs->read_only = false;
117
bs->open_flags |= BDRV_O_RDWR;
118
}
119
53
--
120
--
54
2.20.1
121
2.30.2
55
122
56
123
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
There is no reason why the constraints we put on @replaces should be
3
Instead of keeping additional boolean field, let's store the
4
limited to drive-mirror. Therefore, move the sanity checks from
4
information in BDRV_O_RDWR bit of BlockBackendRootState::open_flags.
5
qmp_drive_mirror() to blockdev_mirror_common() so they apply to
6
blockdev-mirror as well.
7
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-Id: <20210527154056.70294-4-vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
blockdev.c | 55 ++++++++++++++++++++++++++++++++----------------------
10
include/block/block_int.h | 1 -
14
1 file changed, 33 insertions(+), 22 deletions(-)
11
block/block-backend.c | 10 ++--------
12
blockdev.c | 3 +--
13
3 files changed, 3 insertions(+), 11 deletions(-)
15
14
15
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block_int.h
18
+++ b/include/block/block_int.h
19
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
20
21
struct BlockBackendRootState {
22
int open_flags;
23
- bool read_only;
24
BlockdevDetectZeroesOptions detect_zeroes;
25
};
26
27
diff --git a/block/block-backend.c b/block/block-backend.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/block-backend.c
30
+++ b/block/block-backend.c
31
@@ -XXX,XX +XXX,XX @@ bool blk_supports_write_perm(BlockBackend *blk)
32
if (bs) {
33
return !bdrv_is_read_only(bs);
34
} else {
35
- return !blk->root_state.read_only;
36
+ return blk->root_state.open_flags & BDRV_O_RDWR;
37
}
38
}
39
40
@@ -XXX,XX +XXX,XX @@ void blk_update_root_state(BlockBackend *blk)
41
assert(blk->root);
42
43
blk->root_state.open_flags = blk->root->bs->open_flags;
44
- blk->root_state.read_only = bdrv_is_read_only(blk->root->bs);
45
blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
46
}
47
48
@@ -XXX,XX +XXX,XX @@ bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk)
49
*/
50
int blk_get_open_flags_from_root_state(BlockBackend *blk)
51
{
52
- int bs_flags;
53
-
54
- bs_flags = blk->root_state.read_only ? 0 : BDRV_O_RDWR;
55
- bs_flags |= blk->root_state.open_flags & ~BDRV_O_RDWR;
56
-
57
- return bs_flags;
58
+ return blk->root_state.open_flags;
59
}
60
61
BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
16
diff --git a/blockdev.c b/blockdev.c
62
diff --git a/blockdev.c b/blockdev.c
17
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
18
--- a/blockdev.c
64
--- a/blockdev.c
19
+++ b/blockdev.c
65
+++ b/blockdev.c
20
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
66
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
21
sync = MIRROR_SYNC_MODE_FULL;
67
22
}
68
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
23
69
blk_rs = blk_get_root_state(blk);
24
+ if (has_replaces) {
70
- blk_rs->open_flags = bdrv_flags;
25
+ BlockDriverState *to_replace_bs;
71
- blk_rs->read_only = read_only;
26
+ AioContext *replace_aio_context;
72
+ blk_rs->open_flags = bdrv_flags | (read_only ? 0 : BDRV_O_RDWR);
27
+ int64_t bs_size, replace_size;
73
blk_rs->detect_zeroes = detect_zeroes;
28
+
74
29
+ bs_size = bdrv_getlength(bs);
75
qobject_unref(bs_opts);
30
+ if (bs_size < 0) {
31
+ error_setg_errno(errp, -bs_size, "Failed to query device's size");
32
+ return;
33
+ }
34
+
35
+ to_replace_bs = check_to_replace_node(bs, replaces, errp);
36
+ if (!to_replace_bs) {
37
+ return;
38
+ }
39
+
40
+ replace_aio_context = bdrv_get_aio_context(to_replace_bs);
41
+ aio_context_acquire(replace_aio_context);
42
+ replace_size = bdrv_getlength(to_replace_bs);
43
+ aio_context_release(replace_aio_context);
44
+
45
+ if (replace_size < 0) {
46
+ error_setg_errno(errp, -replace_size,
47
+ "Failed to query the replacement node's size");
48
+ return;
49
+ }
50
+ if (bs_size != replace_size) {
51
+ error_setg(errp, "cannot replace image with a mirror image of "
52
+ "different size");
53
+ return;
54
+ }
55
+ }
56
+
57
/* pass the node name to replace to mirror start since it's loose coupling
58
* and will allow to check whether the node still exist at mirror completion
59
*/
60
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
61
}
62
63
if (arg->has_replaces) {
64
- BlockDriverState *to_replace_bs;
65
- AioContext *replace_aio_context;
66
- int64_t replace_size;
67
-
68
if (!arg->has_node_name) {
69
error_setg(errp, "a node-name must be provided when replacing a"
70
" named node of the graph");
71
goto out;
72
}
73
-
74
- to_replace_bs = check_to_replace_node(bs, arg->replaces, &local_err);
75
-
76
- if (!to_replace_bs) {
77
- error_propagate(errp, local_err);
78
- goto out;
79
- }
80
-
81
- replace_aio_context = bdrv_get_aio_context(to_replace_bs);
82
- aio_context_acquire(replace_aio_context);
83
- replace_size = bdrv_getlength(to_replace_bs);
84
- aio_context_release(replace_aio_context);
85
-
86
- if (size != replace_size) {
87
- error_setg(errp, "cannot replace image with a mirror image of "
88
- "different size");
89
- goto out;
90
- }
91
}
92
93
if (arg->mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
94
--
76
--
95
2.20.1
77
2.30.2
96
78
97
79
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
A customer reported that running
4
5
qemu-img convert -t none -O qcow2 -f qcow2 input.qcow2 output.qcow2
6
7
fails for them with the following error message when the images are
8
stored on a GPFS file system :
9
10
qemu-img: error while writing sector 0: Invalid argument
11
12
After analyzing the strace output, it seems like the problem is in
13
handle_aiocb_write_zeroes(): The call to fallocate(FALLOC_FL_PUNCH_HOLE)
14
returns EINVAL, which can apparently happen if the file system has
15
a different idea of the granularity of the operation. It's arguably
16
a bug in GPFS, since the PUNCH_HOLE mode should not result in EINVAL
17
according to the man-page of fallocate(), but the file system is out
18
there in production and so we have to deal with it. In commit 294682cc3a
19
("block: workaround for unaligned byte range in fallocate()") we also
20
already applied the a work-around for the same problem to the earlier
21
fallocate(FALLOC_FL_ZERO_RANGE) call, so do it now similar with the
22
PUNCH_HOLE call. But instead of silently catching and returning
23
-ENOTSUP (which causes the caller to fall back to writing zeroes),
24
let's rather inform the user once about the buggy file system and
25
try the other fallback instead.
26
27
Signed-off-by: Thomas Huth <thuth@redhat.com>
28
Message-Id: <20210527172020.847617-2-thuth@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
---
31
block/file-posix.c | 11 +++++++++++
32
1 file changed, 11 insertions(+)
33
34
diff --git a/block/file-posix.c b/block/file-posix.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/file-posix.c
37
+++ b/block/file-posix.c
38
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_write_zeroes(void *opaque)
39
return ret;
40
}
41
s->has_fallocate = false;
42
+ } else if (ret == -EINVAL) {
43
+ /*
44
+ * Some file systems like older versions of GPFS do not like un-
45
+ * aligned byte ranges, and return EINVAL in such a case, though
46
+ * they should not do it according to the man-page of fallocate().
47
+ * Warn about the bad filesystem and try the final fallback instead.
48
+ */
49
+ warn_report_once("Your file system is misbehaving: "
50
+ "fallocate(FALLOC_FL_PUNCH_HOLE) returned EINVAL. "
51
+ "Please report this bug to your file sytem "
52
+ "vendor.");
53
} else if (ret != -ENOTSUP) {
54
return ret;
55
} else {
56
--
57
2.30.2
58
59
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
If fallocate(... FALLOC_FL_ZERO_RANGE ...) returns EINVAL, it's likely
4
an indication that the file system is buggy and does not implement
5
unaligned accesses right. We still might be lucky with the other
6
fallback fallocate() calls later in this function, though, so we should
7
not return immediately and try the others first.
8
Since FALLOC_FL_ZERO_RANGE could also return EINVAL if the file descriptor
9
is not a regular file, we ignore this filesystem bug silently, without
10
printing an error message for the user.
11
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Message-Id: <20210527172020.847617-3-thuth@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/file-posix.c | 18 +++++++++---------
17
1 file changed, 9 insertions(+), 9 deletions(-)
18
19
diff --git a/block/file-posix.c b/block/file-posix.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/file-posix.c
22
+++ b/block/file-posix.c
23
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_write_zeroes(void *opaque)
24
if (s->has_write_zeroes) {
25
int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE,
26
aiocb->aio_offset, aiocb->aio_nbytes);
27
- if (ret == -EINVAL) {
28
- /*
29
- * Allow falling back to pwrite for file systems that
30
- * do not support fallocate() for an unaligned byte range.
31
- */
32
- return -ENOTSUP;
33
- }
34
- if (ret == 0 || ret != -ENOTSUP) {
35
+ if (ret == -ENOTSUP) {
36
+ s->has_write_zeroes = false;
37
+ } else if (ret == 0 || ret != -EINVAL) {
38
return ret;
39
}
40
- s->has_write_zeroes = false;
41
+ /*
42
+ * Note: Some file systems do not like unaligned byte ranges, and
43
+ * return EINVAL in such a case, though they should not do it according
44
+ * to the man-page of fallocate(). Thus we simply ignore this return
45
+ * value and try the other fallbacks instead.
46
+ */
47
}
48
#endif
49
50
--
51
2.30.2
52
53
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
The logic around **child is not obvious: this reference is used not
4
only to return resulting child, but also to rollback NULL value on
5
transaction abort.
6
7
So, let's add documentation and some assertions.
8
9
While being here, drop extra declaration of bdrv_attach_child_noperm().
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-Id: <20210601075218.79249-2-vsementsov@virtuozzo.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block.c | 24 +++++++++++++++---------
16
1 file changed, 15 insertions(+), 9 deletions(-)
17
18
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
23
24
static void bdrv_replace_child_noperm(BdrvChild *child,
25
BlockDriverState *new_bs);
26
-static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
27
- BlockDriverState *child_bs,
28
- const char *child_name,
29
- const BdrvChildClass *child_class,
30
- BdrvChildRole child_role,
31
- BdrvChild **child,
32
- Transaction *tran,
33
- Error **errp);
34
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
35
Transaction *tran);
36
37
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
38
39
/*
40
* Common part of attaching bdrv child to bs or to blk or to job
41
+ *
42
+ * Resulting new child is returned through @child.
43
+ * At start *@child must be NULL.
44
+ * @child is saved to a new entry of @tran, so that *@child could be reverted to
45
+ * NULL on abort(). So referenced variable must live at least until transaction
46
+ * end.
47
*/
48
static int bdrv_attach_child_common(BlockDriverState *child_bs,
49
const char *child_name,
50
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
51
return 0;
52
}
53
54
+/*
55
+ * Variable referenced by @child must live at least until transaction end.
56
+ * (see bdrv_attach_child_common() doc for details)
57
+ */
58
static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
59
BlockDriverState *child_bs,
60
const char *child_name,
61
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
62
child_role, perm, shared_perm, opaque,
63
&child, tran, errp);
64
if (ret < 0) {
65
- assert(child == NULL);
66
goto out;
67
}
68
69
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
70
71
out:
72
tran_finalize(tran, ret);
73
+ /* child is unset on failure by bdrv_attach_child_common_abort() */
74
+ assert((ret < 0) == !child);
75
+
76
bdrv_unref(child_bs);
77
return child;
78
}
79
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
80
81
out:
82
tran_finalize(tran, ret);
83
+ /* child is unset on failure by bdrv_attach_child_common_abort() */
84
+ assert((ret < 0) == !child);
85
86
bdrv_unref(child_bs);
87
88
--
89
2.30.2
90
91
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
We have different types of parents: block nodes, block backends and
4
jobs. So, it makes sense to specify type together with name.
5
6
While being here also use g_autofree.
7
8
iotest 307 output is updated.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-Id: <20210601075218.79249-3-vsementsov@virtuozzo.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/block-backend.c | 9 ++++-----
16
tests/qemu-iotests/307.out | 2 +-
17
2 files changed, 5 insertions(+), 6 deletions(-)
18
19
diff --git a/block/block-backend.c b/block/block-backend.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/block-backend.c
22
+++ b/block/block-backend.c
23
@@ -XXX,XX +XXX,XX @@ static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
24
static char *blk_root_get_parent_desc(BdrvChild *child)
25
{
26
BlockBackend *blk = child->opaque;
27
- char *dev_id;
28
+ g_autofree char *dev_id = NULL;
29
30
if (blk->name) {
31
- return g_strdup(blk->name);
32
+ return g_strdup_printf("block device '%s'", blk->name);
33
}
34
35
dev_id = blk_get_attached_dev_id(blk);
36
if (*dev_id) {
37
- return dev_id;
38
+ return g_strdup_printf("block device '%s'", dev_id);
39
} else {
40
/* TODO Callback into the BB owner for something more detailed */
41
- g_free(dev_id);
42
- return g_strdup("a block device");
43
+ return g_strdup("an unnamed block device");
44
}
45
}
46
47
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
48
index XXXXXXX..XXXXXXX 100644
49
--- a/tests/qemu-iotests/307.out
50
+++ b/tests/qemu-iotests/307.out
51
@@ -XXX,XX +XXX,XX @@ exports available: 1
52
53
=== Add a writable export ===
54
{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}}
55
-{"error": {"class": "GenericError", "desc": "Conflicts with use by sda as 'root', which does not allow 'write' on fmt"}}
56
+{"error": {"class": "GenericError", "desc": "Conflicts with use by block device 'sda' as 'root', which does not allow 'write' on fmt"}}
57
{"execute": "device_del", "arguments": {"id": "sda"}}
58
{"return": {}}
59
{"data": {"device": "sda", "path": "/machine/peripheral/sda"}, "event": "DEVICE_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
60
--
61
2.30.2
62
63
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
We have different types of parents: block nodes, block backends and
4
jobs. So, it makes sense to specify type together with name.
5
6
Next, this handler us used to compose an error message about permission
7
conflict. And permission conflict occurs in a specific place of block
8
graph. We shouldn't report name of parent device (as it refers another
9
place in block graph), but exactly and only the name of the node. So,
10
use bdrv_get_node_name() directly.
11
12
iotest 283 output is updated.
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Message-Id: <20210601075218.79249-4-vsementsov@virtuozzo.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block.c | 2 +-
20
tests/qemu-iotests/283.out | 2 +-
21
2 files changed, 2 insertions(+), 2 deletions(-)
22
23
diff --git a/block.c b/block.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
26
+++ b/block.c
27
@@ -XXX,XX +XXX,XX @@ int bdrv_parse_cache_mode(const char *mode, int *flags, bool *writethrough)
28
static char *bdrv_child_get_parent_desc(BdrvChild *c)
29
{
30
BlockDriverState *parent = c->opaque;
31
- return g_strdup(bdrv_get_device_or_node_name(parent));
32
+ return g_strdup_printf("node '%s'", bdrv_get_node_name(parent));
33
}
34
35
static void bdrv_child_cb_drained_begin(BdrvChild *child)
36
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/283.out
39
+++ b/tests/qemu-iotests/283.out
40
@@ -XXX,XX +XXX,XX @@
41
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
42
{"return": {}}
43
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
44
-{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Conflicts with use by source as 'image', which does not allow 'write' on base"}}
45
+{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Conflicts with use by node 'source' as 'image', which does not allow 'write' on base"}}
46
47
=== backup-top should be gone after job-finalize ===
48
49
--
50
2.30.2
51
52
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
3
Recently we've fixed a crash by adding .get_parent_aio_context handler
4
to child_vvfat_qcow. Now we want it to support .get_parent_desc as
5
well. child_vvfat_qcow wants to implement own .inherit_options, it's
6
not bad. But omitting all other handlers is a bad idea. Let's inherit
7
the class from child_of_bds instead, similar to chain_child_class and
8
detach_by_driver_cb_class in test-bdrv-drain.c.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20210601075218.79249-5-vsementsov@virtuozzo.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
13
---
6
block/copy-on-read.c | 2 +-
14
block/vvfat.c | 8 +++-----
7
block/crypto.c | 2 +-
15
1 file changed, 3 insertions(+), 5 deletions(-)
8
block/replication.c | 2 +-
9
3 files changed, 3 insertions(+), 3 deletions(-)
10
16
11
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
17
diff --git a/block/vvfat.c b/block/vvfat.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/block/copy-on-read.c
19
--- a/block/vvfat.c
14
+++ b/block/copy-on-read.c
20
+++ b/block/vvfat.c
15
@@ -XXX,XX +XXX,XX @@ static bool cor_recurse_is_first_non_filter(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
22
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
16
}
23
}
17
24
18
25
-static const BdrvChildClass child_vvfat_qcow = {
19
-BlockDriver bdrv_copy_on_read = {
26
- .parent_is_bds = true,
20
+static BlockDriver bdrv_copy_on_read = {
27
- .inherit_options = vvfat_qcow_options,
21
.format_name = "copy-on-read",
28
- .get_parent_aio_context = child_of_bds_get_parent_aio_context,
22
29
-};
23
.bdrv_open = cor_open,
30
+static BdrvChildClass child_vvfat_qcow;
24
diff --git a/block/crypto.c b/block/crypto.c
31
25
index XXXXXXX..XXXXXXX 100644
32
static int enable_write_target(BlockDriverState *bs, Error **errp)
26
--- a/block/crypto.c
33
{
27
+++ b/block/crypto.c
34
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
28
@@ -XXX,XX +XXX,XX @@ static const char *const block_crypto_strong_runtime_opts[] = {
35
29
NULL
36
static void bdrv_vvfat_init(void)
30
};
37
{
31
38
+ child_vvfat_qcow = child_of_bds;
32
-BlockDriver bdrv_crypto_luks = {
39
+ child_vvfat_qcow.inherit_options = vvfat_qcow_options;
33
+static BlockDriver bdrv_crypto_luks = {
40
bdrv_register(&bdrv_vvfat);
34
.format_name = "luks",
41
}
35
.instance_size = sizeof(BlockCrypto),
36
.bdrv_probe = block_crypto_probe_luks,
37
diff --git a/block/replication.c b/block/replication.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/replication.c
40
+++ b/block/replication.c
41
@@ -XXX,XX +XXX,XX @@ static const char *const replication_strong_runtime_opts[] = {
42
NULL
43
};
44
45
-BlockDriver bdrv_replication = {
46
+static BlockDriver bdrv_replication = {
47
.format_name = "replication",
48
.instance_size = sizeof(BDRVReplicationState),
49
42
50
--
43
--
51
2.20.1
44
2.30.2
52
45
53
46
diff view generated by jsdifflib
1
232 is marked as generic, but commit 12efe428c9e added code that assumes
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
qcow2. What the new test really needs is backing files and support for
3
updating the backing file link (.bdrv_change_backing_file).
4
2
5
Split the non-generic code into a new test case 247 and make it work
3
All child classes have this callback. So, drop unreachable code.
6
with qed, too.
7
4
5
Still add an assertion to bdrv_attach_child_common(), to early detect
6
bad classes.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-Id: <20210601075218.79249-6-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
tests/qemu-iotests/232 | 30 ---------------
12
block.c | 7 ++-----
11
tests/qemu-iotests/232.out | 20 ----------
13
1 file changed, 2 insertions(+), 5 deletions(-)
12
tests/qemu-iotests/247 | 79 ++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/247.out | 22 +++++++++++
14
tests/qemu-iotests/group | 1 +
15
5 files changed, 102 insertions(+), 50 deletions(-)
16
create mode 100755 tests/qemu-iotests/247
17
create mode 100644 tests/qemu-iotests/247.out
18
14
19
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
15
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/232
17
--- a/block.c
22
+++ b/tests/qemu-iotests/232
18
+++ b/block.c
23
@@ -XXX,XX +XXX,XX @@ run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,a
19
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
24
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
20
25
run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
21
static char *bdrv_child_user_desc(BdrvChild *c)
26
22
{
27
-echo
23
- if (c->klass->get_parent_desc) {
28
-echo "=== Try commit to backing file with auto-read-only ==="
24
- return c->klass->get_parent_desc(c);
29
-echo
25
- }
30
-
26
-
31
-TEST_IMG="$TEST_IMG.0" _make_test_img $size
27
- return g_strdup("another user");
32
-TEST_IMG="$TEST_IMG.1" _make_test_img $size
28
+ return c->klass->get_parent_desc(c);
33
-TEST_IMG="$TEST_IMG.2" _make_test_img $size
29
}
34
-TEST_IMG="$TEST_IMG.3" _make_test_img $size
30
35
-TEST_IMG="$TEST_IMG.4" _make_test_img $size
31
static bool bdrv_a_allow_b(BdrvChild *a, BdrvChild *b, Error **errp)
36
-
32
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
37
-(cat <<EOF
33
38
-{"execute":"qmp_capabilities"}
34
assert(child);
39
-{"execute":"block-commit",
35
assert(*child == NULL);
40
- "arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}}
36
+ assert(child_class->get_parent_desc);
41
-EOF
37
42
-sleep 1
38
new_child = g_new(BdrvChild, 1);
43
-echo '{"execute":"quit"}'
39
*new_child = (BdrvChild) {
44
-) | $QEMU -qmp stdio -nographic -nodefaults \
45
- -blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \
46
- -blockdev qcow2,node-name=format-0,file=file-0,read-only=on \
47
- -blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \
48
- -blockdev qcow2,node-name=format-1,file=file-1,read-only=on,backing=format-0 \
49
- -blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \
50
- -blockdev qcow2,node-name=format-2,file=file-2,read-only=on,backing=format-1 \
51
- -blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \
52
- -blockdev qcow2,node-name=format-3,file=file-3,read-only=on,backing=format-2 \
53
- -blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \
54
- -blockdev qcow2,node-name=format-4,file=file-4,read-only=on,backing=format-3 |
55
- _filter_qmp
56
-
57
# success, all done
58
echo "*** done"
59
rm -f $seq.full
60
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
61
index XXXXXXX..XXXXXXX 100644
62
--- a/tests/qemu-iotests/232.out
63
+++ b/tests/qemu-iotests/232.out
64
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read
65
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
66
node0: TEST_DIR/t.IMGFMT (file)
67
QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
68
-
69
-=== Try commit to backing file with auto-read-only ===
70
-
71
-Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728
72
-Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
73
-Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
74
-Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728
75
-Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728
76
-QMP_VERSION
77
-{"return": {}}
78
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
79
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
80
-{"return": {}}
81
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
82
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
83
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
84
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
85
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
86
-{"return": {}}
87
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
88
*** done
89
diff --git a/tests/qemu-iotests/247 b/tests/qemu-iotests/247
90
new file mode 100755
91
index XXXXXXX..XXXXXXX
92
--- /dev/null
93
+++ b/tests/qemu-iotests/247
94
@@ -XXX,XX +XXX,XX @@
95
+#!/usr/bin/env bash
96
+#
97
+# Test for auto-read-only with commit block job
98
+#
99
+# Copyright (C) 2019 Red Hat, Inc.
100
+#
101
+# This program is free software; you can redistribute it and/or modify
102
+# it under the terms of the GNU General Public License as published by
103
+# the Free Software Foundation; either version 2 of the License, or
104
+# (at your option) any later version.
105
+#
106
+# This program is distributed in the hope that it will be useful,
107
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
108
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109
+# GNU General Public License for more details.
110
+#
111
+# You should have received a copy of the GNU General Public License
112
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
113
+#
114
+
115
+# creator
116
+owner=kwolf@redhat.com
117
+
118
+seq=`basename $0`
119
+echo "QA output created by $seq"
120
+
121
+status=1    # failure is the default!
122
+
123
+_cleanup()
124
+{
125
+ _cleanup_test_img
126
+ rm -f $TEST_IMG.[01234]
127
+}
128
+trap "_cleanup; exit \$status" 0 1 2 3 15
129
+
130
+# get standard environment, filters and checks
131
+. ./common.rc
132
+. ./common.filter
133
+
134
+# Requires backing files and .bdrv_change_backing_file support
135
+_supported_fmt qcow2 qed
136
+_supported_proto file
137
+_supported_os Linux
138
+
139
+size=128M
140
+
141
+echo
142
+echo "=== Try commit to backing file with auto-read-only ==="
143
+echo
144
+TEST_IMG="$TEST_IMG.0" _make_test_img $size
145
+TEST_IMG="$TEST_IMG.1" _make_test_img $size
146
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
147
+TEST_IMG="$TEST_IMG.3" _make_test_img $size
148
+TEST_IMG="$TEST_IMG.4" _make_test_img $size
149
+
150
+(cat <<EOF
151
+{"execute":"qmp_capabilities"}
152
+{"execute":"block-commit",
153
+ "arguments":{"device":"format-4", "top-node": "format-2", "base-node":"format-0", "job-id":"job0"}}
154
+EOF
155
+sleep 1
156
+echo '{"execute":"quit"}'
157
+) | $QEMU -qmp stdio -nographic -nodefaults \
158
+ -blockdev file,node-name=file-0,filename=$TEST_IMG.0,auto-read-only=on \
159
+ -blockdev $IMGFMT,node-name=format-0,file=file-0,read-only=on \
160
+ -blockdev file,node-name=file-1,filename=$TEST_IMG.1,auto-read-only=on \
161
+ -blockdev $IMGFMT,node-name=format-1,file=file-1,read-only=on,backing=format-0 \
162
+ -blockdev file,node-name=file-2,filename=$TEST_IMG.2,auto-read-only=on \
163
+ -blockdev $IMGFMT,node-name=format-2,file=file-2,read-only=on,backing=format-1 \
164
+ -blockdev file,node-name=file-3,filename=$TEST_IMG.3,auto-read-only=on \
165
+ -blockdev $IMGFMT,node-name=format-3,file=file-3,read-only=on,backing=format-2 \
166
+ -blockdev file,node-name=file-4,filename=$TEST_IMG.4,auto-read-only=on \
167
+ -blockdev $IMGFMT,node-name=format-4,file=file-4,read-only=on,backing=format-3 |
168
+ _filter_qmp
169
+
170
+# success, all done
171
+echo "*** done"
172
+rm -f $seq.full
173
+status=0
174
diff --git a/tests/qemu-iotests/247.out b/tests/qemu-iotests/247.out
175
new file mode 100644
176
index XXXXXXX..XXXXXXX
177
--- /dev/null
178
+++ b/tests/qemu-iotests/247.out
179
@@ -XXX,XX +XXX,XX @@
180
+QA output created by 247
181
+
182
+=== Try commit to backing file with auto-read-only ===
183
+
184
+Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=134217728
185
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
186
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
187
+Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=134217728
188
+Formatting 'TEST_DIR/t.IMGFMT.4', fmt=IMGFMT size=134217728
189
+QMP_VERSION
190
+{"return": {}}
191
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
192
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
193
+{"return": {}}
194
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
195
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
196
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
197
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
198
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
199
+{"return": {}}
200
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
201
+*** done
202
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
203
index XXXXXXX..XXXXXXX 100644
204
--- a/tests/qemu-iotests/group
205
+++ b/tests/qemu-iotests/group
206
@@ -XXX,XX +XXX,XX @@
207
244 rw auto quick
208
245 rw auto
209
246 rw auto quick
210
+247 rw auto quick
211
--
40
--
212
2.20.1
41
2.30.2
213
42
214
43
diff view generated by jsdifflib
1
Coverity doesn't like that the return value of bdrv_check_update_perm()
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
stays unused only in this place (CID 1399710).
3
2
4
Even if checking local_err should be equivalent to checking ret < 0,
3
Now permissions are updated as follows:
5
let's switch to using the return value to be more consistent (and in
4
1. do graph modifications ignoring permissions
6
case of a bug somewhere down the call chain, forgetting to assign errp
5
2. do permission update
7
is more likely than returning 0 for an error case).
8
6
7
(of course, we rollback [1] if [2] fails)
8
9
So, on stage [2] we can't say which users are "old" and which are
10
"new" and exist only since [1]. And current error message is a bit
11
outdated. Let's improve it, to make everything clean.
12
13
While being here, add also a comment and some good assertions.
14
15
iotests 283, 307, qsd-jobs outputs are updated.
16
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Message-Id: <20210601075218.79249-7-vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
13
---
20
---
14
block.c | 7 +++----
21
block.c | 29 ++++++++++++++++++++-------
15
1 file changed, 3 insertions(+), 4 deletions(-)
22
tests/qemu-iotests/283.out | 2 +-
23
tests/qemu-iotests/307.out | 2 +-
24
tests/qemu-iotests/tests/qsd-jobs.out | 2 +-
25
4 files changed, 25 insertions(+), 10 deletions(-)
16
26
17
diff --git a/block.c b/block.c
27
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
29
--- a/block.c
20
+++ b/block.c
30
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
31
@@ -XXX,XX +XXX,XX @@ static char *bdrv_child_user_desc(BdrvChild *c)
22
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
32
return c->klass->get_parent_desc(c);
23
/* Check whether we are allowed to switch c from top to base */
33
}
24
GSList *ignore_children = g_slist_prepend(NULL, c);
34
25
- bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
35
+/*
26
- ignore_children, &local_err);
36
+ * Check that @a allows everything that @b needs. @a and @b must reference same
27
+ ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
37
+ * child node.
28
+ ignore_children, &local_err);
38
+ */
29
g_slist_free(ignore_children);
39
static bool bdrv_a_allow_b(BdrvChild *a, BdrvChild *b, Error **errp)
30
- if (local_err) {
40
{
31
- ret = -EPERM;
41
- g_autofree char *user = NULL;
32
+ if (ret < 0) {
42
- g_autofree char *perm_names = NULL;
33
error_report_err(local_err);
43
+ const char *child_bs_name;
34
goto exit;
44
+ g_autofree char *a_user = NULL;
35
}
45
+ g_autofree char *b_user = NULL;
46
+ g_autofree char *perms = NULL;
47
+
48
+ assert(a->bs);
49
+ assert(a->bs == b->bs);
50
51
if ((b->perm & a->shared_perm) == b->perm) {
52
return true;
53
}
54
55
- perm_names = bdrv_perm_names(b->perm & ~a->shared_perm);
56
- user = bdrv_child_user_desc(a);
57
- error_setg(errp, "Conflicts with use by %s as '%s', which does not "
58
- "allow '%s' on %s",
59
- user, a->name, perm_names, bdrv_get_node_name(b->bs));
60
+ child_bs_name = bdrv_get_node_name(b->bs);
61
+ a_user = bdrv_child_user_desc(a);
62
+ b_user = bdrv_child_user_desc(b);
63
+ perms = bdrv_perm_names(b->perm & ~a->shared_perm);
64
+
65
+ error_setg(errp, "Permission conflict on node '%s': permissions '%s' are "
66
+ "both required by %s (uses node '%s' as '%s' child) and "
67
+ "unshared by %s (uses node '%s' as '%s' child).",
68
+ child_bs_name, perms,
69
+ b_user, child_bs_name, b->name,
70
+ a_user, child_bs_name, a->name);
71
72
return false;
73
}
74
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
75
index XXXXXXX..XXXXXXX 100644
76
--- a/tests/qemu-iotests/283.out
77
+++ b/tests/qemu-iotests/283.out
78
@@ -XXX,XX +XXX,XX @@
79
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
80
{"return": {}}
81
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
82
-{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Conflicts with use by node 'source' as 'image', which does not allow 'write' on base"}}
83
+{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
84
85
=== backup-top should be gone after job-finalize ===
86
87
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
88
index XXXXXXX..XXXXXXX 100644
89
--- a/tests/qemu-iotests/307.out
90
+++ b/tests/qemu-iotests/307.out
91
@@ -XXX,XX +XXX,XX @@ exports available: 1
92
93
=== Add a writable export ===
94
{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}}
95
-{"error": {"class": "GenericError", "desc": "Conflicts with use by block device 'sda' as 'root', which does not allow 'write' on fmt"}}
96
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt': permissions 'write' are both required by an unnamed block device (uses node 'fmt' as 'root' child) and unshared by block device 'sda' (uses node 'fmt' as 'root' child)."}}
97
{"execute": "device_del", "arguments": {"id": "sda"}}
98
{"return": {}}
99
{"data": {"device": "sda", "path": "/machine/peripheral/sda"}, "event": "DEVICE_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
100
diff --git a/tests/qemu-iotests/tests/qsd-jobs.out b/tests/qemu-iotests/tests/qsd-jobs.out
101
index XXXXXXX..XXXXXXX 100644
102
--- a/tests/qemu-iotests/tests/qsd-jobs.out
103
+++ b/tests/qemu-iotests/tests/qsd-jobs.out
104
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
105
{"return": {}}
106
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
107
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
108
-{"error": {"class": "GenericError", "desc": "Conflicts with use by stream job 'job0' as 'intermediate node', which does not allow 'write' on fmt_base"}}
109
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt_base': permissions 'write' are both required by an unnamed block device (uses node 'fmt_base' as 'root' child) and unshared by stream job 'job0' (uses node 'fmt_base' as 'intermediate node' child)."}}
110
{"return": {}}
111
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}}
112
*** done
36
--
113
--
37
2.20.1
114
2.30.2
38
115
39
116
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Sergio Lopez <slp@redhat.com>
2
2
3
There are various actions in this test that must be executed
3
Allow block backends to poll their devices/users to check if they have
4
sequentially, as the result of it depends on the state triggered by the
4
been quiesced when entering a drained section.
5
previous one.
6
5
7
If the last argument of _send_qemu_cmd() is an empty string, it just
6
This will be used in the next patch to wait for the NBD server to be
8
sends the QMP commands without waiting for an answer. While unlikely, it
7
completely quiesced.
9
may happen that the next action in the test gets invoked before QEMU
10
processes the QMP request.
11
8
12
This issue seems to be easier to reproduce on servers with limited
9
Suggested-by: Kevin Wolf <kwolf@redhat.com>
13
resources or highly loaded.
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
11
Reviewed-by: Eric Blake <eblake@redhat.com>
15
With this change, we wait for an answer on all _send_qemu_cmd() calls.
16
17
Signed-off-by: Sergio Lopez <slp@redhat.com>
12
Signed-off-by: Sergio Lopez <slp@redhat.com>
13
Message-Id: <20210602060552.17433-2-slp@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
16
---
20
tests/qemu-iotests/153 | 12 ++++++------
17
include/sysemu/block-backend.h | 4 ++++
21
tests/qemu-iotests/153.out | 6 ++++++
18
block/block-backend.c | 7 ++++++-
22
2 files changed, 12 insertions(+), 6 deletions(-)
19
2 files changed, 10 insertions(+), 1 deletion(-)
23
20
24
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
21
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/153
27
+++ b/tests/qemu-iotests/153
28
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
29
_img_info -U | grep 'file format'
30
fi
31
done
32
- _send_qemu_cmd $h "{ 'execute': 'quit', }" ""
33
+ _send_qemu_cmd $h "{ 'execute': 'quit' }" ''
34
echo
35
echo "Round done"
36
_cleanup_qemu
37
@@ -XXX,XX +XXX,XX @@ echo "Adding drive"
38
_send_qemu_cmd $QEMU_HANDLE \
39
"{ 'execute': 'human-monitor-command',
40
'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=${TEST_IMG}' } }" \
41
- ""
42
+ 'return'
43
44
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
45
46
@@ -XXX,XX +XXX,XX @@ echo "== Closing an image should unlock it =="
47
_send_qemu_cmd $QEMU_HANDLE \
48
"{ 'execute': 'human-monitor-command',
49
'arguments': { 'command-line': 'drive_del d0' } }" \
50
- ""
51
+ 'return'
52
53
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
54
55
@@ -XXX,XX +XXX,XX @@ for d in d0 d1; do
56
_send_qemu_cmd $QEMU_HANDLE \
57
"{ 'execute': 'human-monitor-command',
58
'arguments': { 'command-line': 'drive_add 0 if=none,id=$d,file=${TEST_IMG},readonly=on' } }" \
59
- ""
60
+ 'return'
61
done
62
63
_run_cmd $QEMU_IMG info "${TEST_IMG}"
64
@@ -XXX,XX +XXX,XX @@ _run_cmd $QEMU_IMG info "${TEST_IMG}"
65
_send_qemu_cmd $QEMU_HANDLE \
66
"{ 'execute': 'human-monitor-command',
67
'arguments': { 'command-line': 'drive_del d0' } }" \
68
- ""
69
+ 'return'
70
71
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
72
73
@@ -XXX,XX +XXX,XX @@ echo "Closing the other"
74
_send_qemu_cmd $QEMU_HANDLE \
75
"{ 'execute': 'human-monitor-command',
76
'arguments': { 'command-line': 'drive_del d1' } }" \
77
- ""
78
+ 'return'
79
80
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
81
82
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
83
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
84
--- a/tests/qemu-iotests/153.out
23
--- a/include/sysemu/block-backend.h
85
+++ b/tests/qemu-iotests/153.out
24
+++ b/include/sysemu/block-backend.h
86
@@ -XXX,XX +XXX,XX @@ Is another process using the image [TEST_DIR/t.qcow2]?
25
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDevOps {
87
_qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
26
* Runs when the backend's last drain request ends.
88
{"return": {}}
27
*/
89
Adding drive
28
void (*drained_end)(void *opaque);
90
+{"return": "OKrn"}
29
+ /*
91
30
+ * Is the device still busy?
92
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
31
+ */
93
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
32
+ bool (*drained_poll)(void *opaque);
94
@@ -XXX,XX +XXX,XX @@ Creating overlay with qemu-img when the guest is running should be allowed
33
} BlockDevOps;
95
34
96
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
35
/* This struct is embedded in (the private) BlockBackend struct and contains
97
== Closing an image should unlock it ==
36
diff --git a/block/block-backend.c b/block/block-backend.c
98
+{"return": ""}
37
index XXXXXXX..XXXXXXX 100644
99
38
--- a/block/block-backend.c
100
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
39
+++ b/block/block-backend.c
101
Adding two and closing one
40
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_begin(BdrvChild *child)
102
+{"return": "OKrn"}
41
static bool blk_root_drained_poll(BdrvChild *child)
103
+{"return": "OKrn"}
42
{
104
43
BlockBackend *blk = child->opaque;
105
_qemu_img_wrapper info TEST_DIR/t.qcow2
44
+ bool busy = false;
106
+{"return": ""}
45
assert(blk->quiesce_counter);
107
46
- return !!blk->in_flight;
108
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
47
+
109
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
48
+ if (blk->dev_ops && blk->dev_ops->drained_poll) {
110
Is another process using the image [TEST_DIR/t.qcow2]?
49
+ busy = blk->dev_ops->drained_poll(blk->dev_opaque);
111
Closing the other
50
+ }
112
+{"return": ""}
51
+ return busy || !!blk->in_flight;
113
52
}
114
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
53
115
54
static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter)
116
--
55
--
117
2.20.1
56
2.30.2
118
57
119
58
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Sergio Lopez <slp@redhat.com>
2
2
3
While child_job_drained_begin() calls to job_pause(), the job doesn't
3
Before switching between AioContexts we need to make sure that we're
4
actually transition between states until it runs again and reaches a
4
fully quiesced ("nb_requests == 0" for every client) when entering the
5
pause point. This means bdrv_drained_begin() may return with some jobs
5
drained section.
6
using the node still having 'busy == true'.
7
6
8
As a consequence, block_job_detach_aio_context() may get into a
7
To do this, we set "quiescing = true" for every client on
9
deadlock, waiting for the job to be actually paused, while the coroutine
8
".drained_begin" to prevent new coroutines from being created, and
10
servicing the job is yielding and doesn't get the opportunity to get
9
check if "nb_requests == 0" on ".drained_poll". Finally, once we're
11
scheduled again. This situation can be reproduced by issuing a
10
exiting the drained section, on ".drained_end" we set "quiescing =
12
'block-commit' immediately followed by a 'device_del'.
11
false" and call "nbd_client_receive_next_request()" to resume the
12
processing of new requests.
13
13
14
To ensure bdrv_drained_begin() only returns when the jobs have been
14
With these changes, "blk_aio_attach()" and "blk_aio_detach()" can be
15
paused, we change mirror_drained_poll() to only confirm it's quiesced
15
reverted to be as simple as they were before f148ae7d36.
16
when job->paused == true and there aren't any in-flight requests, except
17
if we reached that point by a drained section initiated by the
18
mirror/commit job itself.
19
16
20
The other block jobs shouldn't need any changes, as the default
17
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1960137
21
drained_poll() behavior is to only confirm it's quiesced if the job is
18
Suggested-by: Kevin Wolf <kwolf@redhat.com>
22
not busy or completed.
23
24
Signed-off-by: Sergio Lopez <slp@redhat.com>
19
Signed-off-by: Sergio Lopez <slp@redhat.com>
20
Message-Id: <20210602060552.17433-3-slp@redhat.com>
21
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
---
23
---
27
block/mirror.c | 16 ++++++++++++++++
24
nbd/server.c | 82 ++++++++++++++++++++++++++++++++++++++--------------
28
1 file changed, 16 insertions(+)
25
1 file changed, 61 insertions(+), 21 deletions(-)
29
26
30
diff --git a/block/mirror.c b/block/mirror.c
27
diff --git a/nbd/server.c b/nbd/server.c
31
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
32
--- a/block/mirror.c
29
--- a/nbd/server.c
33
+++ b/block/mirror.c
30
+++ b/nbd/server.c
34
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob {
31
@@ -XXX,XX +XXX,XX @@ static void nbd_request_put(NBDRequestData *req)
35
bool initial_zeroing_ongoing;
32
g_free(req);
36
int in_active_write_counter;
33
37
bool prepared;
34
client->nb_requests--;
38
+ bool in_drain;
39
} MirrorBlockJob;
40
41
typedef struct MirrorBDSOpaque {
42
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
43
44
/* The mirror job has no requests in flight any more, but we need to
45
* drain potential other users of the BDS before changing the graph. */
46
+ assert(s->in_drain);
47
bdrv_drained_begin(target_bs);
48
bdrv_replace_node(to_replace, target_bs, &local_err);
49
bdrv_drained_end(target_bs);
50
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
51
bs_opaque->job = NULL;
52
53
bdrv_drained_end(src);
54
+ s->in_drain = false;
55
bdrv_unref(mirror_top_bs);
56
bdrv_unref(src);
57
58
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
59
*/
60
trace_mirror_before_drain(s, cnt);
61
62
+ s->in_drain = true;
63
bdrv_drained_begin(bs);
64
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
65
if (cnt > 0 || mirror_flush(s) < 0) {
66
bdrv_drained_end(bs);
67
+ s->in_drain = false;
68
continue;
69
}
70
71
@@ -XXX,XX +XXX,XX @@ immediate_exit:
72
bdrv_dirty_iter_free(s->dbi);
73
74
if (need_drain) {
75
+ s->in_drain = true;
76
bdrv_drained_begin(bs);
77
}
78
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_pause(Job *job)
80
static bool mirror_drained_poll(BlockJob *job)
81
{
82
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
83
+
35
+
84
+ /* If the job isn't paused nor cancelled, we can't be sure that it won't
36
+ if (client->quiescing && client->nb_requests == 0) {
85
+ * issue more requests. We make an exception if we've reached this point
37
+ aio_wait_kick();
86
+ * from one of our own drain sections, to avoid a deadlock waiting for
87
+ * ourselves.
88
+ */
89
+ if (!s->common.job.paused && !s->common.job.cancelled && !s->in_drain) {
90
+ return true;
91
+ }
38
+ }
92
+
39
+
93
return !!s->in_flight;
40
nbd_client_receive_next_request(client);
41
42
nbd_client_put(client);
43
@@ -XXX,XX +XXX,XX @@ static void blk_aio_attached(AioContext *ctx, void *opaque)
44
QTAILQ_FOREACH(client, &exp->clients, next) {
45
qio_channel_attach_aio_context(client->ioc, ctx);
46
47
+ assert(client->nb_requests == 0);
48
assert(client->recv_coroutine == NULL);
49
assert(client->send_coroutine == NULL);
50
-
51
- if (client->quiescing) {
52
- client->quiescing = false;
53
- nbd_client_receive_next_request(client);
54
- }
55
}
94
}
56
}
95
57
58
-static void nbd_aio_detach_bh(void *opaque)
59
+static void blk_aio_detach(void *opaque)
60
{
61
NBDExport *exp = opaque;
62
NBDClient *client;
63
64
+ trace_nbd_blk_aio_detach(exp->name, exp->common.ctx);
65
+
66
QTAILQ_FOREACH(client, &exp->clients, next) {
67
qio_channel_detach_aio_context(client->ioc);
68
+ }
69
+
70
+ exp->common.ctx = NULL;
71
+}
72
+
73
+static void nbd_drained_begin(void *opaque)
74
+{
75
+ NBDExport *exp = opaque;
76
+ NBDClient *client;
77
+
78
+ QTAILQ_FOREACH(client, &exp->clients, next) {
79
client->quiescing = true;
80
+ }
81
+}
82
83
- if (client->recv_coroutine) {
84
- if (client->read_yielding) {
85
- qemu_aio_coroutine_enter(exp->common.ctx,
86
- client->recv_coroutine);
87
- } else {
88
- AIO_WAIT_WHILE(exp->common.ctx, client->recv_coroutine != NULL);
89
- }
90
- }
91
+static void nbd_drained_end(void *opaque)
92
+{
93
+ NBDExport *exp = opaque;
94
+ NBDClient *client;
95
96
- if (client->send_coroutine) {
97
- AIO_WAIT_WHILE(exp->common.ctx, client->send_coroutine != NULL);
98
- }
99
+ QTAILQ_FOREACH(client, &exp->clients, next) {
100
+ client->quiescing = false;
101
+ nbd_client_receive_next_request(client);
102
}
103
}
104
105
-static void blk_aio_detach(void *opaque)
106
+static bool nbd_drained_poll(void *opaque)
107
{
108
NBDExport *exp = opaque;
109
+ NBDClient *client;
110
111
- trace_nbd_blk_aio_detach(exp->name, exp->common.ctx);
112
+ QTAILQ_FOREACH(client, &exp->clients, next) {
113
+ if (client->nb_requests != 0) {
114
+ /*
115
+ * If there's a coroutine waiting for a request on nbd_read_eof()
116
+ * enter it here so we don't depend on the client to wake it up.
117
+ */
118
+ if (client->recv_coroutine != NULL && client->read_yielding) {
119
+ qemu_aio_coroutine_enter(exp->common.ctx,
120
+ client->recv_coroutine);
121
+ }
122
123
- aio_wait_bh_oneshot(exp->common.ctx, nbd_aio_detach_bh, exp);
124
+ return true;
125
+ }
126
+ }
127
128
- exp->common.ctx = NULL;
129
+ return false;
130
}
131
132
static void nbd_eject_notifier(Notifier *n, void *data)
133
@@ -XXX,XX +XXX,XX @@ void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk)
134
blk_add_remove_bs_notifier(blk, &nbd_exp->eject_notifier);
135
}
136
137
+static const BlockDevOps nbd_block_ops = {
138
+ .drained_begin = nbd_drained_begin,
139
+ .drained_end = nbd_drained_end,
140
+ .drained_poll = nbd_drained_poll,
141
+};
142
+
143
static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
144
Error **errp)
145
{
146
@@ -XXX,XX +XXX,XX @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
147
148
exp->allocation_depth = arg->allocation_depth;
149
150
+ /*
151
+ * We need to inhibit request queuing in the block layer to ensure we can
152
+ * be properly quiesced when entering a drained section, as our coroutines
153
+ * servicing pending requests might enter blk_pread().
154
+ */
155
+ blk_set_disable_request_queuing(blk, true);
156
+
157
blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
158
159
+ blk_set_dev_ops(blk, &nbd_block_ops, exp);
160
+
161
QTAILQ_INSERT_TAIL(&exports, exp, next);
162
163
return 0;
164
@@ -XXX,XX +XXX,XX @@ static void nbd_export_delete(BlockExport *blk_exp)
165
}
166
blk_remove_aio_context_notifier(exp->common.blk, blk_aio_attached,
167
blk_aio_detach, exp);
168
+ blk_set_disable_request_queuing(exp->common.blk, false);
169
}
170
171
for (i = 0; i < exp->nr_export_bitmaps; i++) {
96
--
172
--
97
2.20.1
173
2.30.2
98
174
99
175
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Job (especially mirror) may call block_job_error_action several
3
Don't report successful progress on failure, when call_state->ret is
4
times before actual pause if it has several in-flight requests.
4
set.
5
6
block_job_error_action will call job_pause more than once in this case,
7
which lead to following block-job-resume qmp command can't actually
8
resume the job.
9
10
Fix it by do not increase pause level in block_job_error_action if
11
user_paused already set.
12
5
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20210528141628.44287-2-vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
10
---
16
blockjob.c | 8 +++++---
11
block/block-copy.c | 8 +++++---
17
1 file changed, 5 insertions(+), 3 deletions(-)
12
1 file changed, 5 insertions(+), 3 deletions(-)
18
13
19
diff --git a/blockjob.c b/blockjob.c
14
diff --git a/block/block-copy.c b/block/block-copy.c
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/blockjob.c
16
--- a/block/block-copy.c
22
+++ b/blockjob.c
17
+++ b/block/block-copy.c
23
@@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
24
action);
19
20
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
21
&error_is_read);
22
- if (ret < 0 && !t->call_state->ret) {
23
- t->call_state->ret = ret;
24
- t->call_state->error_is_read = error_is_read;
25
+ if (ret < 0) {
26
+ if (!t->call_state->ret) {
27
+ t->call_state->ret = ret;
28
+ t->call_state->error_is_read = error_is_read;
29
+ }
30
} else {
31
progress_work_done(t->s->progress, t->bytes);
25
}
32
}
26
if (action == BLOCK_ERROR_ACTION_STOP) {
27
- job_pause(&job->job);
28
- /* make the pause user visible, which will be resumed from QMP. */
29
- job->job.user_paused = true;
30
+ if (!job->job.user_paused) {
31
+ job_pause(&job->job);
32
+ /* make the pause user visible, which will be resumed from QMP. */
33
+ job->job.user_paused = true;
34
+ }
35
block_job_iostatus_set_err(job, error);
36
}
37
return action;
38
--
33
--
39
2.20.1
34
2.30.2
40
35
41
36
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
There no @device parameter, only the @id one.
3
Currently we update s->use_copy_range and s->copy_size in
4
block_copy_do_copy().
5
6
It's not very good:
7
8
1. block_copy_do_copy() is intended to be a simple function, that wraps
9
bdrv_co_<io> functions for need of block copy. That's why we don't pass
10
BlockCopyTask into it. So, block_copy_do_copy() is bad place for
11
manipulation with generic state of block-copy process
12
13
2. We are going to make block-copy thread-safe. So, it's good to move
14
manipulation with state of block-copy to the places where we'll need
15
critical sections anyway, to not introduce extra synchronization
16
primitives in block_copy_do_copy().
4
17
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Message-Id: <20210528141628.44287-3-vsementsov@virtuozzo.com>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
22
---
9
qapi/block-core.json | 10 +++++-----
23
block/block-copy.c | 72 +++++++++++++++++++++++++++++++---------------
10
1 file changed, 5 insertions(+), 5 deletions(-)
24
1 file changed, 49 insertions(+), 23 deletions(-)
11
25
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
26
diff --git a/block/block-copy.c b/block/block-copy.c
13
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
28
--- a/block/block-copy.c
15
+++ b/qapi/block-core.json
29
+++ b/block/block-copy.c
16
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyTask {
17
#
31
int64_t offset;
18
# Manage read, write and flush latency histograms for the device.
32
int64_t bytes;
19
#
33
bool zeroes;
20
-# If only @device parameter is specified, remove all present latency histograms
34
+ bool copy_range;
21
+# If only @id parameter is specified, remove all present latency histograms
35
QLIST_ENTRY(BlockCopyTask) list;
22
# for the device. Otherwise, add/reset some of (or all) latency histograms.
36
CoQueue wait_queue; /* coroutines blocked on this task */
23
#
37
} BlockCopyTask;
24
# @id: The name or QOM path of the guest device.
38
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
25
@@ -XXX,XX +XXX,XX @@
39
.call_state = call_state,
26
# [0, 10), [10, 50), [50, 100), [100, +inf):
40
.offset = offset,
27
#
41
.bytes = bytes,
28
# -> { "execute": "block-latency-histogram-set",
42
+ .copy_range = s->use_copy_range,
29
-# "arguments": { "device": "drive0",
43
};
30
+# "arguments": { "id": "drive0",
44
qemu_co_queue_init(&task->wait_queue);
31
# "boundaries": [10, 50, 100] } }
45
QLIST_INSERT_HEAD(&s->tasks, task, list);
32
# <- { "return": {} }
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
33
#
47
*
34
@@ -XXX,XX +XXX,XX @@
48
* No sync here: nor bitmap neighter intersecting requests handling, only copy.
35
# not changed (or not created):
49
*
36
#
50
+ * @copy_range is an in-out argument: if *copy_range is false, copy_range is not
37
# -> { "execute": "block-latency-histogram-set",
51
+ * done. If *copy_range is true, copy_range is attempted. If the copy_range
38
-# "arguments": { "device": "drive0",
52
+ * attempt fails, the function falls back to the usual read+write and
39
+# "arguments": { "id": "drive0",
53
+ * *copy_range is set to false. *copy_range and zeroes must not be true
40
# "boundaries-write": [10, 50, 100] } }
54
+ * simultaneously.
41
# <- { "return": {} }
55
+ *
42
#
56
* Returns 0 on success.
43
@@ -XXX,XX +XXX,XX @@
57
*/
44
# write: [0, 1000), [1000, 5000), [5000, +inf)
58
static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
45
#
59
int64_t offset, int64_t bytes,
46
# -> { "execute": "block-latency-histogram-set",
60
- bool zeroes, bool *error_is_read)
47
-# "arguments": { "device": "drive0",
61
+ bool zeroes, bool *copy_range,
48
+# "arguments": { "id": "drive0",
62
+ bool *error_is_read)
49
# "boundaries": [10, 50, 100],
63
{
50
# "boundaries-write": [1000, 5000] } }
64
int ret;
51
# <- { "return": {} }
65
int64_t nbytes = MIN(offset + bytes, s->len) - offset;
52
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
53
# Example: remove all latency histograms:
67
assert(offset + bytes <= s->len ||
54
#
68
offset + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size));
55
# -> { "execute": "block-latency-histogram-set",
69
assert(nbytes < INT_MAX);
56
-# "arguments": { "device": "drive0" } }
70
+ assert(!(*copy_range && zeroes));
57
+# "arguments": { "id": "drive0" } }
71
58
# <- { "return": {} }
72
if (zeroes) {
59
##
73
ret = bdrv_co_pwrite_zeroes(s->target, offset, nbytes, s->write_flags &
60
{ 'command': 'block-latency-histogram-set',
74
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
75
return ret;
76
}
77
78
- if (s->use_copy_range) {
79
+ if (*copy_range) {
80
ret = bdrv_co_copy_range(s->source, offset, s->target, offset, nbytes,
81
0, s->write_flags);
82
if (ret < 0) {
83
trace_block_copy_copy_range_fail(s, offset, ret);
84
- s->use_copy_range = false;
85
- s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
86
+ *copy_range = false;
87
/* Fallback to read+write with allocated buffer */
88
} else {
89
- if (s->use_copy_range) {
90
- /*
91
- * Successful copy-range. Now increase copy_size. copy_range
92
- * does not respect max_transfer (it's a TODO), so we factor
93
- * that in here.
94
- *
95
- * Note: we double-check s->use_copy_range for the case when
96
- * parallel block-copy request unsets it during previous
97
- * bdrv_co_copy_range call.
98
- */
99
- s->copy_size =
100
- MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_COPY_RANGE),
101
- QEMU_ALIGN_DOWN(block_copy_max_transfer(s->source,
102
- s->target),
103
- s->cluster_size));
104
- }
105
- goto out;
106
+ return 0;
107
}
108
}
109
110
@@ -XXX,XX +XXX,XX @@ out:
111
return ret;
112
}
113
114
+static void block_copy_handle_copy_range_result(BlockCopyState *s,
115
+ bool is_success)
116
+{
117
+ if (!s->use_copy_range) {
118
+ /* already disabled */
119
+ return;
120
+ }
121
+
122
+ if (is_success) {
123
+ /*
124
+ * Successful copy-range. Now increase copy_size. copy_range
125
+ * does not respect max_transfer (it's a TODO), so we factor
126
+ * that in here.
127
+ */
128
+ s->copy_size =
129
+ MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_COPY_RANGE),
130
+ QEMU_ALIGN_DOWN(block_copy_max_transfer(s->source,
131
+ s->target),
132
+ s->cluster_size));
133
+ } else {
134
+ /* Copy-range failed, disable it. */
135
+ s->use_copy_range = false;
136
+ s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
137
+ }
138
+}
139
+
140
static coroutine_fn int block_copy_task_entry(AioTask *task)
141
{
142
BlockCopyTask *t = container_of(task, BlockCopyTask, task);
143
bool error_is_read = false;
144
+ bool copy_range = t->copy_range;
145
int ret;
146
147
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
148
- &error_is_read);
149
+ &copy_range, &error_is_read);
150
+ if (t->copy_range) {
151
+ block_copy_handle_copy_range_result(t->s, copy_range);
152
+ }
153
if (ret < 0) {
154
if (!t->call_state->ret) {
155
t->call_state->ret = ret;
156
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
157
g_free(task);
158
continue;
159
}
160
- task->zeroes = ret & BDRV_BLOCK_ZERO;
161
+ if (ret & BDRV_BLOCK_ZERO) {
162
+ task->zeroes = true;
163
+ task->copy_range = false;
164
+ }
165
166
if (s->speed) {
167
if (!call_state->ignore_ratelimit) {
61
--
168
--
62
2.20.1
169
2.30.2
63
170
64
171
diff view generated by jsdifflib
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Commit 509d39aa22909c0ed1aabf896865f19c81fb38a1 added support for read
3
Document that security reports must use 'null-co,read-zeroes=on'
4
only VMDKs of version 3.
4
because otherwise the memory is left uninitialized (which is an
5
on-purpose performance feature).
5
6
6
This commit fixes the probe function to correctly handle descriptors of
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
version 3.
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
9
Message-Id: <20210601162548.2076631-1-philmd@redhat.com>
9
This commit has two effects:
10
1. We no longer need to supply '-f vmdk' when pointing to descriptor
11
files of version 3 in qemu/qemu-img command line arguments.
12
2. This fixes the scenario where a VMDK points to a parent version 3
13
descriptor file which is being probed as "raw" instead of "vmdk".
14
15
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
16
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
17
Signed-off-by: Shmuel Eiderman <shmuel.eiderman@oracle.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
11
---
20
block/vmdk.c | 6 ++++--
12
docs/devel/secure-coding-practices.rst | 9 +++++++++
21
1 file changed, 4 insertions(+), 2 deletions(-)
13
1 file changed, 9 insertions(+)
22
14
23
diff --git a/block/vmdk.c b/block/vmdk.c
15
diff --git a/docs/devel/secure-coding-practices.rst b/docs/devel/secure-coding-practices.rst
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/block/vmdk.c
17
--- a/docs/devel/secure-coding-practices.rst
26
+++ b/block/vmdk.c
18
+++ b/docs/devel/secure-coding-practices.rst
27
@@ -XXX,XX +XXX,XX @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
19
@@ -XXX,XX +XXX,XX @@ structures and only process the local copy. This prevents
28
}
20
time-of-check-to-time-of-use (TOCTOU) race conditions that could cause QEMU to
29
if (end - p >= strlen("version=X\n")) {
21
crash when a vCPU thread modifies guest RAM while device emulation is
30
if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
22
processing it.
31
- strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
23
+
32
+ strncmp("version=2\n", p, strlen("version=2\n")) == 0 ||
24
+Use of null-co block drivers
33
+ strncmp("version=3\n", p, strlen("version=3\n")) == 0) {
25
+----------------------------
34
return 100;
26
+
35
}
27
+The ``null-co`` block driver is designed for performance: its read accesses are
36
}
28
+not initialized by default. In case this driver has to be used for security
37
if (end - p >= strlen("version=X\r\n")) {
29
+research, it must be used with the ``read-zeroes=on`` option which fills read
38
if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
30
+buffers with zeroes. Security issues reported with the default
39
- strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
31
+(``read-zeroes=off``) will be discarded.
40
+ strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0 ||
41
+ strncmp("version=3\r\n", p, strlen("version=3\r\n")) == 0) {
42
return 100;
43
}
44
}
45
--
32
--
46
2.20.1
33
2.30.2
47
34
48
35
diff view generated by jsdifflib