1
The following changes since commit dd2db39d78431ab5a0b78777afaab3d61e94533e:
1
The following changes since commit 825b96dbcee23d134b691fc75618b59c5f53da32:
2
2
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2021-06-01 21:23:26 +0100)
3
Merge tag 'migration-20250310-pull-request' of https://gitlab.com/farosas/qemu into staging (2025-03-11 09:32:07 +0800)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to b317006a3f1f04191a7981cef83417cb2477213b:
9
for you to fetch changes up to df957115c46845e2c0ccc29ac0a75eb9700a9a0d:
10
10
11
docs/secure-coding-practices: Describe how to use 'null-co' block driver (2021-06-02 14:29:14 +0200)
11
scripts/qcow2-to-stdout.py: Add script to write qcow2 images to stdout (2025-03-13 17:57:23 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- NBD server: Fix crashes related to switching between AioContexts
16
- virtio-scsi: add iothread-vq-mapping parameter
17
- file-posix: Workaround for discard/write_zeroes on buggy filesystems
17
- Improve writethrough performance
18
- Follow-up fixes for the reopen vs. permission changes
18
- Fix missing zero init in bdrv_snapshot_goto()
19
- quorum: Fix error handling for flush
19
- Added scripts/qcow2-to-stdout.py
20
- block-copy: Refactor copy_range handling
20
- Code cleanup and iotests fixes
21
- docs: Describe how to use 'null-co' block driver
22
21
23
----------------------------------------------------------------
22
----------------------------------------------------------------
24
Lukas Straub (1):
23
Alberto Garcia (1):
25
block/quorum: Provide .bdrv_co_flush instead of .bdrv_co_flush_to_disk
24
scripts/qcow2-to-stdout.py: Add script to write qcow2 images to stdout
26
25
27
Philippe Mathieu-Daudé (1):
26
Kevin Wolf (8):
28
docs/secure-coding-practices: Describe how to use 'null-co' block driver
27
block: Remove unused blk_op_is_blocked()
28
block: Zero block driver state before reopening
29
file-posix: Support FUA writes
30
block/io: Ignore FUA with cache.no-flush=on
31
aio: Create AioPolledEvent
32
aio-posix: Factor out adjust_polling_time()
33
aio-posix: Separate AioPolledEvent per AioHandler
34
aio-posix: Adjust polling time also for new handlers
29
35
30
Sergio Lopez (2):
36
Stefan Hajnoczi (13):
31
block-backend: add drained_poll
37
scsi-disk: drop unused SCSIDiskState->bh field
32
nbd/server: Use drained block ops to quiesce the server
38
dma: use current AioContext for dma_blk_io()
39
scsi: track per-SCSIRequest AioContext
40
scsi: introduce requests_lock
41
virtio-scsi: introduce event and ctrl virtqueue locks
42
virtio-scsi: protect events_dropped field
43
virtio-scsi: perform TMFs in appropriate AioContexts
44
virtio-blk: extract cleanup_iothread_vq_mapping() function
45
virtio-blk: tidy up iothread_vq_mapping functions
46
virtio: extract iothread-vq-mapping.h API
47
virtio-scsi: add iothread-vq-mapping parameter
48
virtio-scsi: handle ctrl virtqueue in main loop
49
virtio-scsi: only expose cmd vqs via iothread-vq-mapping
33
50
34
Thomas Huth (2):
51
Thomas Huth (1):
35
block/file-posix: Fix problem with fallocate(PUNCH_HOLE) on GPFS
52
iotests: Limit qsd-migrate to working formats
36
block/file-posix: Try other fallbacks after invalid FALLOC_FL_ZERO_RANGE
37
53
38
Vladimir Sementsov-Ogievskiy (14):
54
include/block/aio.h | 5 +-
39
qemu-io-cmds: assert that we don't have .perm requested in no-blk case
55
include/block/raw-aio.h | 19 +-
40
block/vvfat: child_vvfat_qcow: add .get_parent_aio_context, fix crash
56
include/hw/scsi/scsi.h | 8 +-
41
block/vvfat: fix vvfat_child_perm crash
57
include/hw/virtio/iothread-vq-mapping.h | 45 +++
42
block: consistently use bdrv_is_read_only()
58
include/hw/virtio/virtio-scsi.h | 15 +-
43
block: drop BlockDriverState::read_only
59
include/system/block-backend-global-state.h | 1 -
44
block: drop BlockBackendRootState::read_only
60
include/system/dma.h | 3 +-
45
block: document child argument of bdrv_attach_child_common()
61
util/aio-posix.h | 1 +
46
block-backend: improve blk_root_get_parent_desc()
62
block/block-backend.c | 12 -
47
block: improve bdrv_child_get_parent_desc()
63
block/file-posix.c | 29 +-
48
block/vvfat: inherit child_vvfat_qcow from child_of_bds
64
block/io.c | 4 +
49
block: simplify bdrv_child_user_desc()
65
block/io_uring.c | 25 +-
50
block: improve permission conflict error message
66
block/linux-aio.c | 25 +-
51
block-copy: fix block_copy_task_entry() progress update
67
block/snapshot.c | 1 +
52
block-copy: refactor copy_range handling
68
hw/block/virtio-blk.c | 132 +-------
53
69
hw/ide/core.c | 3 +-
54
docs/devel/secure-coding-practices.rst | 9 ++++
70
hw/ide/macio.c | 3 +-
55
include/block/block.h | 1 +
71
hw/scsi/scsi-bus.c | 121 +++++--
56
include/block/block_int.h | 2 -
72
hw/scsi/scsi-disk.c | 24 +-
57
include/sysemu/block-backend.h | 4 ++
73
hw/scsi/virtio-scsi-dataplane.c | 103 ++++--
58
block.c | 82 ++++++++++++++++++++--------------
74
hw/scsi/virtio-scsi.c | 502 ++++++++++++++++------------
59
block/block-backend.c | 26 +++++------
75
hw/virtio/iothread-vq-mapping.c | 131 ++++++++
60
block/block-copy.c | 80 ++++++++++++++++++++++-----------
76
system/dma-helpers.c | 8 +-
61
block/commit.c | 2 +-
77
util/aio-posix.c | 114 ++++---
62
block/file-posix.c | 29 ++++++++----
78
util/async.c | 1 -
63
block/io.c | 4 +-
79
scripts/qcow2-to-stdout.py | 449 +++++++++++++++++++++++++
64
block/qapi.c | 2 +-
80
hw/virtio/meson.build | 1 +
65
block/qcow2-snapshot.c | 2 +-
81
meson.build | 8 +
66
block/qcow2.c | 5 +--
82
tests/qemu-iotests/051.pc.out | 2 +-
67
block/quorum.c | 2 +-
83
tests/qemu-iotests/tests/qsd-migrate | 2 +-
68
block/snapshot.c | 2 +-
84
30 files changed, 1286 insertions(+), 511 deletions(-)
69
block/vhdx-log.c | 2 +-
85
create mode 100644 include/hw/virtio/iothread-vq-mapping.h
70
block/vvfat.c | 14 +++---
86
create mode 100644 hw/virtio/iothread-vq-mapping.c
71
blockdev.c | 3 +-
87
create mode 100755 scripts/qcow2-to-stdout.py
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
Deleted patch
1
From: Lukas Straub <lukasstraub2@web.de>
2
1
3
The quorum block driver uses a custom flush callback to handle the
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.
10
11
Fix this by providing .bdrv_co_flush instead of
12
.bdrv_co_flush_to_disk so the block layer uses the custom flush
13
callback.
14
15
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
16
Reported-by: Minghao Yuan <meeho@qq.com>
17
Message-Id: <20210518134214.11ccf05f@gecko.fritz.box>
18
Tested-by: Zhang Chen <chen.zhang@intel.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block/quorum.c | 2 +-
22
1 file changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/block/quorum.c b/block/quorum.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/quorum.c
27
+++ b/block/quorum.c
28
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
29
.bdrv_dirname = quorum_dirname,
30
.bdrv_co_block_status = quorum_co_block_status,
31
32
- .bdrv_co_flush_to_disk = quorum_co_flush,
33
+ .bdrv_co_flush = quorum_co_flush,
34
35
.bdrv_getlength = quorum_getlength,
36
37
--
38
2.30.2
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block.c | 11 +++++++----
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(-)
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);
142
diff --git a/block/qcow2.c b/block/qcow2.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/block/qcow2.c
145
+++ b/block/qcow2.c
146
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
147
148
/* Clear unknown autoclear feature bits */
149
update_header |= s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK;
150
- update_header =
151
- update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE);
152
+ update_header = update_header && bdrv_is_writable(bs);
153
if (update_header) {
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,
191
--
192
2.30.2
193
194
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This variable is just a cache for !(bs->open_flags & BDRV_O_RDWR),
4
which we have to synchronize everywhere. Let's just drop it and
5
consistently use bdrv_is_read_only().
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210527154056.70294-3-vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block_int.h | 1 -
12
block.c | 7 +------
13
tests/unit/test-block-iothread.c | 6 ------
14
3 files changed, 1 insertion(+), 13 deletions(-)
15
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block_int.h
19
+++ b/include/block/block_int.h
20
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
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;
43
}
44
45
- bs->read_only = true;
46
bs->open_flags &= ~BDRV_O_RDWR;
47
48
return 0;
49
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
50
}
51
52
bs->drv = drv;
53
- bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
54
bs->opaque = g_malloc0(drv->instance_size);
55
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);
62
-
63
ro = bdrv_is_read_only(bs);
64
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
120
--
121
2.30.2
122
123
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Instead of keeping additional boolean field, let's store the
4
information in BDRV_O_RDWR bit of BlockBackendRootState::open_flags.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20210527154056.70294-4-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int.h | 1 -
11
block/block-backend.c | 10 ++--------
12
blockdev.c | 3 +--
13
3 files changed, 3 insertions(+), 11 deletions(-)
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)
62
diff --git a/blockdev.c b/blockdev.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/blockdev.c
65
+++ b/blockdev.c
66
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
67
68
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
69
blk_rs = blk_get_root_state(blk);
70
- blk_rs->open_flags = bdrv_flags;
71
- blk_rs->read_only = read_only;
72
+ blk_rs->open_flags = bdrv_flags | (read_only ? 0 : BDRV_O_RDWR);
73
blk_rs->detect_zeroes = detect_zeroes;
74
75
qobject_unref(bs_opts);
76
--
77
2.30.2
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
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
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/vvfat.c | 8 +++-----
15
1 file changed, 3 insertions(+), 5 deletions(-)
16
17
diff --git a/block/vvfat.c b/block/vvfat.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vvfat.c
20
+++ b/block/vvfat.c
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");
23
}
24
25
-static const BdrvChildClass child_vvfat_qcow = {
26
- .parent_is_bds = true,
27
- .inherit_options = vvfat_qcow_options,
28
- .get_parent_aio_context = child_of_bds_get_parent_aio_context,
29
-};
30
+static BdrvChildClass child_vvfat_qcow;
31
32
static int enable_write_target(BlockDriverState *bs, Error **errp)
33
{
34
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
35
36
static void bdrv_vvfat_init(void)
37
{
38
+ child_vvfat_qcow = child_of_bds;
39
+ child_vvfat_qcow.inherit_options = vvfat_qcow_options;
40
bdrv_register(&bdrv_vvfat);
41
}
42
43
--
44
2.30.2
45
46
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
All child classes have this callback. So, drop unreachable code.
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block.c | 7 ++-----
13
1 file changed, 2 insertions(+), 5 deletions(-)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
20
21
static char *bdrv_child_user_desc(BdrvChild *c)
22
{
23
- if (c->klass->get_parent_desc) {
24
- return c->klass->get_parent_desc(c);
25
- }
26
-
27
- return g_strdup("another user");
28
+ return c->klass->get_parent_desc(c);
29
}
30
31
static bool bdrv_a_allow_b(BdrvChild *a, BdrvChild *b, Error **errp)
32
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
33
34
assert(child);
35
assert(*child == NULL);
36
+ assert(child_class->get_parent_desc);
37
38
new_child = g_new(BdrvChild, 1);
39
*new_child = (BdrvChild) {
40
--
41
2.30.2
42
43
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Now permissions are updated as follows:
4
1. do graph modifications ignoring permissions
5
2. do permission update
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>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block.c | 29 ++++++++++++++++++++-------
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(-)
26
27
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
30
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ static char *bdrv_child_user_desc(BdrvChild *c)
32
return c->klass->get_parent_desc(c);
33
}
34
35
+/*
36
+ * Check that @a allows everything that @b needs. @a and @b must reference same
37
+ * child node.
38
+ */
39
static bool bdrv_a_allow_b(BdrvChild *a, BdrvChild *b, Error **errp)
40
{
41
- g_autofree char *user = NULL;
42
- g_autofree char *perm_names = NULL;
43
+ const char *child_bs_name;
44
+ g_autofree char *a_user = NULL;
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
113
--
114
2.30.2
115
116
diff view generated by jsdifflib
Deleted patch
1
From: Sergio Lopez <slp@redhat.com>
2
1
3
Allow block backends to poll their devices/users to check if they have
4
been quiesced when entering a drained section.
5
6
This will be used in the next patch to wait for the NBD server to be
7
completely quiesced.
8
9
Suggested-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Eric Blake <eblake@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>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
include/sysemu/block-backend.h | 4 ++++
18
block/block-backend.c | 7 ++++++-
19
2 files changed, 10 insertions(+), 1 deletion(-)
20
21
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/sysemu/block-backend.h
24
+++ b/include/sysemu/block-backend.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDevOps {
26
* Runs when the backend's last drain request ends.
27
*/
28
void (*drained_end)(void *opaque);
29
+ /*
30
+ * Is the device still busy?
31
+ */
32
+ bool (*drained_poll)(void *opaque);
33
} BlockDevOps;
34
35
/* This struct is embedded in (the private) BlockBackend struct and contains
36
diff --git a/block/block-backend.c b/block/block-backend.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/block-backend.c
39
+++ b/block/block-backend.c
40
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_begin(BdrvChild *child)
41
static bool blk_root_drained_poll(BdrvChild *child)
42
{
43
BlockBackend *blk = child->opaque;
44
+ bool busy = false;
45
assert(blk->quiesce_counter);
46
- return !!blk->in_flight;
47
+
48
+ if (blk->dev_ops && blk->dev_ops->drained_poll) {
49
+ busy = blk->dev_ops->drained_poll(blk->dev_opaque);
50
+ }
51
+ return busy || !!blk->in_flight;
52
}
53
54
static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter)
55
--
56
2.30.2
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Sergio Lopez <slp@redhat.com>
2
1
3
Before switching between AioContexts we need to make sure that we're
4
fully quiesced ("nb_requests == 0" for every client) when entering the
5
drained section.
6
7
To do this, we set "quiescing = true" for every client on
8
".drained_begin" to prevent new coroutines from being created, and
9
check if "nb_requests == 0" on ".drained_poll". Finally, once we're
10
exiting the drained section, on ".drained_end" we set "quiescing =
11
false" and call "nbd_client_receive_next_request()" to resume the
12
processing of new requests.
13
14
With these changes, "blk_aio_attach()" and "blk_aio_detach()" can be
15
reverted to be as simple as they were before f148ae7d36.
16
17
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1960137
18
Suggested-by: Kevin Wolf <kwolf@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>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
24
nbd/server.c | 82 ++++++++++++++++++++++++++++++++++++++--------------
25
1 file changed, 61 insertions(+), 21 deletions(-)
26
27
diff --git a/nbd/server.c b/nbd/server.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/nbd/server.c
30
+++ b/nbd/server.c
31
@@ -XXX,XX +XXX,XX @@ static void nbd_request_put(NBDRequestData *req)
32
g_free(req);
33
34
client->nb_requests--;
35
+
36
+ if (client->quiescing && client->nb_requests == 0) {
37
+ aio_wait_kick();
38
+ }
39
+
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
}
56
}
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++) {
172
--
173
2.30.2
174
175
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Don't report successful progress on failure, when call_state->ret is
4
set.
5
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>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/block-copy.c | 8 +++++---
12
1 file changed, 5 insertions(+), 3 deletions(-)
13
14
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/block-copy.c
17
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
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);
32
}
33
--
34
2.30.2
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
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().
17
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Message-Id: <20210528141628.44287-3-vsementsov@virtuozzo.com>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/block-copy.c | 72 +++++++++++++++++++++++++++++++---------------
24
1 file changed, 49 insertions(+), 23 deletions(-)
25
26
diff --git a/block/block-copy.c b/block/block-copy.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/block-copy.c
29
+++ b/block/block-copy.c
30
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyTask {
31
int64_t offset;
32
int64_t bytes;
33
bool zeroes;
34
+ bool copy_range;
35
QLIST_ENTRY(BlockCopyTask) list;
36
CoQueue wait_queue; /* coroutines blocked on this task */
37
} BlockCopyTask;
38
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
39
.call_state = call_state,
40
.offset = offset,
41
.bytes = bytes,
42
+ .copy_range = s->use_copy_range,
43
};
44
qemu_co_queue_init(&task->wait_queue);
45
QLIST_INSERT_HEAD(&s->tasks, task, list);
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
47
*
48
* No sync here: nor bitmap neighter intersecting requests handling, only copy.
49
*
50
+ * @copy_range is an in-out argument: if *copy_range is false, copy_range is not
51
+ * done. If *copy_range is true, copy_range is attempted. If the copy_range
52
+ * attempt fails, the function falls back to the usual read+write and
53
+ * *copy_range is set to false. *copy_range and zeroes must not be true
54
+ * simultaneously.
55
+ *
56
* Returns 0 on success.
57
*/
58
static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
59
int64_t offset, int64_t bytes,
60
- bool zeroes, bool *error_is_read)
61
+ bool zeroes, bool *copy_range,
62
+ bool *error_is_read)
63
{
64
int ret;
65
int64_t nbytes = MIN(offset + bytes, s->len) - offset;
66
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
67
assert(offset + bytes <= s->len ||
68
offset + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size));
69
assert(nbytes < INT_MAX);
70
+ assert(!(*copy_range && zeroes));
71
72
if (zeroes) {
73
ret = bdrv_co_pwrite_zeroes(s->target, offset, nbytes, s->write_flags &
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) {
168
--
169
2.30.2
170
171
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
Document that security reports must use 'null-co,read-zeroes=on'
4
because otherwise the memory is left uninitialized (which is an
5
on-purpose performance feature).
6
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-Id: <20210601162548.2076631-1-philmd@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
docs/devel/secure-coding-practices.rst | 9 +++++++++
13
1 file changed, 9 insertions(+)
14
15
diff --git a/docs/devel/secure-coding-practices.rst b/docs/devel/secure-coding-practices.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/secure-coding-practices.rst
18
+++ b/docs/devel/secure-coding-practices.rst
19
@@ -XXX,XX +XXX,XX @@ structures and only process the local copy. This prevents
20
time-of-check-to-time-of-use (TOCTOU) race conditions that could cause QEMU to
21
crash when a vCPU thread modifies guest RAM while device emulation is
22
processing it.
23
+
24
+Use of null-co block drivers
25
+----------------------------
26
+
27
+The ``null-co`` block driver is designed for performance: its read accesses are
28
+not initialized by default. In case this driver has to be used for security
29
+research, it must be used with the ``read-zeroes=on`` option which fills read
30
+buffers with zeroes. Security issues reported with the default
31
+(``read-zeroes=off``) will be discarded.
32
--
33
2.30.2
34
35
diff view generated by jsdifflib