1
The following changes since commit cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea:
1
The following changes since commit 79b677d658d3d35e1e776826ac4abb28cdce69b8:
2
2
3
Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging (2019-01-31 19:26:09 +0000)
3
Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging (2023-02-21 11:28:31 +0000)
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 7471a649fc3a391dd497297013fb2525ca9821ba:
9
for you to fetch changes up to 0f385a2420d2c3f8ae7ed65fbe2712027664059e:
10
10
11
scsi-disk: Add device_id property (2019-02-01 13:48:11 +0100)
11
block/rbd: Add support for layered encryption (2023-02-23 19:49:35 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- vmdk: Support for blockdev-create
16
- Lock the graph, part 2 (BlockDriver callbacks)
17
- block: Apply auto-read-only for ro-whitelist drivers
17
- virtio-scsi: fix SCSIDevice hot unplug with IOThread
18
- virtio-scsi: Fixes related to attaching/detaching iothreads
18
- rbd: Add support for layered encryption
19
- scsi-disk: Fixed erroneously detected multipath setup with multiple
20
disks created with node-names. Added device_id property.
21
- block: Fix hangs in synchronous APIs with iothreads
22
- block: Fix invalidate_cache error path for parent activation
23
- block-backend, mirror, qcow2, vpc, vdi, qemu-iotests:
24
Minor fixes and code improvements
25
19
26
----------------------------------------------------------------
20
----------------------------------------------------------------
27
Alberto Garcia (7):
21
Emanuele Giuseppe Esposito (5):
28
mirror: Release the dirty bitmap if mirror_start_job() fails
22
block/qed: add missing graph rdlock in qed_need_check_timer_entry
29
mirror: Block the source BlockDriverState in mirror_start_job()
23
block: Mark bdrv_co_flush() and callers GRAPH_RDLOCK
30
qcow2: Assert that refcount block offsets fit in the refcount table
24
block: Mark bdrv_co_pdiscard() and callers GRAPH_RDLOCK
31
virtio-scsi: Move BlockBackend back to the main AioContext on unplug
25
block: Mark bdrv_co_copy_range() GRAPH_RDLOCK
32
scsi-disk: Acquire the AioContext in scsi_*_realize()
26
block: Mark bdrv_co_is_inserted() and callers GRAPH_RDLOCK
33
virtio-scsi: Forbid devices with different iothreads sharing a blockdev
34
qtest.py: Wait for the result of qtest commands
35
27
36
Fam Zheng (3):
28
Kevin Wolf (18):
37
vmdk: Refactor vmdk_create_extent
29
block: Make bdrv_can_set_read_only() static
38
vmdk: Implement .bdrv_co_create callback
30
mirror: Fix access of uninitialised fields during start
39
iotests: Filter cid numbers in VMDK extent info
31
block: Mark bdrv_co_truncate() and callers GRAPH_RDLOCK
32
block: Mark bdrv_co_block_status() and callers GRAPH_RDLOCK
33
block: Mark bdrv_co_ioctl() and callers GRAPH_RDLOCK
34
block: Mark bdrv_co_pwrite_zeroes() and callers GRAPH_RDLOCK
35
block: Mark read/write in block/io.c GRAPH_RDLOCK
36
block: Mark public read/write functions GRAPH_RDLOCK
37
block: Mark bdrv_co_pwrite_sync() and callers GRAPH_RDLOCK
38
block: Mark bdrv_co_do_pwrite_zeroes() GRAPH_RDLOCK
39
block: Mark preadv_snapshot/snapshot_block_status GRAPH_RDLOCK
40
block: Mark bdrv_co_create() and callers GRAPH_RDLOCK
41
block: Mark bdrv_co_io_(un)plug() and callers GRAPH_RDLOCK
42
block: Mark bdrv_co_eject/lock_medium() and callers GRAPH_RDLOCK
43
block: Mark bdrv_(un)register_buf() GRAPH_RDLOCK
44
block: Mark bdrv_co_delete_file() and callers GRAPH_RDLOCK
45
block: Mark bdrv_*_dirty_bitmap() and callers GRAPH_RDLOCK
46
block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK
40
47
41
John Snow (1):
48
Or Ozeri (3):
42
iotests/236: fix transaction kwarg order
49
block/rbd: Remove redundant stack variable passphrase_len
50
block/rbd: Add luks-any encryption opening option
51
block/rbd: Add support for layered encryption
43
52
44
Kevin Wolf (7):
53
Stefan Hajnoczi (3):
45
block: Fix hangs in synchronous APIs with iothreads
54
scsi: protect req->aiocb with AioContext lock
46
iotests: Add VMDK tests for blockdev-create
55
dma-helpers: prevent dma_blk_cb() vs dma_aio_cancel() race
47
vmdk: Reject excess extents in blockdev-create
56
virtio-scsi: reset SCSI devices from main loop thread
48
block: Apply auto-read-only for ro-whitelist drivers
49
block: Fix invalidate_cache error path for parent activation
50
scsi-disk: Don't use empty string as device id
51
scsi-disk: Add device_id property
52
57
53
Markus Armbruster (2):
58
qapi/block-core.json | 27 +++++-
54
block: Replace qdict_put() by qdict_put_obj() where appropriate
59
block/coroutines.h | 2 +-
55
block: Eliminate the S_1KiB, S_2KiB, ... macros
60
block/qcow2.h | 27 ++++--
56
61
block/qed.h | 45 +++++----
57
Max Reitz (2):
62
include/block/block-copy.h | 6 +-
58
iotests: Make 234 stable
63
include/block/block-global-state.h | 14 +--
59
iotests: Filter second BLOCK_JOB_ERROR from 229
64
include/block/block-io.h | 110 ++++++++++++----------
60
65
include/block/block_int-common.h | 173 ++++++++++++++++++----------------
61
Peter Maydell (3):
66
include/block/block_int-io.h | 53 ++++++-----
62
block/vpc: Don't take address of fields in packed structs
67
include/block/dirty-bitmap.h | 12 +--
63
block/vdi: Don't take address of fields in packed structs
68
include/hw/virtio/virtio-scsi.h | 11 ++-
64
uuid: Make qemu_uuid_bswap() take and return a QemuUUID
69
include/sysemu/block-backend-io.h | 7 +-
65
70
block.c | 12 ++-
66
Thomas Huth (1):
71
block/backup.c | 3 +
67
block: Remove blk_attach_dev_legacy() / legacy_dev code
72
block/blkdebug.c | 19 ++--
68
73
block/blklogwrites.c | 35 ++++---
69
yuchenlin (1):
74
block/blkreplay.c | 24 +++--
70
qemu-iotests: add test case for dmg
75
block/blkverify.c | 5 +-
71
76
block/block-backend.c | 39 +++++---
72
qapi/block-core.json | 71 +++
77
block/block-copy.c | 32 ++++---
73
qapi/qapi-schema.json | 16 +-
78
block/bochs.c | 2 +-
74
block/qcow2.h | 10 +-
79
block/commit.c | 5 +-
75
include/qemu/units.h | 73 ---
80
block/copy-before-write.c | 33 ++++---
76
include/qemu/uuid.h | 2 +-
81
block/copy-on-read.c | 44 +++++----
77
include/sysemu/block-backend.h | 5 +-
82
block/create.c | 9 +-
78
block.c | 27 +-
83
block/crypto.c | 16 ++--
79
block/blklogwrites.c | 5 +-
84
block/dirty-bitmap.c | 2 +
80
block/block-backend.c | 59 +--
85
block/file-posix.c | 27 +++---
81
block/io.c | 8 +-
86
block/file-win32.c | 7 +-
82
block/mirror.c | 11 +
87
block/filter-compress.c | 36 ++++---
83
block/nbd-client.c | 1 +
88
block/io.c | 108 +++++++++++++--------
84
block/nvme.c | 1 +
89
block/iscsi.c | 28 +++---
85
block/qcow2-refcount.c | 3 +
90
block/mirror.c | 59 ++++++++----
86
block/qcow2.c | 1 +
91
block/parallels.c | 33 +++----
87
block/qed.c | 1 +
92
block/preallocate.c | 38 ++++----
88
block/vdi.c | 57 ++-
93
block/qcow.c | 46 +++++----
89
block/vmdk.c | 532 +++++++++++++++------
94
block/qcow2-cluster.c | 17 ++--
90
block/vpc.c | 4 +-
95
block/qcow2.c | 136 +++++++++++++++------------
91
hw/acpi/vmgenid.c | 6 +-
96
block/qed-check.c | 3 +-
92
hw/scsi/scsi-disk.c | 59 ++-
97
block/qed-table.c | 10 +-
93
hw/scsi/virtio-scsi.c | 13 +
98
block/qed.c | 101 ++++++++++----------
94
tests/test-block-iothread.c | 372 ++++++++++++++
99
block/quorum.c | 62 +++++++-----
95
tests/vmgenid-test.c | 2 +-
100
block/raw-format.c | 76 ++++++++-------
96
util/uuid.c | 10 +-
101
block/rbd.c | 188 ++++++++++++++++++++++++++++++++++---
97
scripts/qtest.py | 6 +
102
block/replication.c | 18 ++--
98
tests/Makefile.include | 2 +
103
block/snapshot-access.c | 8 +-
99
tests/qemu-iotests/141.out | 4 +-
104
block/stream.c | 40 ++++----
100
tests/qemu-iotests/229 | 6 +-
105
block/throttle.c | 36 ++++---
101
tests/qemu-iotests/229.out | 1 -
106
block/vdi.c | 11 +--
102
tests/qemu-iotests/234 | 56 ++-
107
block/vhdx.c | 18 ++--
103
tests/qemu-iotests/234.out | 10 +-
108
block/vmdk.c | 132 ++++++++++++--------------
104
tests/qemu-iotests/236.out | 56 +--
109
block/vpc.c | 11 +--
105
tests/qemu-iotests/237 | 237 +++++++++
110
hw/scsi/scsi-disk.c | 23 +++--
106
tests/qemu-iotests/237.out | 348 ++++++++++++++
111
hw/scsi/scsi-generic.c | 11 ++-
107
tests/qemu-iotests/239 | 53 ++
112
hw/scsi/virtio-scsi.c | 169 ++++++++++++++++++++++++++-------
108
tests/qemu-iotests/239.out | 4 +
113
qemu-img.c | 8 +-
109
tests/qemu-iotests/240 | 129 +++++
114
softmmu/dma-helpers.c | 12 ++-
110
tests/qemu-iotests/240.out | 54 +++
115
tests/unit/test-bdrv-drain.c | 20 ++--
111
tests/qemu-iotests/check | 7 +
116
tests/unit/test-block-iothread.c | 3 +-
112
tests/qemu-iotests/common.filter | 1 +
117
59 files changed, 1355 insertions(+), 907 deletions(-)
113
tests/qemu-iotests/group | 3 +
114
tests/qemu-iotests/iotests.py | 22 +-
115
.../qemu-iotests/sample_images/simple-dmg.dmg.bz2 | Bin 0 -> 3479 bytes
116
44 files changed, 1931 insertions(+), 417 deletions(-)
117
create mode 100644 tests/test-block-iothread.c
118
create mode 100755 tests/qemu-iotests/237
119
create mode 100644 tests/qemu-iotests/237.out
120
create mode 100755 tests/qemu-iotests/239
121
create mode 100644 tests/qemu-iotests/239.out
122
create mode 100755 tests/qemu-iotests/240
123
create mode 100644 tests/qemu-iotests/240.out
124
create mode 100644 tests/qemu-iotests/sample_images/simple-dmg.dmg.bz2
125
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
It is never called outside of block.c.
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Message-Id: <20230203152202.49054-2-kwolf@redhat.com>
5
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
8
---
6
tests/qemu-iotests/common.filter | 1 +
9
include/block/block-io.h | 2 --
7
tests/qemu-iotests/iotests.py | 1 +
10
block.c | 4 ++--
8
2 files changed, 2 insertions(+)
11
2 files changed, 2 insertions(+), 4 deletions(-)
9
12
10
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
13
diff --git a/include/block/block-io.h b/include/block/block-io.h
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/qemu-iotests/common.filter
15
--- a/include/block/block-io.h
13
+++ b/tests/qemu-iotests/common.filter
16
+++ b/include/block/block-io.h
14
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
17
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
15
-e "/table_size: [0-9]\\+/d" \
18
int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
16
-e "/compat: '[^']*'/d" \
19
int64_t bytes);
17
-e "/compat6: \\(on\\|off\\)/d" \
20
18
+ -e "s/cid: [0-9]\+/cid: XXXXXXXXXX/" \
21
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
19
-e "/static: \\(on\\|off\\)/d" \
22
- bool ignore_allow_rdw, Error **errp);
20
-e "/zeroed_grain: \\(on\\|off\\)/d" \
23
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
21
-e "/subformat: '[^']*'/d" \
24
Error **errp);
22
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
25
bool bdrv_is_read_only(BlockDriverState *bs);
26
diff --git a/block.c b/block.c
23
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qemu-iotests/iotests.py
28
--- a/block.c
25
+++ b/tests/qemu-iotests/iotests.py
29
+++ b/block.c
26
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
30
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
27
.replace(imgfmt, 'IMGFMT')
31
return !(bs->open_flags & BDRV_O_RDWR);
28
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
32
}
29
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
33
30
+ line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
34
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
31
lines.append(line)
35
- bool ignore_allow_rdw, Error **errp)
32
return '\n'.join(lines)
36
+static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
37
+ bool ignore_allow_rdw, Error **errp)
38
{
39
IO_CODE();
33
40
34
--
41
--
35
2.20.1
42
2.39.2
36
37
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
bdrv_mirror_top_pwritev() accesses the job object when active mirroring
2
is enabled. It disables this code during early initialisation while
3
s->job isn't set yet.
2
4
3
The mirror_start_job() function used for the commit-active job blocks
5
However, s->job is still set way too early when the job object isn't
4
the source, target and all intermediate nodes for the duration of the
6
fully initialised. For example, &s->ops_in_flight isn't initialised yet
5
job.
7
and the in_flight bitmap doesn't exist yet. This causes crashes when a
8
write request comes in too early.
6
9
7
target <- intermediate <- source
10
Move the assignment of s->job to when the mirror job is actually fully
11
initialised to make sure that the mirror_top driver doesn't access it
12
too early.
8
13
9
Since 4ef85a9c2339 this function creates a dummy mirror_top_bs that
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
goes on top of the source node, and it is this dummy node that gets
15
Message-Id: <20230203152202.49054-3-kwolf@redhat.com>
11
blocked instead. The source node is never blocked or added to the
16
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
job's list of nodes.
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
14
target <- intermediate <- source <- mirror_top
15
16
At the moment I don't think it is possible to exploit this problem
17
because any additional job on 'source' would either be forbidden for
18
other reasons or it would need to involve an additional node that is
19
blocked, causing an error.
20
21
This can be seen in the error messages, however, because they never
22
refer to the source node being blocked:
23
24
$ qemu-img create -f qcow2 hd0.qcow2 1M
25
$ qemu-img create -f qcow2 -b hd0.qcow2 hd1.qcow2
26
$ qemu-io -c 'write 0 1M' hd0.qcow2
27
$ $QEMU -drive if=none,file=hd1.qcow2,node-name=hd1
28
{ "execute": "qmp_capabilities" }
29
{ "execute": "block-commit", "arguments": {"device": "hd1", "speed": 256}}
30
{ "execute": "block-stream", "arguments": {"device": "hd1"}}
31
{ "error": {"class": "GenericError",
32
"desc": "Node 'hd0' is busy: block device is in use by block job: commit"}}
33
34
After this patch the error message refers to 'hd1', as it should.
35
36
The expected output of iotest 141 also needs to be updated for the
37
same reason.
38
39
Signed-off-by: Alberto Garcia <berto@igalia.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
41
---
19
---
42
block/mirror.c | 8 ++++++++
20
block/mirror.c | 8 +++++++-
43
tests/qemu-iotests/141.out | 4 ++--
21
1 file changed, 7 insertions(+), 1 deletion(-)
44
2 files changed, 10 insertions(+), 2 deletions(-)
45
22
46
diff --git a/block/mirror.c b/block/mirror.c
23
diff --git a/block/mirror.c b/block/mirror.c
47
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
48
--- a/block/mirror.c
25
--- a/block/mirror.c
49
+++ b/block/mirror.c
26
+++ b/block/mirror.c
50
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
28
{
29
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
30
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
31
+ MirrorBDSOpaque *mirror_top_opaque = s->mirror_top_bs->opaque;
32
BlockDriverState *target_bs = blk_bs(s->target);
33
bool need_drain = true;
34
BlockDeviceIoStatus iostatus;
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
36
}
37
}
38
39
+ /*
40
+ * Only now the job is fully initialised and mirror_top_bs should start
41
+ * accessing it.
42
+ */
43
+ mirror_top_opaque->job = s;
44
+
45
assert(!s->dbi);
46
s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap);
47
for (;;) {
48
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
49
if (!s) {
51
goto fail;
50
goto fail;
52
}
51
}
53
52
- bs_opaque->job = s;
54
+ ret = block_job_add_bdrv(&s->common, "source", bs, 0,
53
55
+ BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE |
54
/* The block job now has a reference to this node */
56
+ BLK_PERM_CONSISTENT_READ,
55
bdrv_unref(mirror_top_bs);
57
+ errp);
58
+ if (ret < 0) {
59
+ goto fail;
60
+ }
61
+
62
/* Required permissions are already taken with blk_new() */
63
block_job_add_bdrv(&s->common, "target", target, 0, BLK_PERM_ALL,
64
&error_abort);
65
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
66
index XXXXXXX..XXXXXXX 100644
67
--- a/tests/qemu-iotests/141.out
68
+++ b/tests/qemu-iotests/141.out
69
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
70
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
71
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
72
{"return": {}}
73
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
74
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
75
{"return": {}}
76
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
77
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
78
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
79
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
80
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
81
{"return": {}}
82
-{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
83
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
84
{"return": {}}
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
86
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
87
--
56
--
88
2.20.1
57
2.39.2
89
90
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_truncate() need to hold a reader lock for the graph.
1
3
4
For some places, we know that they will hold the lock, but we don't have
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-4-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
include/block/block-io.h | 6 +++---
15
include/block/block_int-common.h | 7 ++++---
16
block/block-backend.c | 1 +
17
block/crypto.c | 2 +-
18
block/io.c | 1 +
19
block/parallels.c | 14 ++++++++------
20
block/preallocate.c | 2 +-
21
block/qcow.c | 17 ++++++++++++-----
22
block/qcow2.c | 14 ++++++++------
23
block/raw-format.c | 6 +++---
24
block/vmdk.c | 2 ++
25
11 files changed, 44 insertions(+), 28 deletions(-)
26
27
diff --git a/include/block/block-io.h b/include/block/block-io.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block-io.h
30
+++ b/include/block/block-io.h
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
32
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
33
int64_t bytes, BdrvRequestFlags flags);
34
35
-int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
36
- PreallocMode prealloc, BdrvRequestFlags flags,
37
- Error **errp);
38
+int coroutine_fn GRAPH_RDLOCK
39
+bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
43
int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
* If @exact is true and this function fails but would succeed
50
* with @exact = false, it should return -ENOTSUP.
51
*/
52
- int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
53
- bool exact, PreallocMode prealloc,
54
- BdrvRequestFlags flags, Error **errp);
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_truncate)(
56
+ BlockDriverState *bs, int64_t offset, bool exact,
57
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
58
+
59
int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
60
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
61
BlockDriverState *bs);
62
diff --git a/block/block-backend.c b/block/block-backend.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/block-backend.c
65
+++ b/block/block-backend.c
66
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
67
Error **errp)
68
{
69
IO_OR_GS_CODE();
70
+ GRAPH_RDLOCK_GUARD();
71
if (!blk_is_available(blk)) {
72
error_setg(errp, "No medium inserted");
73
return -ENOMEDIUM;
74
diff --git a/block/crypto.c b/block/crypto.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/crypto.c
77
+++ b/block/crypto.c
78
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
79
return ret;
80
}
81
82
-static int coroutine_fn
83
+static int coroutine_fn GRAPH_RDLOCK
84
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
85
PreallocMode prealloc, BdrvRequestFlags flags,
86
Error **errp)
87
diff --git a/block/io.c b/block/io.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/io.c
90
+++ b/block/io.c
91
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
92
int64_t old_size, new_bytes;
93
int ret;
94
IO_CODE();
95
+ assert_bdrv_graph_readable();
96
97
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
98
if (!drv) {
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
104
return start_off;
105
}
106
107
-static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
108
- int64_t sector_num,
109
- int nb_sectors, int *pnum)
110
+static int64_t coroutine_fn GRAPH_RDLOCK
111
+allocate_clusters(BlockDriverState *bs, int64_t sector_num,
112
+ int nb_sectors, int *pnum)
113
{
114
int ret = 0;
115
BDRVParallelsState *s = bs->opaque;
116
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
117
QEMUIOVector hd_qiov;
118
int ret = 0;
119
120
+ assume_graph_lock(); /* FIXME */
121
+
122
qemu_iovec_init(&hd_qiov, qiov->niov);
123
124
while (nb_sectors > 0) {
125
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
126
}
127
128
129
-static int coroutine_fn parallels_co_check(BlockDriverState *bs,
130
- BdrvCheckResult *res,
131
- BdrvCheckMode fix)
132
+static int coroutine_fn GRAPH_RDLOCK
133
+parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
134
+ BdrvCheckMode fix)
135
{
136
BDRVParallelsState *s = bs->opaque;
137
int64_t size, prev_off, high_off;
138
diff --git a/block/preallocate.c b/block/preallocate.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/preallocate.c
141
+++ b/block/preallocate.c
142
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
143
flags);
144
}
145
146
-static int coroutine_fn
147
+static int coroutine_fn GRAPH_RDLOCK
148
preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
149
bool exact, PreallocMode prealloc,
150
BdrvRequestFlags flags, Error **errp)
151
diff --git a/block/qcow.c b/block/qcow.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/qcow.c
154
+++ b/block/qcow.c
155
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
156
* return 0 if not allocated, 1 if *result is assigned, and negative
157
* errno on failure.
158
*/
159
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
160
- uint64_t offset, int allocate,
161
- int compressed_size,
162
- int n_start, int n_end,
163
- uint64_t *result)
164
+static int coroutine_fn GRAPH_RDLOCK
165
+get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
166
+ int compressed_size, int n_start, int n_end,
167
+ uint64_t *result)
168
{
169
BDRVQcowState *s = bs->opaque;
170
int min_index, i, j, l1_index, l2_index, ret;
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
172
int64_t n;
173
uint64_t cluster_offset;
174
175
+ assume_graph_lock(); /* FIXME */
176
+
177
qemu_co_mutex_lock(&s->lock);
178
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
179
qemu_co_mutex_unlock(&s->lock);
180
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
181
uint8_t *buf;
182
void *orig_buf;
183
184
+ assume_graph_lock(); /* FIXME */
185
+
186
if (qiov->niov > 1) {
187
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
188
if (buf == NULL) {
189
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
190
uint8_t *buf;
191
void *orig_buf;
192
193
+ assume_graph_lock(); /* FIXME */
194
+
195
s->cluster_cache_offset = -1; /* disable compressed cache */
196
197
/* We must always copy the iov when encrypting, so we
198
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
199
uint8_t *buf, *out_buf;
200
uint64_t cluster_offset;
201
202
+ assume_graph_lock(); /* FIXME */
203
+
204
buf = qemu_blockalign(bs, s->cluster_size);
205
if (bytes != s->cluster_size) {
206
if (bytes > s->cluster_size ||
207
diff --git a/block/qcow2.c b/block/qcow2.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/block/qcow2.c
210
+++ b/block/qcow2.c
211
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
212
*
213
* Returns: 0 on success, -errno on failure.
214
*/
215
-static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
216
- uint64_t new_length, PreallocMode mode,
217
- Error **errp)
218
+static int coroutine_fn GRAPH_RDLOCK
219
+preallocate_co(BlockDriverState *bs, uint64_t offset, uint64_t new_length,
220
+ PreallocMode mode, Error **errp)
221
{
222
BDRVQcow2State *s = bs->opaque;
223
uint64_t bytes;
224
@@ -XXX,XX +XXX,XX @@ fail:
225
return ret;
226
}
227
228
-static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
229
- bool exact, PreallocMode prealloc,
230
- BdrvRequestFlags flags, Error **errp)
231
+static int coroutine_fn GRAPH_RDLOCK
232
+qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
233
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
234
{
235
BDRVQcow2State *s = bs->opaque;
236
uint64_t old_length;
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
AioTaskPool *aio = NULL;
239
int ret = 0;
240
241
+ assume_graph_lock(); /* FIXME */
242
+
243
if (has_data_file(bs)) {
244
return -ENOTSUP;
245
}
246
diff --git a/block/raw-format.c b/block/raw-format.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/raw-format.c
249
+++ b/block/raw-format.c
250
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
251
}
252
}
253
254
-static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
255
- bool exact, PreallocMode prealloc,
256
- BdrvRequestFlags flags, Error **errp)
257
+static int coroutine_fn GRAPH_RDLOCK
258
+raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
259
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
260
{
261
BDRVRawState *s = bs->opaque;
262
263
diff --git a/block/vmdk.c b/block/vmdk.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/block/vmdk.c
266
+++ b/block/vmdk.c
267
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
268
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
269
QEMUIOVector *qiov)
270
{
271
+ assume_graph_lock(); /* FIXME */
272
+
273
if (bytes == 0) {
274
/* The caller will write bytes 0 to signal EOF.
275
* When receive it, we align EOF to a sector boundary. */
276
--
277
2.39.2
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_block_status() need to hold a reader lock for the graph.
2
3
3
At the moment I don't see how to make this function fail after the
4
For some places, we know that they will hold the lock, but we don't have
4
dirty bitmap has been created, but if that was possible then we would
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
hit the assert(QLIST_EMPTY(&bs->dirty_bitmaps)) in bdrv_close().
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
6
8
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20230203152202.49054-5-kwolf@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
14
---
10
block/mirror.c | 3 +++
15
block/coroutines.h | 2 +-
11
1 file changed, 3 insertions(+)
16
include/block/block-copy.h | 6 +++---
17
include/block/block-io.h | 22 +++++++++++-----------
18
include/block/block_int-common.h | 3 ++-
19
block/backup.c | 3 +++
20
block/block-backend.c | 2 ++
21
block/block-copy.c | 19 +++++++++++--------
22
block/io.c | 13 ++++++++-----
23
block/mirror.c | 14 +++++++++-----
24
block/qcow.c | 11 ++++-------
25
block/quorum.c | 9 ++++-----
26
block/stream.c | 32 ++++++++++++++++++--------------
27
qemu-img.c | 4 +++-
28
tests/unit/test-block-iothread.c | 3 ++-
29
14 files changed, 81 insertions(+), 62 deletions(-)
12
30
31
diff --git a/block/coroutines.h b/block/coroutines.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/coroutines.h
34
+++ b/block/coroutines.h
35
@@ -XXX,XX +XXX,XX @@ bdrv_co_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
36
int coroutine_fn GRAPH_RDLOCK
37
bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp);
38
39
-int coroutine_fn
40
+int coroutine_fn GRAPH_RDLOCK
41
bdrv_co_common_block_status_above(BlockDriverState *bs,
42
BlockDriverState *base,
43
bool include_base,
44
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block-copy.h
47
+++ b/include/block/block-copy.h
48
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
49
void block_copy_state_free(BlockCopyState *s);
50
51
void block_copy_reset(BlockCopyState *s, int64_t offset, int64_t bytes);
52
-int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
53
- int64_t offset,
54
- int64_t *count);
55
+
56
+int64_t coroutine_fn GRAPH_RDLOCK
57
+block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count);
58
59
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
60
bool ignore_ratelimit, uint64_t timeout_ns,
61
diff --git a/include/block/block-io.h b/include/block/block-io.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/block/block-io.h
64
+++ b/include/block/block-io.h
65
@@ -XXX,XX +XXX,XX @@ int bdrv_block_status(BlockDriverState *bs, int64_t offset,
66
int64_t bytes, int64_t *pnum, int64_t *map,
67
BlockDriverState **file);
68
69
-int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
70
- BlockDriverState *base,
71
- int64_t offset, int64_t bytes,
72
- int64_t *pnum, int64_t *map,
73
- BlockDriverState **file);
74
+int coroutine_fn GRAPH_RDLOCK
75
+bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base,
76
+ int64_t offset, int64_t bytes, int64_t *pnum,
77
+ int64_t *map, BlockDriverState **file);
78
int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
79
int64_t offset, int64_t bytes, int64_t *pnum,
80
int64_t *map, BlockDriverState **file);
81
82
-int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
83
- int64_t bytes, int64_t *pnum);
84
+int coroutine_fn GRAPH_RDLOCK
85
+bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
86
+ int64_t *pnum);
87
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
88
int64_t *pnum);
89
90
-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
91
- BlockDriverState *base,
92
- bool include_base, int64_t offset,
93
- int64_t bytes, int64_t *pnum);
94
+int coroutine_fn GRAPH_RDLOCK
95
+bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
96
+ bool include_base, int64_t offset, int64_t bytes,
97
+ int64_t *pnum);
98
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
99
bool include_base, int64_t offset, int64_t bytes,
100
int64_t *pnum);
101
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
102
index XXXXXXX..XXXXXXX 100644
103
--- a/include/block/block_int-common.h
104
+++ b/include/block/block_int-common.h
105
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
106
* *pnum value for the block-status cache on protocol nodes, prior
107
* to clamping *pnum for return to its caller.
108
*/
109
- int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
110
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)(
111
+ BlockDriverState *bs,
112
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
113
int64_t *map, BlockDriverState **file);
114
115
diff --git a/block/backup.c b/block/backup.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/block/backup.c
118
+++ b/block/backup.c
119
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
120
return -ECANCELED;
121
}
122
123
+ /* rdlock protects the subsequent call to bdrv_is_allocated() */
124
+ bdrv_graph_co_rdlock();
125
ret = block_copy_reset_unallocated(s->bcs, offset, &count);
126
+ bdrv_graph_co_rdunlock();
127
if (ret < 0) {
128
return ret;
129
}
130
diff --git a/block/block-backend.c b/block/block-backend.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/block-backend.c
133
+++ b/block/block-backend.c
134
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
135
BlockDriverState **file)
136
{
137
IO_CODE();
138
+ GRAPH_RDLOCK_GUARD();
139
return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
140
map, file);
141
}
142
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
143
int64_t bytes, int64_t *pnum)
144
{
145
IO_CODE();
146
+ GRAPH_RDLOCK_GUARD();
147
return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
148
bytes, pnum);
149
}
150
diff --git a/block/block-copy.c b/block/block-copy.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block/block-copy.c
153
+++ b/block/block-copy.c
154
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
155
return ret;
156
}
157
158
-static coroutine_fn int block_copy_block_status(BlockCopyState *s,
159
- int64_t offset,
160
- int64_t bytes, int64_t *pnum)
161
+static coroutine_fn GRAPH_RDLOCK
162
+int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes,
163
+ int64_t *pnum)
164
{
165
int64_t num;
166
BlockDriverState *base;
167
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_block_status(BlockCopyState *s,
168
* Check if the cluster starting at offset is allocated or not.
169
* return via pnum the number of contiguous clusters sharing this allocation.
170
*/
171
-static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
172
- int64_t offset,
173
- int64_t *pnum)
174
+static int coroutine_fn GRAPH_RDLOCK
175
+block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
176
+ int64_t *pnum)
177
{
178
BlockDriverState *bs = s->source->bs;
179
int64_t count, total_count = 0;
180
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
181
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
182
183
while (true) {
184
+ /* protected in backup_run() */
185
ret = bdrv_co_is_allocated(bs, offset, bytes, &count);
186
if (ret < 0) {
187
return ret;
188
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
189
* Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
190
* clusters found and -errno on failure.
191
*/
192
-static int coroutine_fn
193
+static int coroutine_fn GRAPH_RDLOCK
194
block_copy_dirty_clusters(BlockCopyCallState *call_state)
195
{
196
BlockCopyState *s = call_state->s;
197
@@ -XXX,XX +XXX,XX @@ void block_copy_kick(BlockCopyCallState *call_state)
198
* it means that some I/O operation failed in context of _this_ block_copy call,
199
* not some parallel operation.
200
*/
201
-static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
202
+static int coroutine_fn GRAPH_RDLOCK
203
+block_copy_common(BlockCopyCallState *call_state)
204
{
205
int ret;
206
BlockCopyState *s = call_state->s;
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
208
209
static void coroutine_fn block_copy_async_co_entry(void *opaque)
210
{
211
+ GRAPH_RDLOCK_GUARD();
212
block_copy_common(opaque);
213
}
214
215
diff --git a/block/io.c b/block/io.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/io.c
218
+++ b/block/io.c
219
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
220
* BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are
221
* set to the host mapping and BDS corresponding to the guest offset.
222
*/
223
-static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
224
- bool want_zero,
225
- int64_t offset, int64_t bytes,
226
- int64_t *pnum, int64_t *map,
227
- BlockDriverState **file)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
230
+ int64_t offset, int64_t bytes,
231
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
232
{
233
int64_t total_size;
234
int64_t n; /* bytes */
235
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
236
bool has_filtered_child;
237
238
assert(pnum);
239
+ assert_bdrv_graph_readable();
240
*pnum = 0;
241
total_size = bdrv_getlength(bs);
242
if (total_size < 0) {
243
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
244
IO_CODE();
245
246
assert(!include_base || base); /* Can't include NULL base */
247
+ assert_bdrv_graph_readable();
248
249
if (!depth) {
250
depth = &dummy;
251
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
252
int64_t pnum = bytes;
253
IO_CODE();
254
255
+ assume_graph_lock(); /* FIXME */
256
+
257
if (!bytes) {
258
return 1;
259
}
13
diff --git a/block/mirror.c b/block/mirror.c
260
diff --git a/block/mirror.c b/block/mirror.c
14
index XXXXXXX..XXXXXXX 100644
261
index XXXXXXX..XXXXXXX 100644
15
--- a/block/mirror.c
262
--- a/block/mirror.c
16
+++ b/block/mirror.c
263
+++ b/block/mirror.c
17
@@ -XXX,XX +XXX,XX @@ fail:
264
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
18
g_free(s->replaces);
265
MirrorMethod mirror_method = MIRROR_METHOD_COPY;
19
blk_unref(s->target);
266
20
bs_opaque->job = NULL;
267
assert(!(offset % s->granularity));
21
+ if (s->dirty_bitmap) {
268
- ret = bdrv_block_status_above(source, NULL, offset,
22
+ bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);
269
- nb_chunks * s->granularity,
270
- &io_bytes, NULL, NULL);
271
+ WITH_GRAPH_RDLOCK_GUARD() {
272
+ ret = bdrv_block_status_above(source, NULL, offset,
273
+ nb_chunks * s->granularity,
274
+ &io_bytes, NULL, NULL);
23
+ }
275
+ }
24
job_early_fail(&s->common.job);
276
if (ret < 0) {
25
}
277
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
26
278
} else if (ret & BDRV_BLOCK_DATA) {
279
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
280
return 0;
281
}
282
283
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes,
284
- &count);
285
+ WITH_GRAPH_RDLOCK_GUARD() {
286
+ ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
287
+ bytes, &count);
288
+ }
289
if (ret < 0) {
290
return ret;
291
}
292
diff --git a/block/qcow.c b/block/qcow.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/block/qcow.c
295
+++ b/block/qcow.c
296
@@ -XXX,XX +XXX,XX @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
297
return 1;
298
}
299
300
-static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
301
- bool want_zero,
302
- int64_t offset, int64_t bytes,
303
- int64_t *pnum, int64_t *map,
304
- BlockDriverState **file)
305
+static int coroutine_fn GRAPH_RDLOCK
306
+qcow_co_block_status(BlockDriverState *bs, bool want_zero,
307
+ int64_t offset, int64_t bytes, int64_t *pnum,
308
+ int64_t *map, BlockDriverState **file)
309
{
310
BDRVQcowState *s = bs->opaque;
311
int index_in_cluster, ret;
312
int64_t n;
313
uint64_t cluster_offset;
314
315
- assume_graph_lock(); /* FIXME */
316
-
317
qemu_co_mutex_lock(&s->lock);
318
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
319
qemu_co_mutex_unlock(&s->lock);
320
diff --git a/block/quorum.c b/block/quorum.c
321
index XXXXXXX..XXXXXXX 100644
322
--- a/block/quorum.c
323
+++ b/block/quorum.c
324
@@ -XXX,XX +XXX,XX @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
325
* return BDRV_BLOCK_ZERO if *all* children agree that a certain
326
* region contains zeroes, and BDRV_BLOCK_DATA otherwise.
327
*/
328
-static int coroutine_fn quorum_co_block_status(BlockDriverState *bs,
329
- bool want_zero,
330
- int64_t offset, int64_t count,
331
- int64_t *pnum, int64_t *map,
332
- BlockDriverState **file)
333
+static int coroutine_fn GRAPH_RDLOCK
334
+quorum_co_block_status(BlockDriverState *bs, bool want_zero,
335
+ int64_t offset, int64_t count,
336
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
337
{
338
BDRVQuorumState *s = bs->opaque;
339
int i, ret;
340
diff --git a/block/stream.c b/block/stream.c
341
index XXXXXXX..XXXXXXX 100644
342
--- a/block/stream.c
343
+++ b/block/stream.c
344
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
345
346
copy = false;
347
348
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
349
- if (ret == 1) {
350
- /* Allocated in the top, no need to copy. */
351
- } else if (ret >= 0) {
352
- /* Copy if allocated in the intermediate images. Limit to the
353
- * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */
354
- ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
355
- s->base_overlay, true,
356
- offset, n, &n);
357
- /* Finish early if end of backing file has been reached */
358
- if (ret == 0 && n == 0) {
359
- n = len - offset;
360
+ WITH_GRAPH_RDLOCK_GUARD() {
361
+ ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
362
+ if (ret == 1) {
363
+ /* Allocated in the top, no need to copy. */
364
+ } else if (ret >= 0) {
365
+ /*
366
+ * Copy if allocated in the intermediate images. Limit to the
367
+ * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).
368
+ */
369
+ ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
370
+ s->base_overlay, true,
371
+ offset, n, &n);
372
+ /* Finish early if end of backing file has been reached */
373
+ if (ret == 0 && n == 0) {
374
+ n = len - offset;
375
+ }
376
+
377
+ copy = (ret > 0);
378
}
379
-
380
- copy = (ret > 0);
381
}
382
trace_stream_one_iteration(s, offset, n, ret);
383
if (copy) {
384
diff --git a/qemu-img.c b/qemu-img.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/qemu-img.c
387
+++ b/qemu-img.c
388
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
389
qemu_co_mutex_unlock(&s->lock);
390
break;
391
}
392
- n = convert_iteration_sectors(s, s->sector_num);
393
+ WITH_GRAPH_RDLOCK_GUARD() {
394
+ n = convert_iteration_sectors(s, s->sector_num);
395
+ }
396
if (n < 0) {
397
qemu_co_mutex_unlock(&s->lock);
398
s->ret = n;
399
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/tests/unit/test-block-iothread.c
402
+++ b/tests/unit/test-block-iothread.c
403
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_truncate(BlockBackend *blk)
404
g_assert_cmpint(ret, ==, -EINVAL);
405
}
406
407
-static void test_sync_op_block_status(BdrvChild *c)
408
+/* Disable TSA to make bdrv_test.bdrv_co_block_status writable */
409
+static void TSA_NO_TSA test_sync_op_block_status(BdrvChild *c)
410
{
411
int ret;
412
int64_t n;
27
--
413
--
28
2.20.1
414
2.39.2
29
30
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_ioctl() need to hold a reader lock for the graph.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20230203152202.49054-6-kwolf@redhat.com>
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/block/block-io.h | 3 ++-
10
include/block/block_int-common.h | 9 +++++----
11
block/block-backend.c | 1 +
12
block/io.c | 1 +
13
block/raw-format.c | 4 ++--
14
5 files changed, 11 insertions(+), 7 deletions(-)
15
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
21
void bdrv_aio_cancel_async(BlockAIOCB *acb);
22
23
/* sg packet commands */
24
-int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
25
+int coroutine_fn GRAPH_RDLOCK
26
+bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
27
28
/* Ensure contents are flushed to disk. */
29
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
30
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block_int-common.h
33
+++ b/include/block/block_int-common.h
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
35
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
36
37
/* to control generic scsi devices */
38
- BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
39
- unsigned long int req, void *buf,
40
+ BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
41
+ BlockDriverState *bs, unsigned long int req, void *buf,
42
BlockCompletionFunc *cb, void *opaque);
43
- int coroutine_fn (*bdrv_co_ioctl)(BlockDriverState *bs,
44
- unsigned long int req, void *buf);
45
+
46
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_ioctl)(
47
+ BlockDriverState *bs, unsigned long int req, void *buf);
48
49
/*
50
* Returns 0 for completed check, -errno for internal errors.
51
diff --git a/block/block-backend.c b/block/block-backend.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/block-backend.c
54
+++ b/block/block-backend.c
55
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
56
IO_CODE();
57
58
blk_wait_while_drained(blk);
59
+ GRAPH_RDLOCK_GUARD();
60
61
if (!blk_is_available(blk)) {
62
return -ENOMEDIUM;
63
diff --git a/block/io.c b/block/io.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/io.c
66
+++ b/block/io.c
67
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
68
};
69
BlockAIOCB *acb;
70
IO_CODE();
71
+ assert_bdrv_graph_readable();
72
73
bdrv_inc_in_flight(bs);
74
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
75
diff --git a/block/raw-format.c b/block/raw-format.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/raw-format.c
78
+++ b/block/raw-format.c
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
80
bdrv_co_lock_medium(bs->file->bs, locked);
81
}
82
83
-static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
84
- unsigned long int req, void *buf)
85
+static int coroutine_fn GRAPH_RDLOCK
86
+raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
87
{
88
BDRVRawState *s = bs->opaque;
89
if (s->offset || s->has_size) {
90
--
91
2.39.2
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
This function is called in two different places:
4
it might not be actually aligned enough for that pointer type (and
4
- timer callback, which does not take the graph rdlock.
5
thus cause a crash on dereference on some host architectures). Newer
5
- bdrv_qed_drain_begin(), which is .bdrv_drain_begin()
6
versions of clang warn about this. Avoid the bug by generating the
6
callback documented as function that does not take the lock.
7
UUID into a local variable which is definitely safely aligned and
8
then copying it into place.
9
7
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Since it calls recursive functions that traverse the
9
graph, we need to protect them with the graph rdlock.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-7-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
16
---
13
block/vpc.c | 4 +++-
17
block/qed.c | 4 +++-
14
1 file changed, 3 insertions(+), 1 deletion(-)
18
1 file changed, 3 insertions(+), 1 deletion(-)
15
19
16
diff --git a/block/vpc.c b/block/vpc.c
20
diff --git a/block/qed.c b/block/qed.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vpc.c
22
--- a/block/qed.c
19
+++ b/block/vpc.c
23
+++ b/block/qed.c
20
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
21
int64_t total_size;
25
qemu_co_mutex_unlock(&s->table_lock);
22
int disk_type;
26
}
23
int ret = -EIO;
27
24
+ QemuUUID uuid;
28
-static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
25
29
+static void coroutine_fn GRAPH_RDLOCK qed_need_check_timer(BDRVQEDState *s)
26
assert(opts->driver == BLOCKDEV_DRIVER_VPC);
30
{
27
vpc_opts = &opts->u.vpc;
31
int ret;
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
32
29
33
trace_qed_need_check_timer_cb(s);
30
footer->type = cpu_to_be32(disk_type);
34
+ assert_bdrv_graph_readable();
31
35
32
- qemu_uuid_generate(&footer->uuid);
36
if (!qed_plug_allocating_write_reqs(s)) {
33
+ qemu_uuid_generate(&uuid);
37
return;
34
+ footer->uuid = uuid;
38
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
35
39
static void coroutine_fn qed_need_check_timer_entry(void *opaque)
36
footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));
40
{
37
41
BDRVQEDState *s = opaque;
42
+ GRAPH_RDLOCK_GUARD();
43
44
qed_need_check_timer(opaque);
45
bdrv_dec_in_flight(s->bs);
38
--
46
--
39
2.20.1
47
2.39.2
40
41
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The extracted vmdk_init_extent takes a BlockBackend object and
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
initializes the format metadata. It is the common part between "qemu-img
4
bdrv_co_flush() need to hold a reader lock for the graph.
5
create" and "blockdev-create".
6
5
7
Add a "BlockBackend *pbb" parameter to vmdk_create_extent, to return the
6
For some places, we know that they will hold the lock, but we don't have
8
opened BB to the caller in the next patch.
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
9
10
10
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Markus Armbruster <armbru@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-8-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
16
---
14
block/vmdk.c | 69 ++++++++++++++++++++++++++++++++--------------------
17
block/qcow2.h | 5 +++-
15
1 file changed, 43 insertions(+), 26 deletions(-)
18
block/qed.h | 29 +++++++++++++--------
19
include/block/block-io.h | 2 +-
20
include/block/block_int-common.h | 12 +++++----
21
block/blkdebug.c | 2 +-
22
block/blklogwrites.c | 21 ++++++++++-----
23
block/blkreplay.c | 2 +-
24
block/blkverify.c | 2 +-
25
block/block-backend.c | 3 ++-
26
block/copy-before-write.c | 2 +-
27
block/file-posix.c | 4 +--
28
block/io.c | 7 +++++
29
block/mirror.c | 2 +-
30
block/preallocate.c | 2 +-
31
block/qed-check.c | 3 ++-
32
block/qed-table.c | 6 ++---
33
block/qed.c | 44 +++++++++++++++++++-------------
34
block/quorum.c | 2 +-
35
block/throttle.c | 2 +-
36
block/vmdk.c | 6 +++--
37
20 files changed, 98 insertions(+), 60 deletions(-)
16
38
39
diff --git a/block/qcow2.h b/block/qcow2.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.h
42
+++ b/block/qcow2.h
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
44
/* qcow2-cluster.c functions */
45
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
46
bool exact_size);
47
-int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
48
+
49
+int coroutine_fn GRAPH_RDLOCK
50
+qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
51
+
52
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
53
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
54
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
55
diff --git a/block/qed.h b/block/qed.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qed.h
58
+++ b/block/qed.h
59
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
60
* Table I/O functions
61
*/
62
int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
63
-int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index,
64
- unsigned int n);
65
-int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
66
- unsigned int n);
67
+
68
+int coroutine_fn GRAPH_RDLOCK
69
+qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
70
+
71
+int coroutine_fn GRAPH_RDLOCK
72
+qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
73
+
74
int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
75
uint64_t offset);
76
int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
77
uint64_t offset);
78
-int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
79
- unsigned int index, unsigned int n,
80
- bool flush);
81
-int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
82
- unsigned int index, unsigned int n,
83
- bool flush);
84
+
85
+int coroutine_fn GRAPH_RDLOCK
86
+qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
87
+ unsigned int n, bool flush);
88
+
89
+int coroutine_fn GRAPH_RDLOCK
90
+qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
91
+ unsigned int index, unsigned int n, bool flush);
92
93
/**
94
* Cluster functions
95
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
96
/**
97
* Consistency check
98
*/
99
-int coroutine_fn qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
100
+int coroutine_fn GRAPH_RDLOCK
101
+qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
102
+
103
104
QEDTable *qed_alloc_table(BDRVQEDState *s);
105
106
diff --git a/include/block/block-io.h b/include/block/block-io.h
107
index XXXXXXX..XXXXXXX 100644
108
--- a/include/block/block-io.h
109
+++ b/include/block/block-io.h
110
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
111
bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
112
113
/* Ensure contents are flushed to disk. */
114
-int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
115
+int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
116
117
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
118
int64_t bytes);
119
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
120
index XXXXXXX..XXXXXXX 100644
121
--- a/include/block/block_int-common.h
122
+++ b/include/block/block_int-common.h
123
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
124
BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
125
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
126
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
127
- BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
128
- BlockCompletionFunc *cb, void *opaque);
129
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
130
+ BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
131
BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
132
int64_t offset, int bytes,
133
BlockCompletionFunc *cb, void *opaque);
134
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
135
* layers, if needed. This function is needed for deterministic
136
* synchronization of the flush finishing callback.
137
*/
138
- int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
139
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
140
141
/* Delete a created file. */
142
int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
143
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
144
* Flushes all data that was already written to the OS all the way down to
145
* the disk (for example file-posix.c calls fsync()).
146
*/
147
- int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
148
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_disk)(
149
+ BlockDriverState *bs);
150
151
/*
152
* Flushes all internal caches to the OS. The data may still sit in a
153
* writeback cache of the host OS, but it will survive a crash of the qemu
154
* process.
155
*/
156
- int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
157
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_os)(
158
+ BlockDriverState *bs);
159
160
/*
161
* Truncate @bs to @offset bytes using the given @prealloc mode
162
diff --git a/block/blkdebug.c b/block/blkdebug.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/block/blkdebug.c
165
+++ b/block/blkdebug.c
166
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
167
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
168
}
169
170
-static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
171
+static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
172
{
173
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
174
175
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/block/blklogwrites.c
178
+++ b/block/blklogwrites.c
179
@@ -XXX,XX +XXX,XX @@ typedef struct BlkLogWritesFileReq {
180
uint64_t bytes;
181
int file_flags;
182
QEMUIOVector *qiov;
183
- int (*func)(struct BlkLogWritesFileReq *r);
184
+ int GRAPH_RDLOCK_PTR (*func)(struct BlkLogWritesFileReq *r);
185
int file_ret;
186
} BlkLogWritesFileReq;
187
188
@@ -XXX,XX +XXX,XX @@ typedef struct {
189
int log_ret;
190
} BlkLogWritesLogReq;
191
192
-static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
193
+static void coroutine_fn GRAPH_RDLOCK
194
+blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
195
{
196
BDRVBlkLogWritesState *s = lr->bs->opaque;
197
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
198
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
199
}
200
}
201
202
-static void coroutine_fn blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
203
+static void coroutine_fn GRAPH_RDLOCK
204
+blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
205
{
206
fr->file_ret = fr->func(fr);
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
212
QEMUIOVector *qiov, int flags,
213
- int (*file_func)(BlkLogWritesFileReq *r),
214
+ int /*GRAPH_RDLOCK*/ (*file_func)(BlkLogWritesFileReq *r),
215
uint64_t entry_flags, bool is_zero_write)
216
{
217
QEMUIOVector log_qiov;
218
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
219
fr->file_flags);
220
}
221
222
-static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
223
+static int coroutine_fn GRAPH_RDLOCK
224
+blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
225
{
226
return bdrv_co_flush(fr->bs->file->bs);
227
}
228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
229
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
QEMUIOVector *qiov, BdrvRequestFlags flags)
231
{
232
+ assume_graph_lock(); /* FIXME */
233
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
234
blk_log_writes_co_do_file_pwritev, 0, false);
235
}
236
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
237
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
238
int64_t bytes, BdrvRequestFlags flags)
239
{
240
+ assume_graph_lock(); /* FIXME */
241
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
242
blk_log_writes_co_do_file_pwrite_zeroes, 0,
243
true);
244
}
245
246
-static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
247
+static int coroutine_fn GRAPH_RDLOCK
248
+blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
249
{
250
return blk_log_writes_co_log(bs, 0, 0, NULL, 0,
251
blk_log_writes_co_do_file_flush,
252
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
253
static int coroutine_fn
254
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
255
{
256
+ assume_graph_lock(); /* FIXME */
257
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
258
blk_log_writes_co_do_file_pdiscard,
259
LOG_DISCARD_FLAG, false);
260
diff --git a/block/blkreplay.c b/block/blkreplay.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/block/blkreplay.c
263
+++ b/block/blkreplay.c
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
265
return ret;
266
}
267
268
-static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
269
+static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
270
{
271
uint64_t reqid = blkreplay_next_id();
272
int ret = bdrv_co_flush(bs->file->bs);
273
diff --git a/block/blkverify.c b/block/blkverify.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/block/blkverify.c
276
+++ b/block/blkverify.c
277
@@ -XXX,XX +XXX,XX @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
278
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
279
}
280
281
-static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
282
+static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs)
283
{
284
BDRVBlkverifyState *s = bs->opaque;
285
286
diff --git a/block/block-backend.c b/block/block-backend.c
287
index XXXXXXX..XXXXXXX 100644
288
--- a/block/block-backend.c
289
+++ b/block/block-backend.c
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
291
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
292
static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
293
{
294
- blk_wait_while_drained(blk);
295
IO_CODE();
296
+ blk_wait_while_drained(blk);
297
+ GRAPH_RDLOCK_GUARD();
298
299
if (!blk_is_available(blk)) {
300
return -ENOMEDIUM;
301
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
302
index XXXXXXX..XXXXXXX 100644
303
--- a/block/copy-before-write.c
304
+++ b/block/copy-before-write.c
305
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
306
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
307
}
308
309
-static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
310
+static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs)
311
{
312
if (!bs->file) {
313
return 0;
314
diff --git a/block/file-posix.c b/block/file-posix.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/block/file-posix.c
317
+++ b/block/file-posix.c
318
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
319
}
320
#endif /* __linux__ */
321
322
-static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
323
- Error **errp)
324
+static void coroutine_fn GRAPH_RDLOCK
325
+raw_co_invalidate_cache(BlockDriverState *bs, Error **errp)
326
{
327
BDRVRawState *s = bs->opaque;
328
int ret;
329
diff --git a/block/io.c b/block/io.c
330
index XXXXXXX..XXXXXXX 100644
331
--- a/block/io.c
332
+++ b/block/io.c
333
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
334
int ret;
335
IO_CODE();
336
337
+ assume_graph_lock(); /* FIXME */
338
+
339
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
340
if (ret < 0) {
341
return ret;
342
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
343
QEMUIOVector local_qiov;
344
int ret;
345
346
+ assume_graph_lock(); /* FIXME */
347
+
348
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
349
350
if (!drv) {
351
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
352
int head = 0;
353
int tail = 0;
354
355
+ assume_graph_lock(); /* FIXME */
356
+
357
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
358
INT64_MAX);
359
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
360
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
361
int ret = 0;
362
IO_CODE();
363
364
+ assert_bdrv_graph_readable();
365
bdrv_inc_in_flight(bs);
366
367
if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
368
diff --git a/block/mirror.c b/block/mirror.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/block/mirror.c
371
+++ b/block/mirror.c
372
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
373
return ret;
374
}
375
376
-static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)
377
+static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
378
{
379
if (bs->backing == NULL) {
380
/* we can be here after failed bdrv_append in mirror_start_job */
381
diff --git a/block/preallocate.c b/block/preallocate.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/block/preallocate.c
384
+++ b/block/preallocate.c
385
@@ -XXX,XX +XXX,XX @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
386
return 0;
387
}
388
389
-static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
390
+static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
391
{
392
return bdrv_co_flush(bs->file->bs);
393
}
394
diff --git a/block/qed-check.c b/block/qed-check.c
395
index XXXXXXX..XXXXXXX 100644
396
--- a/block/qed-check.c
397
+++ b/block/qed-check.c
398
@@ -XXX,XX +XXX,XX @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
399
/**
400
* Descend tables and check each cluster is referenced once only
401
*/
402
-static int coroutine_fn qed_check_l1_table(QEDCheck *check, QEDTable *table)
403
+static int coroutine_fn GRAPH_RDLOCK
404
+qed_check_l1_table(QEDCheck *check, QEDTable *table)
405
{
406
BDRVQEDState *s = check->s;
407
unsigned int i, num_invalid_l1 = 0;
408
diff --git a/block/qed-table.c b/block/qed-table.c
409
index XXXXXXX..XXXXXXX 100644
410
--- a/block/qed-table.c
411
+++ b/block/qed-table.c
412
@@ -XXX,XX +XXX,XX @@ out:
413
*
414
* Called with table_lock held.
415
*/
416
-static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
417
- QEDTable *table, unsigned int index,
418
- unsigned int n, bool flush)
419
+static int coroutine_fn GRAPH_RDLOCK
420
+qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
421
+ unsigned int index, unsigned int n, bool flush)
422
{
423
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
424
unsigned int start, end, i;
425
diff --git a/block/qed.c b/block/qed.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/block/qed.c
428
+++ b/block/qed.c
429
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_init_state(BlockDriverState *bs)
430
}
431
432
/* Called with table_lock held. */
433
-static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
434
- int flags, Error **errp)
435
+static int coroutine_fn GRAPH_RDLOCK
436
+bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
437
{
438
BDRVQEDState *s = bs->opaque;
439
QEDHeader le_header;
440
@@ -XXX,XX +XXX,XX @@ typedef struct QEDOpenCo {
441
int ret;
442
} QEDOpenCo;
443
444
-static void coroutine_fn bdrv_qed_open_entry(void *opaque)
445
+static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque)
446
{
447
QEDOpenCo *qoc = opaque;
448
BDRVQEDState *s = qoc->bs->opaque;
449
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
450
};
451
int ret;
452
453
+ assume_graph_lock(); /* FIXME */
454
+
455
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
456
if (ret < 0) {
457
return ret;
458
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb)
459
*
460
* Called with table_lock held.
461
*/
462
-static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
463
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_l1_update(QEDAIOCB *acb)
464
{
465
BDRVQEDState *s = acb_to_s(acb);
466
CachedL2Table *l2_table = acb->request.l2_table;
467
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
468
*
469
* Called with table_lock held.
470
*/
471
-static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
472
+static int coroutine_fn GRAPH_RDLOCK
473
+qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
474
{
475
BDRVQEDState *s = acb_to_s(acb);
476
bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1;
477
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
478
*
479
* Called with table_lock held.
480
*/
481
-static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb)
482
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_cow(QEDAIOCB *acb)
483
{
484
BDRVQEDState *s = acb_to_s(acb);
485
uint64_t start, len, offset;
486
@@ -XXX,XX +XXX,XX @@ static bool qed_should_set_need_check(BDRVQEDState *s)
487
*
488
* Called with table_lock held.
489
*/
490
-static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
491
+static int coroutine_fn GRAPH_RDLOCK
492
+qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
493
{
494
BDRVQEDState *s = acb_to_s(acb);
495
int ret;
496
@@ -XXX,XX +XXX,XX @@ out:
497
*
498
* Called with table_lock held.
499
*/
500
-static int coroutine_fn qed_aio_write_data(void *opaque, int ret,
501
- uint64_t offset, size_t len)
502
+static int coroutine_fn GRAPH_RDLOCK
503
+qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
504
{
505
QEDAIOCB *acb = opaque;
506
507
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
508
/**
509
* Begin next I/O or complete the request
510
*/
511
-static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
512
+static int coroutine_fn GRAPH_RDLOCK qed_aio_next_io(QEDAIOCB *acb)
513
{
514
BDRVQEDState *s = acb_to_s(acb);
515
uint64_t offset;
516
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
517
return ret;
518
}
519
520
-static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num,
521
- QEMUIOVector *qiov, int nb_sectors,
522
- int flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
525
+ int nb_sectors, int flags)
526
{
527
QEDAIOCB acb = {
528
.bs = bs,
529
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
530
int64_t sector_num, int nb_sectors,
531
QEMUIOVector *qiov)
532
{
533
+ assume_graph_lock(); /* FIXME */
534
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
535
}
536
537
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
538
int64_t sector_num, int nb_sectors,
539
QEMUIOVector *qiov, int flags)
540
{
541
+ assume_graph_lock(); /* FIXME */
542
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
543
}
544
545
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
546
{
547
BDRVQEDState *s = bs->opaque;
548
549
+ assume_graph_lock(); /* FIXME */
550
+
551
/*
552
* Zero writes start without an I/O buffer. If a buffer becomes necessary
553
* then it will be allocated during request processing.
554
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
555
return ret;
556
}
557
558
-static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
559
- Error **errp)
560
+static void coroutine_fn GRAPH_RDLOCK
561
+bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp)
562
{
563
BDRVQEDState *s = bs->opaque;
564
int ret;
565
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
566
}
567
}
568
569
-static int coroutine_fn bdrv_qed_co_check(BlockDriverState *bs,
570
- BdrvCheckResult *result,
571
- BdrvCheckMode fix)
572
+static int coroutine_fn GRAPH_RDLOCK
573
+bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
574
+ BdrvCheckMode fix)
575
{
576
BDRVQEDState *s = bs->opaque;
577
int ret;
578
diff --git a/block/quorum.c b/block/quorum.c
579
index XXXXXXX..XXXXXXX 100644
580
--- a/block/quorum.c
581
+++ b/block/quorum.c
582
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
583
return result;
584
}
585
586
-static coroutine_fn int quorum_co_flush(BlockDriverState *bs)
587
+static coroutine_fn GRAPH_RDLOCK int quorum_co_flush(BlockDriverState *bs)
588
{
589
BDRVQuorumState *s = bs->opaque;
590
QuorumVoteVersion *winner = NULL;
591
diff --git a/block/throttle.c b/block/throttle.c
592
index XXXXXXX..XXXXXXX 100644
593
--- a/block/throttle.c
594
+++ b/block/throttle.c
595
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
596
BDRV_REQ_WRITE_COMPRESSED);
597
}
598
599
-static int coroutine_fn throttle_co_flush(BlockDriverState *bs)
600
+static int coroutine_fn GRAPH_RDLOCK throttle_co_flush(BlockDriverState *bs)
601
{
602
return bdrv_co_flush(bs->file->bs);
603
}
17
diff --git a/block/vmdk.c b/block/vmdk.c
604
diff --git a/block/vmdk.c b/block/vmdk.c
18
index XXXXXXX..XXXXXXX 100644
605
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vmdk.c
606
--- a/block/vmdk.c
20
+++ b/block/vmdk.c
607
+++ b/block/vmdk.c
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
608
@@ -XXX,XX +XXX,XX @@ exit:
22
return ret;
609
return ret;
23
}
610
}
24
611
25
-static int vmdk_create_extent(const char *filename, int64_t filesize,
612
-static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
26
- bool flat, bool compress, bool zeroed_grain,
613
- uint32_t offset)
27
- QemuOpts *opts, Error **errp)
614
+static int coroutine_fn GRAPH_RDLOCK
28
+static int vmdk_init_extent(BlockBackend *blk,
615
+vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
29
+ int64_t filesize, bool flat,
616
{
30
+ bool compress, bool zeroed_grain,
617
offset = cpu_to_le32(offset);
31
+ Error **errp)
618
/* update L2 table */
32
{
619
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
33
int ret, i;
620
uint64_t bytes_done = 0;
34
- BlockBackend *blk = NULL;
621
VmdkMetaData m_data;
35
VMDK4Header header;
622
36
- Error *local_err = NULL;
623
+ assume_graph_lock(); /* FIXME */
37
uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
624
+
38
uint32_t *gd_buf = NULL;
625
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
39
int gd_buf_size;
626
error_report("Wrong offset: offset=0x%" PRIx64
40
627
" total_sectors=0x%" PRIx64,
41
- ret = bdrv_create_file(filename, opts, &local_err);
42
- if (ret < 0) {
43
- error_propagate(errp, local_err);
44
- goto exit;
45
- }
46
-
47
- blk = blk_new_open(filename, NULL, NULL,
48
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
49
- &local_err);
50
- if (blk == NULL) {
51
- error_propagate(errp, local_err);
52
- ret = -EIO;
53
- goto exit;
54
- }
55
-
56
- blk_set_allow_write_beyond_eof(blk, true);
57
-
58
if (flat) {
59
ret = blk_truncate(blk, filesize, PREALLOC_MODE_OFF, errp);
60
goto exit;
61
@@ -XXX,XX +XXX,XX @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
62
gd_buf, gd_buf_size, 0);
63
if (ret < 0) {
64
error_setg(errp, QERR_IO_ERROR);
65
- goto exit;
66
}
67
68
ret = 0;
69
+exit:
70
+ g_free(gd_buf);
71
+ return ret;
72
+}
73
+
74
+static int vmdk_create_extent(const char *filename, int64_t filesize,
75
+ bool flat, bool compress, bool zeroed_grain,
76
+ BlockBackend **pbb,
77
+ QemuOpts *opts, Error **errp)
78
+{
79
+ int ret;
80
+ BlockBackend *blk = NULL;
81
+ Error *local_err = NULL;
82
+
83
+ ret = bdrv_create_file(filename, opts, &local_err);
84
+ if (ret < 0) {
85
+ error_propagate(errp, local_err);
86
+ goto exit;
87
+ }
88
+
89
+ blk = blk_new_open(filename, NULL, NULL,
90
+ BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
91
+ &local_err);
92
+ if (blk == NULL) {
93
+ error_propagate(errp, local_err);
94
+ ret = -EIO;
95
+ goto exit;
96
+ }
97
+
98
+ blk_set_allow_write_beyond_eof(blk, true);
99
+
100
+ ret = vmdk_init_extent(blk, filesize, flat, compress, zeroed_grain, errp);
101
exit:
102
if (blk) {
103
- blk_unref(blk);
104
+ if (pbb) {
105
+ *pbb = blk;
106
+ } else {
107
+ blk_unref(blk);
108
+ blk = NULL;
109
+ }
110
}
111
- g_free(gd_buf);
112
return ret;
113
}
114
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
116
snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename);
117
118
if (vmdk_create_extent(ext_filename, size,
119
- flat, compress, zeroed_grain, opts, errp)) {
120
+ flat, compress, zeroed_grain, NULL, opts, errp)) {
121
ret = -EINVAL;
122
goto exit;
123
}
124
--
628
--
125
2.20.1
629
2.39.2
126
127
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The last user of blk_attach_dev_legacy() was the code in xen_disk which
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
has recently been reworked. Now there is no user for this legacy function
4
bdrv_co_pdiscard() need to hold a reader lock for the graph.
5
anymore. Thus we can finally remove all code related to the "legacy_dev"
6
flag, too, and turn the related "void *" in block-backend.c into proper
7
"DeviceState *" to fix some of the remaining TODOs there.
8
5
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
For some places, we know that they will hold the lock, but we don't have
10
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20230203152202.49054-9-kwolf@redhat.com>
13
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
15
---
13
include/sysemu/block-backend.h | 5 ++--
16
include/block/block-io.h | 5 +++--
14
block/block-backend.c | 54 ++++++----------------------------
17
include/block/block_int-common.h | 15 +++++++++------
15
2 files changed, 11 insertions(+), 48 deletions(-)
18
include/block/block_int-io.h | 2 +-
19
block/blkdebug.c | 4 ++--
20
block/blklogwrites.c | 5 ++---
21
block/blkreplay.c | 4 ++--
22
block/block-backend.c | 1 +
23
block/copy-before-write.c | 8 ++++----
24
block/copy-on-read.c | 4 ++--
25
block/filter-compress.c | 4 ++--
26
block/io.c | 2 ++
27
block/mirror.c | 14 +++++++++-----
28
block/preallocate.c | 4 ++--
29
block/raw-format.c | 4 ++--
30
block/snapshot-access.c | 4 ++--
31
block/throttle.c | 4 ++--
32
16 files changed, 47 insertions(+), 37 deletions(-)
16
33
17
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
34
diff --git a/include/block/block-io.h b/include/block/block-io.h
18
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
19
--- a/include/sysemu/block-backend.h
36
--- a/include/block/block-io.h
20
+++ b/include/sysemu/block-backend.h
37
+++ b/include/block/block-io.h
21
@@ -XXX,XX +XXX,XX @@ void blk_iostatus_disable(BlockBackend *blk);
38
@@ -XXX,XX +XXX,XX @@ bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
22
void blk_iostatus_reset(BlockBackend *blk);
39
/* Ensure contents are flushed to disk. */
23
void blk_iostatus_set_err(BlockBackend *blk, int error);
40
int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
24
int blk_attach_dev(BlockBackend *blk, DeviceState *dev);
41
25
-void blk_attach_dev_legacy(BlockBackend *blk, void *dev);
42
-int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
26
-void blk_detach_dev(BlockBackend *blk, void *dev);
43
- int64_t bytes);
27
-void *blk_get_attached_dev(BlockBackend *blk);
44
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
28
+void blk_detach_dev(BlockBackend *blk, DeviceState *dev);
45
+ int64_t bytes);
29
+DeviceState *blk_get_attached_dev(BlockBackend *blk);
46
+
30
char *blk_get_attached_dev_id(BlockBackend *blk);
47
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
31
BlockBackend *blk_by_dev(void *dev);
48
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
32
BlockBackend *blk_by_qdev_id(const char *id, Error **errp);
49
int64_t bytes, int64_t *pnum, int64_t *map,
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
56
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
57
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
58
- BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
59
- int64_t offset, int bytes,
60
+
61
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pdiscard)(
62
+ BlockDriverState *bs, int64_t offset, int bytes,
63
BlockCompletionFunc *cb, void *opaque);
64
65
int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
66
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
67
*/
68
int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
69
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
70
- int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs,
71
- int64_t offset, int64_t bytes);
72
+
73
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
74
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
75
76
/*
77
* Map [offset, offset + nbytes) range onto a child of @bs to copy from,
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
79
int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
80
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
81
int64_t *map, BlockDriverState **file);
82
- int coroutine_fn (*bdrv_co_pdiscard_snapshot)(BlockDriverState *bs,
83
- int64_t offset, int64_t bytes);
84
+
85
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
86
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
87
88
/*
89
* Invalidate any cached meta-data.
90
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
91
index XXXXXXX..XXXXXXX 100644
92
--- a/include/block/block_int-io.h
93
+++ b/include/block/block_int-io.h
94
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
95
int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
96
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
97
int64_t *map, BlockDriverState **file);
98
-int coroutine_fn bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
99
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
100
int64_t offset, int64_t bytes);
101
102
103
diff --git a/block/blkdebug.c b/block/blkdebug.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/blkdebug.c
106
+++ b/block/blkdebug.c
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
108
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
109
}
110
111
-static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
112
- int64_t offset, int64_t bytes)
113
+static int coroutine_fn GRAPH_RDLOCK
114
+blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
115
{
116
uint32_t align = bs->bl.pdiscard_alignment;
117
int err;
118
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/block/blklogwrites.c
121
+++ b/block/blklogwrites.c
122
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
123
return bdrv_co_flush(fr->bs->file->bs);
124
}
125
126
-static int coroutine_fn
127
+static int coroutine_fn GRAPH_RDLOCK
128
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
129
{
130
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
131
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
132
LOG_FLUSH_FLAG, false);
133
}
134
135
-static int coroutine_fn
136
+static int coroutine_fn GRAPH_RDLOCK
137
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
138
{
139
- assume_graph_lock(); /* FIXME */
140
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
141
blk_log_writes_co_do_file_pdiscard,
142
LOG_DISCARD_FLAG, false);
143
diff --git a/block/blkreplay.c b/block/blkreplay.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/block/blkreplay.c
146
+++ b/block/blkreplay.c
147
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
148
return ret;
149
}
150
151
-static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
152
- int64_t offset, int64_t bytes)
153
+static int coroutine_fn GRAPH_RDLOCK
154
+blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
155
{
156
uint64_t reqid = blkreplay_next_id();
157
int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
33
diff --git a/block/block-backend.c b/block/block-backend.c
158
diff --git a/block/block-backend.c b/block/block-backend.c
34
index XXXXXXX..XXXXXXX 100644
159
index XXXXXXX..XXXXXXX 100644
35
--- a/block/block-backend.c
160
--- a/block/block-backend.c
36
+++ b/block/block-backend.c
161
+++ b/block/block-backend.c
37
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
162
@@ -XXX,XX +XXX,XX @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
38
QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
163
IO_CODE();
39
BlockBackendPublic public;
164
40
165
blk_wait_while_drained(blk);
41
- void *dev; /* attached device model, if any */
166
+ GRAPH_RDLOCK_GUARD();
42
- bool legacy_dev; /* true if dev is not a DeviceState */
167
43
- /* TODO change to DeviceState when all users are qdevified */
168
ret = blk_check_byte_request(blk, offset, bytes);
44
+ DeviceState *dev; /* attached device model, if any */
169
if (ret < 0) {
45
const BlockDevOps *dev_ops;
170
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
46
void *dev_opaque;
171
index XXXXXXX..XXXXXXX 100644
47
172
--- a/block/copy-before-write.c
48
@@ -XXX,XX +XXX,XX @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
173
+++ b/block/copy-before-write.c
49
*shared_perm = blk->shared_perm;
174
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
50
}
51
52
-static int blk_do_attach_dev(BlockBackend *blk, void *dev)
53
+/*
54
+ * Attach device model @dev to @blk.
55
+ * Return 0 on success, -EBUSY when a device model is attached already.
56
+ */
57
+int blk_attach_dev(BlockBackend *blk, DeviceState *dev)
58
{
59
if (blk->dev) {
60
return -EBUSY;
61
@@ -XXX,XX +XXX,XX @@ static int blk_do_attach_dev(BlockBackend *blk, void *dev)
62
63
blk_ref(blk);
64
blk->dev = dev;
65
- blk->legacy_dev = false;
66
blk_iostatus_reset(blk);
67
68
return 0;
175
return 0;
69
}
176
}
70
177
71
-/*
178
-static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
72
- * Attach device model @dev to @blk.
179
- int64_t offset, int64_t bytes)
73
- * Return 0 on success, -EBUSY when a device model is attached already.
180
+static int coroutine_fn GRAPH_RDLOCK
74
- */
181
+cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
75
-int blk_attach_dev(BlockBackend *blk, DeviceState *dev)
182
{
76
-{
183
int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
77
- return blk_do_attach_dev(blk, dev);
184
if (ret < 0) {
78
-}
185
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
79
-
186
return ret;
80
-/*
187
}
81
- * Attach device model @dev to @blk.
188
82
- * @blk must not have a device model attached already.
189
-static int coroutine_fn cbw_co_pdiscard_snapshot(BlockDriverState *bs,
83
- * TODO qdevified devices don't use this, remove when devices are qdevified
190
- int64_t offset, int64_t bytes)
84
- */
191
+static int coroutine_fn GRAPH_RDLOCK
85
-void blk_attach_dev_legacy(BlockBackend *blk, void *dev)
192
+cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
86
-{
193
{
87
- if (blk_do_attach_dev(blk, dev) < 0) {
194
BDRVCopyBeforeWriteState *s = bs->opaque;
88
- abort();
195
89
- }
196
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
90
- blk->legacy_dev = true;
197
index XXXXXXX..XXXXXXX 100644
91
-}
198
--- a/block/copy-on-read.c
92
-
199
+++ b/block/copy-on-read.c
93
/*
200
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
94
* Detach device model @dev from @blk.
201
}
95
* @dev must be currently attached to @blk.
202
96
*/
203
97
-void blk_detach_dev(BlockBackend *blk, void *dev)
204
-static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
98
-/* TODO change to DeviceState *dev when all users are qdevified */
205
- int64_t offset, int64_t bytes)
99
+void blk_detach_dev(BlockBackend *blk, DeviceState *dev)
206
+static int coroutine_fn GRAPH_RDLOCK
100
{
207
+cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
101
assert(blk->dev == dev);
208
{
102
blk->dev = NULL;
209
return bdrv_co_pdiscard(bs->file, offset, bytes);
103
@@ -XXX,XX +XXX,XX @@ void blk_detach_dev(BlockBackend *blk, void *dev)
210
}
104
/*
211
diff --git a/block/filter-compress.c b/block/filter-compress.c
105
* Return the device model attached to @blk if any, else null.
212
index XXXXXXX..XXXXXXX 100644
106
*/
213
--- a/block/filter-compress.c
107
-void *blk_get_attached_dev(BlockBackend *blk)
214
+++ b/block/filter-compress.c
108
-/* TODO change to return DeviceState * when all users are qdevified */
215
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
109
+DeviceState *blk_get_attached_dev(BlockBackend *blk)
216
}
110
{
217
111
return blk->dev;
218
112
}
219
-static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
113
@@ -XXX,XX +XXX,XX @@ void *blk_get_attached_dev(BlockBackend *blk)
220
- int64_t offset, int64_t bytes)
114
* device attached to the BlockBackend. */
221
+static int coroutine_fn GRAPH_RDLOCK
115
char *blk_get_attached_dev_id(BlockBackend *blk)
222
+compress_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
116
{
223
{
117
- DeviceState *dev;
224
return bdrv_co_pdiscard(bs->file, offset, bytes);
118
-
225
}
119
- assert(!blk->legacy_dev);
226
diff --git a/block/io.c b/block/io.c
120
- dev = blk->dev;
227
index XXXXXXX..XXXXXXX 100644
121
+ DeviceState *dev = blk->dev;
228
--- a/block/io.c
122
229
+++ b/block/io.c
123
if (!dev) {
230
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
124
return g_strdup("");
231
int head, tail, align;
125
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_dev(void *dev)
232
BlockDriverState *bs = child->bs;
126
void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
233
IO_CODE();
127
void *opaque)
234
+ assert_bdrv_graph_readable();
128
{
235
129
- /* All drivers that use blk_set_dev_ops() are qdevified and we want to keep
236
if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
130
- * it that way, so we can assume blk->dev, if present, is a DeviceState if
237
return -ENOMEDIUM;
131
- * blk->dev_ops is set. Non-device users may use dev_ops without device. */
238
@@ -XXX,XX +XXX,XX @@ bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
132
- assert(!blk->legacy_dev);
239
BlockDriver *drv = bs->drv;
133
-
240
int ret;
134
blk->dev_ops = ops;
241
IO_CODE();
135
blk->dev_opaque = opaque;
242
+ assert_bdrv_graph_readable();
136
243
137
@@ -XXX,XX +XXX,XX @@ void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp)
244
if (!drv) {
138
bool tray_was_open, tray_is_open;
245
return -ENOMEDIUM;
139
Error *local_err = NULL;
246
diff --git a/block/mirror.c b/block/mirror.c
140
247
index XXXXXXX..XXXXXXX 100644
141
- assert(!blk->legacy_dev);
248
--- a/block/mirror.c
142
-
249
+++ b/block/mirror.c
143
tray_was_open = blk_dev_is_tray_open(blk);
250
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
144
blk->dev_ops->change_media_cb(blk->dev_opaque, load, &local_err);
251
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
145
if (local_err) {
252
}
146
@@ -XXX,XX +XXX,XX @@ void blk_eject(BlockBackend *blk, bool eject_flag)
253
147
BlockDriverState *bs = blk_bs(blk);
254
-static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs,
148
char *id;
255
- MirrorMethod method, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
149
256
- int flags)
150
- /* blk_eject is only called by qdevified devices */
257
+static int coroutine_fn GRAPH_RDLOCK
151
- assert(!blk->legacy_dev);
258
+bdrv_mirror_top_do_write(BlockDriverState *bs, MirrorMethod method,
152
-
259
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
153
if (bs) {
260
+ int flags)
154
bdrv_eject(bs, eject_flag);
261
{
155
}
262
MirrorOp *op = NULL;
263
MirrorBDSOpaque *s = bs->opaque;
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
265
int ret = 0;
266
bool copy_to_target = false;
267
268
+ assume_graph_lock(); /* FIXME */
269
+
270
if (s->job) {
271
copy_to_target = s->job->ret >= 0 &&
272
!job_is_cancelled(&s->job->common.job) &&
273
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
274
static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
275
int64_t offset, int64_t bytes, BdrvRequestFlags flags)
276
{
277
+ assume_graph_lock(); /* FIXME */
278
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
279
flags);
280
}
281
282
-static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
283
- int64_t offset, int64_t bytes)
284
+static int coroutine_fn GRAPH_RDLOCK
285
+bdrv_mirror_top_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
286
{
287
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, offset, bytes,
288
NULL, 0);
289
diff --git a/block/preallocate.c b/block/preallocate.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/preallocate.c
292
+++ b/block/preallocate.c
293
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_preadv_part(
294
flags);
295
}
296
297
-static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs,
298
- int64_t offset, int64_t bytes)
299
+static int coroutine_fn GRAPH_RDLOCK
300
+preallocate_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
301
{
302
return bdrv_co_pdiscard(bs->file, offset, bytes);
303
}
304
diff --git a/block/raw-format.c b/block/raw-format.c
305
index XXXXXXX..XXXXXXX 100644
306
--- a/block/raw-format.c
307
+++ b/block/raw-format.c
308
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
309
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
310
}
311
312
-static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
313
- int64_t offset, int64_t bytes)
314
+static int coroutine_fn GRAPH_RDLOCK
315
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
316
{
317
int ret;
318
319
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/block/snapshot-access.c
322
+++ b/block/snapshot-access.c
323
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_block_status(BlockDriverState *bs,
324
bytes, pnum, map, file);
325
}
326
327
-static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs,
328
- int64_t offset, int64_t bytes)
329
+static int coroutine_fn GRAPH_RDLOCK
330
+snapshot_access_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
331
{
332
return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes);
333
}
334
diff --git a/block/throttle.c b/block/throttle.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/block/throttle.c
337
+++ b/block/throttle.c
338
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
339
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
340
}
341
342
-static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
343
- int64_t offset, int64_t bytes)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
346
{
347
ThrottleGroupMember *tgm = bs->opaque;
348
throttle_group_co_io_limits_intercept(tgm, bytes, true);
156
--
349
--
157
2.20.1
350
2.39.2
158
159
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_pwrite_zeroes() need to hold a reader lock for the graph.
2
3
3
Patch created mechanically by rerunning:
4
For some places, we know that they will hold the lock, but we don't have
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
4
8
5
$ spatch --sp-file scripts/coccinelle/qobject.cocci \
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
     --macro-file scripts/cocci-macro-file.h \
10
Message-Id: <20230203152202.49054-10-kwolf@redhat.com>
7
     --dir block --in-place
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
9
Signed-off-by: Markus Armbruster <armbru@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
13
---
14
block/blklogwrites.c | 5 ++---
14
block/qcow2.h | 6 ++++--
15
1 file changed, 2 insertions(+), 3 deletions(-)
15
include/block/block-io.h | 9 +++++----
16
include/block/block_int-common.h | 5 +++--
17
block/blkdebug.c | 6 +++---
18
block/blklogwrites.c | 5 ++---
19
block/blkreplay.c | 5 +++--
20
block/block-copy.c | 13 +++++++------
21
block/copy-before-write.c | 5 +++--
22
block/copy-on-read.c | 6 +++---
23
block/filter-compress.c | 6 +++---
24
block/io.c | 12 +++++++++---
25
block/mirror.c | 6 +++---
26
block/preallocate.c | 11 +++++++----
27
block/qcow2.c | 30 ++++++++++++++++++------------
28
block/qed.c | 9 +++------
29
block/quorum.c | 15 ++++++++++-----
30
block/raw-format.c | 6 +++---
31
block/throttle.c | 6 +++---
32
18 files changed, 92 insertions(+), 69 deletions(-)
16
33
34
diff --git a/block/qcow2.h b/block/qcow2.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/qcow2.h
37
+++ b/block/qcow2.h
38
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
39
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
40
uint64_t bytes, enum qcow2_discard_type type,
41
bool full_discard);
42
-int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
43
- uint64_t bytes, int flags);
44
+
45
+int coroutine_fn GRAPH_RDLOCK
46
+qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
47
+ int flags);
48
49
int qcow2_expand_zero_clusters(BlockDriverState *bs,
50
BlockDriverAmendStatusCB *status_cb,
51
diff --git a/include/block/block-io.h b/include/block/block-io.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/block/block-io.h
54
+++ b/include/block/block-io.h
55
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
56
* function is not suitable for zeroing the entire image in a single request
57
* because it may allocate memory for the entire region.
58
*/
59
-int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
60
- int64_t bytes, BdrvRequestFlags flags);
61
+int coroutine_fn GRAPH_RDLOCK
62
+bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes,
63
+ BdrvRequestFlags flags);
64
65
int coroutine_fn GRAPH_RDLOCK
66
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
67
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
68
bool include_base, int64_t offset, int64_t bytes,
69
int64_t *pnum);
70
71
-int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
72
- int64_t bytes);
73
+int coroutine_fn GRAPH_RDLOCK
74
+bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
75
76
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
77
Error **errp);
78
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
79
index XXXXXXX..XXXXXXX 100644
80
--- a/include/block/block_int-common.h
81
+++ b/include/block/block_int-common.h
82
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
83
* function pointer may be NULL or return -ENOSUP and .bdrv_co_writev()
84
* will be called instead.
85
*/
86
- int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
87
- int64_t offset, int64_t bytes, BdrvRequestFlags flags);
88
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwrite_zeroes)(
89
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
90
+ BdrvRequestFlags flags);
91
92
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
93
BlockDriverState *bs, int64_t offset, int64_t bytes);
94
diff --git a/block/blkdebug.c b/block/blkdebug.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/blkdebug.c
97
+++ b/block/blkdebug.c
98
@@ -XXX,XX +XXX,XX @@ static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
99
return bdrv_co_flush(bs->file->bs);
100
}
101
102
-static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
103
- int64_t offset, int64_t bytes,
104
- BdrvRequestFlags flags)
105
+static int coroutine_fn GRAPH_RDLOCK
106
+blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
107
+ BdrvRequestFlags flags)
108
{
109
uint32_t align = MAX(bs->bl.request_alignment,
110
bs->bl.pwrite_zeroes_alignment);
17
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
111
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
18
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blklogwrites.c
113
--- a/block/blklogwrites.c
20
+++ b/block/blklogwrites.c
114
+++ b/block/blklogwrites.c
21
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_filename(BlockDriverState *bs,
115
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
22
qdict_put_str(opts, "driver", "blklogwrites");
116
fr->qiov, fr->file_flags);
23
117
}
24
qobject_ref(bs->file->bs->full_open_options);
118
25
- qdict_put_obj(opts, "file", QOBJECT(bs->file->bs->full_open_options));
119
-static int coroutine_fn
26
+ qdict_put(opts, "file", bs->file->bs->full_open_options);
120
+static int coroutine_fn GRAPH_RDLOCK
27
qobject_ref(s->log_file->bs->full_open_options);
121
blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
28
- qdict_put_obj(opts, "log",
122
{
29
- QOBJECT(s->log_file->bs->full_open_options));
123
return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes,
30
+ qdict_put(opts, "log", s->log_file->bs->full_open_options);
124
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
31
qdict_put_int(opts, "log-sector-size", s->sectorsize);
125
blk_log_writes_co_do_file_pwritev, 0, false);
32
126
}
33
bs->full_open_options = opts;
127
128
-static int coroutine_fn
129
+static int coroutine_fn GRAPH_RDLOCK
130
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
131
int64_t bytes, BdrvRequestFlags flags)
132
{
133
- assume_graph_lock(); /* FIXME */
134
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
135
blk_log_writes_co_do_file_pwrite_zeroes, 0,
136
true);
137
diff --git a/block/blkreplay.c b/block/blkreplay.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/blkreplay.c
140
+++ b/block/blkreplay.c
141
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
142
return ret;
143
}
144
145
-static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
146
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
147
+static int coroutine_fn GRAPH_RDLOCK
148
+blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
149
+ BdrvRequestFlags flags)
150
{
151
uint64_t reqid = blkreplay_next_id();
152
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
153
diff --git a/block/block-copy.c b/block/block-copy.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/block-copy.c
156
+++ b/block/block-copy.c
157
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
158
* value of @method should be used for subsequent tasks.
159
* Returns 0 on success.
160
*/
161
-static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
162
- int64_t offset, int64_t bytes,
163
- BlockCopyMethod *method,
164
- bool *error_is_read)
165
+static int coroutine_fn GRAPH_RDLOCK
166
+block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
167
+ BlockCopyMethod *method, bool *error_is_read)
168
{
169
int ret;
170
int64_t nbytes = MIN(offset + bytes, s->len) - offset;
171
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
172
BlockCopyMethod method = t->method;
173
int ret;
174
175
- ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
176
- &error_is_read);
177
+ WITH_GRAPH_RDLOCK_GUARD() {
178
+ ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
179
+ &error_is_read);
180
+ }
181
182
WITH_QEMU_LOCK_GUARD(&s->lock) {
183
if (s->method == t->method) {
184
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/block/copy-before-write.c
187
+++ b/block/copy-before-write.c
188
@@ -XXX,XX +XXX,XX @@ cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
189
return bdrv_co_pdiscard(bs->file, offset, bytes);
190
}
191
192
-static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
193
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
194
+static int coroutine_fn GRAPH_RDLOCK
195
+cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
196
+ BdrvRequestFlags flags)
197
{
198
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
199
if (ret < 0) {
200
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
201
index XXXXXXX..XXXXXXX 100644
202
--- a/block/copy-on-read.c
203
+++ b/block/copy-on-read.c
204
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
205
}
206
207
208
-static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
209
- int64_t offset, int64_t bytes,
210
- BdrvRequestFlags flags)
211
+static int coroutine_fn GRAPH_RDLOCK
212
+cor_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
213
+ BdrvRequestFlags flags)
214
{
215
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
216
}
217
diff --git a/block/filter-compress.c b/block/filter-compress.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/filter-compress.c
220
+++ b/block/filter-compress.c
221
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
222
}
223
224
225
-static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
226
- int64_t offset, int64_t bytes,
227
- BdrvRequestFlags flags)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+compress_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
+ BdrvRequestFlags flags)
231
{
232
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
233
}
234
diff --git a/block/io.c b/block/io.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/block/io.c
237
+++ b/block/io.c
238
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
239
int64_t progress = 0;
240
bool skip_write;
241
242
+ assume_graph_lock(); /* FIXME */
243
+
244
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
245
246
if (!drv) {
247
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
248
bs->bl.request_alignment);
249
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
250
251
+ assert_bdrv_graph_readable();
252
bdrv_check_request(offset, bytes, &error_abort);
253
254
if (!drv) {
255
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
256
int64_t bytes_remaining = bytes;
257
int max_transfer;
258
259
+ assume_graph_lock(); /* FIXME */
260
+
261
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
262
263
if (!drv) {
264
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
265
{
266
IO_CODE();
267
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
268
+ assert_bdrv_graph_readable();
269
270
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
271
flags &= ~BDRV_REQ_MAY_UNMAP;
272
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
273
int64_t pnum = bytes;
274
IO_CODE();
275
276
- assume_graph_lock(); /* FIXME */
277
-
278
if (!bytes) {
279
return 1;
280
}
281
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
282
}
283
}
284
285
-static int coroutine_fn bdrv_co_copy_range_internal(
286
+static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
287
BdrvChild *src, int64_t src_offset, BdrvChild *dst,
288
int64_t dst_offset, int64_t bytes,
289
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
291
BdrvRequestFlags write_flags)
292
{
293
IO_CODE();
294
+ assume_graph_lock(); /* FIXME */
295
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
296
read_flags, write_flags);
297
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
298
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
299
BdrvRequestFlags write_flags)
300
{
301
IO_CODE();
302
+ assume_graph_lock(); /* FIXME */
303
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
304
read_flags, write_flags);
305
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
306
diff --git a/block/mirror.c b/block/mirror.c
307
index XXXXXXX..XXXXXXX 100644
308
--- a/block/mirror.c
309
+++ b/block/mirror.c
310
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
311
return bdrv_co_flush(bs->backing->bs);
312
}
313
314
-static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
315
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
318
+ int64_t bytes, BdrvRequestFlags flags)
319
{
320
- assume_graph_lock(); /* FIXME */
321
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
322
flags);
323
}
324
diff --git a/block/preallocate.c b/block/preallocate.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/block/preallocate.c
327
+++ b/block/preallocate.c
328
@@ -XXX,XX +XXX,XX @@ static bool has_prealloc_perms(BlockDriverState *bs)
329
* want_merge_zero is used to merge write-zero request with preallocation in
330
* one bdrv_co_pwrite_zeroes() call.
331
*/
332
-static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
333
- int64_t bytes, bool want_merge_zero)
334
+static bool coroutine_fn GRAPH_RDLOCK
335
+handle_write(BlockDriverState *bs, int64_t offset, int64_t bytes,
336
+ bool want_merge_zero)
337
{
338
BDRVPreallocateState *s = bs->opaque;
339
int64_t end = offset + bytes;
340
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
341
return want_merge_zero;
342
}
343
344
-static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs,
345
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
346
+static int coroutine_fn GRAPH_RDLOCK
347
+preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
348
+ int64_t bytes, BdrvRequestFlags flags)
349
{
350
bool want_merge_zero =
351
!(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK));
352
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
353
size_t qiov_offset,
354
BdrvRequestFlags flags)
355
{
356
+ assume_graph_lock(); /* FIXME */
357
handle_write(bs, offset, bytes, false);
358
359
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
360
diff --git a/block/qcow2.c b/block/qcow2.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/qcow2.c
363
+++ b/block/qcow2.c
364
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
365
* Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error.
366
* Note that returning 0 does not guarantee non-zero data.
367
*/
368
-static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
369
+static int coroutine_fn GRAPH_RDLOCK
370
+is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
371
{
372
/*
373
* This check is designed for optimization shortcut so it must be
374
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
375
m->cow_end.nb_bytes);
376
}
377
378
-static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
379
- QCowL2Meta *l2meta)
380
+static int coroutine_fn GRAPH_RDLOCK
381
+handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
382
{
383
BDRVQcow2State *s = bs->opaque;
384
QCowL2Meta *m;
385
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
386
* l2meta - if not NULL, qcow2_co_pwritev_task() will consume it. Caller must
387
* not use it somehow after qcow2_co_pwritev_task() call
388
*/
389
-static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
390
- uint64_t host_offset,
391
- uint64_t offset, uint64_t bytes,
392
- QEMUIOVector *qiov,
393
- uint64_t qiov_offset,
394
- QCowL2Meta *l2meta)
395
+static coroutine_fn GRAPH_RDLOCK
396
+int qcow2_co_pwritev_task(BlockDriverState *bs, uint64_t host_offset,
397
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
398
+ uint64_t qiov_offset, QCowL2Meta *l2meta)
399
{
400
int ret;
401
BDRVQcow2State *s = bs->opaque;
402
@@ -XXX,XX +XXX,XX @@ out_locked:
403
return ret;
404
}
405
406
-static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
407
+/*
408
+ * This function can count as GRAPH_RDLOCK because qcow2_co_pwritev_part() holds
409
+ * the graph lock and keeps it until this coroutine has terminated.
410
+ */
411
+static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
412
{
413
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
414
415
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
416
QCowL2Meta *l2meta = NULL;
417
AioTaskPool *aio = NULL;
418
419
+ assume_graph_lock(); /* FIXME */
420
+
421
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
422
423
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
424
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
425
return res >= 0 && (res & BDRV_BLOCK_ZERO) && bytes == 0;
426
}
427
428
-static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
429
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
430
+static int coroutine_fn GRAPH_RDLOCK
431
+qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
432
+ BdrvRequestFlags flags)
433
{
434
int ret;
435
BDRVQcow2State *s = bs->opaque;
436
diff --git a/block/qed.c b/block/qed.c
437
index XXXXXXX..XXXXXXX 100644
438
--- a/block/qed.c
439
+++ b/block/qed.c
440
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
441
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
442
}
443
444
-static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
445
- int64_t offset,
446
- int64_t bytes,
447
- BdrvRequestFlags flags)
448
+static int coroutine_fn GRAPH_RDLOCK
449
+bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
450
+ BdrvRequestFlags flags)
451
{
452
BDRVQEDState *s = bs->opaque;
453
454
- assume_graph_lock(); /* FIXME */
455
-
456
/*
457
* Zero writes start without an I/O buffer. If a buffer becomes necessary
458
* then it will be allocated during request processing.
459
diff --git a/block/quorum.c b/block/quorum.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/block/quorum.c
462
+++ b/block/quorum.c
463
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
464
return ret;
465
}
466
467
-static void coroutine_fn write_quorum_entry(void *opaque)
468
+/*
469
+ * This function can count as GRAPH_RDLOCK because quorum_co_pwritev() holds the
470
+ * graph lock and keeps it until this coroutine has terminated.
471
+ */
472
+static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
473
{
474
QuorumCo *co = opaque;
475
QuorumAIOCB *acb = co->acb;
476
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
477
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
478
int i, ret;
479
480
+ assume_graph_lock(); /* FIXME */
481
+
482
for (i = 0; i < s->num_children; i++) {
483
Coroutine *co;
484
QuorumCo data = {
485
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
486
return ret;
487
}
488
489
-static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
490
- int64_t offset, int64_t bytes,
491
- BdrvRequestFlags flags)
492
-
493
+static int coroutine_fn GRAPH_RDLOCK
494
+quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
495
+ BdrvRequestFlags flags)
496
{
497
return quorum_co_pwritev(bs, offset, bytes, NULL,
498
flags | BDRV_REQ_ZERO_WRITE);
499
diff --git a/block/raw-format.c b/block/raw-format.c
500
index XXXXXXX..XXXXXXX 100644
501
--- a/block/raw-format.c
502
+++ b/block/raw-format.c
503
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
504
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
505
}
506
507
-static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
508
- int64_t offset, int64_t bytes,
509
- BdrvRequestFlags flags)
510
+static int coroutine_fn GRAPH_RDLOCK
511
+raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
512
+ BdrvRequestFlags flags)
513
{
514
int ret;
515
516
diff --git a/block/throttle.c b/block/throttle.c
517
index XXXXXXX..XXXXXXX 100644
518
--- a/block/throttle.c
519
+++ b/block/throttle.c
520
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
521
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
522
}
523
524
-static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
525
- int64_t offset, int64_t bytes,
526
- BdrvRequestFlags flags)
527
+static int coroutine_fn GRAPH_RDLOCK
528
+throttle_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
529
+ BdrvRequestFlags flags)
530
{
531
ThrottleGroupMember *tgm = bs->opaque;
532
throttle_group_co_io_limits_intercept(tgm, bytes, true);
34
--
533
--
35
2.20.1
534
2.39.2
36
37
diff view generated by jsdifflib
1
The new device_id property specifies which value to use for the vendor
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
specific designator in the Device Identification VPD page.
2
bdrv_driver_*() need to hold a reader lock for the graph. It doesn't add
3
the annotation to public functions yet.
3
4
4
In particular, this is necessary for libvirt to maintain guest ABI
5
For some places, we know that they will hold the lock, but we don't have
5
compatibility when no serial number is given and a VM is switched from
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
-drive (where the BlockBackend name is used) to -blockdev (where the
7
with a FIXME comment. These places will be removed once everything is
7
vendor specific designator is left out by default).
8
properly annotated.
8
9
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-Id: <20230203152202.49054-11-kwolf@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
14
---
12
hw/scsi/scsi-disk.c | 24 ++++++++++++++++--------
15
block/qcow2.h | 5 ++-
13
1 file changed, 16 insertions(+), 8 deletions(-)
16
include/block/block_int-common.h | 40 ++++++++++---------
17
block/io.c | 66 +++++++++++++++-----------------
18
block/parallels.c | 8 ++--
19
block/qcow.c | 20 ++++------
20
block/qcow2-cluster.c | 10 ++---
21
block/qcow2.c | 37 ++++++++++--------
22
block/qed.c | 14 +++----
23
block/quorum.c | 8 ++--
24
block/vmdk.c | 4 +-
25
10 files changed, 101 insertions(+), 111 deletions(-)
14
26
15
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
27
diff --git a/block/qcow2.h b/block/qcow2.h
16
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/scsi/scsi-disk.c
29
--- a/block/qcow2.h
18
+++ b/hw/scsi/scsi-disk.c
30
+++ b/block/qcow2.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct SCSIDiskState
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
20
char *serial;
32
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
21
char *vendor;
33
uint64_t *coffset, int *csize);
22
char *product;
34
23
+ char *device_id;
35
-int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
24
bool tray_open;
36
- QCowL2Meta *m);
25
bool tray_locked;
37
+int coroutine_fn GRAPH_RDLOCK
38
+qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
39
+
40
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
41
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
42
uint64_t bytes, enum qcow2_discard_type type,
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
Error **errp);
49
50
/* aio */
51
- BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
52
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs,
53
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
54
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
55
- BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
56
+
57
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pwritev)(BlockDriverState *bs,
58
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
59
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
60
+
61
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
62
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
63
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
65
BlockDriverState *bs, int64_t offset, int bytes,
66
BlockCompletionFunc *cb, void *opaque);
67
68
- int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
69
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_readv)(BlockDriverState *bs,
70
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
71
72
/**
73
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
74
*
75
* The buffer in @qiov may point directly to guest memory.
76
*/
77
- int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
78
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv)(BlockDriverState *bs,
79
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
80
BdrvRequestFlags flags);
81
82
- int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs,
83
- int64_t offset, int64_t bytes,
84
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_part)(
85
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
86
QEMUIOVector *qiov, size_t qiov_offset,
87
BdrvRequestFlags flags);
88
89
- int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
90
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_writev)(BlockDriverState *bs,
91
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
92
int flags);
93
/**
94
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
95
*
96
* The buffer in @qiov may point directly to guest memory.
97
*/
98
- int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
99
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
100
- BdrvRequestFlags flags);
101
- int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs,
102
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset,
103
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev)(
104
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
105
BdrvRequestFlags flags);
106
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_part)(
107
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
108
+ size_t qiov_offset, BdrvRequestFlags flags);
109
26
/*
110
/*
27
@@ -XXX,XX +XXX,XX @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
111
* Efficiently zero a region of the disk image. Typically an image format
28
112
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
29
case 0x83: /* Device identification page, mandatory */
113
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
30
{
114
Error **errp);
31
- const char *str = s->serial ?: blk_name(s->qdev.conf.blk);
115
32
- int max_len = s->serial ? 20 : 255 - 8;
116
- int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
33
- int id_len = strlen(str);
117
- int64_t offset, int64_t bytes, QEMUIOVector *qiov);
34
+ int id_len = s->device_id ? MIN(strlen(s->device_id), 255 - 8) : 0;
118
- int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs,
35
119
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
36
- if (id_len > max_len) {
120
- size_t qiov_offset);
37
- id_len = max_len;
121
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed)(
38
- }
122
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
39
DPRINTF("Inquiry EVPD[Device identification] "
123
+ QEMUIOVector *qiov);
40
"buffer size %zd\n", req->cmd.xfer);
124
+
41
125
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed_part)(
42
@@ -XXX,XX +XXX,XX @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
126
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
43
outbuf[buflen++] = 0; /* not officially assigned */
127
+ QEMUIOVector *qiov, size_t qiov_offset);
44
outbuf[buflen++] = 0; /* reserved */
128
45
outbuf[buflen++] = id_len; /* length of data following */
129
int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
46
- memcpy(outbuf + buflen, str, id_len);
130
BlockDriverInfo *bdi);
47
+ memcpy(outbuf + buflen, s->device_id, id_len);
131
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
buflen += id_len;
132
BlockDriverState *bs, const char *name, Error **errp);
49
}
133
};
50
134
51
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
135
-static inline bool block_driver_can_compress(BlockDriver *drv)
52
if (!s->vendor) {
136
+static inline bool TSA_NO_TSA block_driver_can_compress(BlockDriver *drv)
53
s->vendor = g_strdup("QEMU");
137
{
138
return drv->bdrv_co_pwritev_compressed ||
139
drv->bdrv_co_pwritev_compressed_part;
140
diff --git a/block/io.c b/block/io.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/io.c
143
+++ b/block/io.c
144
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
145
bool have_limits;
146
147
GLOBAL_STATE_CODE();
148
+ assume_graph_lock(); /* FIXME */
149
150
if (tran) {
151
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
152
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
153
aio_co_wake(co->coroutine);
154
}
155
156
-static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
157
- int64_t offset, int64_t bytes,
158
- QEMUIOVector *qiov,
159
- size_t qiov_offset, int flags)
160
+static int coroutine_fn GRAPH_RDLOCK
161
+bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
162
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
163
{
164
BlockDriver *drv = bs->drv;
165
int64_t sector_num;
166
@@ -XXX,XX +XXX,XX @@ out:
167
return ret;
168
}
169
170
-static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
171
- int64_t offset, int64_t bytes,
172
- QEMUIOVector *qiov,
173
- size_t qiov_offset,
174
- BdrvRequestFlags flags)
175
+static int coroutine_fn GRAPH_RDLOCK
176
+bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
177
+ QEMUIOVector *qiov, size_t qiov_offset,
178
+ BdrvRequestFlags flags)
179
{
180
BlockDriver *drv = bs->drv;
181
bool emulate_fua = false;
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
183
QEMUIOVector local_qiov;
184
int ret;
185
186
- assume_graph_lock(); /* FIXME */
187
-
188
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
189
190
if (!drv) {
191
@@ -XXX,XX +XXX,XX @@ emulate_flags:
192
return ret;
193
}
194
195
-static int coroutine_fn
196
+static int coroutine_fn GRAPH_RDLOCK
197
bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
198
int64_t bytes, QEMUIOVector *qiov,
199
size_t qiov_offset)
200
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
201
return ret;
202
}
203
204
-static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
205
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
206
- size_t qiov_offset, int flags)
207
+static int coroutine_fn GRAPH_RDLOCK
208
+bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
209
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
210
{
211
BlockDriverState *bs = child->bs;
212
213
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
214
int64_t progress = 0;
215
bool skip_write;
216
217
- assume_graph_lock(); /* FIXME */
218
-
219
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
220
221
if (!drv) {
222
@@ -XXX,XX +XXX,XX @@ err:
223
* handles copy on read, zeroing after EOF, and fragmentation of large
224
* reads; any other features must be implemented by the caller.
225
*/
226
-static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
227
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
228
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
229
+static int coroutine_fn GRAPH_RDLOCK
230
+bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
231
+ int64_t offset, int64_t bytes, int64_t align,
232
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
233
{
234
BlockDriverState *bs = child->bs;
235
int64_t total_bytes, max_bytes;
236
@@ -XXX,XX +XXX,XX @@ static bool bdrv_init_padding(BlockDriverState *bs,
237
return true;
238
}
239
240
-static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
241
- BdrvTrackedRequest *req,
242
- BdrvRequestPadding *pad,
243
- bool zero_middle)
244
+static int coroutine_fn GRAPH_RDLOCK
245
+bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req,
246
+ BdrvRequestPadding *pad, bool zero_middle)
247
{
248
QEMUIOVector local_qiov;
249
BlockDriverState *bs = child->bs;
250
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
251
int ret;
252
IO_CODE();
253
254
+ assume_graph_lock(); /* FIXME */
255
+
256
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
257
258
if (!bdrv_co_is_inserted(bs)) {
259
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
260
* Forwards an already correctly aligned write request to the BlockDriver,
261
* after possibly fragmenting it.
262
*/
263
-static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
264
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
265
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset,
266
- BdrvRequestFlags flags)
267
+static int coroutine_fn GRAPH_RDLOCK
268
+bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req,
269
+ int64_t offset, int64_t bytes, int64_t align,
270
+ QEMUIOVector *qiov, size_t qiov_offset,
271
+ BdrvRequestFlags flags)
272
{
273
BlockDriverState *bs = child->bs;
274
BlockDriver *drv = bs->drv;
275
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
276
int64_t bytes_remaining = bytes;
277
int max_transfer;
278
279
- assume_graph_lock(); /* FIXME */
280
-
281
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
282
283
if (!drv) {
284
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
285
return ret;
286
}
287
288
-static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
289
- int64_t offset,
290
- int64_t bytes,
291
- BdrvRequestFlags flags,
292
- BdrvTrackedRequest *req)
293
+static int coroutine_fn GRAPH_RDLOCK
294
+bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
295
+ BdrvRequestFlags flags, BdrvTrackedRequest *req)
296
{
297
BlockDriverState *bs = child->bs;
298
QEMUIOVector local_qiov;
299
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
300
bool padded = false;
301
IO_CODE();
302
303
+ assume_graph_lock(); /* FIXME */
304
+
305
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
306
307
if (!bdrv_co_is_inserted(bs)) {
308
diff --git a/block/parallels.c b/block/parallels.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/block/parallels.c
311
+++ b/block/parallels.c
312
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
313
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
314
}
315
316
-static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
317
- int64_t sector_num, int nb_sectors,
318
- QEMUIOVector *qiov, int flags)
319
+static int coroutine_fn GRAPH_RDLOCK
320
+parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
321
+ QEMUIOVector *qiov, int flags)
322
{
323
BDRVParallelsState *s = bs->opaque;
324
uint64_t bytes_done = 0;
325
QEMUIOVector hd_qiov;
326
int ret = 0;
327
328
- assume_graph_lock(); /* FIXME */
329
-
330
qemu_iovec_init(&hd_qiov, qiov->niov);
331
332
while (nb_sectors > 0) {
333
diff --git a/block/qcow.c b/block/qcow.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/block/qcow.c
336
+++ b/block/qcow.c
337
@@ -XXX,XX +XXX,XX @@ static void qcow_refresh_limits(BlockDriverState *bs, Error **errp)
338
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
339
}
340
341
-static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
342
- int64_t bytes, QEMUIOVector *qiov,
343
- BdrvRequestFlags flags)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
346
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
347
{
348
BDRVQcowState *s = bs->opaque;
349
int offset_in_cluster;
350
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
351
uint8_t *buf;
352
void *orig_buf;
353
354
- assume_graph_lock(); /* FIXME */
355
-
356
if (qiov->niov > 1) {
357
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
358
if (buf == NULL) {
359
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
360
return ret;
361
}
362
363
-static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
364
- int64_t bytes, QEMUIOVector *qiov,
365
- BdrvRequestFlags flags)
366
+static int coroutine_fn GRAPH_RDLOCK
367
+qcow_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
368
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
369
{
370
BDRVQcowState *s = bs->opaque;
371
int offset_in_cluster;
372
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
373
uint8_t *buf;
374
void *orig_buf;
375
376
- assume_graph_lock(); /* FIXME */
377
-
378
s->cluster_cache_offset = -1; /* disable compressed cache */
379
380
/* We must always copy the iov when encrypting, so we
381
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
382
383
/* XXX: put compressed sectors first, then all the cluster aligned
384
tables to avoid losing bytes in alignment */
385
-static coroutine_fn int
386
+static int coroutine_fn GRAPH_RDLOCK
387
qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
388
QEMUIOVector *qiov)
389
{
390
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
391
uint8_t *buf, *out_buf;
392
uint64_t cluster_offset;
393
394
- assume_graph_lock(); /* FIXME */
395
-
396
buf = qemu_blockalign(bs, s->cluster_size);
397
if (bytes != s->cluster_size) {
398
if (bytes > s->cluster_size ||
399
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/block/qcow2-cluster.c
402
+++ b/block/qcow2-cluster.c
403
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
404
return count;
405
}
406
407
-static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
408
- uint64_t src_cluster_offset,
409
- unsigned offset_in_cluster,
410
- QEMUIOVector *qiov)
411
+static int coroutine_fn GRAPH_RDLOCK
412
+do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
413
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
414
{
415
int ret;
416
417
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
418
return 0;
419
}
420
421
-static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m)
422
+static int coroutine_fn GRAPH_RDLOCK
423
+perform_cow(BlockDriverState *bs, QCowL2Meta *m)
424
{
425
BDRVQcow2State *s = bs->opaque;
426
Qcow2COWRegion *start = &m->cow_start;
427
diff --git a/block/qcow2.c b/block/qcow2.c
428
index XXXXXXX..XXXXXXX 100644
429
--- a/block/qcow2.c
430
+++ b/block/qcow2.c
431
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
432
return status;
433
}
434
435
-static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
436
- QCowL2Meta **pl2meta,
437
- bool link_l2)
438
+static int coroutine_fn GRAPH_RDLOCK
439
+qcow2_handle_l2meta(BlockDriverState *bs, QCowL2Meta **pl2meta, bool link_l2)
440
{
441
int ret = 0;
442
QCowL2Meta *l2meta = *pl2meta;
443
@@ -XXX,XX +XXX,XX @@ static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
444
t->l2meta);
445
}
446
447
-static coroutine_fn int qcow2_co_pwritev_part(
448
- BlockDriverState *bs, int64_t offset, int64_t bytes,
449
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
450
+static int coroutine_fn GRAPH_RDLOCK
451
+qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
452
+ QEMUIOVector *qiov, size_t qiov_offset,
453
+ BdrvRequestFlags flags)
454
{
455
BDRVQcow2State *s = bs->opaque;
456
int offset_in_cluster;
457
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
458
QCowL2Meta *l2meta = NULL;
459
AioTaskPool *aio = NULL;
460
461
- assume_graph_lock(); /* FIXME */
462
-
463
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
464
465
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
466
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
467
uint64_t host_offset;
468
QCowL2Meta *l2meta = NULL;
469
470
+ assume_graph_lock(); /* FIXME */
471
assert(!bs->encrypted);
472
473
qemu_co_mutex_lock(&s->lock);
474
@@ -XXX,XX +XXX,XX @@ fail:
475
return ret;
476
}
477
478
-static coroutine_fn int
479
+static int coroutine_fn GRAPH_RDLOCK
480
qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
481
uint64_t offset, uint64_t bytes,
482
QEMUIOVector *qiov, size_t qiov_offset)
483
@@ -XXX,XX +XXX,XX @@ fail:
484
return ret;
485
}
486
487
-static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
488
+/*
489
+ * This function can count as GRAPH_RDLOCK because
490
+ * qcow2_co_pwritev_compressed_part() holds the graph lock and keeps it until
491
+ * this coroutine has terminated.
492
+ */
493
+static int coroutine_fn GRAPH_RDLOCK
494
+qcow2_co_pwritev_compressed_task_entry(AioTask *task)
495
{
496
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
497
498
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
499
* XXX: put compressed sectors first, then all the cluster aligned
500
* tables to avoid losing bytes in alignment
501
*/
502
-static coroutine_fn int
503
+static int coroutine_fn GRAPH_RDLOCK
504
qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
505
int64_t offset, int64_t bytes,
506
QEMUIOVector *qiov, size_t qiov_offset)
507
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
508
AioTaskPool *aio = NULL;
509
int ret = 0;
510
511
- assume_graph_lock(); /* FIXME */
512
-
513
if (has_data_file(bs)) {
514
return -ENOTSUP;
54
}
515
}
55
+ if (!s->device_id) {
516
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
56
+ if (s->serial) {
517
return pos;
57
+ s->device_id = g_strdup_printf("%.20s", s->serial);
518
}
58
+ } else {
519
59
+ const char *str = blk_name(s->qdev.conf.blk);
520
-static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
60
+ if (str && *str) {
521
- QEMUIOVector *qiov, int64_t pos)
61
+ s->device_id = g_strdup(str);
522
+static int coroutine_fn GRAPH_RDLOCK
62
+ }
523
+qcow2_co_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
63
+ }
524
{
64
+ }
525
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
65
526
if (offset < 0) {
66
if (blk_is_sg(s->qdev.conf.blk)) {
527
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
67
error_setg(errp, "unwanted /dev/sg*");
528
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
68
@@ -XXX,XX +XXX,XX @@ static const TypeInfo scsi_disk_base_info = {
529
}
69
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
530
70
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
531
-static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
71
DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
532
- QEMUIOVector *qiov, int64_t pos)
72
- DEFINE_PROP_STRING("product", SCSIDiskState, product)
533
+static int coroutine_fn GRAPH_RDLOCK
73
+ DEFINE_PROP_STRING("product", SCSIDiskState, product), \
534
+qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
74
+ DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id)
535
{
75
+
536
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
76
537
if (offset < 0) {
77
static Property scsi_hd_properties[] = {
538
diff --git a/block/qed.c b/block/qed.c
78
DEFINE_SCSI_DISK_PROPERTIES(),
539
index XXXXXXX..XXXXXXX 100644
540
--- a/block/qed.c
541
+++ b/block/qed.c
542
@@ -XXX,XX +XXX,XX @@ qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
543
return qed_aio_next_io(&acb);
544
}
545
546
-static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
547
- int64_t sector_num, int nb_sectors,
548
- QEMUIOVector *qiov)
549
+static int coroutine_fn GRAPH_RDLOCK
550
+bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
551
+ QEMUIOVector *qiov)
552
{
553
- assume_graph_lock(); /* FIXME */
554
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
555
}
556
557
-static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
558
- int64_t sector_num, int nb_sectors,
559
- QEMUIOVector *qiov, int flags)
560
+static int coroutine_fn GRAPH_RDLOCK
561
+bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
562
+ QEMUIOVector *qiov, int flags)
563
{
564
- assume_graph_lock(); /* FIXME */
565
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
566
}
567
568
diff --git a/block/quorum.c b/block/quorum.c
569
index XXXXXXX..XXXXXXX 100644
570
--- a/block/quorum.c
571
+++ b/block/quorum.c
572
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
573
}
574
}
575
576
-static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
577
- int64_t bytes, QEMUIOVector *qiov,
578
- BdrvRequestFlags flags)
579
+static int coroutine_fn GRAPH_RDLOCK
580
+quorum_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
581
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
582
{
583
BDRVQuorumState *s = bs->opaque;
584
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
585
int i, ret;
586
587
- assume_graph_lock(); /* FIXME */
588
-
589
for (i = 0; i < s->num_children; i++) {
590
Coroutine *co;
591
QuorumCo data = {
592
diff --git a/block/vmdk.c b/block/vmdk.c
593
index XXXXXXX..XXXXXXX 100644
594
--- a/block/vmdk.c
595
+++ b/block/vmdk.c
596
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
597
return ret;
598
}
599
600
-static int coroutine_fn
601
+static int coroutine_fn GRAPH_RDLOCK
602
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
603
QEMUIOVector *qiov)
604
{
605
- assume_graph_lock(); /* FIXME */
606
-
607
if (bytes == 0) {
608
/* The caller will write bytes 0 to signal EOF.
609
* When receive it, we align EOF to a sector boundary. */
79
--
610
--
80
2.20.1
611
2.39.2
81
82
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_pread*/pwrite*() need to hold a reader lock for the graph.
2
3
3
We define 54 macros for the powers of two >= 1024. We use six, in six
4
For some places, we know that they will hold the lock, but we don't have
4
macro definitions. Four of them could just as well use the common MiB
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
macro, so do that. The remaining two can't, because they get passed
6
with a FIXME comment. These places will be removed once everything is
6
to stringify. Replace the macro by the literal number there.
7
properly annotated.
7
Slightly harder to read in one instance (1048576 vs. S_1MiB), so add a
8
comment there. The other instance is a wash: 65536 vs S_64KiB. 65536
9
has been good enough for more than seven years there.
10
8
11
This effectively reverts commit 540b8492618 and 1240ac558d3.
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
10
Message-Id: <20230203152202.49054-12-kwolf@redhat.com>
13
Signed-off-by: Markus Armbruster <armbru@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
13
---
19
block/qcow2.h | 10 +++---
14
block/qcow2.h | 9 ++---
20
include/qemu/units.h | 73 --------------------------------------------
15
block/qed.h | 18 +++++-----
21
block/vdi.c | 3 +-
16
include/block/block_int-io.h | 14 ++++----
22
3 files changed, 7 insertions(+), 79 deletions(-)
17
block/blkdebug.c | 4 +--
18
block/blklogwrites.c | 7 ++--
19
block/blkreplay.c | 10 +++---
20
block/block-backend.c | 2 ++
21
block/bochs.c | 2 +-
22
block/commit.c | 5 +--
23
block/copy-before-write.c | 16 ++++-----
24
block/copy-on-read.c | 26 ++++++---------
25
block/crypto.c | 4 +--
26
block/filter-compress.c | 19 +++++------
27
block/io.c | 7 ++--
28
block/mirror.c | 18 +++++-----
29
block/parallels.c | 8 +++--
30
block/preallocate.c | 18 +++++-----
31
block/qcow.c | 8 ++---
32
block/qcow2-cluster.c | 7 ++--
33
block/qcow2.c | 53 +++++++++++++++--------------
34
block/qed-table.c | 4 +--
35
block/qed.c | 31 +++++++++--------
36
block/quorum.c | 29 ++++++++++------
37
block/raw-format.c | 12 +++----
38
block/replication.c | 15 ++++-----
39
block/throttle.c | 21 +++++-------
40
block/vdi.c | 4 +--
41
block/vhdx.c | 11 +++---
42
block/vmdk.c | 65 +++++++++++++++---------------------
43
block/vpc.c | 4 +--
44
tests/unit/test-bdrv-drain.c | 20 ++++++-----
45
31 files changed, 233 insertions(+), 238 deletions(-)
23
46
24
diff --git a/block/qcow2.h b/block/qcow2.h
47
diff --git a/block/qcow2.h b/block/qcow2.h
25
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.h
49
--- a/block/qcow2.h
27
+++ b/block/qcow2.h
50
+++ b/block/qcow2.h
51
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
52
Error **errp);
53
54
/* qcow2-refcount.c functions */
55
-int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
56
+int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs);
57
void qcow2_refcount_close(BlockDriverState *bs);
58
59
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
60
@@ -XXX,XX +XXX,XX @@ void qcow2_free_snapshots(BlockDriverState *bs);
61
int qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
62
int qcow2_write_snapshots(BlockDriverState *bs);
63
64
-int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
65
- BdrvCheckResult *result,
66
- BdrvCheckMode fix);
67
+int coroutine_fn GRAPH_RDLOCK
68
+qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
69
+ BdrvCheckMode fix);
70
+
71
int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
72
BdrvCheckResult *result,
73
BdrvCheckMode fix);
74
diff --git a/block/qed.h b/block/qed.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/qed.h
77
+++ b/block/qed.h
78
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
79
/**
80
* Table I/O functions
81
*/
82
-int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
83
+int coroutine_fn GRAPH_RDLOCK qed_read_l1_table_sync(BDRVQEDState *s);
84
85
int coroutine_fn GRAPH_RDLOCK
86
qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
87
@@ -XXX,XX +XXX,XX @@ qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
88
int coroutine_fn GRAPH_RDLOCK
89
qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
90
91
-int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
92
- uint64_t offset);
93
-int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
94
- uint64_t offset);
95
+int coroutine_fn GRAPH_RDLOCK
96
+qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
97
+
98
+int coroutine_fn GRAPH_RDLOCK
99
+qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
100
101
int coroutine_fn GRAPH_RDLOCK
102
qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
103
@@ -XXX,XX +XXX,XX @@ qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
104
/**
105
* Cluster functions
106
*/
107
-int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
108
- uint64_t pos, size_t *len,
109
- uint64_t *img_offset);
110
+int coroutine_fn GRAPH_RDLOCK
111
+qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
112
+ size_t *len, uint64_t *img_offset);
113
114
/**
115
* Consistency check
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
117
int coroutine_fn GRAPH_RDLOCK
118
qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
119
120
-
121
QEDTable *qed_alloc_table(BDRVQEDState *s);
122
123
/**
124
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
125
index XXXXXXX..XXXXXXX 100644
126
--- a/include/block/block_int-io.h
127
+++ b/include/block/block_int-io.h
128
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
129
int64_t offset, int64_t bytes);
130
131
132
-int coroutine_fn bdrv_co_preadv(BdrvChild *child,
133
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child,
134
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
135
BdrvRequestFlags flags);
136
-int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
137
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child,
138
int64_t offset, int64_t bytes,
139
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
140
-int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
141
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child,
142
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
143
BdrvRequestFlags flags);
144
-int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
145
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child,
146
int64_t offset, int64_t bytes,
147
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
148
149
-static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
150
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child,
151
int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
152
{
153
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
154
IO_CODE();
155
+ assert_bdrv_graph_readable();
156
157
return bdrv_co_preadv(child, offset, bytes, &qiov, flags);
158
}
159
160
-static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
161
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child,
162
int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
163
{
164
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
165
IO_CODE();
166
+ assert_bdrv_graph_readable();
167
168
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
169
}
170
diff --git a/block/blkdebug.c b/block/blkdebug.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/blkdebug.c
173
+++ b/block/blkdebug.c
174
@@ -XXX,XX +XXX,XX @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
175
return -error;
176
}
177
178
-static int coroutine_fn
179
+static int coroutine_fn GRAPH_RDLOCK
180
blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
181
QEMUIOVector *qiov, BdrvRequestFlags flags)
182
{
183
@@ -XXX,XX +XXX,XX @@ blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
184
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
185
}
186
187
-static int coroutine_fn
188
+static int coroutine_fn GRAPH_RDLOCK
189
blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
190
QEMUIOVector *qiov, BdrvRequestFlags flags)
191
{
192
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/blklogwrites.c
195
+++ b/block/blklogwrites.c
196
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
197
bs->bl.request_alignment = s->sectorsize;
198
}
199
200
-static int coroutine_fn
201
+static int coroutine_fn GRAPH_RDLOCK
202
blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
203
QEMUIOVector *qiov, BdrvRequestFlags flags)
204
{
205
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
206
return fr.file_ret;
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
212
{
213
return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes,
214
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
215
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
216
}
217
218
-static int coroutine_fn
219
+static int coroutine_fn GRAPH_RDLOCK
220
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
221
QEMUIOVector *qiov, BdrvRequestFlags flags)
222
{
223
- assume_graph_lock(); /* FIXME */
224
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
225
blk_log_writes_co_do_file_pwritev, 0, false);
226
}
227
diff --git a/block/blkreplay.c b/block/blkreplay.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/block/blkreplay.c
230
+++ b/block/blkreplay.c
231
@@ -XXX,XX +XXX,XX @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
232
replay_block_event(req->bh, reqid);
233
}
234
235
-static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
236
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
237
+static int coroutine_fn GRAPH_RDLOCK
238
+blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
239
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
240
{
241
uint64_t reqid = blkreplay_next_id();
242
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
243
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
244
return ret;
245
}
246
247
-static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
248
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
249
+static int coroutine_fn GRAPH_RDLOCK
250
+blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
251
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
252
{
253
uint64_t reqid = blkreplay_next_id();
254
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
255
diff --git a/block/block-backend.c b/block/block-backend.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/block/block-backend.c
258
+++ b/block/block-backend.c
259
@@ -XXX,XX +XXX,XX @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
260
IO_CODE();
261
262
blk_wait_while_drained(blk);
263
+ GRAPH_RDLOCK_GUARD();
264
265
/* Call blk_bs() only after waiting, the graph may have changed */
266
bs = blk_bs(blk);
267
@@ -XXX,XX +XXX,XX @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
268
IO_CODE();
269
270
blk_wait_while_drained(blk);
271
+ GRAPH_RDLOCK_GUARD();
272
273
/* Call blk_bs() only after waiting, the graph may have changed */
274
bs = blk_bs(blk);
275
diff --git a/block/bochs.c b/block/bochs.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/block/bochs.c
278
+++ b/block/bochs.c
279
@@ -XXX,XX +XXX,XX @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
280
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
281
}
282
283
-static int coroutine_fn
284
+static int coroutine_fn GRAPH_RDLOCK
285
bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
286
QEMUIOVector *qiov, BdrvRequestFlags flags)
287
{
288
diff --git a/block/commit.c b/block/commit.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/block/commit.c
291
+++ b/block/commit.c
292
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver commit_job_driver = {
293
},
294
};
295
296
-static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
297
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
298
+static int coroutine_fn GRAPH_RDLOCK
299
+bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
300
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
301
{
302
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
303
}
304
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
305
index XXXXXXX..XXXXXXX 100644
306
--- a/block/copy-before-write.c
307
+++ b/block/copy-before-write.c
308
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVCopyBeforeWriteState {
309
int snapshot_error;
310
} BDRVCopyBeforeWriteState;
311
312
-static coroutine_fn int cbw_co_preadv(
313
- BlockDriverState *bs, int64_t offset, int64_t bytes,
314
- QEMUIOVector *qiov, BdrvRequestFlags flags)
315
+static int coroutine_fn GRAPH_RDLOCK
316
+cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
317
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
318
{
319
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
320
}
321
@@ -XXX,XX +XXX,XX @@ cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
322
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
323
}
324
325
-static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
326
- int64_t offset,
327
- int64_t bytes,
328
- QEMUIOVector *qiov,
329
- BdrvRequestFlags flags)
330
+static coroutine_fn GRAPH_RDLOCK
331
+int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
333
{
334
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
335
if (ret < 0) {
336
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
337
BdrvChild *file;
338
int ret;
339
340
+ assume_graph_lock(); /* FIXME */
341
+
342
/* TODO: upgrade to async loop using AioTask */
343
while (bytes) {
344
int64_t cur_bytes;
345
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/block/copy-on-read.c
348
+++ b/block/copy-on-read.c
349
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
350
}
351
352
353
-static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
354
- int64_t offset, int64_t bytes,
355
- QEMUIOVector *qiov,
356
- size_t qiov_offset,
357
- BdrvRequestFlags flags)
358
+static int coroutine_fn GRAPH_RDLOCK
359
+cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
360
+ QEMUIOVector *qiov, size_t qiov_offset,
361
+ BdrvRequestFlags flags)
362
{
363
int64_t n;
364
int local_flags;
365
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
366
}
367
368
369
-static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
370
- int64_t offset,
371
- int64_t bytes,
372
- QEMUIOVector *qiov,
373
- size_t qiov_offset,
374
- BdrvRequestFlags flags)
375
+static int coroutine_fn GRAPH_RDLOCK
376
+cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
377
+ QEMUIOVector *qiov, size_t qiov_offset,
378
+ BdrvRequestFlags flags)
379
{
380
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
381
flags);
382
@@ -XXX,XX +XXX,XX @@ cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
383
}
384
385
386
-static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
387
- int64_t offset,
388
- int64_t bytes,
389
- QEMUIOVector *qiov)
390
+static int coroutine_fn GRAPH_RDLOCK
391
+cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
392
+ QEMUIOVector *qiov)
393
{
394
return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
395
BDRV_REQ_WRITE_COMPRESSED);
396
diff --git a/block/crypto.c b/block/crypto.c
397
index XXXXXXX..XXXXXXX 100644
398
--- a/block/crypto.c
399
+++ b/block/crypto.c
400
@@ -XXX,XX +XXX,XX @@ static int block_crypto_reopen_prepare(BDRVReopenState *state,
401
*/
402
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
403
404
-static coroutine_fn int
405
+static int coroutine_fn GRAPH_RDLOCK
406
block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
407
QEMUIOVector *qiov, BdrvRequestFlags flags)
408
{
409
@@ -XXX,XX +XXX,XX @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
410
}
411
412
413
-static coroutine_fn int
414
+static int coroutine_fn GRAPH_RDLOCK
415
block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
416
QEMUIOVector *qiov, BdrvRequestFlags flags)
417
{
418
diff --git a/block/filter-compress.c b/block/filter-compress.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/filter-compress.c
421
+++ b/block/filter-compress.c
422
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
423
}
424
425
426
-static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
427
- int64_t offset, int64_t bytes,
428
- QEMUIOVector *qiov,
429
- size_t qiov_offset,
430
- BdrvRequestFlags flags)
431
+static int coroutine_fn GRAPH_RDLOCK
432
+compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
433
+ QEMUIOVector *qiov, size_t qiov_offset,
434
+ BdrvRequestFlags flags)
435
{
436
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
437
flags);
438
}
439
440
441
-static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
442
- int64_t offset,
443
- int64_t bytes,
444
- QEMUIOVector *qiov,
445
- size_t qiov_offset,
446
- BdrvRequestFlags flags)
447
+static int coroutine_fn GRAPH_RDLOCK
448
+compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
449
+ QEMUIOVector *qiov, size_t qiov_offset,
450
+ BdrvRequestFlags flags)
451
{
452
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
453
flags | BDRV_REQ_WRITE_COMPRESSED);
454
diff --git a/block/io.c b/block/io.c
455
index XXXXXXX..XXXXXXX 100644
456
--- a/block/io.c
457
+++ b/block/io.c
458
@@ -XXX,XX +XXX,XX @@ bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
459
unsigned int nb_sectors;
460
QEMUIOVector local_qiov;
461
int ret;
462
+ assert_bdrv_graph_readable();
463
464
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
465
assert(!(flags & ~bs->supported_read_flags));
466
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
467
unsigned int nb_sectors;
468
QEMUIOVector local_qiov;
469
int ret;
470
+ assert_bdrv_graph_readable();
471
472
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
473
474
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
475
BlockDriver *drv = bs->drv;
476
QEMUIOVector local_qiov;
477
int ret;
478
+ assert_bdrv_graph_readable();
479
480
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
481
482
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
483
int ret;
484
IO_CODE();
485
486
- assume_graph_lock(); /* FIXME */
487
-
488
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
489
490
if (!bdrv_co_is_inserted(bs)) {
491
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
492
bool padded = false;
493
IO_CODE();
494
495
- assume_graph_lock(); /* FIXME */
496
-
497
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
498
499
if (!bdrv_co_is_inserted(bs)) {
500
diff --git a/block/mirror.c b/block/mirror.c
501
index XXXXXXX..XXXXXXX 100644
502
--- a/block/mirror.c
503
+++ b/block/mirror.c
504
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_co_read(void *opaque)
505
op->is_in_flight = true;
506
trace_mirror_one_iteration(s, op->offset, op->bytes);
507
508
- ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
509
- &op->qiov, 0);
510
+ WITH_GRAPH_RDLOCK_GUARD() {
511
+ ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
512
+ &op->qiov, 0);
513
+ }
514
mirror_read_complete(op, ret);
515
}
516
517
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn active_write_settle(MirrorOp *op)
518
g_free(op);
519
}
520
521
-static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
522
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
525
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
526
{
527
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
528
}
529
@@ -XXX,XX +XXX,XX @@ out:
530
return ret;
531
}
532
533
-static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
534
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
535
+static int coroutine_fn GRAPH_RDLOCK
536
+bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
537
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
538
{
539
MirrorBDSOpaque *s = bs->opaque;
540
QEMUIOVector bounce_qiov;
541
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
542
int ret = 0;
543
bool copy_to_target = false;
544
545
- assume_graph_lock(); /* FIXME */
546
-
547
if (s->job) {
548
copy_to_target = s->job->ret >= 0 &&
549
!job_is_cancelled(&s->job->common.job) &&
550
diff --git a/block/parallels.c b/block/parallels.c
551
index XXXXXXX..XXXXXXX 100644
552
--- a/block/parallels.c
553
+++ b/block/parallels.c
554
@@ -XXX,XX +XXX,XX @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num,
555
}
556
557
558
-static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
559
+static int coroutine_fn GRAPH_RDLOCK
560
+parallels_co_flush_to_os(BlockDriverState *bs)
561
{
562
BDRVParallelsState *s = bs->opaque;
563
unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
564
@@ -XXX,XX +XXX,XX @@ parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
565
return ret;
566
}
567
568
-static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
569
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
570
+static int coroutine_fn GRAPH_RDLOCK
571
+parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
572
+ QEMUIOVector *qiov)
573
{
574
BDRVParallelsState *s = bs->opaque;
575
uint64_t bytes_done = 0;
576
diff --git a/block/preallocate.c b/block/preallocate.c
577
index XXXXXXX..XXXXXXX 100644
578
--- a/block/preallocate.c
579
+++ b/block/preallocate.c
580
@@ -XXX,XX +XXX,XX @@ static void preallocate_reopen_abort(BDRVReopenState *state)
581
state->opaque = NULL;
582
}
583
584
-static coroutine_fn int preallocate_co_preadv_part(
585
- BlockDriverState *bs, int64_t offset, int64_t bytes,
586
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
587
+static int coroutine_fn GRAPH_RDLOCK
588
+preallocate_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
589
+ QEMUIOVector *qiov, size_t qiov_offset,
590
+ BdrvRequestFlags flags)
591
{
592
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
593
flags);
594
@@ -XXX,XX +XXX,XX @@ preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
595
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
596
}
597
598
-static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
599
- int64_t offset,
600
- int64_t bytes,
601
- QEMUIOVector *qiov,
602
- size_t qiov_offset,
603
- BdrvRequestFlags flags)
604
+static int coroutine_fn GRAPH_RDLOCK
605
+preallocate_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
606
+ QEMUIOVector *qiov, size_t qiov_offset,
607
+ BdrvRequestFlags flags)
608
{
609
- assume_graph_lock(); /* FIXME */
610
handle_write(bs, offset, bytes, false);
611
612
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
613
diff --git a/block/qcow.c b/block/qcow.c
614
index XXXXXXX..XXXXXXX 100644
615
--- a/block/qcow.c
616
+++ b/block/qcow.c
617
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
618
619
static QemuOptsList qcow_create_opts;
620
621
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
622
- uint64_t cluster_offset);
623
+static int coroutine_fn GRAPH_RDLOCK
624
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
625
626
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
627
{
628
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
629
return 0;
630
}
631
632
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
633
- uint64_t cluster_offset)
634
+static int coroutine_fn GRAPH_RDLOCK
635
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
636
{
637
BDRVQcowState *s = bs->opaque;
638
int ret, csize;
639
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
640
index XXXXXXX..XXXXXXX 100644
641
--- a/block/qcow2-cluster.c
642
+++ b/block/qcow2-cluster.c
643
@@ -XXX,XX +XXX,XX @@ do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
644
return 0;
645
}
646
647
-static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
648
- uint64_t cluster_offset,
649
- unsigned offset_in_cluster,
650
- QEMUIOVector *qiov)
651
+static int coroutine_fn GRAPH_RDLOCK
652
+do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset,
653
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
654
{
655
BDRVQcow2State *s = bs->opaque;
656
int ret;
657
diff --git a/block/qcow2.c b/block/qcow2.c
658
index XXXXXXX..XXXXXXX 100644
659
--- a/block/qcow2.c
660
+++ b/block/qcow2.c
661
@@ -XXX,XX +XXX,XX @@ static void qcow2_add_check_result(BdrvCheckResult *out,
662
}
663
}
664
665
-static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
666
- BdrvCheckResult *result,
667
- BdrvCheckMode fix)
668
+static int coroutine_fn GRAPH_RDLOCK
669
+qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result,
670
+ BdrvCheckMode fix)
671
{
672
BdrvCheckResult snapshot_res = {};
673
BdrvCheckResult refcount_res = {};
674
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
675
return ret;
676
}
677
678
-static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
679
- BdrvCheckResult *result,
680
- BdrvCheckMode fix)
681
+static int coroutine_fn GRAPH_RDLOCK
682
+qcow2_co_check(BlockDriverState *bs, BdrvCheckResult *result,
683
+ BdrvCheckMode fix)
684
{
685
BDRVQcow2State *s = bs->opaque;
686
int ret;
687
@@ -XXX,XX +XXX,XX @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp)
688
}
689
690
/* Called with s->lock held. */
691
-static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
692
- int flags, bool open_data_file,
693
- Error **errp)
694
+static int coroutine_fn GRAPH_RDLOCK
695
+qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
696
+ bool open_data_file, Error **errp)
697
{
698
ERRP_GUARD();
699
BDRVQcow2State *s = bs->opaque;
700
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_open_entry(void *opaque)
701
QCow2OpenCo *qoc = opaque;
702
BDRVQcow2State *s = qoc->bs->opaque;
703
704
+ assume_graph_lock(); /* FIXME */
705
+
706
qemu_co_mutex_lock(&s->lock);
707
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
708
qoc->errp);
709
@@ -XXX,XX +XXX,XX @@ out:
710
return ret;
711
}
712
713
-static coroutine_fn int
714
+static int coroutine_fn GRAPH_RDLOCK
715
qcow2_co_preadv_encrypted(BlockDriverState *bs,
716
uint64_t host_offset,
717
uint64_t offset,
718
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
719
return 0;
720
}
721
722
-static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
723
- QCow2SubclusterType subc_type,
724
- uint64_t host_offset,
725
- uint64_t offset, uint64_t bytes,
726
- QEMUIOVector *qiov,
727
- size_t qiov_offset)
728
+static int coroutine_fn GRAPH_RDLOCK
729
+qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type,
730
+ uint64_t host_offset, uint64_t offset, uint64_t bytes,
731
+ QEMUIOVector *qiov, size_t qiov_offset)
732
{
733
BDRVQcow2State *s = bs->opaque;
734
735
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
736
g_assert_not_reached();
737
}
738
739
-static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
740
+/*
741
+ * This function can count as GRAPH_RDLOCK because qcow2_co_preadv_part() holds
742
+ * the graph lock and keeps it until this coroutine has terminated.
743
+ */
744
+static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_task_entry(AioTask *task)
745
{
746
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
747
748
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
749
t->qiov, t->qiov_offset);
750
}
751
752
-static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
753
- int64_t offset, int64_t bytes,
754
- QEMUIOVector *qiov,
755
- size_t qiov_offset,
756
- BdrvRequestFlags flags)
757
+static int coroutine_fn GRAPH_RDLOCK
758
+qcow2_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
759
+ QEMUIOVector *qiov, size_t qiov_offset,
760
+ BdrvRequestFlags flags)
761
{
762
BDRVQcow2State *s = bs->opaque;
763
int ret = 0;
764
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
765
qcow2_do_close(bs, true);
766
}
767
768
-static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
769
- Error **errp)
770
+static void coroutine_fn GRAPH_RDLOCK
771
+qcow2_co_invalidate_cache(BlockDriverState *bs, Error **errp)
772
{
773
ERRP_GUARD();
774
BDRVQcow2State *s = bs->opaque;
775
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
776
return ret;
777
}
778
779
-static int coroutine_fn
780
+static int coroutine_fn GRAPH_RDLOCK
781
qcow2_co_preadv_compressed(BlockDriverState *bs,
782
uint64_t l2_entry,
783
uint64_t offset,
784
diff --git a/block/qed-table.c b/block/qed-table.c
785
index XXXXXXX..XXXXXXX 100644
786
--- a/block/qed-table.c
787
+++ b/block/qed-table.c
28
@@ -XXX,XX +XXX,XX @@
788
@@ -XXX,XX +XXX,XX @@
29
789
#include "qemu/memalign.h"
30
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
790
31
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
791
/* Called with table_lock held. */
32
-#define QCOW_MAX_REFTABLE_SIZE S_8MiB
792
-static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
33
+#define QCOW_MAX_REFTABLE_SIZE (8 * MiB)
793
- QEDTable *table)
34
794
+static int coroutine_fn GRAPH_RDLOCK
35
/* 32 MB L1 table is enough for 2 PB images at 64k cluster size
795
+qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
36
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
796
{
37
-#define QCOW_MAX_L1_SIZE S_32MiB
797
unsigned int bytes = s->header.cluster_size * s->header.table_size;
38
+#define QCOW_MAX_L1_SIZE (32 * MiB)
798
39
799
diff --git a/block/qed.c b/block/qed.c
40
/* Allow for an average of 1k per snapshot table entry, should be plenty of
800
index XXXXXXX..XXXXXXX 100644
41
* space for snapshot names and IDs */
801
--- a/block/qed.c
42
@@ -XXX,XX +XXX,XX @@
802
+++ b/block/qed.c
43
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
803
@@ -XXX,XX +XXX,XX @@ int qed_write_header_sync(BDRVQEDState *s)
44
804
*
45
#ifdef CONFIG_LINUX
805
* No new allocating reqs can start while this function runs.
46
-#define DEFAULT_L2_CACHE_MAX_SIZE S_32MiB
806
*/
47
+#define DEFAULT_L2_CACHE_MAX_SIZE (32 * MiB)
807
-static int coroutine_fn qed_write_header(BDRVQEDState *s)
48
#define DEFAULT_CACHE_CLEAN_INTERVAL 600 /* seconds */
808
+static int coroutine_fn GRAPH_RDLOCK qed_write_header(BDRVQEDState *s)
49
#else
809
{
50
-#define DEFAULT_L2_CACHE_MAX_SIZE S_8MiB
810
/* We must write full sectors for O_DIRECT but cannot necessarily generate
51
+#define DEFAULT_L2_CACHE_MAX_SIZE (8 * MiB)
811
* the data following the header if an unrecognized compat feature is
52
/* Cache clean interval is currently available only on Linux, so must be 0 */
812
@@ -XXX,XX +XXX,XX @@ fail:
53
#define DEFAULT_CACHE_CLEAN_INTERVAL 0
813
return ret;
54
#endif
814
}
55
815
56
-#define DEFAULT_CLUSTER_SIZE S_64KiB
816
-static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
57
+#define DEFAULT_CLUSTER_SIZE 65536
817
- bool want_zero,
58
818
- int64_t pos, int64_t bytes,
59
#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts"
819
- int64_t *pnum, int64_t *map,
60
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
820
- BlockDriverState **file)
61
diff --git a/include/qemu/units.h b/include/qemu/units.h
821
+static int coroutine_fn GRAPH_RDLOCK
62
index XXXXXXX..XXXXXXX 100644
822
+bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos,
63
--- a/include/qemu/units.h
823
+ int64_t bytes, int64_t *pnum, int64_t *map,
64
+++ b/include/qemu/units.h
824
+ BlockDriverState **file)
65
@@ -XXX,XX +XXX,XX @@
825
{
66
#define PiB (INT64_C(1) << 50)
826
BDRVQEDState *s = bs->opaque;
67
#define EiB (INT64_C(1) << 60)
827
size_t len = MIN(bytes, SIZE_MAX);
68
828
@@ -XXX,XX +XXX,XX @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
69
-/*
829
* This function reads qiov->size bytes starting at pos from the backing file.
70
- * The following lookup table is intended to be used when a literal string of
830
* If there is no backing file then zeroes are read.
71
- * the number of bytes is required (for example if it needs to be stringified).
831
*/
72
- * It can also be used for generic shortcuts of power-of-two sizes.
832
-static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
73
- * This table is generated using the AWK script below:
833
- QEMUIOVector *qiov)
74
- *
834
+static int coroutine_fn GRAPH_RDLOCK
75
- * BEGIN {
835
+qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov)
76
- * suffix="KMGTPE";
836
{
77
- * for(i=10; i<64; i++) {
837
if (s->bs->backing) {
78
- * val=2**i;
838
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
79
- * s=substr(suffix, int(i/10), 1);
839
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
80
- * n=2**(i%10);
840
* @len: Number of bytes
81
- * pad=21-int(log(n)/log(10));
841
* @offset: Byte offset in image file
82
- * printf("#define S_%d%siB %*d\n", n, s, pad, val);
842
*/
83
- * }
843
-static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
84
- * }
844
- uint64_t pos, uint64_t len,
85
- */
845
- uint64_t offset)
86
-
846
+static int coroutine_fn GRAPH_RDLOCK
87
-#define S_1KiB 1024
847
+qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len,
88
-#define S_2KiB 2048
848
+ uint64_t offset)
89
-#define S_4KiB 4096
849
{
90
-#define S_8KiB 8192
850
QEMUIOVector qiov;
91
-#define S_16KiB 16384
851
int ret;
92
-#define S_32KiB 32768
852
@@ -XXX,XX +XXX,XX @@ qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
93
-#define S_64KiB 65536
853
*
94
-#define S_128KiB 131072
854
* Called with table_lock *not* held.
95
-#define S_256KiB 262144
855
*/
96
-#define S_512KiB 524288
856
-static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
97
-#define S_1MiB 1048576
857
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb)
98
-#define S_2MiB 2097152
858
{
99
-#define S_4MiB 4194304
859
BDRVQEDState *s = acb_to_s(acb);
100
-#define S_8MiB 8388608
860
uint64_t offset = acb->cur_cluster +
101
-#define S_16MiB 16777216
861
@@ -XXX,XX +XXX,XX @@ qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
102
-#define S_32MiB 33554432
862
*
103
-#define S_64MiB 67108864
863
* Called with table_lock held.
104
-#define S_128MiB 134217728
864
*/
105
-#define S_256MiB 268435456
865
-static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset,
106
-#define S_512MiB 536870912
866
- size_t len)
107
-#define S_1GiB 1073741824
867
+static int coroutine_fn GRAPH_RDLOCK
108
-#define S_2GiB 2147483648
868
+qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len)
109
-#define S_4GiB 4294967296
869
{
110
-#define S_8GiB 8589934592
870
BDRVQEDState *s = acb_to_s(acb);
111
-#define S_16GiB 17179869184
871
int r;
112
-#define S_32GiB 34359738368
872
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
113
-#define S_64GiB 68719476736
873
*
114
-#define S_128GiB 137438953472
874
* Called with table_lock held.
115
-#define S_256GiB 274877906944
875
*/
116
-#define S_512GiB 549755813888
876
-static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
117
-#define S_1TiB 1099511627776
877
- uint64_t offset, size_t len)
118
-#define S_2TiB 2199023255552
878
+static int coroutine_fn GRAPH_RDLOCK
119
-#define S_4TiB 4398046511104
879
+qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len)
120
-#define S_8TiB 8796093022208
880
{
121
-#define S_16TiB 17592186044416
881
QEDAIOCB *acb = opaque;
122
-#define S_32TiB 35184372088832
882
BDRVQEDState *s = acb_to_s(acb);
123
-#define S_64TiB 70368744177664
883
diff --git a/block/quorum.c b/block/quorum.c
124
-#define S_128TiB 140737488355328
884
index XXXXXXX..XXXXXXX 100644
125
-#define S_256TiB 281474976710656
885
--- a/block/quorum.c
126
-#define S_512TiB 562949953421312
886
+++ b/block/quorum.c
127
-#define S_1PiB 1125899906842624
887
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
128
-#define S_2PiB 2251799813685248
888
}
129
-#define S_4PiB 4503599627370496
889
}
130
-#define S_8PiB 9007199254740992
890
131
-#define S_16PiB 18014398509481984
891
-static void coroutine_fn quorum_rewrite_entry(void *opaque)
132
-#define S_32PiB 36028797018963968
892
+/*
133
-#define S_64PiB 72057594037927936
893
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
134
-#define S_128PiB 144115188075855872
894
+ * the graph lock and keeps it until this coroutine has terminated.
135
-#define S_256PiB 288230376151711744
895
+ */
136
-#define S_512PiB 576460752303423488
896
+static void coroutine_fn GRAPH_RDLOCK quorum_rewrite_entry(void *opaque)
137
-#define S_1EiB 1152921504606846976
897
{
138
-#define S_2EiB 2305843009213693952
898
QuorumCo *co = opaque;
139
-#define S_4EiB 4611686018427387904
899
QuorumAIOCB *acb = co->acb;
140
-#define S_8EiB 9223372036854775808
900
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn quorum_rewrite_entry(void *opaque)
141
-
901
}
142
#endif
902
}
903
904
-static bool quorum_rewrite_bad_versions(QuorumAIOCB *acb,
905
- QuorumVoteValue *value)
906
+static bool coroutine_fn GRAPH_RDLOCK
907
+quorum_rewrite_bad_versions(QuorumAIOCB *acb, QuorumVoteValue *value)
908
{
909
QuorumVoteVersion *version;
910
QuorumVoteItem *item;
911
@@ -XXX,XX +XXX,XX @@ static int quorum_vote_error(QuorumAIOCB *acb)
912
return ret;
913
}
914
915
-static void quorum_vote(QuorumAIOCB *acb)
916
+static void coroutine_fn GRAPH_RDLOCK quorum_vote(QuorumAIOCB *acb)
917
{
918
bool quorum = true;
919
int i, j, ret;
920
@@ -XXX,XX +XXX,XX @@ free_exit:
921
quorum_free_vote_list(&acb->votes);
922
}
923
924
-static void coroutine_fn read_quorum_children_entry(void *opaque)
925
+/*
926
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
927
+ * the graph lock and keeps it until this coroutine has terminated.
928
+ */
929
+static void coroutine_fn GRAPH_RDLOCK read_quorum_children_entry(void *opaque)
930
{
931
QuorumCo *co = opaque;
932
QuorumAIOCB *acb = co->acb;
933
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn read_quorum_children_entry(void *opaque)
934
}
935
}
936
937
-static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
938
+static int coroutine_fn GRAPH_RDLOCK read_quorum_children(QuorumAIOCB *acb)
939
{
940
BDRVQuorumState *s = acb->bs->opaque;
941
int i;
942
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
943
return acb->vote_ret;
944
}
945
946
-static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
947
+static int coroutine_fn GRAPH_RDLOCK read_fifo_child(QuorumAIOCB *acb)
948
{
949
BDRVQuorumState *s = acb->bs->opaque;
950
int n, ret;
951
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
952
return ret;
953
}
954
955
-static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
956
- int64_t offset, int64_t bytes,
957
- QEMUIOVector *qiov,
958
- BdrvRequestFlags flags)
959
+static int coroutine_fn GRAPH_RDLOCK
960
+quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
961
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
962
{
963
BDRVQuorumState *s = bs->opaque;
964
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
965
diff --git a/block/raw-format.c b/block/raw-format.c
966
index XXXXXXX..XXXXXXX 100644
967
--- a/block/raw-format.c
968
+++ b/block/raw-format.c
969
@@ -XXX,XX +XXX,XX @@ static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
970
return 0;
971
}
972
973
-static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
974
- int64_t bytes, QEMUIOVector *qiov,
975
- BdrvRequestFlags flags)
976
+static int coroutine_fn GRAPH_RDLOCK
977
+raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
978
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
979
{
980
int ret;
981
982
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
983
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
984
}
985
986
-static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
987
- int64_t bytes, QEMUIOVector *qiov,
988
- BdrvRequestFlags flags)
989
+static int coroutine_fn GRAPH_RDLOCK
990
+raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
991
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
992
{
993
void *buf = NULL;
994
BlockDriver *drv;
995
diff --git a/block/replication.c b/block/replication.c
996
index XXXXXXX..XXXXXXX 100644
997
--- a/block/replication.c
998
+++ b/block/replication.c
999
@@ -XXX,XX +XXX,XX @@ static int replication_return_value(BDRVReplicationState *s, int ret)
1000
return ret;
1001
}
1002
1003
-static coroutine_fn int replication_co_readv(BlockDriverState *bs,
1004
- int64_t sector_num,
1005
- int remaining_sectors,
1006
- QEMUIOVector *qiov)
1007
+static int coroutine_fn GRAPH_RDLOCK
1008
+replication_co_readv(BlockDriverState *bs, int64_t sector_num,
1009
+ int remaining_sectors, QEMUIOVector *qiov)
1010
{
1011
BDRVReplicationState *s = bs->opaque;
1012
int ret;
1013
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
1014
return replication_return_value(s, ret);
1015
}
1016
1017
-static coroutine_fn int replication_co_writev(BlockDriverState *bs,
1018
- int64_t sector_num,
1019
- int remaining_sectors,
1020
- QEMUIOVector *qiov,
1021
- int flags)
1022
+static int coroutine_fn GRAPH_RDLOCK
1023
+replication_co_writev(BlockDriverState *bs, int64_t sector_num,
1024
+ int remaining_sectors, QEMUIOVector *qiov, int flags)
1025
{
1026
BDRVReplicationState *s = bs->opaque;
1027
QEMUIOVector hd_qiov;
1028
diff --git a/block/throttle.c b/block/throttle.c
1029
index XXXXXXX..XXXXXXX 100644
1030
--- a/block/throttle.c
1031
+++ b/block/throttle.c
1032
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
1033
return bdrv_co_getlength(bs->file->bs);
1034
}
1035
1036
-static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1037
- int64_t offset, int64_t bytes,
1038
- QEMUIOVector *qiov,
1039
- BdrvRequestFlags flags)
1040
+static int coroutine_fn GRAPH_RDLOCK
1041
+throttle_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1042
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1043
{
1044
1045
ThrottleGroupMember *tgm = bs->opaque;
1046
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1047
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
1048
}
1049
1050
-static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
1051
- int64_t offset, int64_t bytes,
1052
- QEMUIOVector *qiov,
1053
- BdrvRequestFlags flags)
1054
+static int coroutine_fn GRAPH_RDLOCK
1055
+throttle_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1056
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1057
{
1058
ThrottleGroupMember *tgm = bs->opaque;
1059
throttle_group_co_io_limits_intercept(tgm, bytes, true);
1060
@@ -XXX,XX +XXX,XX @@ throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
1061
return bdrv_co_pdiscard(bs->file, offset, bytes);
1062
}
1063
1064
-static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
1065
- int64_t offset,
1066
- int64_t bytes,
1067
- QEMUIOVector *qiov)
1068
+static int coroutine_fn GRAPH_RDLOCK
1069
+throttle_co_pwritev_compressed(BlockDriverState *bs, int64_t offset,
1070
+ int64_t bytes, QEMUIOVector *qiov)
1071
{
1072
return throttle_co_pwritev(bs, offset, bytes, qiov,
1073
BDRV_REQ_WRITE_COMPRESSED);
143
diff --git a/block/vdi.c b/block/vdi.c
1074
diff --git a/block/vdi.c b/block/vdi.c
144
index XXXXXXX..XXXXXXX 100644
1075
index XXXXXXX..XXXXXXX 100644
145
--- a/block/vdi.c
1076
--- a/block/vdi.c
146
+++ b/block/vdi.c
1077
+++ b/block/vdi.c
147
@@ -XXX,XX +XXX,XX @@
1078
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
148
#define BLOCK_OPT_STATIC "static"
1079
(s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
149
1080
}
150
#define SECTOR_SIZE 512
1081
151
-#define DEFAULT_CLUSTER_SIZE S_1MiB
1082
-static int coroutine_fn
152
+#define DEFAULT_CLUSTER_SIZE 1048576
1083
+static int coroutine_fn GRAPH_RDLOCK
153
+/* Note: can't use 1 * MiB, because it's passed to stringify() */
1084
vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
154
1085
QEMUIOVector *qiov, BdrvRequestFlags flags)
155
#if defined(CONFIG_VDI_DEBUG)
1086
{
156
#define VDI_DEBUG 1
1087
@@ -XXX,XX +XXX,XX @@ vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1088
return ret;
1089
}
1090
1091
-static int coroutine_fn
1092
+static int coroutine_fn GRAPH_RDLOCK
1093
vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1094
QEMUIOVector *qiov, BdrvRequestFlags flags)
1095
{
1096
diff --git a/block/vhdx.c b/block/vhdx.c
1097
index XXXXXXX..XXXXXXX 100644
1098
--- a/block/vhdx.c
1099
+++ b/block/vhdx.c
1100
@@ -XXX,XX +XXX,XX @@ vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1101
}
1102
1103
1104
-static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
1105
- int nb_sectors, QEMUIOVector *qiov)
1106
+static int coroutine_fn GRAPH_RDLOCK
1107
+vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1108
+ QEMUIOVector *qiov)
1109
{
1110
BDRVVHDXState *s = bs->opaque;
1111
int ret = 0;
1112
@@ -XXX,XX +XXX,XX @@ int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
1113
return ret;
1114
}
1115
1116
-static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
1117
- int nb_sectors, QEMUIOVector *qiov,
1118
- int flags)
1119
+static int coroutine_fn GRAPH_RDLOCK
1120
+vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1121
+ QEMUIOVector *qiov, int flags)
1122
{
1123
int ret = -ENOTSUP;
1124
BDRVVHDXState *s = bs->opaque;
1125
diff --git a/block/vmdk.c b/block/vmdk.c
1126
index XXXXXXX..XXXXXXX 100644
1127
--- a/block/vmdk.c
1128
+++ b/block/vmdk.c
1129
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
1130
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
1131
* it for call to write user data in the request.
1132
*/
1133
-static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
1134
- VmdkExtent *extent,
1135
- uint64_t cluster_offset,
1136
- uint64_t offset,
1137
- uint64_t skip_start_bytes,
1138
- uint64_t skip_end_bytes,
1139
- bool zeroed)
1140
+static int coroutine_fn GRAPH_RDLOCK
1141
+get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent,
1142
+ uint64_t cluster_offset, uint64_t offset,
1143
+ uint64_t skip_start_bytes, uint64_t skip_end_bytes,
1144
+ bool zeroed)
1145
{
1146
int ret = VMDK_OK;
1147
int64_t cluster_bytes;
1148
@@ -XXX,XX +XXX,XX @@ vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
1149
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
1150
* VMDK_ERROR if failed.
1151
*/
1152
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
1153
- VmdkExtent *extent,
1154
- VmdkMetaData *m_data,
1155
- uint64_t offset,
1156
- bool allocate,
1157
- uint64_t *cluster_offset,
1158
- uint64_t skip_start_bytes,
1159
- uint64_t skip_end_bytes)
1160
+static int coroutine_fn GRAPH_RDLOCK
1161
+get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent,
1162
+ VmdkMetaData *m_data, uint64_t offset, bool allocate,
1163
+ uint64_t *cluster_offset, uint64_t skip_start_bytes,
1164
+ uint64_t skip_end_bytes)
1165
{
1166
unsigned int l1_index, l2_offset, l2_index;
1167
int min_index, i, j;
1168
@@ -XXX,XX +XXX,XX @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
1169
return extent_relative_offset % cluster_size;
1170
}
1171
1172
-static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1173
- bool want_zero,
1174
- int64_t offset, int64_t bytes,
1175
- int64_t *pnum, int64_t *map,
1176
- BlockDriverState **file)
1177
+static int coroutine_fn GRAPH_RDLOCK
1178
+vmdk_co_block_status(BlockDriverState *bs, bool want_zero,
1179
+ int64_t offset, int64_t bytes, int64_t *pnum,
1180
+ int64_t *map, BlockDriverState **file)
1181
{
1182
BDRVVmdkState *s = bs->opaque;
1183
int64_t index_in_cluster, n, ret;
1184
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1185
return ret;
1186
}
1187
1188
-static int coroutine_fn
1189
+static int coroutine_fn GRAPH_RDLOCK
1190
vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1191
int64_t offset_in_cluster, QEMUIOVector *qiov,
1192
uint64_t qiov_offset, uint64_t n_bytes,
1193
@@ -XXX,XX +XXX,XX @@ vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1194
return ret;
1195
}
1196
1197
-static int coroutine_fn
1198
+static int coroutine_fn GRAPH_RDLOCK
1199
vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1200
- int64_t offset_in_cluster, QEMUIOVector *qiov,
1201
- int bytes)
1202
+ int64_t offset_in_cluster, QEMUIOVector *qiov, int bytes)
1203
{
1204
int ret;
1205
int cluster_bytes, buf_bytes;
1206
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1207
return ret;
1208
}
1209
1210
-static int coroutine_fn
1211
+static int coroutine_fn GRAPH_RDLOCK
1212
vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1213
QEMUIOVector *qiov, BdrvRequestFlags flags)
1214
{
1215
@@ -XXX,XX +XXX,XX @@ fail:
1216
*
1217
* Returns: error code with 0 for success.
1218
*/
1219
-static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1220
- uint64_t bytes, QEMUIOVector *qiov,
1221
- bool zeroed, bool zero_dry_run)
1222
+static int coroutine_fn GRAPH_RDLOCK
1223
+vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1224
+ QEMUIOVector *qiov, bool zeroed, bool zero_dry_run)
1225
{
1226
BDRVVmdkState *s = bs->opaque;
1227
VmdkExtent *extent = NULL;
1228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1229
uint64_t bytes_done = 0;
1230
VmdkMetaData m_data;
1231
1232
- assume_graph_lock(); /* FIXME */
1233
-
1234
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
1235
error_report("Wrong offset: offset=0x%" PRIx64
1236
" total_sectors=0x%" PRIx64,
1237
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1238
return 0;
1239
}
1240
1241
-static int coroutine_fn
1242
+static int coroutine_fn GRAPH_RDLOCK
1243
vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1244
QEMUIOVector *qiov, BdrvRequestFlags flags)
1245
{
1246
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
1247
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
1248
}
1249
1250
-static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
1251
- int64_t offset,
1252
- int64_t bytes,
1253
- BdrvRequestFlags flags)
1254
+static int coroutine_fn GRAPH_RDLOCK
1255
+vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
1256
+ BdrvRequestFlags flags)
1257
{
1258
int ret;
1259
BDRVVmdkState *s = bs->opaque;
1260
@@ -XXX,XX +XXX,XX @@ static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
1261
return info;
1262
}
1263
1264
-static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
1265
- BdrvCheckResult *result,
1266
- BdrvCheckMode fix)
1267
+static int coroutine_fn GRAPH_RDLOCK
1268
+vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
1269
{
1270
BDRVVmdkState *s = bs->opaque;
1271
VmdkExtent *extent = NULL;
1272
diff --git a/block/vpc.c b/block/vpc.c
1273
index XXXXXXX..XXXXXXX 100644
1274
--- a/block/vpc.c
1275
+++ b/block/vpc.c
1276
@@ -XXX,XX +XXX,XX @@ vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1277
return 0;
1278
}
1279
1280
-static int coroutine_fn
1281
+static int coroutine_fn GRAPH_RDLOCK
1282
vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1283
QEMUIOVector *qiov, BdrvRequestFlags flags)
1284
{
1285
@@ -XXX,XX +XXX,XX @@ fail:
1286
return ret;
1287
}
1288
1289
-static int coroutine_fn
1290
+static int coroutine_fn GRAPH_RDLOCK
1291
vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1292
QEMUIOVector *qiov, BdrvRequestFlags flags)
1293
{
1294
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
1295
index XXXXXXX..XXXXXXX 100644
1296
--- a/tests/unit/test-bdrv-drain.c
1297
+++ b/tests/unit/test-bdrv-drain.c
1298
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_top_close(BlockDriverState *bs)
1299
}
1300
}
1301
1302
-static int coroutine_fn bdrv_test_top_co_preadv(BlockDriverState *bs,
1303
- int64_t offset, int64_t bytes,
1304
- QEMUIOVector *qiov,
1305
- BdrvRequestFlags flags)
1306
+static int coroutine_fn GRAPH_RDLOCK
1307
+bdrv_test_top_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1308
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1309
{
1310
BDRVTestTopState *tts = bs->opaque;
1311
return bdrv_co_preadv(tts->wait_child, offset, bytes, qiov, flags);
1312
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
1313
void *buffer = g_malloc(65536);
1314
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
1315
1316
+ GRAPH_RDLOCK_GUARD();
1317
+
1318
/* Pretend some internal write operation from parent to child.
1319
* Important: We have to read from the child, not from the parent!
1320
* Draining works by first propagating it all up the tree to the
1321
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_test_close(BlockDriverState *bs)
1322
* Otherwise:
1323
* Set .has_read to true and return success.
1324
*/
1325
-static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs,
1326
- int64_t offset,
1327
- int64_t bytes,
1328
- QEMUIOVector *qiov,
1329
- BdrvRequestFlags flags)
1330
+static int coroutine_fn GRAPH_RDLOCK
1331
+bdrv_replace_test_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1333
{
1334
BDRVReplaceTestState *s = bs->opaque;
1335
1336
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_read_entry(void *opaque)
1337
int ret;
1338
1339
/* Queue a read request post-drain */
1340
+ bdrv_graph_co_rdlock();
1341
ret = bdrv_replace_test_co_preadv(bs, 0, 1, &qiov, 0);
1342
+ bdrv_graph_co_rdunlock();
1343
+
1344
g_assert(ret >= 0);
1345
bdrv_dec_in_flight(bs);
1346
}
157
--
1347
--
158
2.20.1
1348
2.39.2
159
160
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_pwrite_sync() need to hold a reader lock for the graph.
2
3
3
The cmd() method of the QEMUQtestProtocol class sends a qtest command
4
For some places, we know that they will hold the lock, but we don't have
4
to QEMU but doesn't wait for the return message ("OK", "FAIL", "ERR").
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
Because of this, it can return control to the caller before the
6
with a FIXME comment. These places will be removed once everything is
6
command has actually finished.
7
properly annotated.
7
8
8
In cases like clock_step or clock_set this means that cmd() can return
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
before all the timers triggered by the clock change have been fired.
10
Message-Id: <20230203152202.49054-13-kwolf@redhat.com>
10
This can be fixed by making cmd() wait for the output of the qtest
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
command.
12
13
This fixes iotests 093 and 136, which are flaky since commit
14
8258292e18c39480b64eba9f3551 when the machine is under heavy workload.
15
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
13
---
20
scripts/qtest.py | 6 ++++++
14
block/qcow2.h | 2 +-
21
1 file changed, 6 insertions(+)
15
include/block/block-io.h | 7 ++++---
16
block/io.c | 3 +--
17
3 files changed, 6 insertions(+), 6 deletions(-)
22
18
23
diff --git a/scripts/qtest.py b/scripts/qtest.py
19
diff --git a/block/qcow2.h b/block/qcow2.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/scripts/qtest.py
21
--- a/block/qcow2.h
26
+++ b/scripts/qtest.py
22
+++ b/block/qcow2.h
27
@@ -XXX,XX +XXX,XX @@ class QEMUQtestProtocol(object):
23
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
28
"""
24
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
29
self._address = address
25
BlockDriverAmendStatusCB *status_cb,
30
self._sock = self._get_sock()
26
void *cb_opaque, Error **errp);
31
+ self._sockfile = None
27
-int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
32
if server:
28
+int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
33
self._sock.bind(self._address)
29
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
34
self._sock.listen(1)
30
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
35
@@ -XXX,XX +XXX,XX @@ class QEMUQtestProtocol(object):
31
36
@raise socket.error on socket connection errors
32
diff --git a/include/block/block-io.h b/include/block/block-io.h
37
"""
33
index XXXXXXX..XXXXXXX 100644
38
self._sock.connect(self._address)
34
--- a/include/block/block-io.h
39
+ self._sockfile = self._sock.makefile()
35
+++ b/include/block/block-io.h
40
36
@@ -XXX,XX +XXX,XX @@ int co_wrapper_mixed_bdrv_rdlock
41
def accept(self):
37
bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
42
"""
38
const void *buf, BdrvRequestFlags flags);
43
@@ -XXX,XX +XXX,XX @@ class QEMUQtestProtocol(object):
39
44
@raise socket.error on socket connection errors
40
-int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
45
"""
41
- int64_t bytes, const void *buf,
46
self._sock, _ = self._sock.accept()
42
- BdrvRequestFlags flags);
47
+ self._sockfile = self._sock.makefile()
43
+int coroutine_fn GRAPH_RDLOCK
48
44
+bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
49
def cmd(self, qtest_cmd):
45
+ const void *buf, BdrvRequestFlags flags);
50
"""
46
+
51
@@ -XXX,XX +XXX,XX @@ class QEMUQtestProtocol(object):
47
/*
52
@param qtest_cmd: qtest command text to be sent
48
* Efficiently zero a region of the disk image. Note that this is a regular
53
"""
49
* I/O request like read or write and should have a reasonable size. This
54
self._sock.sendall((qtest_cmd + "\n").encode('utf-8'))
50
diff --git a/block/io.c b/block/io.c
55
+ resp = self._sockfile.readline()
51
index XXXXXXX..XXXXXXX 100644
56
+ return resp
52
--- a/block/io.c
57
53
+++ b/block/io.c
58
def close(self):
54
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
59
self._sock.close()
55
{
60
+ self._sockfile.close()
56
int ret;
61
57
IO_CODE();
62
def settimeout(self, timeout):
58
-
63
self._sock.settimeout(timeout)
59
- assume_graph_lock(); /* FIXME */
60
+ assert_bdrv_graph_readable();
61
62
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
63
if (ret < 0) {
64
--
64
--
65
2.20.1
65
2.39.2
66
67
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
All callers are already GRAPH_RDLOCK, so just add the annotation and
2
remove assume_graph_lock().
2
3
3
It's not enough to order the kwargs for consistent QMP log output,
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
we must also sort any sub-dictionaries in lists that appear as values.
5
Message-Id: <20230203152202.49054-14-kwolf@redhat.com>
5
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reported-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
tests/qemu-iotests/236.out | 56 +++++++++++++++++------------------
9
block/io.c | 7 +++----
13
tests/qemu-iotests/iotests.py | 21 ++++++-------
10
1 file changed, 3 insertions(+), 4 deletions(-)
14
2 files changed, 39 insertions(+), 38 deletions(-)
15
11
16
diff --git a/tests/qemu-iotests/236.out b/tests/qemu-iotests/236.out
12
diff --git a/block/io.c b/block/io.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/236.out
14
--- a/block/io.c
19
+++ b/tests/qemu-iotests/236.out
15
+++ b/block/io.c
20
@@ -XXX,XX +XXX,XX @@ write -P0xcd 0x3ff0000 64k
16
@@ -XXX,XX +XXX,XX @@ fail:
21
"actions": [
17
return ret;
22
{
18
}
23
"data": {
19
24
- "node": "drive0",
20
-static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
25
- "name": "bitmapB"
21
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
26
+ "name": "bitmapB",
22
+static int coroutine_fn GRAPH_RDLOCK
27
+ "node": "drive0"
23
+bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
28
},
24
+ BdrvRequestFlags flags)
29
"type": "block-dirty-bitmap-disable"
25
{
30
},
26
BlockDriver *drv = bs->drv;
31
{
27
QEMUIOVector qiov;
32
"data": {
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
33
- "node": "drive0",
29
int head = 0;
34
+ "granularity": 65536,
30
int tail = 0;
35
"name": "bitmapC",
31
36
- "granularity": 65536
32
- assume_graph_lock(); /* FIXME */
37
+ "node": "drive0"
33
-
38
},
34
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
39
"type": "block-dirty-bitmap-add"
35
INT64_MAX);
40
},
36
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
41
{
42
"data": {
43
- "node": "drive0",
44
- "name": "bitmapA"
45
+ "name": "bitmapA",
46
+ "node": "drive0"
47
},
48
"type": "block-dirty-bitmap-clear"
49
},
50
@@ -XXX,XX +XXX,XX @@ write -P0xcd 0x3ff0000 64k
51
"actions": [
52
{
53
"data": {
54
- "node": "drive0",
55
- "name": "bitmapB"
56
+ "name": "bitmapB",
57
+ "node": "drive0"
58
},
59
"type": "block-dirty-bitmap-disable"
60
},
61
{
62
"data": {
63
- "node": "drive0",
64
+ "granularity": 65536,
65
"name": "bitmapC",
66
- "granularity": 65536
67
+ "node": "drive0"
68
},
69
"type": "block-dirty-bitmap-add"
70
},
71
{
72
"data": {
73
- "node": "drive0",
74
- "name": "bitmapC"
75
+ "name": "bitmapC",
76
+ "node": "drive0"
77
},
78
"type": "block-dirty-bitmap-disable"
79
},
80
{
81
"data": {
82
- "node": "drive0",
83
- "name": "bitmapC"
84
+ "name": "bitmapC",
85
+ "node": "drive0"
86
},
87
"type": "block-dirty-bitmap-enable"
88
}
89
@@ -XXX,XX +XXX,XX @@ write -P0xea 0x3fe0000 64k
90
"actions": [
91
{
92
"data": {
93
- "node": "drive0",
94
- "name": "bitmapA"
95
+ "name": "bitmapA",
96
+ "node": "drive0"
97
},
98
"type": "block-dirty-bitmap-disable"
99
},
100
{
101
"data": {
102
- "node": "drive0",
103
- "name": "bitmapC"
104
+ "name": "bitmapC",
105
+ "node": "drive0"
106
},
107
"type": "block-dirty-bitmap-disable"
108
}
109
@@ -XXX,XX +XXX,XX @@ write -P0xea 0x3fe0000 64k
110
"actions": [
111
{
112
"data": {
113
- "node": "drive0",
114
"disabled": true,
115
+ "granularity": 65536,
116
"name": "bitmapD",
117
- "granularity": 65536
118
+ "node": "drive0"
119
},
120
"type": "block-dirty-bitmap-add"
121
},
122
{
123
"data": {
124
- "node": "drive0",
125
- "target": "bitmapD",
126
"bitmaps": [
127
"bitmapB",
128
"bitmapC"
129
- ]
130
+ ],
131
+ "node": "drive0",
132
+ "target": "bitmapD"
133
},
134
"type": "block-dirty-bitmap-merge"
135
},
136
@@ -XXX,XX +XXX,XX @@ write -P0xea 0x3fe0000 64k
137
"actions": [
138
{
139
"data": {
140
- "node": "drive0",
141
"disabled": true,
142
+ "granularity": 65536,
143
"name": "bitmapD",
144
- "granularity": 65536
145
+ "node": "drive0"
146
},
147
"type": "block-dirty-bitmap-add"
148
},
149
{
150
"data": {
151
- "node": "drive0",
152
- "target": "bitmapD",
153
"bitmaps": [
154
"bitmapB",
155
"bitmapC"
156
- ]
157
+ ],
158
+ "node": "drive0",
159
+ "target": "bitmapD"
160
},
161
"type": "block-dirty-bitmap-merge"
162
}
163
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
164
index XXXXXXX..XXXXXXX 100644
165
--- a/tests/qemu-iotests/iotests.py
166
+++ b/tests/qemu-iotests/iotests.py
167
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args):
168
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
169
return exitcode
170
171
-def ordered_kwargs(kwargs):
172
- # kwargs prior to 3.6 are not ordered, so:
173
- od = OrderedDict()
174
- for k, v in sorted(kwargs.items()):
175
- if isinstance(v, dict):
176
- od[k] = ordered_kwargs(v)
177
- else:
178
- od[k] = v
179
- return od
180
+def ordered_qmp(qmsg):
181
+ # Dictionaries are not ordered prior to 3.6, therefore:
182
+ if isinstance(qmsg, list):
183
+ return [ordered_qmp(atom) for atom in qmsg]
184
+ if isinstance(qmsg, dict):
185
+ od = OrderedDict()
186
+ for k, v in sorted(qmsg.items()):
187
+ od[k] = ordered_qmp(v)
188
+ return od
189
+ return qmsg
190
191
def qemu_img_create(*args):
192
args = list(args)
193
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
194
def qmp_log(self, cmd, filters=[], indent=None, **kwargs):
195
full_cmd = OrderedDict((
196
("execute", cmd),
197
- ("arguments", ordered_kwargs(kwargs))
198
+ ("arguments", ordered_qmp(kwargs))
199
))
200
log(full_cmd, filters, indent=indent)
201
result = self.qmp(cmd, **kwargs)
202
--
37
--
203
2.20.1
38
2.39.2
204
205
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Without this filter, this test sometimes fails.
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
bdrv_co_copy_range() need to hold a reader lock for the graph.
4
5
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20230203152202.49054-15-kwolf@redhat.com>
9
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
11
---
9
tests/qemu-iotests/229 | 6 +++++-
12
include/block/block-io.h | 9 +++++----
10
tests/qemu-iotests/229.out | 1 -
13
include/block/block_int-common.h | 24 ++++++++----------------
11
2 files changed, 5 insertions(+), 2 deletions(-)
14
include/block/block_int-io.h | 20 ++++++++++----------
15
block/block-backend.c | 2 ++
16
block/file-posix.c | 16 +++++++---------
17
block/io.c | 7 +++++--
18
block/iscsi.c | 28 ++++++++++++----------------
19
block/qcow2.c | 5 ++---
20
block/raw-format.c | 28 ++++++++++++----------------
21
qemu-img.c | 4 +++-
22
10 files changed, 66 insertions(+), 77 deletions(-)
12
23
13
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
24
diff --git a/include/block/block-io.h b/include/block/block-io.h
14
index XXXXXXX..XXXXXXX 100755
25
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/229
26
--- a/include/block/block-io.h
16
+++ b/tests/qemu-iotests/229
27
+++ b/include/block/block-io.h
17
@@ -XXX,XX +XXX,XX @@ echo
28
@@ -XXX,XX +XXX,XX @@ bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
18
echo '=== Force cancel job paused in error state ==='
29
*
19
echo
30
* Returns: 0 if succeeded; negative error code if failed.
20
31
**/
21
+# Filter out BLOCK_JOB_ERROR events because they may or may not occur.
32
-int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
22
+# Cancelling the job means resuming it for a bit before it is actually
33
- BdrvChild *dst, int64_t dst_offset,
23
+# aborted, and in that time it may or may not re-encounter the error.
34
- int64_t bytes, BdrvRequestFlags read_flags,
24
success_or_failure="y" _send_qemu_cmd $QEMU_HANDLE \
35
- BdrvRequestFlags write_flags);
25
"{'execute': 'block-job-cancel',
36
+int coroutine_fn GRAPH_RDLOCK
26
'arguments': { 'device': 'testdisk',
37
+bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
27
'force': true}}" \
38
+ BdrvChild *dst, int64_t dst_offset,
28
- "BLOCK_JOB_CANCELLED" "Assertion"
39
+ int64_t bytes, BdrvRequestFlags read_flags,
29
+ "BLOCK_JOB_CANCELLED" "Assertion" \
40
+ BdrvRequestFlags write_flags);
30
+ | grep -v '"BLOCK_JOB_ERROR"'
41
31
42
/*
32
# success, all done
43
* "I/O or GS" API functions. These functions can run without
33
echo "*** done"
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
34
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
45
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
36
--- a/tests/qemu-iotests/229.out
47
+++ b/include/block/block_int-common.h
37
+++ b/tests/qemu-iotests/229.out
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
49
* See the comment of bdrv_co_copy_range for the parameter and return value
39
50
* semantics.
40
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
51
*/
41
{"return": {}}
52
- int coroutine_fn (*bdrv_co_copy_range_from)(BlockDriverState *bs,
42
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}}
53
- BdrvChild *src,
43
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
54
- int64_t offset,
44
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
55
- BdrvChild *dst,
45
*** done
56
- int64_t dst_offset,
57
- int64_t bytes,
58
- BdrvRequestFlags read_flags,
59
- BdrvRequestFlags write_flags);
60
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_from)(
61
+ BlockDriverState *bs, BdrvChild *src, int64_t offset,
62
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
63
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
64
65
/*
66
* Map [offset, offset + nbytes) range onto a child of bs to copy data to,
67
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
68
* See the comment of bdrv_co_copy_range for the parameter and return value
69
* semantics.
70
*/
71
- int coroutine_fn (*bdrv_co_copy_range_to)(BlockDriverState *bs,
72
- BdrvChild *src,
73
- int64_t src_offset,
74
- BdrvChild *dst,
75
- int64_t dst_offset,
76
- int64_t bytes,
77
- BdrvRequestFlags read_flags,
78
- BdrvRequestFlags write_flags);
79
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_to)(
80
+ BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
81
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
82
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
83
84
/*
85
* Building block for bdrv_block_status[_above] and
86
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/include/block/block_int-io.h
89
+++ b/include/block/block_int-io.h
90
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
91
void bdrv_inc_in_flight(BlockDriverState *bs);
92
void bdrv_dec_in_flight(BlockDriverState *bs);
93
94
-int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
95
- BdrvChild *dst, int64_t dst_offset,
96
- int64_t bytes,
97
- BdrvRequestFlags read_flags,
98
- BdrvRequestFlags write_flags);
99
-int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
100
- BdrvChild *dst, int64_t dst_offset,
101
- int64_t bytes,
102
- BdrvRequestFlags read_flags,
103
- BdrvRequestFlags write_flags);
104
+int coroutine_fn GRAPH_RDLOCK
105
+bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
106
+ BdrvChild *dst, int64_t dst_offset,
107
+ int64_t bytes, BdrvRequestFlags read_flags,
108
+ BdrvRequestFlags write_flags);
109
+int coroutine_fn GRAPH_RDLOCK
110
+bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
111
+ BdrvChild *dst, int64_t dst_offset,
112
+ int64_t bytes, BdrvRequestFlags read_flags,
113
+ BdrvRequestFlags write_flags);
114
115
int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
116
int64_t hint);
117
diff --git a/block/block-backend.c b/block/block-backend.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/block-backend.c
120
+++ b/block/block-backend.c
121
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
122
if (r) {
123
return r;
124
}
125
+
126
+ GRAPH_RDLOCK_GUARD();
127
return bdrv_co_copy_range(blk_in->root, off_in,
128
blk_out->root, off_out,
129
bytes, read_flags, write_flags);
130
diff --git a/block/file-posix.c b/block/file-posix.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/file-posix.c
133
+++ b/block/file-posix.c
134
@@ -XXX,XX +XXX,XX @@ static void raw_abort_perm_update(BlockDriverState *bs)
135
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
136
}
137
138
-static int coroutine_fn raw_co_copy_range_from(
139
+static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from(
140
BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
141
BdrvChild *dst, int64_t dst_offset, int64_t bytes,
142
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags)
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(
144
read_flags, write_flags);
145
}
146
147
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
148
- BdrvChild *src,
149
- int64_t src_offset,
150
- BdrvChild *dst,
151
- int64_t dst_offset,
152
- int64_t bytes,
153
- BdrvRequestFlags read_flags,
154
- BdrvRequestFlags write_flags)
155
+static int coroutine_fn GRAPH_RDLOCK
156
+raw_co_copy_range_to(BlockDriverState *bs,
157
+ BdrvChild *src, int64_t src_offset,
158
+ BdrvChild *dst, int64_t dst_offset,
159
+ int64_t bytes, BdrvRequestFlags read_flags,
160
+ BdrvRequestFlags write_flags)
161
{
162
RawPosixAIOData acb;
163
BDRVRawState *s = bs->opaque;
164
diff --git a/block/io.c b/block/io.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/io.c
167
+++ b/block/io.c
168
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
169
{
170
BdrvTrackedRequest req;
171
int ret;
172
+ assert_bdrv_graph_readable();
173
174
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
175
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
176
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
177
BdrvRequestFlags write_flags)
178
{
179
IO_CODE();
180
- assume_graph_lock(); /* FIXME */
181
+ assert_bdrv_graph_readable();
182
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
183
read_flags, write_flags);
184
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
185
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
186
BdrvRequestFlags write_flags)
187
{
188
IO_CODE();
189
- assume_graph_lock(); /* FIXME */
190
+ assert_bdrv_graph_readable();
191
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
192
read_flags, write_flags);
193
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
194
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
195
BdrvRequestFlags write_flags)
196
{
197
IO_CODE();
198
+ assert_bdrv_graph_readable();
199
+
200
return bdrv_co_copy_range_from(src, src_offset,
201
dst, dst_offset,
202
bytes, read_flags, write_flags);
203
diff --git a/block/iscsi.c b/block/iscsi.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/iscsi.c
206
+++ b/block/iscsi.c
207
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn iscsi_co_invalidate_cache(BlockDriverState *bs,
208
iscsi_allocmap_invalidate(iscsilun);
209
}
210
211
-static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs,
212
- BdrvChild *src,
213
- int64_t src_offset,
214
- BdrvChild *dst,
215
- int64_t dst_offset,
216
- int64_t bytes,
217
- BdrvRequestFlags read_flags,
218
- BdrvRequestFlags write_flags)
219
+static int coroutine_fn GRAPH_RDLOCK
220
+iscsi_co_copy_range_from(BlockDriverState *bs,
221
+ BdrvChild *src, int64_t src_offset,
222
+ BdrvChild *dst, int64_t dst_offset,
223
+ int64_t bytes, BdrvRequestFlags read_flags,
224
+ BdrvRequestFlags write_flags)
225
{
226
return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
227
read_flags, write_flags);
228
@@ -XXX,XX +XXX,XX @@ static void iscsi_xcopy_data(struct iscsi_data *data,
229
src_lba, dst_lba);
230
}
231
232
-static int coroutine_fn iscsi_co_copy_range_to(BlockDriverState *bs,
233
- BdrvChild *src,
234
- int64_t src_offset,
235
- BdrvChild *dst,
236
- int64_t dst_offset,
237
- int64_t bytes,
238
- BdrvRequestFlags read_flags,
239
- BdrvRequestFlags write_flags)
240
+static int coroutine_fn GRAPH_RDLOCK
241
+iscsi_co_copy_range_to(BlockDriverState *bs,
242
+ BdrvChild *src, int64_t src_offset,
243
+ BdrvChild *dst, int64_t dst_offset,
244
+ int64_t bytes, BdrvRequestFlags read_flags,
245
+ BdrvRequestFlags write_flags)
246
{
247
IscsiLun *dst_lun = dst->bs->opaque;
248
IscsiLun *src_lun;
249
diff --git a/block/qcow2.c b/block/qcow2.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/block/qcow2.c
252
+++ b/block/qcow2.c
253
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
254
return ret;
255
}
256
257
-static int coroutine_fn
258
+static int coroutine_fn GRAPH_RDLOCK
259
qcow2_co_copy_range_from(BlockDriverState *bs,
260
BdrvChild *src, int64_t src_offset,
261
BdrvChild *dst, int64_t dst_offset,
262
@@ -XXX,XX +XXX,XX @@ out:
263
return ret;
264
}
265
266
-static int coroutine_fn
267
+static int coroutine_fn GRAPH_RDLOCK
268
qcow2_co_copy_range_to(BlockDriverState *bs,
269
BdrvChild *src, int64_t src_offset,
270
BdrvChild *dst, int64_t dst_offset,
271
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
272
uint64_t host_offset;
273
QCowL2Meta *l2meta = NULL;
274
275
- assume_graph_lock(); /* FIXME */
276
assert(!bs->encrypted);
277
278
qemu_co_mutex_lock(&s->lock);
279
diff --git a/block/raw-format.c b/block/raw-format.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/block/raw-format.c
282
+++ b/block/raw-format.c
283
@@ -XXX,XX +XXX,XX @@ static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
284
return bdrv_probe_geometry(bs->file->bs, geo);
285
}
286
287
-static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
288
- BdrvChild *src,
289
- int64_t src_offset,
290
- BdrvChild *dst,
291
- int64_t dst_offset,
292
- int64_t bytes,
293
- BdrvRequestFlags read_flags,
294
- BdrvRequestFlags write_flags)
295
+static int coroutine_fn GRAPH_RDLOCK
296
+raw_co_copy_range_from(BlockDriverState *bs,
297
+ BdrvChild *src, int64_t src_offset,
298
+ BdrvChild *dst, int64_t dst_offset,
299
+ int64_t bytes, BdrvRequestFlags read_flags,
300
+ BdrvRequestFlags write_flags)
301
{
302
int ret;
303
304
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
305
bytes, read_flags, write_flags);
306
}
307
308
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
309
- BdrvChild *src,
310
- int64_t src_offset,
311
- BdrvChild *dst,
312
- int64_t dst_offset,
313
- int64_t bytes,
314
- BdrvRequestFlags read_flags,
315
- BdrvRequestFlags write_flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+raw_co_copy_range_to(BlockDriverState *bs,
318
+ BdrvChild *src, int64_t src_offset,
319
+ BdrvChild *dst, int64_t dst_offset,
320
+ int64_t bytes, BdrvRequestFlags read_flags,
321
+ BdrvRequestFlags write_flags)
322
{
323
int ret;
324
325
diff --git a/qemu-img.c b/qemu-img.c
326
index XXXXXXX..XXXXXXX 100644
327
--- a/qemu-img.c
328
+++ b/qemu-img.c
329
@@ -XXX,XX +XXX,XX @@ retry:
330
331
if (s->ret == -EINPROGRESS) {
332
if (copy_range) {
333
- ret = convert_co_copy_range(s, sector_num, n);
334
+ WITH_GRAPH_RDLOCK_GUARD() {
335
+ ret = convert_co_copy_range(s, sector_num, n);
336
+ }
337
if (ret) {
338
s->copy_range = false;
339
goto retry;
46
--
340
--
47
2.20.1
341
2.39.2
48
49
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20230203152202.49054-16-kwolf@redhat.com>
3
Currently qemu_uuid_bswap() takes a pointer to the QemuUUID to
3
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
be byte-swapped. This means it can't be used when the UUID
5
to be swapped is in a packed member of a struct. It's also
6
out of line with the general bswap*() functions we provide
7
in bswap.h, which take the value to be swapped and return it.
8
9
Make qemu_uuid_bswap() take a QemuUUID and return the swapped version.
10
11
This fixes some clang warnings about taking the address of
12
a packed struct member in block/vdi.c.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
16
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
5
---
19
include/qemu/uuid.h | 2 +-
6
include/block/block_int-common.h | 12 +++++++-----
20
block/vdi.c | 16 ++++++++--------
7
include/block/block_int-io.h | 8 ++++----
21
hw/acpi/vmgenid.c | 6 ++----
8
block/copy-before-write.c | 6 ++----
22
tests/vmgenid-test.c | 2 +-
9
block/io.c | 2 ++
23
util/uuid.c | 10 +++++-----
10
block/snapshot-access.c | 4 ++--
24
5 files changed, 17 insertions(+), 19 deletions(-)
11
5 files changed, 17 insertions(+), 15 deletions(-)
25
12
26
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
13
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
27
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
28
--- a/include/qemu/uuid.h
15
--- a/include/block/block_int-common.h
29
+++ b/include/qemu/uuid.h
16
+++ b/include/block/block_int-common.h
30
@@ -XXX,XX +XXX,XX @@ char *qemu_uuid_unparse_strdup(const QemuUUID *uuid);
17
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
31
18
* - receive the snapshot's actual length (which may differ from bs's
32
int qemu_uuid_parse(const char *str, QemuUUID *uuid);
19
* length)
33
20
*/
34
-void qemu_uuid_bswap(QemuUUID *uuid);
21
- int coroutine_fn (*bdrv_co_preadv_snapshot)(BlockDriverState *bs,
35
+QemuUUID qemu_uuid_bswap(QemuUUID uuid);
22
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
36
23
- int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
37
#endif
24
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
38
diff --git a/block/vdi.c b/block/vdi.c
25
- int64_t *map, BlockDriverState **file);
26
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_snapshot)(
27
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
28
+ QEMUIOVector *qiov, size_t qiov_offset);
29
+
30
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)(
31
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
32
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
33
34
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
35
BlockDriverState *bs, int64_t offset, int64_t bytes);
36
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
39
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
40
--- a/block/vdi.c
38
--- a/include/block/block_int-io.h
41
+++ b/block/vdi.c
39
+++ b/include/block/block_int-io.h
42
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_cpu(VdiHeader *header)
40
@@ -XXX,XX +XXX,XX @@
43
header->block_extra = le32_to_cpu(header->block_extra);
41
* the I/O API.
44
header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
42
*/
45
header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
43
46
- qemu_uuid_bswap(&header->uuid_image);
44
-int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
47
- qemu_uuid_bswap(&header->uuid_last_snap);
45
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child,
48
- qemu_uuid_bswap(&header->uuid_link);
46
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
49
- qemu_uuid_bswap(&header->uuid_parent);
47
-int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
50
+ header->uuid_image = qemu_uuid_bswap(header->uuid_image);
48
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
51
+ header->uuid_last_snap = qemu_uuid_bswap(header->uuid_last_snap);
49
- int64_t *map, BlockDriverState **file);
52
+ header->uuid_link = qemu_uuid_bswap(header->uuid_link);
50
+int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status(
53
+ header->uuid_parent = qemu_uuid_bswap(header->uuid_parent);
51
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
52
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
53
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
54
int64_t offset, int64_t bytes);
55
56
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/copy-before-write.c
59
+++ b/block/copy-before-write.c
60
@@ -XXX,XX +XXX,XX @@ cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
61
g_free(req);
54
}
62
}
55
63
56
static void vdi_header_to_le(VdiHeader *header)
64
-static coroutine_fn int
57
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_le(VdiHeader *header)
65
+static int coroutine_fn GRAPH_RDLOCK
58
header->block_extra = cpu_to_le32(header->block_extra);
66
cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
59
header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
67
QEMUIOVector *qiov, size_t qiov_offset)
60
header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
68
{
61
- qemu_uuid_bswap(&header->uuid_image);
69
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
62
- qemu_uuid_bswap(&header->uuid_last_snap);
70
BdrvChild *file;
63
- qemu_uuid_bswap(&header->uuid_link);
71
int ret;
64
- qemu_uuid_bswap(&header->uuid_parent);
72
65
+ header->uuid_image = qemu_uuid_bswap(header->uuid_image);
73
- assume_graph_lock(); /* FIXME */
66
+ header->uuid_last_snap = qemu_uuid_bswap(header->uuid_last_snap);
74
-
67
+ header->uuid_link = qemu_uuid_bswap(header->uuid_link);
75
/* TODO: upgrade to async loop using AioTask */
68
+ header->uuid_parent = qemu_uuid_bswap(header->uuid_parent);
76
while (bytes) {
77
int64_t cur_bytes;
78
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
79
return 0;
69
}
80
}
70
81
71
static void vdi_header_print(VdiHeader *header)
82
-static int coroutine_fn
72
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
83
+static int coroutine_fn GRAPH_RDLOCK
84
cbw_co_snapshot_block_status(BlockDriverState *bs,
85
bool want_zero, int64_t offset, int64_t bytes,
86
int64_t *pnum, int64_t *map,
87
diff --git a/block/io.c b/block/io.c
73
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/acpi/vmgenid.c
89
--- a/block/io.c
75
+++ b/hw/acpi/vmgenid.c
90
+++ b/block/io.c
76
@@ -XXX,XX +XXX,XX @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
91
@@ -XXX,XX +XXX,XX @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
77
* first, since that's what the guest expects
92
BlockDriver *drv = bs->drv;
78
*/
93
int ret;
79
g_array_set_size(guid, VMGENID_FW_CFG_SIZE - ARRAY_SIZE(guid_le.data));
94
IO_CODE();
80
- guid_le = vms->guid;
95
+ assert_bdrv_graph_readable();
81
- qemu_uuid_bswap(&guid_le);
96
82
+ guid_le = qemu_uuid_bswap(vms->guid);
97
if (!drv) {
83
/* The GUID is written at a fixed offset into the fw_cfg file
98
return -ENOMEDIUM;
84
* in order to implement the "OVMF SDT Header probe suppressor"
99
@@ -XXX,XX +XXX,XX @@ bdrv_co_snapshot_block_status(BlockDriverState *bs,
85
* see docs/specs/vmgenid.txt for more details
100
BlockDriver *drv = bs->drv;
86
@@ -XXX,XX +XXX,XX @@ static void vmgenid_update_guest(VmGenIdState *vms)
101
int ret;
87
* however, will expect the fields to be little-endian.
102
IO_CODE();
88
* Perform a byte swap immediately before writing.
103
+ assert_bdrv_graph_readable();
89
*/
104
90
- guid_le = vms->guid;
105
if (!drv) {
91
- qemu_uuid_bswap(&guid_le);
106
return -ENOMEDIUM;
92
+ guid_le = qemu_uuid_bswap(vms->guid);
107
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
93
/* The GUID is written at a fixed offset into the fw_cfg file
94
* in order to implement the "OVMF SDT Header probe suppressor"
95
* see docs/specs/vmgenid.txt for more details.
96
diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
97
index XXXXXXX..XXXXXXX 100644
108
index XXXXXXX..XXXXXXX 100644
98
--- a/tests/vmgenid-test.c
109
--- a/block/snapshot-access.c
99
+++ b/tests/vmgenid-test.c
110
+++ b/block/snapshot-access.c
100
@@ -XXX,XX +XXX,XX @@ static void read_guid_from_memory(QTestState *qts, QemuUUID *guid)
111
@@ -XXX,XX +XXX,XX @@
101
/* The GUID is in little-endian format in the guest, while QEMU
112
#include "qemu/cutils.h"
102
* uses big-endian. Swap after reading.
113
#include "block/block_int.h"
103
*/
114
104
- qemu_uuid_bswap(guid);
115
-static coroutine_fn int
105
+ *guid = qemu_uuid_bswap(*guid);
116
+static int coroutine_fn GRAPH_RDLOCK
117
snapshot_access_co_preadv_part(BlockDriverState *bs,
118
int64_t offset, int64_t bytes,
119
QEMUIOVector *qiov, size_t qiov_offset,
120
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_preadv_part(BlockDriverState *bs,
121
return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset);
106
}
122
}
107
123
108
static void read_guid_from_monitor(QTestState *qts, QemuUUID *guid)
124
-static int coroutine_fn
109
diff --git a/util/uuid.c b/util/uuid.c
125
+static int coroutine_fn GRAPH_RDLOCK
110
index XXXXXXX..XXXXXXX 100644
126
snapshot_access_co_block_status(BlockDriverState *bs,
111
--- a/util/uuid.c
127
bool want_zero, int64_t offset,
112
+++ b/util/uuid.c
128
int64_t bytes, int64_t *pnum,
113
@@ -XXX,XX +XXX,XX @@ int qemu_uuid_parse(const char *str, QemuUUID *uuid)
114
115
/* Swap from UUID format endian (BE) to the opposite or vice versa.
116
*/
117
-void qemu_uuid_bswap(QemuUUID *uuid)
118
+QemuUUID qemu_uuid_bswap(QemuUUID uuid)
119
{
120
- assert(QEMU_PTR_IS_ALIGNED(uuid, sizeof(uint32_t)));
121
- bswap32s(&uuid->fields.time_low);
122
- bswap16s(&uuid->fields.time_mid);
123
- bswap16s(&uuid->fields.time_high_and_version);
124
+ bswap32s(&uuid.fields.time_low);
125
+ bswap16s(&uuid.fields.time_mid);
126
+ bswap16s(&uuid.fields.time_high_and_version);
127
+ return uuid;
128
}
129
--
129
--
130
2.20.1
130
2.39.2
131
132
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_create() need to hold a reader lock for the graph.
2
3
3
Taking the address of a field in a packed struct is a bad idea, because
4
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
it might not be actually aligned enough for that pointer type (and
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
thus cause a crash on dereference on some host architectures). Newer
6
Message-Id: <20230203152202.49054-17-kwolf@redhat.com>
6
versions of clang warn about this.
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
8
Instead of passing UUID related functions the address of a possibly
9
unaligned QemuUUID struct, use local variables and then copy to/from
10
the struct field as appropriate.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
9
---
15
block/vdi.c | 38 +++++++++++++++++++++++++-------------
10
include/block/block-global-state.h | 14 ++++---
16
1 file changed, 25 insertions(+), 13 deletions(-)
11
include/block/block_int-common.h | 11 +++---
12
block.c | 1 +
13
block/create.c | 9 ++++-
14
block/crypto.c | 7 ++--
15
block/file-posix.c | 7 ++--
16
block/file-win32.c | 7 ++--
17
block/parallels.c | 7 ++--
18
block/qcow.c | 6 +--
19
block/qcow2.c | 7 ++--
20
block/qed.c | 7 ++--
21
block/raw-format.c | 7 ++--
22
block/vdi.c | 7 ++--
23
block/vhdx.c | 7 ++--
24
block/vmdk.c | 63 ++++++++++++++----------------
25
block/vpc.c | 7 ++--
26
16 files changed, 84 insertions(+), 90 deletions(-)
17
27
28
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block-global-state.h
31
+++ b/include/block/block-global-state.h
32
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_find_protocol(const char *filename,
33
Error **errp);
34
BlockDriver *bdrv_find_format(const char *format_name);
35
36
-int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
37
- QemuOpts *opts, Error **errp);
38
-int co_wrapper bdrv_create(BlockDriver *drv, const char *filename,
39
- QemuOpts *opts, Error **errp);
40
+int coroutine_fn GRAPH_RDLOCK
41
+bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts,
42
+ Error **errp);
43
44
-int coroutine_fn bdrv_co_create_file(const char *filename, QemuOpts *opts,
45
- Error **errp);
46
+int co_wrapper_bdrv_rdlock bdrv_create(BlockDriver *drv, const char *filename,
47
+ QemuOpts *opts, Error **errp);
48
+
49
+int coroutine_fn GRAPH_RDLOCK
50
+bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp);
51
52
BlockDriverState *bdrv_new(void);
53
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
54
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/block/block_int-common.h
57
+++ b/include/block/block_int-common.h
58
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
59
Error **errp);
60
void (*bdrv_close)(BlockDriverState *bs);
61
62
- int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
63
- Error **errp);
64
- int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv,
65
- const char *filename,
66
- QemuOpts *opts,
67
- Error **errp);
68
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
69
+ BlockdevCreateOptions *opts, Error **errp);
70
+
71
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create_opts)(
72
+ BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
73
74
int (*bdrv_amend_options)(BlockDriverState *bs,
75
QemuOpts *opts,
76
diff --git a/block.c b/block.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block.c
79
+++ b/block.c
80
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
81
int ret;
82
GLOBAL_STATE_CODE();
83
ERRP_GUARD();
84
+ assert_bdrv_graph_readable();
85
86
if (!drv->bdrv_co_create_opts) {
87
error_setg(errp, "Driver '%s' does not support image creation",
88
diff --git a/block/create.c b/block/create.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/create.c
91
+++ b/block/create.c
92
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
93
int ret;
94
95
GLOBAL_STATE_CODE();
96
+ GRAPH_RDLOCK_GUARD();
97
98
job_progress_set_remaining(&s->common, 1);
99
ret = s->drv->bdrv_co_create(s->opts, errp);
100
@@ -XXX,XX +XXX,XX @@ static const JobDriver blockdev_create_job_driver = {
101
.run = blockdev_create_run,
102
};
103
104
+/* Checking whether the function is present doesn't require the graph lock */
105
+static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv)
106
+{
107
+ return drv->bdrv_co_create;
108
+}
109
+
110
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
111
Error **errp)
112
{
113
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
114
}
115
116
/* Error out if the driver doesn't support .bdrv_co_create */
117
- if (!drv->bdrv_co_create) {
118
+ if (!has_bdrv_co_create(drv)) {
119
error_setg(errp, "Driver does not support blockdev-create");
120
return;
121
}
122
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
125
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ fail:
127
return ret;
128
}
129
130
-static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv,
131
- const char *filename,
132
- QemuOpts *opts,
133
- Error **errp)
134
+static int coroutine_fn GRAPH_RDLOCK
135
+block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
136
+ QemuOpts *opts, Error **errp)
137
{
138
QCryptoBlockCreateOptions *create_opts = NULL;
139
BlockDriverState *bs = NULL;
140
diff --git a/block/file-posix.c b/block/file-posix.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/file-posix.c
143
+++ b/block/file-posix.c
144
@@ -XXX,XX +XXX,XX @@ out:
145
return result;
146
}
147
148
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
149
- const char *filename,
150
- QemuOpts *opts,
151
- Error **errp)
152
+static int coroutine_fn GRAPH_RDLOCK
153
+raw_co_create_opts(BlockDriver *drv, const char *filename,
154
+ QemuOpts *opts, Error **errp)
155
{
156
BlockdevCreateOptions options;
157
int64_t total_size = 0;
158
diff --git a/block/file-win32.c b/block/file-win32.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/file-win32.c
161
+++ b/block/file-win32.c
162
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
163
return 0;
164
}
165
166
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
167
- const char *filename,
168
- QemuOpts *opts,
169
- Error **errp)
170
+static int coroutine_fn GRAPH_RDLOCK
171
+raw_co_create_opts(BlockDriver *drv, const char *filename,
172
+ QemuOpts *opts, Error **errp)
173
{
174
BlockdevCreateOptions options;
175
int64_t total_size = 0;
176
diff --git a/block/parallels.c b/block/parallels.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/block/parallels.c
179
+++ b/block/parallels.c
180
@@ -XXX,XX +XXX,XX @@ exit:
181
goto out;
182
}
183
184
-static int coroutine_fn parallels_co_create_opts(BlockDriver *drv,
185
- const char *filename,
186
- QemuOpts *opts,
187
- Error **errp)
188
+static int coroutine_fn GRAPH_RDLOCK
189
+parallels_co_create_opts(BlockDriver *drv, const char *filename,
190
+ QemuOpts *opts, Error **errp)
191
{
192
BlockdevCreateOptions *create_options = NULL;
193
BlockDriverState *bs = NULL;
194
diff --git a/block/qcow.c b/block/qcow.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/block/qcow.c
197
+++ b/block/qcow.c
198
@@ -XXX,XX +XXX,XX @@ exit:
199
return ret;
200
}
201
202
-static int coroutine_fn qcow_co_create_opts(BlockDriver *drv,
203
- const char *filename,
204
- QemuOpts *opts, Error **errp)
205
+static int coroutine_fn GRAPH_RDLOCK
206
+qcow_co_create_opts(BlockDriver *drv, const char *filename,
207
+ QemuOpts *opts, Error **errp)
208
{
209
BlockdevCreateOptions *create_options = NULL;
210
BlockDriverState *bs = NULL;
211
diff --git a/block/qcow2.c b/block/qcow2.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/block/qcow2.c
214
+++ b/block/qcow2.c
215
@@ -XXX,XX +XXX,XX @@ out:
216
return ret;
217
}
218
219
-static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
220
- const char *filename,
221
- QemuOpts *opts,
222
- Error **errp)
223
+static int coroutine_fn GRAPH_RDLOCK
224
+qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
225
+ Error **errp)
226
{
227
BlockdevCreateOptions *create_options = NULL;
228
QDict *qdict;
229
diff --git a/block/qed.c b/block/qed.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/block/qed.c
232
+++ b/block/qed.c
233
@@ -XXX,XX +XXX,XX @@ out:
234
return ret;
235
}
236
237
-static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
238
- const char *filename,
239
- QemuOpts *opts,
240
- Error **errp)
241
+static int coroutine_fn GRAPH_RDLOCK
242
+bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
243
+ QemuOpts *opts, Error **errp)
244
{
245
BlockdevCreateOptions *create_options = NULL;
246
QDict *qdict;
247
diff --git a/block/raw-format.c b/block/raw-format.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/block/raw-format.c
250
+++ b/block/raw-format.c
251
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
252
return bdrv_has_zero_init(bs->file->bs);
253
}
254
255
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
256
- const char *filename,
257
- QemuOpts *opts,
258
- Error **errp)
259
+static int coroutine_fn GRAPH_RDLOCK
260
+raw_co_create_opts(BlockDriver *drv, const char *filename,
261
+ QemuOpts *opts, Error **errp)
262
{
263
return bdrv_co_create_file(filename, opts, errp);
264
}
18
diff --git a/block/vdi.c b/block/vdi.c
265
diff --git a/block/vdi.c b/block/vdi.c
19
index XXXXXXX..XXXXXXX 100644
266
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vdi.c
267
--- a/block/vdi.c
21
+++ b/block/vdi.c
268
+++ b/block/vdi.c
22
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_le(VdiHeader *header)
269
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options,
23
270
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
24
static void vdi_header_print(VdiHeader *header)
271
}
25
{
272
26
- char uuid[37];
273
-static int coroutine_fn vdi_co_create_opts(BlockDriver *drv,
27
+ char uuidstr[37];
274
- const char *filename,
28
+ QemuUUID uuid;
275
- QemuOpts *opts,
29
logout("text %s", header->text);
276
- Error **errp)
30
logout("signature 0x%08x\n", header->signature);
277
+static int coroutine_fn GRAPH_RDLOCK
31
logout("header size 0x%04x\n", header->header_size);
278
+vdi_co_create_opts(BlockDriver *drv, const char *filename,
32
@@ -XXX,XX +XXX,XX @@ static void vdi_header_print(VdiHeader *header)
279
+ QemuOpts *opts, Error **errp)
33
logout("block extra 0x%04x\n", header->block_extra);
280
{
34
logout("blocks tot. 0x%04x\n", header->blocks_in_image);
281
QDict *qdict = NULL;
35
logout("blocks all. 0x%04x\n", header->blocks_allocated);
282
BlockdevCreateOptions *create_options = NULL;
36
- qemu_uuid_unparse(&header->uuid_image, uuid);
283
diff --git a/block/vhdx.c b/block/vhdx.c
37
- logout("uuid image %s\n", uuid);
284
index XXXXXXX..XXXXXXX 100644
38
- qemu_uuid_unparse(&header->uuid_last_snap, uuid);
285
--- a/block/vhdx.c
39
- logout("uuid snap %s\n", uuid);
286
+++ b/block/vhdx.c
40
- qemu_uuid_unparse(&header->uuid_link, uuid);
287
@@ -XXX,XX +XXX,XX @@ delete_and_exit:
41
- logout("uuid link %s\n", uuid);
288
return ret;
42
- qemu_uuid_unparse(&header->uuid_parent, uuid);
289
}
43
- logout("uuid parent %s\n", uuid);
290
44
+ uuid = header->uuid_image;
291
-static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv,
45
+ qemu_uuid_unparse(&uuid, uuidstr);
292
- const char *filename,
46
+ logout("uuid image %s\n", uuidstr);
293
- QemuOpts *opts,
47
+ uuid = header->uuid_last_snap;
294
- Error **errp)
48
+ qemu_uuid_unparse(&uuid, uuidstr);
295
+static int coroutine_fn GRAPH_RDLOCK
49
+ logout("uuid snap %s\n", uuidstr);
296
+vhdx_co_create_opts(BlockDriver *drv, const char *filename,
50
+ uuid = header->uuid_link;
297
+ QemuOpts *opts, Error **errp)
51
+ qemu_uuid_unparse(&uuid, uuidstr);
298
{
52
+ logout("uuid link %s\n", uuidstr);
299
BlockdevCreateOptions *create_options = NULL;
53
+ uuid = header->uuid_parent;
300
QDict *qdict;
54
+ qemu_uuid_unparse(&uuid, uuidstr);
301
diff --git a/block/vmdk.c b/block/vmdk.c
55
+ logout("uuid parent %s\n", uuidstr);
302
index XXXXXXX..XXXXXXX 100644
56
}
303
--- a/block/vmdk.c
57
304
+++ b/block/vmdk.c
58
static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
305
@@ -XXX,XX +XXX,XX @@ exit:
59
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
306
return ret;
60
size_t bmap_size;
307
}
308
309
-static int coroutine_fn vmdk_create_extent(const char *filename,
310
- int64_t filesize, bool flat,
311
- bool compress, bool zeroed_grain,
312
- BlockBackend **pbb,
313
- QemuOpts *opts, Error **errp)
314
+static int coroutine_fn GRAPH_RDLOCK
315
+vmdk_create_extent(const char *filename, int64_t filesize, bool flat,
316
+ bool compress, bool zeroed_grain, BlockBackend **pbb,
317
+ QemuOpts *opts, Error **errp)
318
{
61
int ret;
319
int ret;
320
BlockBackend *blk = NULL;
321
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
322
* non-split format.
323
* idx >= 1: get the n-th extent if in a split subformat
324
*/
325
-typedef BlockBackend * coroutine_fn (*vmdk_create_extent_fn)(int64_t size,
326
- int idx,
327
- bool flat,
328
- bool split,
329
- bool compress,
330
- bool zeroed_grain,
331
- void *opaque,
332
- Error **errp);
333
+typedef BlockBackend * coroutine_fn /* GRAPH_RDLOCK */
334
+ (*vmdk_create_extent_fn)(int64_t size, int idx, bool flat, bool split,
335
+ bool compress, bool zeroed_grain, void *opaque,
336
+ Error **errp);
337
338
static void vmdk_desc_add_extent(GString *desc,
339
const char *extent_line_fmt,
340
@@ -XXX,XX +XXX,XX @@ static void vmdk_desc_add_extent(GString *desc,
341
g_free(basename);
342
}
343
344
-static int coroutine_fn vmdk_co_do_create(int64_t size,
345
- BlockdevVmdkSubformat subformat,
346
- BlockdevVmdkAdapterType adapter_type,
347
- const char *backing_file,
348
- const char *hw_version,
349
- const char *toolsversion,
350
- bool compat6,
351
- bool zeroed_grain,
352
- vmdk_create_extent_fn extent_fn,
353
- void *opaque,
354
- Error **errp)
355
+static int coroutine_fn GRAPH_RDLOCK
356
+vmdk_co_do_create(int64_t size,
357
+ BlockdevVmdkSubformat subformat,
358
+ BlockdevVmdkAdapterType adapter_type,
359
+ const char *backing_file,
360
+ const char *hw_version,
361
+ const char *toolsversion,
362
+ bool compat6,
363
+ bool zeroed_grain,
364
+ vmdk_create_extent_fn extent_fn,
365
+ void *opaque,
366
+ Error **errp)
367
{
368
int extent_idx;
369
BlockBackend *blk = NULL;
370
@@ -XXX,XX +XXX,XX @@ typedef struct {
371
QemuOpts *opts;
372
} VMDKCreateOptsData;
373
374
-static BlockBackend * coroutine_fn vmdk_co_create_opts_cb(int64_t size, int idx,
375
- bool flat, bool split, bool compress,
376
- bool zeroed_grain, void *opaque,
377
- Error **errp)
378
+static BlockBackend * coroutine_fn GRAPH_RDLOCK
379
+vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
380
+ bool compress, bool zeroed_grain, void *opaque,
381
+ Error **errp)
382
{
383
BlockBackend *blk = NULL;
384
BlockDriverState *bs = NULL;
385
@@ -XXX,XX +XXX,XX @@ exit:
386
return blk;
387
}
388
389
-static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
390
- const char *filename,
391
- QemuOpts *opts,
392
- Error **errp)
393
+static int coroutine_fn GRAPH_RDLOCK
394
+vmdk_co_create_opts(BlockDriver *drv, const char *filename,
395
+ QemuOpts *opts, Error **errp)
396
{
62
Error *local_err = NULL;
397
Error *local_err = NULL;
63
+ QemuUUID uuid_link, uuid_parent;
398
char *desc = NULL;
64
399
@@ -XXX,XX +XXX,XX @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
65
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
400
return blk;
66
false, errp);
401
}
67
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
402
68
goto fail;
403
-static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
69
}
404
- Error **errp)
70
405
+static int coroutine_fn GRAPH_RDLOCK
71
+ uuid_link = header.uuid_link;
406
+vmdk_co_create(BlockdevCreateOptions *create_options, Error **errp)
72
+ uuid_parent = header.uuid_parent;
407
{
73
+
408
BlockdevCreateOptionsVmdk *opts;
74
if (header.disk_size % SECTOR_SIZE != 0) {
409
75
/* 'VBoxManage convertfromraw' can create images with odd disk sizes.
410
diff --git a/block/vpc.c b/block/vpc.c
76
We accept them but round the disk size to the next multiple of
411
index XXXXXXX..XXXXXXX 100644
77
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
412
--- a/block/vpc.c
78
(uint64_t)header.blocks_in_image * header.block_size);
413
+++ b/block/vpc.c
79
ret = -ENOTSUP;
414
@@ -XXX,XX +XXX,XX @@ out:
80
goto fail;
415
return ret;
81
- } else if (!qemu_uuid_is_null(&header.uuid_link)) {
416
}
82
+ } else if (!qemu_uuid_is_null(&uuid_link)) {
417
83
error_setg(errp, "unsupported VDI image (non-NULL link UUID)");
418
-static int coroutine_fn vpc_co_create_opts(BlockDriver *drv,
84
ret = -ENOTSUP;
419
- const char *filename,
85
goto fail;
420
- QemuOpts *opts,
86
- } else if (!qemu_uuid_is_null(&header.uuid_parent)) {
421
- Error **errp)
87
+ } else if (!qemu_uuid_is_null(&uuid_parent)) {
422
+static int coroutine_fn GRAPH_RDLOCK
88
error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
423
+vpc_co_create_opts(BlockDriver *drv, const char *filename,
89
ret = -ENOTSUP;
424
+ QemuOpts *opts, Error **errp)
90
goto fail;
425
{
91
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
426
BlockdevCreateOptions *create_options = NULL;
92
BlockDriverState *bs_file = NULL;
427
QDict *qdict;
93
BlockBackend *blk = NULL;
94
uint32_t *bmap = NULL;
95
+ QemuUUID uuid;
96
97
assert(create_options->driver == BLOCKDEV_DRIVER_VDI);
98
vdi_opts = &create_options->u.vdi;
99
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
100
if (image_type == VDI_TYPE_STATIC) {
101
header.blocks_allocated = blocks;
102
}
103
- qemu_uuid_generate(&header.uuid_image);
104
- qemu_uuid_generate(&header.uuid_last_snap);
105
+ qemu_uuid_generate(&uuid);
106
+ header.uuid_image = uuid;
107
+ qemu_uuid_generate(&uuid);
108
+ header.uuid_last_snap = uuid;
109
/* There is no need to set header.uuid_link or header.uuid_parent here. */
110
if (VDI_DEBUG) {
111
vdi_header_print(&header);
112
--
428
--
113
2.20.1
429
2.39.2
114
115
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_io_plug() and bdrv_co_io_unplug() need to hold a reader lock for
3
the graph.
2
4
3
This patch forbids attaching a disk to a SCSI device if its using a
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
different AioContext. Test case included.
6
Message-Id: <20230203152202.49054-18-kwolf@redhat.com>
5
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
---
9
hw/scsi/virtio-scsi.c | 7 +++++++
10
include/block/block-io.h | 4 ++--
10
tests/qemu-iotests/240 | 22 ++++++++++++++++++++++
11
include/block/block_int-common.h | 5 +++--
11
tests/qemu-iotests/240.out | 20 ++++++++++++++++++++
12
block/block-backend.c | 2 ++
12
3 files changed, 49 insertions(+)
13
block/io.c | 2 ++
14
4 files changed, 9 insertions(+), 4 deletions(-)
13
15
14
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/scsi/virtio-scsi.c
18
--- a/include/block/block-io.h
17
+++ b/hw/scsi/virtio-scsi.c
19
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
20
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
19
SCSIDevice *sd = SCSI_DEVICE(dev);
21
20
22
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
21
if (s->ctx && !s->dataplane_fenced) {
23
22
+ AioContext *ctx;
24
-void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
23
if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
25
-void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
24
return;
26
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
25
}
27
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
26
+ ctx = blk_get_aio_context(sd->conf.blk);
28
27
+ if (ctx != s->ctx && ctx != qemu_get_aio_context()) {
29
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
28
+ error_setg(errp, "Cannot attach a blockdev that is using "
30
const char *name,
29
+ "a different iothread");
31
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
30
+ return;
31
+ }
32
virtio_scsi_acquire(s);
33
blk_set_aio_context(sd->conf.blk, s->ctx);
34
virtio_scsi_release(s);
35
diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240
36
index XXXXXXX..XXXXXXX 100755
37
--- a/tests/qemu-iotests/240
38
+++ b/tests/qemu-iotests/240
39
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
40
{ "execute": "quit"}
41
EOF
42
43
+echo
44
+echo === Attach two SCSI disks using the same block device but different iothreads ===
45
+echo
46
+
47
+run_qemu <<EOF
48
+{ "execute": "qmp_capabilities" }
49
+{ "execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true}}
50
+{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread0"}}
51
+{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread1"}}
52
+{ "execute": "device_add", "arguments": {"id": "scsi0", "driver": "${virtio_scsi}", "iothread": "iothread0"}}
53
+{ "execute": "device_add", "arguments": {"id": "scsi1", "driver": "${virtio_scsi}", "iothread": "iothread1"}}
54
+{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0", "bus": "scsi0.0"}}
55
+{ "execute": "device_add", "arguments": {"id": "scsi-hd1", "driver": "scsi-hd", "drive": "hd0", "bus": "scsi1.0"}}
56
+{ "execute": "device_del", "arguments": {"id": "scsi-hd0"}}
57
+{ "execute": "device_add", "arguments": {"id": "scsi-hd1", "driver": "scsi-hd", "drive": "hd0", "bus": "scsi1.0"}}
58
+{ "execute": "device_del", "arguments": {"id": "scsi-hd1"}}
59
+{ "execute": "device_del", "arguments": {"id": "scsi0"}}
60
+{ "execute": "device_del", "arguments": {"id": "scsi1"}}
61
+{ "execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
62
+{ "execute": "quit"}
63
+EOF
64
+
65
# success, all done
66
echo "*** done"
67
rm -f $seq.full
68
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
69
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
70
--- a/tests/qemu-iotests/240.out
33
--- a/include/block/block_int-common.h
71
+++ b/tests/qemu-iotests/240.out
34
+++ b/include/block/block_int-common.h
72
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
35
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
73
{"return": {}}
36
BlkdebugEvent event);
74
{"return": {}}
37
75
{"return": {}}
38
/* io queue for linux-aio */
76
+
39
- void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
77
+=== Attach two SCSI disks using the same block device but different iothreads ===
40
- void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
78
+
41
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs);
79
+Testing:
42
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_unplug)(
80
+QMP_VERSION
43
+ BlockDriverState *bs);
81
+{"return": {}}
44
82
+{"return": {}}
45
/**
83
+{"return": {}}
46
* bdrv_drain_begin is called if implemented in the beginning of a
84
+{"return": {}}
47
diff --git a/block/block-backend.c b/block/block-backend.c
85
+{"return": {}}
48
index XXXXXXX..XXXXXXX 100644
86
+{"return": {}}
49
--- a/block/block-backend.c
87
+{"return": {}}
50
+++ b/block/block-backend.c
88
+{"error": {"class": "GenericError", "desc": "Cannot attach a blockdev that is using a different iothread"}}
51
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
89
+{"return": {}}
52
{
90
+{"return": {}}
53
BlockDriverState *bs = blk_bs(blk);
91
+{"return": {}}
54
IO_CODE();
92
+{"return": {}}
55
+ GRAPH_RDLOCK_GUARD();
93
+{"return": {}}
56
94
+{"return": {}}
57
if (bs) {
95
+{"return": {}}
58
bdrv_co_io_plug(bs);
96
*** done
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
60
{
61
BlockDriverState *bs = blk_bs(blk);
62
IO_CODE();
63
+ GRAPH_RDLOCK_GUARD();
64
65
if (bs) {
66
bdrv_co_io_unplug(bs);
67
diff --git a/block/io.c b/block/io.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/block/io.c
70
+++ b/block/io.c
71
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
72
{
73
BdrvChild *child;
74
IO_CODE();
75
+ assert_bdrv_graph_readable();
76
77
QLIST_FOREACH(child, &bs->children, next) {
78
bdrv_co_io_plug(child->bs);
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
80
{
81
BdrvChild *child;
82
IO_CODE();
83
+ assert_bdrv_graph_readable();
84
85
assert(bs->io_plugged);
86
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
97
--
87
--
98
2.20.1
88
2.39.2
99
100
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Refcount table entries have a field to store the offset of the
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
refcount block. The rest of the bits of the entry are currently
4
bdrv_co_is_inserted() need to hold a reader lock for the graph.
5
reserved.
6
5
7
The offset is always taken from the entry using REFT_OFFSET_MASK to
6
blk_is_inserted() is done as a co_wrapper_mixed_bdrv_rdlock (unlike most
8
ensure that we only use the bits that belong to that field.
7
other blk_* functions) because it is called a lot from other blk_co_*()
8
functions that already hold the lock. These calls go through
9
blk_is_available(), which becomes a co_wrapper_mixed_bdrv_rdlock, too,
10
for the same reason.
9
11
10
While that mask is used every time we read from the refcount table, it
12
Functions that run in a coroutine and can call bdrv_co_is_available()
11
is never used when we write to it. Due to the other constraints of the
13
directly are changed to do so, which results in better TSA coverage.
12
qcow2 format QEMU can never produce refcount block offsets that don't
13
fit in that field so any such offset when allocating a refcount block
14
would indicate a bug in QEMU.
15
14
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20230203152202.49054-19-kwolf@redhat.com>
18
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
---
20
block/qcow2-refcount.c | 3 +++
21
include/block/block-io.h | 4 ++--
21
1 file changed, 3 insertions(+)
22
include/block/block_int-common.h | 3 ++-
23
include/sysemu/block-backend-io.h | 7 ++++---
24
block.c | 1 +
25
block/block-backend.c | 25 ++++++++++++++-----------
26
5 files changed, 23 insertions(+), 17 deletions(-)
22
27
23
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
24
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2-refcount.c
30
--- a/include/block/block-io.h
26
+++ b/block/qcow2-refcount.c
31
+++ b/include/block/block-io.h
27
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
32
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs);
28
return new_block;
33
bool bdrv_is_sg(BlockDriverState *bs);
34
int bdrv_get_flags(BlockDriverState *bs);
35
36
-bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
37
-bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
38
+bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
39
+bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
40
41
void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
42
void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
49
50
/* removable device specific */
51
- bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
52
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
53
+ BlockDriverState *bs);
54
void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
55
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
56
57
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/sysemu/block-backend-io.h
60
+++ b/include/sysemu/block-backend-io.h
61
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
62
void blk_inc_in_flight(BlockBackend *blk);
63
void blk_dec_in_flight(BlockBackend *blk);
64
65
-bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
66
-bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
67
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_inserted(BlockBackend *blk);
68
+bool co_wrapper_mixed_bdrv_rdlock blk_is_inserted(BlockBackend *blk);
69
70
-bool blk_is_available(BlockBackend *blk);
71
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_available(BlockBackend *blk);
72
+bool co_wrapper_mixed_bdrv_rdlock blk_is_available(BlockBackend *blk);
73
74
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
75
void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
76
diff --git a/block.c b/block.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block.c
79
+++ b/block.c
80
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
81
BlockDriver *drv = bs->drv;
82
BdrvChild *child;
83
IO_CODE();
84
+ assert_bdrv_graph_readable();
85
86
if (!drv) {
87
return false;
88
diff --git a/block/block-backend.c b/block/block-backend.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/block-backend.c
91
+++ b/block/block-backend.c
92
@@ -XXX,XX +XXX,XX @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
93
blk->disable_request_queuing = disable;
94
}
95
96
-static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
97
- int64_t offset, int64_t bytes)
98
+static int coroutine_fn GRAPH_RDLOCK
99
+blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
100
{
101
int64_t len;
102
103
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
104
return -EIO;
29
}
105
}
30
106
31
+ /* The offset must fit in the offset field of the refcount table entry */
107
- if (!blk_is_available(blk)) {
32
+ assert((new_block & REFT_OFFSET_MASK) == new_block);
108
+ if (!blk_co_is_available(blk)) {
33
+
109
return -ENOMEDIUM;
34
/* If we're allocating the block at offset 0 then something is wrong */
110
}
35
if (new_block == 0) {
111
36
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
112
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
113
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
114
{
115
IO_CODE();
116
+ GRAPH_RDLOCK_GUARD();
117
118
- if (!blk_is_available(blk)) {
119
+ if (!blk_co_is_available(blk)) {
120
return -ENOMEDIUM;
121
}
122
123
@@ -XXX,XX +XXX,XX @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
124
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
125
{
126
IO_CODE();
127
+ GRAPH_RDLOCK_GUARD();
128
129
- if (!blk_is_available(blk)) {
130
+ if (!blk_co_is_available(blk)) {
131
return -ENOMEDIUM;
132
}
133
134
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
135
blk_wait_while_drained(blk);
136
GRAPH_RDLOCK_GUARD();
137
138
- if (!blk_is_available(blk)) {
139
+ if (!blk_co_is_available(blk)) {
140
return -ENOMEDIUM;
141
}
142
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
144
blk_wait_while_drained(blk);
145
GRAPH_RDLOCK_GUARD();
146
147
- if (!blk_is_available(blk)) {
148
+ if (!blk_co_is_available(blk)) {
149
return -ENOMEDIUM;
150
}
151
152
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
153
{
154
BlockDriverState *bs = blk_bs(blk);
155
IO_CODE();
156
+ assert_bdrv_graph_readable();
157
158
return bs && bdrv_co_is_inserted(bs);
159
}
160
161
-bool blk_is_available(BlockBackend *blk)
162
+bool coroutine_fn blk_co_is_available(BlockBackend *blk)
163
{
164
IO_CODE();
165
- return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
166
+ return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk);
167
}
168
169
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
170
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
171
{
172
IO_OR_GS_CODE();
173
GRAPH_RDLOCK_GUARD();
174
- if (!blk_is_available(blk)) {
175
+ if (!blk_co_is_available(blk)) {
176
error_setg(errp, "No medium inserted");
177
return -ENOMEDIUM;
178
}
179
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
180
{
181
int r;
182
IO_CODE();
183
+ GRAPH_RDLOCK_GUARD();
184
185
r = blk_check_byte_request(blk_in, off_in, bytes);
186
if (r) {
187
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
188
return r;
189
}
190
191
- GRAPH_RDLOCK_GUARD();
192
return bdrv_co_copy_range(blk_in->root, off_in,
193
blk_out->root, off_out,
194
bytes, read_flags, write_flags);
37
--
195
--
38
2.20.1
196
2.39.2
39
40
diff view generated by jsdifflib
1
In the block layer, synchronous APIs are often implemented by creating a
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
coroutine that calls the asynchronous coroutine-based implementation and
2
bdrv_co_eject() and bdrv_co_lock_medium() need to hold a reader lock for
3
then waiting for completion with BDRV_POLL_WHILE().
3
the graph.
4
4
5
For this to work with iothreads (more specifically, when the synchronous
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
API is called in a thread that is not the home thread of the block
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
device, so that the coroutine will run in a different thread), we must
7
Message-Id: <20230203152202.49054-20-kwolf@redhat.com>
8
make sure to call aio_wait_kick() at the end of the operation. Many
8
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
places are missing this, so that BDRV_POLL_WHILE() keeps hanging even if
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
the condition has long become false.
10
---
11
include/block/block-io.h | 7 +++++--
12
include/block/block_int-common.h | 6 ++++--
13
block.c | 2 ++
14
block/block-backend.c | 2 ++
15
block/copy-on-read.c | 6 ++++--
16
block/filter-compress.c | 4 ++--
17
block/raw-format.c | 6 ++++--
18
7 files changed, 23 insertions(+), 10 deletions(-)
11
19
12
Note that bdrv_dec_in_flight() involves an aio_wait_kick() call. This
20
diff --git a/include/block/block-io.h b/include/block/block-io.h
13
corresponds to the BDRV_POLL_WHILE() in the drain functions, but it is
21
index XXXXXXX..XXXXXXX 100644
14
generally not enough for most other operations because they haven't set
22
--- a/include/block/block-io.h
15
the return value in the coroutine entry stub yet. To avoid race
23
+++ b/include/block/block-io.h
16
conditions there, we need to kick after setting the return value.
24
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
17
25
bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
18
The race window is small enough that the problem doesn't usually surface
26
bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
19
in the common path. However, it does surface and causes easily
27
20
reproducible hangs if the operation can return early before even calling
28
-void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
21
bdrv_inc/dec_in_flight, which many of them do (trivial error or no-op
29
-void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
22
success paths).
30
+void coroutine_fn GRAPH_RDLOCK
23
31
+bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
24
The bug in bdrv_truncate(), bdrv_check() and bdrv_invalidate_cache() is
32
+
25
slightly different: These functions even neglected to schedule the
33
+void coroutine_fn GRAPH_RDLOCK
26
coroutine in the home thread of the node. This avoids the hang, but is
34
+bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
27
obviously wrong, too. Fix those to schedule the coroutine in the right
35
28
AioContext in addition to adding aio_wait_kick() calls.
36
const char *bdrv_get_format_name(BlockDriverState *bs);
29
37
30
Cc: qemu-stable@nongnu.org
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
31
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
index XXXXXXX..XXXXXXX 100644
32
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
40
--- a/include/block/block_int-common.h
33
---
41
+++ b/include/block/block_int-common.h
34
block.c | 6 +-
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
35
block/block-backend.c | 5 +
43
/* removable device specific */
36
block/io.c | 8 +-
44
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
37
block/nbd-client.c | 1 +
45
BlockDriverState *bs);
38
block/nvme.c | 1 +
46
- void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
39
block/qcow2.c | 1 +
47
- void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
40
block/qed.c | 1 +
48
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_eject)(
41
tests/test-block-iothread.c | 372 ++++++++++++++++++++++++++++++++++++
49
+ BlockDriverState *bs, bool eject_flag);
42
tests/Makefile.include | 2 +
50
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_lock_medium)(
43
9 files changed, 394 insertions(+), 3 deletions(-)
51
+ BlockDriverState *bs, bool locked);
44
create mode 100644 tests/test-block-iothread.c
52
45
53
/* to control generic scsi devices */
54
BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
46
diff --git a/block.c b/block.c
55
diff --git a/block.c b/block.c
47
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
48
--- a/block.c
57
--- a/block.c
49
+++ b/block.c
58
+++ b/block.c
50
@@ -XXX,XX +XXX,XX @@ static void bdrv_check_co_entry(void *opaque)
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
51
{
60
{
52
CheckCo *cco = opaque;
61
BlockDriver *drv = bs->drv;
53
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
62
IO_CODE();
54
+ aio_wait_kick();
63
+ assert_bdrv_graph_readable();
55
}
64
56
65
if (drv && drv->bdrv_co_eject) {
57
int bdrv_check(BlockDriverState *bs,
66
drv->bdrv_co_eject(bs, eject_flag);
58
@@ -XXX,XX +XXX,XX @@ int bdrv_check(BlockDriverState *bs,
67
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
59
bdrv_check_co_entry(&cco);
68
{
60
} else {
69
BlockDriver *drv = bs->drv;
61
co = qemu_coroutine_create(bdrv_check_co_entry, &cco);
70
IO_CODE();
62
- qemu_coroutine_enter(co);
71
+ assert_bdrv_graph_readable();
63
+ bdrv_coroutine_enter(bs, co);
72
trace_bdrv_lock_medium(bs, locked);
64
BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS);
73
65
}
74
if (drv && drv->bdrv_co_lock_medium) {
66
67
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_invalidate_cache_co_entry(void *opaque)
68
InvalidateCacheCo *ico = opaque;
69
bdrv_co_invalidate_cache(ico->bs, ico->errp);
70
ico->done = true;
71
+ aio_wait_kick();
72
}
73
74
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
76
bdrv_invalidate_cache_co_entry(&ico);
77
} else {
78
co = qemu_coroutine_create(bdrv_invalidate_cache_co_entry, &ico);
79
- qemu_coroutine_enter(co);
80
+ bdrv_coroutine_enter(bs, co);
81
BDRV_POLL_WHILE(bs, !ico.done);
82
}
83
}
84
diff --git a/block/block-backend.c b/block/block-backend.c
75
diff --git a/block/block-backend.c b/block/block-backend.c
85
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
86
--- a/block/block-backend.c
77
--- a/block/block-backend.c
87
+++ b/block/block-backend.c
78
+++ b/block/block-backend.c
88
@@ -XXX,XX +XXX,XX @@ static void blk_read_entry(void *opaque)
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
89
80
{
90
rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, qiov->size,
81
BlockDriverState *bs = blk_bs(blk);
91
qiov, rwco->flags);
82
IO_CODE();
92
+ aio_wait_kick();
83
+ GRAPH_RDLOCK_GUARD();
84
85
if (bs) {
86
bdrv_co_lock_medium(bs, locked);
87
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
88
BlockDriverState *bs = blk_bs(blk);
89
char *id;
90
IO_CODE();
91
+ GRAPH_RDLOCK_GUARD();
92
93
if (bs) {
94
bdrv_co_eject(bs, eject_flag);
95
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/block/copy-on-read.c
98
+++ b/block/copy-on-read.c
99
@@ -XXX,XX +XXX,XX @@ cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
93
}
100
}
94
101
95
static void blk_write_entry(void *opaque)
102
96
@@ -XXX,XX +XXX,XX @@ static void blk_write_entry(void *opaque)
103
-static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
97
104
+static void coroutine_fn GRAPH_RDLOCK
98
rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, qiov->size,
105
+cor_co_eject(BlockDriverState *bs, bool eject_flag)
99
qiov, rwco->flags);
106
{
100
+ aio_wait_kick();
107
bdrv_co_eject(bs->file->bs, eject_flag);
101
}
108
}
102
109
103
static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
110
104
@@ -XXX,XX +XXX,XX @@ static void blk_ioctl_entry(void *opaque)
111
-static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
105
112
+static void coroutine_fn GRAPH_RDLOCK
106
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
113
+cor_co_lock_medium(BlockDriverState *bs, bool locked)
107
qiov->iov[0].iov_base);
114
{
108
+ aio_wait_kick();
115
bdrv_co_lock_medium(bs->file->bs, locked);
109
}
116
}
110
117
diff --git a/block/filter-compress.c b/block/filter-compress.c
111
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
118
index XXXXXXX..XXXXXXX 100644
112
@@ -XXX,XX +XXX,XX @@ static void blk_flush_entry(void *opaque)
119
--- a/block/filter-compress.c
120
+++ b/block/filter-compress.c
121
@@ -XXX,XX +XXX,XX @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
122
}
123
124
125
-static void coroutine_fn
126
+static void coroutine_fn GRAPH_RDLOCK
127
compress_co_eject(BlockDriverState *bs, bool eject_flag)
113
{
128
{
114
BlkRwCo *rwco = opaque;
129
bdrv_co_eject(bs->file->bs, eject_flag);
115
rwco->ret = blk_co_flush(rwco->blk);
116
+ aio_wait_kick();
117
}
130
}
118
131
119
int blk_flush(BlockBackend *blk)
132
120
@@ -XXX,XX +XXX,XX @@ static void blk_pdiscard_entry(void *opaque)
133
-static void coroutine_fn
121
QEMUIOVector *qiov = rwco->iobuf;
134
+static void coroutine_fn GRAPH_RDLOCK
122
135
compress_co_lock_medium(BlockDriverState *bs, bool locked)
123
rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, qiov->size);
136
{
124
+ aio_wait_kick();
137
bdrv_co_lock_medium(bs->file->bs, locked);
138
diff --git a/block/raw-format.c b/block/raw-format.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/raw-format.c
141
+++ b/block/raw-format.c
142
@@ -XXX,XX +XXX,XX @@ raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
143
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
125
}
144
}
126
145
127
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
146
-static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
128
diff --git a/block/io.c b/block/io.c
147
+static void coroutine_fn GRAPH_RDLOCK
129
index XXXXXXX..XXXXXXX 100644
148
+raw_co_eject(BlockDriverState *bs, bool eject_flag)
130
--- a/block/io.c
149
{
131
+++ b/block/io.c
150
bdrv_co_eject(bs->file->bs, eject_flag);
132
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
133
rwco->qiov->size, rwco->qiov,
134
rwco->flags);
135
}
136
+ aio_wait_kick();
137
}
151
}
138
152
139
/*
153
-static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
140
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque)
154
+static void coroutine_fn GRAPH_RDLOCK
141
data->offset, data->bytes,
155
+raw_co_lock_medium(BlockDriverState *bs, bool locked)
142
data->pnum, data->map, data->file);
156
{
143
data->done = true;
157
bdrv_co_lock_medium(bs->file->bs, locked);
144
+ aio_wait_kick();
145
}
158
}
146
147
/*
148
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_rw_vmstate_entry(void *opaque)
149
{
150
BdrvVmstateCo *co = opaque;
151
co->ret = bdrv_co_rw_vmstate(co->bs, co->qiov, co->pos, co->is_read);
152
+ aio_wait_kick();
153
}
154
155
static inline int
156
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque)
157
FlushCo *rwco = opaque;
158
159
rwco->ret = bdrv_co_flush(rwco->bs);
160
+ aio_wait_kick();
161
}
162
163
int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
164
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
165
DiscardCo *rwco = opaque;
166
167
rwco->ret = bdrv_co_pdiscard(rwco->child, rwco->offset, rwco->bytes);
168
+ aio_wait_kick();
169
}
170
171
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
172
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
173
TruncateCo *tco = opaque;
174
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
175
tco->errp);
176
+ aio_wait_kick();
177
}
178
179
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
180
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
181
bdrv_truncate_co_entry(&tco);
182
} else {
183
co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
184
- qemu_coroutine_enter(co);
185
+ bdrv_coroutine_enter(child->bs, co);
186
BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
187
}
188
189
diff --git a/block/nbd-client.c b/block/nbd-client.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/block/nbd-client.c
192
+++ b/block/nbd-client.c
193
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
194
s->quit = true;
195
nbd_recv_coroutines_wake_all(s);
196
s->read_reply_co = NULL;
197
+ aio_wait_kick();
198
}
199
200
static int nbd_co_send_request(BlockDriverState *bs,
201
diff --git a/block/nvme.c b/block/nvme.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/block/nvme.c
204
+++ b/block/nvme.c
205
@@ -XXX,XX +XXX,XX @@ static void nvme_cmd_sync_cb(void *opaque, int ret)
206
{
207
int *pret = opaque;
208
*pret = ret;
209
+ aio_wait_kick();
210
}
211
212
static int nvme_cmd_sync(BlockDriverState *bs, NVMeQueuePair *q,
213
diff --git a/block/qcow2.c b/block/qcow2.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/block/qcow2.c
216
+++ b/block/qcow2.c
217
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
218
/* From bdrv_co_create. */
219
qcow2_open_entry(&qoc);
220
} else {
221
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
222
qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
223
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
224
}
225
diff --git a/block/qed.c b/block/qed.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/block/qed.c
228
+++ b/block/qed.c
229
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
230
if (qemu_in_coroutine()) {
231
bdrv_qed_open_entry(&qoc);
232
} else {
233
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
234
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
235
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
236
}
237
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
238
new file mode 100644
239
index XXXXXXX..XXXXXXX
240
--- /dev/null
241
+++ b/tests/test-block-iothread.c
242
@@ -XXX,XX +XXX,XX @@
243
+/*
244
+ * Block tests for iothreads
245
+ *
246
+ * Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
247
+ *
248
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
249
+ * of this software and associated documentation files (the "Software"), to deal
250
+ * in the Software without restriction, including without limitation the rights
251
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
252
+ * copies of the Software, and to permit persons to whom the Software is
253
+ * furnished to do so, subject to the following conditions:
254
+ *
255
+ * The above copyright notice and this permission notice shall be included in
256
+ * all copies or substantial portions of the Software.
257
+ *
258
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
259
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
260
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
261
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
262
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
263
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
264
+ * THE SOFTWARE.
265
+ */
266
+
267
+#include "qemu/osdep.h"
268
+#include "block/block.h"
269
+#include "block/blockjob_int.h"
270
+#include "sysemu/block-backend.h"
271
+#include "qapi/error.h"
272
+#include "iothread.h"
273
+
274
+static int coroutine_fn bdrv_test_co_prwv(BlockDriverState *bs,
275
+ uint64_t offset, uint64_t bytes,
276
+ QEMUIOVector *qiov, int flags)
277
+{
278
+ return 0;
279
+}
280
+
281
+static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
282
+ int64_t offset, int bytes)
283
+{
284
+ return 0;
285
+}
286
+
287
+static int coroutine_fn
288
+bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset,
289
+ PreallocMode prealloc, Error **errp)
290
+{
291
+ return 0;
292
+}
293
+
294
+static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
295
+ bool want_zero,
296
+ int64_t offset, int64_t count,
297
+ int64_t *pnum, int64_t *map,
298
+ BlockDriverState **file)
299
+{
300
+ *pnum = count;
301
+ return 0;
302
+}
303
+
304
+static BlockDriver bdrv_test = {
305
+ .format_name = "test",
306
+ .instance_size = 1,
307
+
308
+ .bdrv_co_preadv = bdrv_test_co_prwv,
309
+ .bdrv_co_pwritev = bdrv_test_co_prwv,
310
+ .bdrv_co_pdiscard = bdrv_test_co_pdiscard,
311
+ .bdrv_co_truncate = bdrv_test_co_truncate,
312
+ .bdrv_co_block_status = bdrv_test_co_block_status,
313
+};
314
+
315
+static void test_sync_op_pread(BdrvChild *c)
316
+{
317
+ uint8_t buf[512];
318
+ int ret;
319
+
320
+ /* Success */
321
+ ret = bdrv_pread(c, 0, buf, sizeof(buf));
322
+ g_assert_cmpint(ret, ==, 512);
323
+
324
+ /* Early error: Negative offset */
325
+ ret = bdrv_pread(c, -2, buf, sizeof(buf));
326
+ g_assert_cmpint(ret, ==, -EIO);
327
+}
328
+
329
+static void test_sync_op_pwrite(BdrvChild *c)
330
+{
331
+ uint8_t buf[512];
332
+ int ret;
333
+
334
+ /* Success */
335
+ ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
336
+ g_assert_cmpint(ret, ==, 512);
337
+
338
+ /* Early error: Negative offset */
339
+ ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
340
+ g_assert_cmpint(ret, ==, -EIO);
341
+}
342
+
343
+static void test_sync_op_blk_pread(BlockBackend *blk)
344
+{
345
+ uint8_t buf[512];
346
+ int ret;
347
+
348
+ /* Success */
349
+ ret = blk_pread(blk, 0, buf, sizeof(buf));
350
+ g_assert_cmpint(ret, ==, 512);
351
+
352
+ /* Early error: Negative offset */
353
+ ret = blk_pread(blk, -2, buf, sizeof(buf));
354
+ g_assert_cmpint(ret, ==, -EIO);
355
+}
356
+
357
+static void test_sync_op_blk_pwrite(BlockBackend *blk)
358
+{
359
+ uint8_t buf[512];
360
+ int ret;
361
+
362
+ /* Success */
363
+ ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
364
+ g_assert_cmpint(ret, ==, 512);
365
+
366
+ /* Early error: Negative offset */
367
+ ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
368
+ g_assert_cmpint(ret, ==, -EIO);
369
+}
370
+
371
+static void test_sync_op_load_vmstate(BdrvChild *c)
372
+{
373
+ uint8_t buf[512];
374
+ int ret;
375
+
376
+ /* Error: Driver does not support snapshots */
377
+ ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
378
+ g_assert_cmpint(ret, ==, -ENOTSUP);
379
+}
380
+
381
+static void test_sync_op_save_vmstate(BdrvChild *c)
382
+{
383
+ uint8_t buf[512];
384
+ int ret;
385
+
386
+ /* Error: Driver does not support snapshots */
387
+ ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
388
+ g_assert_cmpint(ret, ==, -ENOTSUP);
389
+}
390
+
391
+static void test_sync_op_pdiscard(BdrvChild *c)
392
+{
393
+ int ret;
394
+
395
+ /* Normal success path */
396
+ c->bs->open_flags |= BDRV_O_UNMAP;
397
+ ret = bdrv_pdiscard(c, 0, 512);
398
+ g_assert_cmpint(ret, ==, 0);
399
+
400
+ /* Early success: UNMAP not supported */
401
+ c->bs->open_flags &= ~BDRV_O_UNMAP;
402
+ ret = bdrv_pdiscard(c, 0, 512);
403
+ g_assert_cmpint(ret, ==, 0);
404
+
405
+ /* Early error: Negative offset */
406
+ ret = bdrv_pdiscard(c, -2, 512);
407
+ g_assert_cmpint(ret, ==, -EIO);
408
+}
409
+
410
+static void test_sync_op_blk_pdiscard(BlockBackend *blk)
411
+{
412
+ int ret;
413
+
414
+ /* Early success: UNMAP not supported */
415
+ ret = blk_pdiscard(blk, 0, 512);
416
+ g_assert_cmpint(ret, ==, 0);
417
+
418
+ /* Early error: Negative offset */
419
+ ret = blk_pdiscard(blk, -2, 512);
420
+ g_assert_cmpint(ret, ==, -EIO);
421
+}
422
+
423
+static void test_sync_op_truncate(BdrvChild *c)
424
+{
425
+ int ret;
426
+
427
+ /* Normal success path */
428
+ ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
429
+ g_assert_cmpint(ret, ==, 0);
430
+
431
+ /* Early error: Negative offset */
432
+ ret = bdrv_truncate(c, -2, PREALLOC_MODE_OFF, NULL);
433
+ g_assert_cmpint(ret, ==, -EINVAL);
434
+
435
+ /* Error: Read-only image */
436
+ c->bs->read_only = true;
437
+ c->bs->open_flags &= ~BDRV_O_RDWR;
438
+
439
+ ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
440
+ g_assert_cmpint(ret, ==, -EACCES);
441
+
442
+ c->bs->read_only = false;
443
+ c->bs->open_flags |= BDRV_O_RDWR;
444
+}
445
+
446
+static void test_sync_op_block_status(BdrvChild *c)
447
+{
448
+ int ret;
449
+ int64_t n;
450
+
451
+ /* Normal success path */
452
+ ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
453
+ g_assert_cmpint(ret, ==, 0);
454
+
455
+ /* Early success: No driver support */
456
+ bdrv_test.bdrv_co_block_status = NULL;
457
+ ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
458
+ g_assert_cmpint(ret, ==, 1);
459
+
460
+ /* Early success: bytes = 0 */
461
+ ret = bdrv_is_allocated(c->bs, 0, 0, &n);
462
+ g_assert_cmpint(ret, ==, 0);
463
+
464
+ /* Early success: Offset > image size*/
465
+ ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
466
+ g_assert_cmpint(ret, ==, 0);
467
+}
468
+
469
+static void test_sync_op_flush(BdrvChild *c)
470
+{
471
+ int ret;
472
+
473
+ /* Normal success path */
474
+ ret = bdrv_flush(c->bs);
475
+ g_assert_cmpint(ret, ==, 0);
476
+
477
+ /* Early success: Read-only image */
478
+ c->bs->read_only = true;
479
+ c->bs->open_flags &= ~BDRV_O_RDWR;
480
+
481
+ ret = bdrv_flush(c->bs);
482
+ g_assert_cmpint(ret, ==, 0);
483
+
484
+ c->bs->read_only = false;
485
+ c->bs->open_flags |= BDRV_O_RDWR;
486
+}
487
+
488
+static void test_sync_op_blk_flush(BlockBackend *blk)
489
+{
490
+ BlockDriverState *bs = blk_bs(blk);
491
+ int ret;
492
+
493
+ /* Normal success path */
494
+ ret = blk_flush(blk);
495
+ g_assert_cmpint(ret, ==, 0);
496
+
497
+ /* Early success: Read-only image */
498
+ bs->read_only = true;
499
+ bs->open_flags &= ~BDRV_O_RDWR;
500
+
501
+ ret = blk_flush(blk);
502
+ g_assert_cmpint(ret, ==, 0);
503
+
504
+ bs->read_only = false;
505
+ bs->open_flags |= BDRV_O_RDWR;
506
+}
507
+
508
+static void test_sync_op_check(BdrvChild *c)
509
+{
510
+ BdrvCheckResult result;
511
+ int ret;
512
+
513
+ /* Error: Driver does not implement check */
514
+ ret = bdrv_check(c->bs, &result, 0);
515
+ g_assert_cmpint(ret, ==, -ENOTSUP);
516
+}
517
+
518
+static void test_sync_op_invalidate_cache(BdrvChild *c)
519
+{
520
+ /* Early success: Image is not inactive */
521
+ bdrv_invalidate_cache(c->bs, NULL);
522
+}
523
+
524
+
525
+typedef struct SyncOpTest {
526
+ const char *name;
527
+ void (*fn)(BdrvChild *c);
528
+ void (*blkfn)(BlockBackend *blk);
529
+} SyncOpTest;
530
+
531
+const SyncOpTest sync_op_tests[] = {
532
+ {
533
+ .name = "/sync-op/pread",
534
+ .fn = test_sync_op_pread,
535
+ .blkfn = test_sync_op_blk_pread,
536
+ }, {
537
+ .name = "/sync-op/pwrite",
538
+ .fn = test_sync_op_pwrite,
539
+ .blkfn = test_sync_op_blk_pwrite,
540
+ }, {
541
+ .name = "/sync-op/load_vmstate",
542
+ .fn = test_sync_op_load_vmstate,
543
+ }, {
544
+ .name = "/sync-op/save_vmstate",
545
+ .fn = test_sync_op_save_vmstate,
546
+ }, {
547
+ .name = "/sync-op/pdiscard",
548
+ .fn = test_sync_op_pdiscard,
549
+ .blkfn = test_sync_op_blk_pdiscard,
550
+ }, {
551
+ .name = "/sync-op/truncate",
552
+ .fn = test_sync_op_truncate,
553
+ }, {
554
+ .name = "/sync-op/block_status",
555
+ .fn = test_sync_op_block_status,
556
+ }, {
557
+ .name = "/sync-op/flush",
558
+ .fn = test_sync_op_flush,
559
+ .blkfn = test_sync_op_blk_flush,
560
+ }, {
561
+ .name = "/sync-op/check",
562
+ .fn = test_sync_op_check,
563
+ }, {
564
+ .name = "/sync-op/invalidate_cache",
565
+ .fn = test_sync_op_invalidate_cache,
566
+ },
567
+};
568
+
569
+/* Test synchronous operations that run in a different iothread, so we have to
570
+ * poll for the coroutine there to return. */
571
+static void test_sync_op(const void *opaque)
572
+{
573
+ const SyncOpTest *t = opaque;
574
+ IOThread *iothread = iothread_new();
575
+ AioContext *ctx = iothread_get_aio_context(iothread);
576
+ BlockBackend *blk;
577
+ BlockDriverState *bs;
578
+ BdrvChild *c;
579
+
580
+ blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
581
+ bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
582
+ bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
583
+ blk_insert_bs(blk, bs, &error_abort);
584
+ c = QLIST_FIRST(&bs->parents);
585
+
586
+ blk_set_aio_context(blk, ctx);
587
+ aio_context_acquire(ctx);
588
+ t->fn(c);
589
+ if (t->blkfn) {
590
+ t->blkfn(blk);
591
+ }
592
+ aio_context_release(ctx);
593
+ blk_set_aio_context(blk, qemu_get_aio_context());
594
+
595
+ bdrv_unref(bs);
596
+ blk_unref(blk);
597
+}
598
+
599
+int main(int argc, char **argv)
600
+{
601
+ int i;
602
+
603
+ bdrv_init();
604
+ qemu_init_main_loop(&error_abort);
605
+
606
+ g_test_init(&argc, &argv, NULL);
607
+
608
+ for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) {
609
+ const SyncOpTest *t = &sync_op_tests[i];
610
+ g_test_add_data_func(t->name, t, test_sync_op);
611
+ }
612
+
613
+ return g_test_run();
614
+}
615
diff --git a/tests/Makefile.include b/tests/Makefile.include
616
index XXXXXXX..XXXXXXX 100644
617
--- a/tests/Makefile.include
618
+++ b/tests/Makefile.include
619
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-bdrv-drain$(EXESUF)
620
check-unit-y += tests/test-blockjob$(EXESUF)
621
check-unit-y += tests/test-blockjob-txn$(EXESUF)
622
check-unit-y += tests/test-block-backend$(EXESUF)
623
+check-unit-y += tests/test-block-iothread$(EXESUF)
624
check-unit-y += tests/test-image-locking$(EXESUF)
625
check-unit-y += tests/test-x86-cpuid$(EXESUF)
626
# all code tested by test-x86-cpuid is inside topology.h
627
@@ -XXX,XX +XXX,XX @@ tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(te
628
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
629
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
630
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
631
+tests/test-block-iothread$(EXESUF): tests/test-block-iothread.o $(test-block-obj-y) $(test-util-obj-y)
632
tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y)
633
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
634
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
635
--
159
--
636
2.20.1
160
2.39.2
637
638
diff view generated by jsdifflib
1
Signed-off-by: Fam Zheng <famz@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_register_buf() and bdrv_unregister_buf() need to hold a reader lock
3
for the graph.
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20230203152202.49054-21-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
---
9
---
4
tests/qemu-iotests/237 | 233 +++++++++++++++++++++++++
10
include/block/block_int-common.h | 7 ++++---
5
tests/qemu-iotests/237.out | 347 +++++++++++++++++++++++++++++++++++++
11
block/io.c | 14 ++++++++++----
6
tests/qemu-iotests/group | 1 +
12
2 files changed, 14 insertions(+), 7 deletions(-)
7
3 files changed, 581 insertions(+)
8
create mode 100755 tests/qemu-iotests/237
9
create mode 100644 tests/qemu-iotests/237.out
10
13
11
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
12
new file mode 100755
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX
16
--- a/include/block/block_int-common.h
14
--- /dev/null
17
+++ b/include/block/block_int-common.h
15
+++ b/tests/qemu-iotests/237
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
16
@@ -XXX,XX +XXX,XX @@
19
*
17
+#!/usr/bin/env python
20
* Returns: true on success, false on failure
18
+#
21
*/
19
+# Test vmdk and file image creation
22
- bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size,
20
+#
23
- Error **errp);
21
+# Copyright (C) 2018 Red Hat, Inc.
24
- void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size);
22
+#
25
+ bool GRAPH_RDLOCK_PTR (*bdrv_register_buf)(
23
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
26
+ BlockDriverState *bs, void *host, size_t size, Error **errp);
24
+#
27
+ void GRAPH_RDLOCK_PTR (*bdrv_unregister_buf)(
25
+# This program is free software; you can redistribute it and/or modify
28
+ BlockDriverState *bs, void *host, size_t size);
26
+# it under the terms of the GNU General Public License as published by
29
27
+# the Free Software Foundation; either version 2 of the License, or
30
/*
28
+# (at your option) any later version.
31
* This field is modified only under the BQL, and is part of
29
+#
32
diff --git a/block/io.c b/block/io.c
30
+# This program is distributed in the hope that it will be useful,
33
index XXXXXXX..XXXXXXX 100644
31
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
--- a/block/io.c
32
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+++ b/block/io.c
33
+# GNU General Public License for more details.
36
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
34
+#
37
}
35
+# You should have received a copy of the GNU General Public License
38
36
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
/* Helper that undoes bdrv_register_buf() when it fails partway through */
37
+#
40
-static void bdrv_register_buf_rollback(BlockDriverState *bs,
41
- void *host,
42
- size_t size,
43
- BdrvChild *final_child)
44
+static void GRAPH_RDLOCK
45
+bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size,
46
+ BdrvChild *final_child)
47
{
48
BdrvChild *child;
49
50
+ GLOBAL_STATE_CODE();
51
+ assert_bdrv_graph_readable();
38
+
52
+
39
+import iotests
53
QLIST_FOREACH(child, &bs->children, next) {
40
+from iotests import imgfmt
54
if (child == final_child) {
55
break;
56
@@ -XXX,XX +XXX,XX @@ bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
57
BdrvChild *child;
58
59
GLOBAL_STATE_CODE();
60
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
41
+
61
+
42
+iotests.verify_image_format(supported_fmts=['vmdk'])
62
if (bs->drv && bs->drv->bdrv_register_buf) {
63
if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
64
return false;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
66
BdrvChild *child;
67
68
GLOBAL_STATE_CODE();
69
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
43
+
70
+
44
+def blockdev_create(vm, options):
71
if (bs->drv && bs->drv->bdrv_unregister_buf) {
45
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
72
bs->drv->bdrv_unregister_buf(bs, host, size);
46
+
73
}
47
+ if 'return' in result:
48
+ assert result['return'] == {}
49
+ vm.run_job('job0')
50
+ iotests.log("")
51
+
52
+with iotests.FilePath('t.vmdk') as disk_path, \
53
+ iotests.FilePath('t.vmdk.1') as extent1_path, \
54
+ iotests.FilePath('t.vmdk.2') as extent2_path, \
55
+ iotests.FilePath('t.vmdk.3') as extent3_path, \
56
+ iotests.VM() as vm:
57
+
58
+ #
59
+ # Successful image creation (defaults)
60
+ #
61
+ iotests.log("=== Successful image creation (defaults) ===")
62
+ iotests.log("")
63
+
64
+ size = 5 * 1024 * 1024 * 1024
65
+
66
+ vm.launch()
67
+ blockdev_create(vm, { 'driver': 'file',
68
+ 'filename': disk_path,
69
+ 'size': 0 })
70
+
71
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
72
+ node_name='imgfile')
73
+
74
+ blockdev_create(vm, { 'driver': imgfmt,
75
+ 'file': 'imgfile',
76
+ 'size': size })
77
+ vm.shutdown()
78
+
79
+ iotests.img_info_log(disk_path)
80
+
81
+ #
82
+ # Successful image creation (inline blockdev-add, explicit defaults)
83
+ #
84
+ iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===")
85
+ iotests.log("")
86
+
87
+ # Choose a different size to show that we got a new image
88
+ size = 64 * 1024 * 1024
89
+
90
+ vm.launch()
91
+ blockdev_create(vm, { 'driver': 'file',
92
+ 'filename': disk_path,
93
+ 'size': 0 })
94
+
95
+ blockdev_create(vm, { 'driver': imgfmt,
96
+ 'file': {
97
+ 'driver': 'file',
98
+ 'filename': disk_path,
99
+ },
100
+ 'size': size,
101
+ 'extents': [],
102
+ 'subformat': 'monolithicSparse',
103
+ 'adapter-type': 'ide',
104
+ 'hwversion': '4',
105
+ 'zeroed-grain': False })
106
+ vm.shutdown()
107
+
108
+ iotests.img_info_log(disk_path)
109
+
110
+ #
111
+ # Successful image creation (non-default options)
112
+ #
113
+ iotests.log("=== Successful image creation (with non-default options) ===")
114
+ iotests.log("")
115
+
116
+ # Choose a different size to show that we got a new image
117
+ size = 32 * 1024 * 1024
118
+
119
+ vm.launch()
120
+ blockdev_create(vm, { 'driver': 'file',
121
+ 'filename': disk_path,
122
+ 'size': 0 })
123
+
124
+ blockdev_create(vm, { 'driver': imgfmt,
125
+ 'file': {
126
+ 'driver': 'file',
127
+ 'filename': disk_path,
128
+ },
129
+ 'size': size,
130
+ 'extents': [],
131
+ 'subformat': 'monolithicSparse',
132
+ 'adapter-type': 'buslogic',
133
+ 'zeroed-grain': True })
134
+ vm.shutdown()
135
+
136
+ iotests.img_info_log(disk_path)
137
+
138
+ #
139
+ # Invalid BlockdevRef
140
+ #
141
+ iotests.log("=== Invalid BlockdevRef ===")
142
+ iotests.log("")
143
+
144
+ vm.launch()
145
+ blockdev_create(vm, { 'driver': imgfmt,
146
+ 'file': "this doesn't exist",
147
+ 'size': size })
148
+ vm.shutdown()
149
+
150
+ #
151
+ # Adapter types
152
+ #
153
+
154
+ iotests.log("=== Adapter types ===")
155
+ iotests.log("")
156
+
157
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
158
+
159
+ # Valid
160
+ iotests.log("== Valid adapter types ==")
161
+ iotests.log("")
162
+
163
+ vm.launch()
164
+ for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]:
165
+ blockdev_create(vm, { 'driver': imgfmt,
166
+ 'file': 'node0',
167
+ 'size': size,
168
+ 'adapter-type': adapter_type })
169
+ vm.shutdown()
170
+
171
+ # Invalid
172
+ iotests.log("== Invalid adapter types ==")
173
+ iotests.log("")
174
+
175
+ vm.launch()
176
+ for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]:
177
+ blockdev_create(vm, { 'driver': imgfmt,
178
+ 'file': 'node0',
179
+ 'size': size,
180
+ 'adapter-type': adapter_type })
181
+ vm.shutdown()
182
+
183
+ #
184
+ # Other subformats
185
+ #
186
+ iotests.log("=== Other subformats ===")
187
+ iotests.log("")
188
+
189
+ for path in [ extent1_path, extent2_path, extent3_path ]:
190
+ msg = iotests.qemu_img_pipe('create', '-f', imgfmt, path, '0')
191
+ iotests.log(msg, [iotests.filter_testfiles])
192
+
193
+ vm.add_blockdev('driver=file,filename=%s,node-name=ext1' % (extent1_path))
194
+ vm.add_blockdev('driver=file,filename=%s,node-name=ext2' % (extent2_path))
195
+ vm.add_blockdev('driver=file,filename=%s,node-name=ext3' % (extent3_path))
196
+
197
+ # Missing extent
198
+ iotests.log("== Missing extent ==")
199
+ iotests.log("")
200
+
201
+ vm.launch()
202
+ blockdev_create(vm, { 'driver': imgfmt,
203
+ 'file': 'node0',
204
+ 'size': size,
205
+ 'subformat': 'monolithicFlat' })
206
+ vm.shutdown()
207
+
208
+ # Correct extent
209
+ iotests.log("== Correct extent ==")
210
+ iotests.log("")
211
+
212
+ vm.launch()
213
+ blockdev_create(vm, { 'driver': imgfmt,
214
+ 'file': 'node0',
215
+ 'size': size,
216
+ 'subformat': 'monolithicFlat',
217
+ 'extents': ['ext1'] })
218
+ vm.shutdown()
219
+
220
+ # Extra extent
221
+ iotests.log("== Extra extent ==")
222
+ iotests.log("")
223
+
224
+ vm.launch()
225
+ blockdev_create(vm, { 'driver': imgfmt,
226
+ 'file': 'node0',
227
+ 'size': 512,
228
+ 'subformat': 'monolithicFlat',
229
+ 'extents': ['ext1', 'ext2', 'ext3'] })
230
+ vm.shutdown()
231
+
232
+ # Split formats
233
+ iotests.log("== Split formats ==")
234
+ iotests.log("")
235
+
236
+ for size in [ 512, 1073741824, 2147483648, 5368709120 ]:
237
+ for subfmt in [ 'twoGbMaxExtentFlat', 'twoGbMaxExtentSparse' ]:
238
+ iotests.log("= %s %d =" % (subfmt, size))
239
+ iotests.log("")
240
+
241
+ vm.launch()
242
+ blockdev_create(vm, { 'driver': imgfmt,
243
+ 'file': 'node0',
244
+ 'size': size,
245
+ 'subformat': subfmt,
246
+ 'extents': ['ext1', 'ext2', 'ext3'] })
247
+ vm.shutdown()
248
+
249
+ iotests.img_info_log(disk_path)
250
diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out
251
new file mode 100644
252
index XXXXXXX..XXXXXXX
253
--- /dev/null
254
+++ b/tests/qemu-iotests/237.out
255
@@ -XXX,XX +XXX,XX @@
256
+=== Successful image creation (defaults) ===
257
+
258
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
259
+{"return": {}}
260
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
261
+{"return": {}}
262
+
263
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}}
264
+{"return": {}}
265
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
266
+{"return": {}}
267
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
268
+{"return": {}}
269
+
270
+image: TEST_IMG
271
+file format: IMGFMT
272
+virtual size: 5.0G (5368709120 bytes)
273
+cluster_size: 65536
274
+Format specific information:
275
+ cid: XXXXXXXXXX
276
+ parent cid: XXXXXXXXXX
277
+ create type: monolithicSparse
278
+ extents:
279
+ [0]:
280
+ virtual size: 5368709120
281
+ filename: TEST_IMG
282
+ cluster size: 65536
283
+ format:
284
+
285
+=== Successful image creation (inline blockdev-add, explicit defaults) ===
286
+
287
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
288
+{"return": {}}
289
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
290
+{"return": {}}
291
+
292
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
293
+{"return": {}}
294
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
295
+{"return": {}}
296
+
297
+image: TEST_IMG
298
+file format: IMGFMT
299
+virtual size: 64M (67108864 bytes)
300
+cluster_size: 65536
301
+Format specific information:
302
+ cid: XXXXXXXXXX
303
+ parent cid: XXXXXXXXXX
304
+ create type: monolithicSparse
305
+ extents:
306
+ [0]:
307
+ virtual size: 67108864
308
+ filename: TEST_IMG
309
+ cluster size: 65536
310
+ format:
311
+
312
+=== Successful image creation (with non-default options) ===
313
+
314
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
315
+{"return": {}}
316
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
317
+{"return": {}}
318
+
319
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
320
+{"return": {}}
321
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
322
+{"return": {}}
323
+
324
+image: TEST_IMG
325
+file format: IMGFMT
326
+virtual size: 32M (33554432 bytes)
327
+cluster_size: 65536
328
+Format specific information:
329
+ cid: XXXXXXXXXX
330
+ parent cid: XXXXXXXXXX
331
+ create type: monolithicSparse
332
+ extents:
333
+ [0]:
334
+ virtual size: 33554432
335
+ filename: TEST_IMG
336
+ cluster size: 65536
337
+ format:
338
+
339
+=== Invalid BlockdevRef ===
340
+
341
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
342
+{"return": {}}
343
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
344
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
345
+{"return": {}}
346
+
347
+=== Adapter types ===
348
+
349
+== Valid adapter types ==
350
+
351
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
352
+{"return": {}}
353
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
354
+{"return": {}}
355
+
356
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
357
+{"return": {}}
358
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
359
+{"return": {}}
360
+
361
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
362
+{"return": {}}
363
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
364
+{"return": {}}
365
+
366
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
367
+{"return": {}}
368
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
369
+{"return": {}}
370
+
371
+== Invalid adapter types ==
372
+
373
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
374
+{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
375
+
376
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
377
+{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
378
+
379
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
380
+{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
381
+
382
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
383
+{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
384
+
385
+=== Other subformats ===
386
+
387
+Formatting 'TEST_DIR/PID-t.vmdk.1', fmt=vmdk size=0 compat6=off hwversion=undefined
388
+
389
+Formatting 'TEST_DIR/PID-t.vmdk.2', fmt=vmdk size=0 compat6=off hwversion=undefined
390
+
391
+Formatting 'TEST_DIR/PID-t.vmdk.3', fmt=vmdk size=0 compat6=off hwversion=undefined
392
+
393
+== Missing extent ==
394
+
395
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
396
+{"return": {}}
397
+Job failed: Extent [0] not specified
398
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
399
+{"return": {}}
400
+
401
+== Correct extent ==
402
+
403
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
404
+{"return": {}}
405
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
406
+{"return": {}}
407
+
408
+== Extra extent ==
409
+
410
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
411
+{"return": {}}
412
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
413
+{"return": {}}
414
+
415
+== Split formats ==
416
+
417
+= twoGbMaxExtentFlat 512 =
418
+
419
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
420
+{"return": {}}
421
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
422
+{"return": {}}
423
+
424
+image: TEST_IMG
425
+file format: IMGFMT
426
+virtual size: 512 (512 bytes)
427
+Format specific information:
428
+ cid: XXXXXXXXXX
429
+ parent cid: XXXXXXXXXX
430
+ create type: twoGbMaxExtentFlat
431
+ extents:
432
+ [0]:
433
+ virtual size: 512
434
+ filename: TEST_IMG.1
435
+ format: FLAT
436
+
437
+= twoGbMaxExtentSparse 512 =
438
+
439
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
440
+{"return": {}}
441
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
442
+{"return": {}}
443
+
444
+image: TEST_IMG
445
+file format: IMGFMT
446
+virtual size: 512 (512 bytes)
447
+cluster_size: 65536
448
+Format specific information:
449
+ cid: XXXXXXXXXX
450
+ parent cid: XXXXXXXXXX
451
+ create type: twoGbMaxExtentSparse
452
+ extents:
453
+ [0]:
454
+ virtual size: 512
455
+ filename: TEST_IMG.1
456
+ cluster size: 65536
457
+ format: SPARSE
458
+
459
+= twoGbMaxExtentFlat 1073741824 =
460
+
461
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
462
+{"return": {}}
463
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
464
+{"return": {}}
465
+
466
+image: TEST_IMG
467
+file format: IMGFMT
468
+virtual size: 1.0G (1073741824 bytes)
469
+Format specific information:
470
+ cid: XXXXXXXXXX
471
+ parent cid: XXXXXXXXXX
472
+ create type: twoGbMaxExtentFlat
473
+ extents:
474
+ [0]:
475
+ virtual size: 1073741824
476
+ filename: TEST_IMG.1
477
+ format: FLAT
478
+
479
+= twoGbMaxExtentSparse 1073741824 =
480
+
481
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
482
+{"return": {}}
483
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
484
+{"return": {}}
485
+
486
+image: TEST_IMG
487
+file format: IMGFMT
488
+virtual size: 1.0G (1073741824 bytes)
489
+cluster_size: 65536
490
+Format specific information:
491
+ cid: XXXXXXXXXX
492
+ parent cid: XXXXXXXXXX
493
+ create type: twoGbMaxExtentSparse
494
+ extents:
495
+ [0]:
496
+ virtual size: 1073741824
497
+ filename: TEST_IMG.1
498
+ cluster size: 65536
499
+ format: SPARSE
500
+
501
+= twoGbMaxExtentFlat 2147483648 =
502
+
503
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
504
+{"return": {}}
505
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
506
+{"return": {}}
507
+
508
+image: TEST_IMG
509
+file format: IMGFMT
510
+virtual size: 2.0G (2147483648 bytes)
511
+Format specific information:
512
+ cid: XXXXXXXXXX
513
+ parent cid: XXXXXXXXXX
514
+ create type: twoGbMaxExtentFlat
515
+ extents:
516
+ [0]:
517
+ virtual size: 2147483648
518
+ filename: TEST_IMG.1
519
+ format: FLAT
520
+
521
+= twoGbMaxExtentSparse 2147483648 =
522
+
523
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
524
+{"return": {}}
525
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
526
+{"return": {}}
527
+
528
+image: TEST_IMG
529
+file format: IMGFMT
530
+virtual size: 2.0G (2147483648 bytes)
531
+cluster_size: 65536
532
+Format specific information:
533
+ cid: XXXXXXXXXX
534
+ parent cid: XXXXXXXXXX
535
+ create type: twoGbMaxExtentSparse
536
+ extents:
537
+ [0]:
538
+ virtual size: 2147483648
539
+ filename: TEST_IMG.1
540
+ cluster size: 65536
541
+ format: SPARSE
542
+
543
+= twoGbMaxExtentFlat 5368709120 =
544
+
545
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
546
+{"return": {}}
547
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
548
+{"return": {}}
549
+
550
+image: TEST_IMG
551
+file format: IMGFMT
552
+virtual size: 5.0G (5368709120 bytes)
553
+Format specific information:
554
+ cid: XXXXXXXXXX
555
+ parent cid: XXXXXXXXXX
556
+ create type: twoGbMaxExtentFlat
557
+ extents:
558
+ [0]:
559
+ virtual size: 2147483648
560
+ filename: TEST_IMG.1
561
+ format: FLAT
562
+ [1]:
563
+ virtual size: 2147483648
564
+ filename: TEST_IMG.2
565
+ format: FLAT
566
+ [2]:
567
+ virtual size: 1073741824
568
+ filename: TEST_IMG.3
569
+ format: FLAT
570
+
571
+= twoGbMaxExtentSparse 5368709120 =
572
+
573
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
574
+{"return": {}}
575
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
576
+{"return": {}}
577
+
578
+image: TEST_IMG
579
+file format: IMGFMT
580
+virtual size: 5.0G (5368709120 bytes)
581
+cluster_size: 65536
582
+Format specific information:
583
+ cid: XXXXXXXXXX
584
+ parent cid: XXXXXXXXXX
585
+ create type: twoGbMaxExtentSparse
586
+ extents:
587
+ [0]:
588
+ virtual size: 2147483648
589
+ filename: TEST_IMG.1
590
+ cluster size: 65536
591
+ format: SPARSE
592
+ [1]:
593
+ virtual size: 2147483648
594
+ filename: TEST_IMG.2
595
+ cluster size: 65536
596
+ format: SPARSE
597
+ [2]:
598
+ virtual size: 1073741824
599
+ filename: TEST_IMG.3
600
+ cluster size: 65536
601
+ format: SPARSE
602
+
603
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
604
index XXXXXXX..XXXXXXX 100644
605
--- a/tests/qemu-iotests/group
606
+++ b/tests/qemu-iotests/group
607
@@ -XXX,XX +XXX,XX @@
608
234 auto quick migration
609
235 auto quick
610
236 auto quick
611
+237 rw auto quick
612
238 auto quick
613
239 rw auto quick
614
--
74
--
615
2.20.1
75
2.39.2
616
617
diff view generated by jsdifflib
1
bdrv_co_invalidate_cache() clears the BDRV_O_INACTIVE flag before
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
actually activating a node so that the correct permissions etc. are
2
bdrv_co_delete_file() need to hold a reader lock for the graph.
3
taken. In case of errors, the flag must be restored so that the next
4
call to bdrv_co_invalidate_cache() retries activation.
5
3
6
Restoring the flag was missing in the error path for a failed
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
parent->role->activate() call. The consequence is that this attempt to
5
Message-Id: <20230203152202.49054-22-kwolf@redhat.com>
8
activate all images correctly fails because we still set errp, however
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
on the next attempt BDRV_O_INACTIVE is already clear, so we return
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
success without actually retrying the failed action.
8
---
9
include/block/block-io.h | 8 ++++++--
10
include/block/block_int-common.h | 4 ++--
11
block.c | 1 +
12
3 files changed, 9 insertions(+), 4 deletions(-)
11
13
12
An example where this is observable in practice is migration to a QEMU
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
13
instance that has a raw format block node attached to a guest device
15
index XXXXXXX..XXXXXXX 100644
14
with share-rw=off (the default) while another process holds
16
--- a/include/block/block-io.h
15
BLK_PERM_WRITE for the same image. In this case, all activation steps
17
+++ b/include/block/block-io.h
16
before parent->role->activate() succeed because raw can tolerate other
18
@@ -XXX,XX +XXX,XX @@ int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
17
writers to the image. Only the parent callback (in particular
19
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
18
blk_root_activate()) tries to implement the share-rw=on property and
20
BlockDriverState *in_bs, Error **errp);
19
requests exclusive write permissions. This fails when the migration
21
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
20
completes and correctly displays an error. However, a manual 'cont' will
22
-int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
21
incorrectly resume the VM without calling blk_root_activate() again.
23
-void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs);
22
24
+
23
This case is described in more detail in the following bug report:
25
+int coroutine_fn GRAPH_RDLOCK
24
https://bugzilla.redhat.com/show_bug.cgi?id=1531888
26
+bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
25
27
+
26
Fix this by correctly restoring the BDRV_O_INACTIVE flag in the error
28
+void coroutine_fn GRAPH_RDLOCK
27
path.
29
+bdrv_co_delete_file_noerr(BlockDriverState *bs);
28
30
29
Cc: qemu-stable@nongnu.org
31
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
/* async block I/O */
31
Tested-by: Markus Armbruster <armbru@redhat.com>
33
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
32
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
34
index XXXXXXX..XXXXXXX 100644
33
---
35
--- a/include/block/block_int-common.h
34
block.c | 1 +
36
+++ b/include/block/block_int-common.h
35
1 file changed, 1 insertion(+)
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
38
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
39
40
/* Delete a created file. */
41
- int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
42
- Error **errp);
43
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_delete_file)(
44
+ BlockDriverState *bs, Error **errp);
45
46
/*
47
* Flushes all data that was already written to the OS all the way down to
37
diff --git a/block.c b/block.c
48
diff --git a/block.c b/block.c
38
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
39
--- a/block.c
50
--- a/block.c
40
+++ b/block.c
51
+++ b/block.c
41
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
52
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
42
if (parent->role->activate) {
53
43
parent->role->activate(parent, &local_err);
54
IO_CODE();
44
if (local_err) {
55
assert(bs != NULL);
45
+ bs->open_flags |= BDRV_O_INACTIVE;
56
+ assert_bdrv_graph_readable();
46
error_propagate(errp, local_err);
57
47
return;
58
if (!bs->drv) {
48
}
59
error_setg(errp, "Block node '%s' is not opened", bs->filename);
49
--
60
--
50
2.20.1
61
2.39.2
51
52
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_*_dirty_bitmap() need to hold a reader lock for the graph.
2
3
3
This test waits for a MIGRATION event with status=completed on the
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
source VM before querying the migration status on both source and
5
Message-Id: <20230203152202.49054-23-kwolf@redhat.com>
5
destination. However, just because the source says migration has
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
completed does not mean the destination thinks the same. Therefore, in
7
some cases, the destination VM may still report "active" instead of
8
"completed" when asked for its migration status.
9
10
Fix this by enabling migration events on both VMs and waiting until both
11
source and destination emit a status=completed MIGRATION event.
12
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
8
---
16
tests/qemu-iotests/234 | 56 ++++++++++++++++++++------------------
9
include/block/block-io.h | 14 ++++++--------
17
tests/qemu-iotests/234.out | 10 +++++--
10
include/block/block_int-common.h | 6 ++++--
18
2 files changed, 38 insertions(+), 28 deletions(-)
11
include/block/dirty-bitmap.h | 12 ++++++------
12
block/dirty-bitmap.c | 2 ++
13
4 files changed, 18 insertions(+), 16 deletions(-)
19
14
20
diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234
15
diff --git a/include/block/block-io.h b/include/block/block-io.h
21
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/234
17
--- a/include/block/block-io.h
23
+++ b/tests/qemu-iotests/234
18
+++ b/include/block/block-io.h
24
@@ -XXX,XX +XXX,XX @@ import os
19
@@ -XXX,XX +XXX,XX @@ AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
25
iotests.verify_image_format(supported_fmts=['qcow2'])
20
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
26
iotests.verify_platform(['linux'])
21
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
27
22
28
+def enable_migration_events(vm, name):
23
-bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
29
+ iotests.log('Enabling migration QMP events on %s...' % name)
24
- const char *name,
30
+ iotests.log(vm.qmp('migrate-set-capabilities', capabilities=[
25
- uint32_t granularity,
31
+ {
26
- Error **errp);
32
+ 'capability': 'events',
27
-bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
33
+ 'state': True
28
- const char *name,
34
+ }
29
- uint32_t granularity,
35
+ ]))
30
- Error **errp);
31
+bool coroutine_fn GRAPH_RDLOCK
32
+bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
33
+ uint32_t granularity, Error **errp);
34
+bool co_wrapper_bdrv_rdlock
35
+bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
36
+ uint32_t granularity, Error **errp);
37
38
/**
39
*
40
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int-common.h
43
+++ b/include/block/block_int-common.h
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
45
void (*bdrv_drain_end)(BlockDriverState *bs);
46
47
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
48
- bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
36
+
49
+
37
+def wait_migration(vm):
50
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_can_store_new_dirty_bitmap)(
38
+ while True:
51
BlockDriverState *bs, const char *name, uint32_t granularity,
39
+ event = vm.event_wait('MIGRATION')
52
Error **errp);
40
+ iotests.log(event, filters=[iotests.filter_qmp_event])
53
- int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
41
+ if event['data']['status'] == 'completed':
42
+ break
43
+
54
+
44
with iotests.FilePath('img') as img_path, \
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_remove_persistent_dirty_bitmap)(
45
iotests.FilePath('backing') as backing_path, \
56
BlockDriverState *bs, const char *name, Error **errp);
46
iotests.FilePath('mig_fifo_a') as fifo_a, \
57
};
47
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
58
48
.add_blockdev('%s,file=drive0-backing-file,node-name=drive0-backing' % (iotests.imgfmt))
59
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
49
.launch())
50
51
+ enable_migration_events(vm_a, 'A')
52
+
53
iotests.log('Launching destination VM...')
54
(vm_b.add_blockdev('file,filename=%s,node-name=drive0-file' % (img_path))
55
.add_blockdev('%s,file=drive0-file,node-name=drive0' % (iotests.imgfmt))
56
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
57
.add_incoming("exec: cat '%s'" % (fifo_a))
58
.launch())
59
60
+ enable_migration_events(vm_b, 'B')
61
+
62
# Add a child node that was created after the parent node. The reverse case
63
# is covered by the -blockdev options above.
64
iotests.log(vm_a.qmp('blockdev-snapshot', node='drive0-backing',
65
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
66
iotests.log(vm_b.qmp('blockdev-snapshot', node='drive0-backing',
67
overlay='drive0'))
68
69
- iotests.log('Enabling migration QMP events on A...')
70
- iotests.log(vm_a.qmp('migrate-set-capabilities', capabilities=[
71
- {
72
- 'capability': 'events',
73
- 'state': True
74
- }
75
- ]))
76
-
77
iotests.log('Starting migration to B...')
78
iotests.log(vm_a.qmp('migrate', uri='exec:cat >%s' % (fifo_a)))
79
with iotests.Timeout(3, 'Migration does not complete'):
80
- while True:
81
- event = vm_a.event_wait('MIGRATION')
82
- iotests.log(event, filters=[iotests.filter_qmp_event])
83
- if event['data']['status'] == 'completed':
84
- break
85
+ # Wait for the source first (which includes setup=setup)
86
+ wait_migration(vm_a)
87
+ # Wait for the destination second (which does not)
88
+ wait_migration(vm_b)
89
90
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
91
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
92
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
93
.add_incoming("exec: cat '%s'" % (fifo_b))
94
.launch())
95
96
+ enable_migration_events(vm_a, 'A')
97
+
98
iotests.log(vm_a.qmp('blockdev-snapshot', node='drive0-backing',
99
overlay='drive0'))
100
101
- iotests.log('Enabling migration QMP events on B...')
102
- iotests.log(vm_b.qmp('migrate-set-capabilities', capabilities=[
103
- {
104
- 'capability': 'events',
105
- 'state': True
106
- }
107
- ]))
108
-
109
iotests.log('Starting migration back to A...')
110
iotests.log(vm_b.qmp('migrate', uri='exec:cat >%s' % (fifo_b)))
111
with iotests.Timeout(3, 'Migration does not complete'):
112
- while True:
113
- event = vm_b.event_wait('MIGRATION')
114
- iotests.log(event, filters=[iotests.filter_qmp_event])
115
- if event['data']['status'] == 'completed':
116
- break
117
+ # Wait for the source first (which includes setup=setup)
118
+ wait_migration(vm_b)
119
+ # Wait for the destination second (which does not)
120
+ wait_migration(vm_a)
121
122
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
123
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
124
diff --git a/tests/qemu-iotests/234.out b/tests/qemu-iotests/234.out
125
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
126
--- a/tests/qemu-iotests/234.out
61
--- a/include/block/dirty-bitmap.h
127
+++ b/tests/qemu-iotests/234.out
62
+++ b/include/block/dirty-bitmap.h
128
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@ int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
129
Launching source VM...
64
void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap);
130
+Enabling migration QMP events on A...
65
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
131
+{"return": {}}
66
132
Launching destination VM...
67
-int coroutine_fn bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
133
+Enabling migration QMP events on B...
68
- const char *name,
134
{"return": {}}
69
- Error **errp);
135
{"return": {}}
70
-int co_wrapper bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
136
-Enabling migration QMP events on A...
71
- const char *name,
137
{"return": {}}
72
- Error **errp);
138
Starting migration to B...
73
+int coroutine_fn GRAPH_RDLOCK
139
{"return": {}}
74
+bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
140
{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
75
+ Error **errp);
141
{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
76
+int co_wrapper_bdrv_rdlock
142
{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
77
+bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
143
+{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
78
+ Error **errp);
144
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
79
145
completed
80
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
146
completed
81
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
147
{"return": {"running": false, "singlestep": false, "status": "postmigrate"}}
82
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
148
@@ -XXX,XX +XXX,XX @@ completed
83
index XXXXXXX..XXXXXXX 100644
149
Add a second parent to drive0-file...
84
--- a/block/dirty-bitmap.c
150
{"return": {}}
85
+++ b/block/dirty-bitmap.c
151
Restart A with -incoming and second parent...
86
@@ -XXX,XX +XXX,XX @@ int coroutine_fn
152
+Enabling migration QMP events on A...
87
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
153
{"return": {}}
88
Error **errp)
154
-Enabling migration QMP events on B...
89
{
155
{"return": {}}
90
+ assert_bdrv_graph_readable();
156
Starting migration back to A...
91
if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) {
157
{"return": {}}
92
return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
158
{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
93
}
159
{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
94
@@ -XXX,XX +XXX,XX @@ bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
160
{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
95
uint32_t granularity, Error **errp)
161
+{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
96
{
162
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
97
BlockDriver *drv = bs->drv;
163
completed
98
+ assert_bdrv_graph_readable();
164
completed
99
165
{"return": {"running": true, "singlestep": false, "status": "running"}}
100
if (!drv) {
101
error_setg_errno(errp, ENOMEDIUM,
166
--
102
--
167
2.20.1
103
2.39.2
168
169
diff view generated by jsdifflib
1
If QEMU was configured with a driver in --block-drv-ro-whitelist, trying
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
to use that driver read-write resulted in an error message even if
2
bdrv_co_refresh_total_sectors() need to hold a reader lock for the
3
auto-read-only=on was set.
3
graph.
4
5
Consider auto-read-only=on for the whitelist checking and use it to
6
automatically degrade to read-only for block drivers on the read-only
7
whitelist.
8
4
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-Id: <20230203152202.49054-24-kwolf@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block.c | 20 +++++++++++++-------
10
include/block/block-io.h | 8 ++++----
14
1 file changed, 13 insertions(+), 7 deletions(-)
11
include/block/block_int-common.h | 4 +++-
12
include/block/block_int-io.h | 7 ++++---
13
block.c | 3 +++
14
block/blkdebug.c | 3 ++-
15
block/blklogwrites.c | 3 ++-
16
block/blkreplay.c | 3 ++-
17
block/blkverify.c | 3 ++-
18
block/copy-on-read.c | 2 +-
19
block/crypto.c | 3 ++-
20
block/filter-compress.c | 3 ++-
21
block/mirror.c | 3 +++
22
block/preallocate.c | 3 ++-
23
block/quorum.c | 3 ++-
24
block/raw-format.c | 3 ++-
25
block/replication.c | 3 ++-
26
block/stream.c | 8 +++++---
27
block/throttle.c | 3 ++-
28
18 files changed, 45 insertions(+), 23 deletions(-)
15
29
30
diff --git a/include/block/block-io.h b/include/block/block-io.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block-io.h
33
+++ b/include/block/block-io.h
34
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
35
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
36
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
37
38
-int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
39
-int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
40
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_nb_sectors(BlockDriverState *bs);
41
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_nb_sectors(BlockDriverState *bs);
42
43
-int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
44
-int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
45
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs);
46
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs);
47
48
int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
49
int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BlockDriverState *bs, int64_t offset, bool exact,
56
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
57
58
- int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
59
+ int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_getlength)(
60
+ BlockDriverState *bs);
61
+
62
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
63
BlockDriverState *bs);
64
65
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/block_int-io.h
68
+++ b/include/block/block_int-io.h
69
@@ -XXX,XX +XXX,XX @@ bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
70
int64_t bytes, BdrvRequestFlags read_flags,
71
BdrvRequestFlags write_flags);
72
73
-int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
74
- int64_t hint);
75
-int co_wrapper_mixed
76
+int coroutine_fn GRAPH_RDLOCK
77
+bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
78
+
79
+int co_wrapper_mixed_bdrv_rdlock
80
bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
81
82
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
16
diff --git a/block.c b/block.c
83
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
85
--- a/block.c
19
+++ b/block.c
86
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
87
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
21
bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
88
{
22
89
BlockDriver *drv = bs->drv;
23
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
90
IO_CODE();
24
- error_setg(errp,
91
+ assert_bdrv_graph_readable();
25
- !bs->read_only && bdrv_is_whitelisted(drv, true)
92
26
- ? "Driver '%s' can only be used for read-only devices"
93
if (!drv) {
27
- : "Driver '%s' is not whitelisted",
94
return -ENOMEDIUM;
28
- drv->format_name);
95
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
29
- ret = -ENOTSUP;
96
{
30
- goto fail_opts;
97
BlockDriver *drv = bs->drv;
31
+ if (!bs->read_only && bdrv_is_whitelisted(drv, true)) {
98
IO_CODE();
32
+ ret = bdrv_apply_auto_read_only(bs, NULL, NULL);
99
+ assert_bdrv_graph_readable();
33
+ } else {
100
34
+ ret = -ENOTSUP;
101
if (!drv)
35
+ }
102
return -ENOMEDIUM;
36
+ if (ret < 0) {
103
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
37
+ error_setg(errp,
104
{
38
+ !bs->read_only && bdrv_is_whitelisted(drv, true)
105
int64_t ret;
39
+ ? "Driver '%s' can only be used for read-only devices"
106
IO_CODE();
40
+ : "Driver '%s' is not whitelisted",
107
+ assert_bdrv_graph_readable();
41
+ drv->format_name);
108
42
+ goto fail_opts;
109
ret = bdrv_co_nb_sectors(bs);
110
if (ret < 0) {
111
diff --git a/block/blkdebug.c b/block/blkdebug.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/blkdebug.c
114
+++ b/block/blkdebug.c
115
@@ -XXX,XX +XXX,XX @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
116
return false;
117
}
118
119
-static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
120
+static int64_t coroutine_fn GRAPH_RDLOCK
121
+blkdebug_co_getlength(BlockDriverState *bs)
122
{
123
return bdrv_co_getlength(bs->file->bs);
124
}
125
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/block/blklogwrites.c
128
+++ b/block/blklogwrites.c
129
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_close(BlockDriverState *bs)
130
s->log_file = NULL;
131
}
132
133
-static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
134
+static int64_t coroutine_fn GRAPH_RDLOCK
135
+blk_log_writes_co_getlength(BlockDriverState *bs)
136
{
137
return bdrv_co_getlength(bs->file->bs);
138
}
139
diff --git a/block/blkreplay.c b/block/blkreplay.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/block/blkreplay.c
142
+++ b/block/blkreplay.c
143
@@ -XXX,XX +XXX,XX @@ fail:
144
return ret;
145
}
146
147
-static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
148
+static int64_t coroutine_fn GRAPH_RDLOCK
149
+blkreplay_co_getlength(BlockDriverState *bs)
150
{
151
return bdrv_co_getlength(bs->file->bs);
152
}
153
diff --git a/block/blkverify.c b/block/blkverify.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/blkverify.c
156
+++ b/block/blkverify.c
157
@@ -XXX,XX +XXX,XX @@ static void blkverify_close(BlockDriverState *bs)
158
s->test_file = NULL;
159
}
160
161
-static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
162
+static int64_t coroutine_fn GRAPH_RDLOCK
163
+blkverify_co_getlength(BlockDriverState *bs)
164
{
165
BDRVBlkverifyState *s = bs->opaque;
166
167
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/block/copy-on-read.c
170
+++ b/block/copy-on-read.c
171
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
172
}
173
174
175
-static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
176
+static int64_t coroutine_fn GRAPH_RDLOCK cor_co_getlength(BlockDriverState *bs)
177
{
178
return bdrv_co_getlength(bs->file->bs);
179
}
180
diff --git a/block/crypto.c b/block/crypto.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/block/crypto.c
183
+++ b/block/crypto.c
184
@@ -XXX,XX +XXX,XX @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
185
}
186
187
188
-static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
189
+static int64_t coroutine_fn GRAPH_RDLOCK
190
+block_crypto_co_getlength(BlockDriverState *bs)
191
{
192
BlockCrypto *crypto = bs->opaque;
193
int64_t len = bdrv_co_getlength(bs->file->bs);
194
diff --git a/block/filter-compress.c b/block/filter-compress.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/block/filter-compress.c
197
+++ b/block/filter-compress.c
198
@@ -XXX,XX +XXX,XX @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
199
}
200
201
202
-static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
203
+static int64_t coroutine_fn GRAPH_RDLOCK
204
+compress_co_getlength(BlockDriverState *bs)
205
{
206
return bdrv_co_getlength(bs->file->bs);
207
}
208
diff --git a/block/mirror.c b/block/mirror.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/mirror.c
211
+++ b/block/mirror.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
213
goto immediate_exit;
214
}
215
216
+ bdrv_graph_co_rdlock();
217
s->bdev_length = bdrv_co_getlength(bs);
218
+ bdrv_graph_co_rdunlock();
219
+
220
if (s->bdev_length < 0) {
221
ret = s->bdev_length;
222
goto immediate_exit;
223
diff --git a/block/preallocate.c b/block/preallocate.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/preallocate.c
226
+++ b/block/preallocate.c
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
228
return bdrv_co_flush(bs->file->bs);
229
}
230
231
-static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
232
+static int64_t coroutine_fn GRAPH_RDLOCK
233
+preallocate_co_getlength(BlockDriverState *bs)
234
{
235
int64_t ret;
236
BDRVPreallocateState *s = bs->opaque;
237
diff --git a/block/quorum.c b/block/quorum.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/quorum.c
240
+++ b/block/quorum.c
241
@@ -XXX,XX +XXX,XX @@ quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
242
flags | BDRV_REQ_ZERO_WRITE);
243
}
244
245
-static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
246
+static int64_t coroutine_fn GRAPH_RDLOCK
247
+quorum_co_getlength(BlockDriverState *bs)
248
{
249
BDRVQuorumState *s = bs->opaque;
250
int64_t result;
251
diff --git a/block/raw-format.c b/block/raw-format.c
252
index XXXXXXX..XXXXXXX 100644
253
--- a/block/raw-format.c
254
+++ b/block/raw-format.c
255
@@ -XXX,XX +XXX,XX @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
256
return bdrv_co_pdiscard(bs->file, offset, bytes);
257
}
258
259
-static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
260
+static int64_t coroutine_fn GRAPH_RDLOCK
261
+raw_co_getlength(BlockDriverState *bs)
262
{
263
int64_t len;
264
BDRVRawState *s = bs->opaque;
265
diff --git a/block/replication.c b/block/replication.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/replication.c
268
+++ b/block/replication.c
269
@@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
270
return;
271
}
272
273
-static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
274
+static int64_t coroutine_fn GRAPH_RDLOCK
275
+replication_co_getlength(BlockDriverState *bs)
276
{
277
return bdrv_co_getlength(bs->file->bs);
278
}
279
diff --git a/block/stream.c b/block/stream.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/block/stream.c
282
+++ b/block/stream.c
283
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
284
return 0;
285
}
286
287
- len = bdrv_getlength(s->target_bs);
288
- if (len < 0) {
289
- return len;
290
+ WITH_GRAPH_RDLOCK_GUARD() {
291
+ len = bdrv_co_getlength(s->target_bs);
292
+ if (len < 0) {
293
+ return len;
43
+ }
294
+ }
44
}
295
}
45
296
job_progress_set_remaining(&s->common.job, len);
46
/* bdrv_new() and bdrv_close() make it so */
297
298
diff --git a/block/throttle.c b/block/throttle.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/block/throttle.c
301
+++ b/block/throttle.c
302
@@ -XXX,XX +XXX,XX @@ static void throttle_close(BlockDriverState *bs)
303
}
304
305
306
-static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
307
+static int64_t coroutine_fn GRAPH_RDLOCK
308
+throttle_co_getlength(BlockDriverState *bs)
309
{
310
return bdrv_co_getlength(bs->file->bs);
311
}
47
--
312
--
48
2.20.1
313
2.39.2
49
50
diff view generated by jsdifflib
1
scsi-disk includes in the Device Identification VPD page, depending on
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
configuration amongst others, a vendor specific designator that consists
3
either of the serial number if given or the BlockBackend name (which is
4
a host detail that better shouldn't have been leaked to the guest, but
5
now we have to maintain it for compatibility).
6
2
7
With anonymous BlockBackends, i.e. scsi-disk devices constructed with
3
If requests are being processed in the IOThread when a SCSIDevice is
8
drive=<node-name>, and no serial number explicitly specified, this ends
4
unplugged, scsi_device_purge_requests() -> scsi_req_cancel_async() races
9
up as an empty string. If this happens to more than one disk, we have
5
with I/O completion callbacks. Both threads load and store req->aiocb.
10
accidentally signalled to the OS that this is a multipath setup, which
6
This can lead to assert(r->req.aiocb == NULL) failures and undefined
11
is obviously not what was intended.
7
behavior.
12
8
13
Instead of using an empty string for the vendor specific designator,
9
Protect r->req.aiocb with the AioContext lock to prevent the race.
14
simply leave out that designator, which makes Linux detect such setups
15
as separate disks again.
16
10
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230221212218.1378734-2-stefanha@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
---
16
---
21
hw/scsi/scsi-disk.c | 14 ++++++++------
17
hw/scsi/scsi-disk.c | 23 ++++++++++++++++-------
22
1 file changed, 8 insertions(+), 6 deletions(-)
18
hw/scsi/scsi-generic.c | 11 ++++++-----
19
2 files changed, 22 insertions(+), 12 deletions(-)
23
20
24
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
21
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/scsi/scsi-disk.c
23
--- a/hw/scsi/scsi-disk.c
27
+++ b/hw/scsi/scsi-disk.c
24
+++ b/hw/scsi/scsi-disk.c
28
@@ -XXX,XX +XXX,XX @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
25
@@ -XXX,XX +XXX,XX @@ static void scsi_aio_complete(void *opaque, int ret)
29
DPRINTF("Inquiry EVPD[Device identification] "
26
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
30
"buffer size %zd\n", req->cmd.xfer);
27
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
31
28
32
- outbuf[buflen++] = 0x2; /* ASCII */
29
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
33
- outbuf[buflen++] = 0; /* not officially assigned */
30
+
34
- outbuf[buflen++] = 0; /* reserved */
31
assert(r->req.aiocb != NULL);
35
- outbuf[buflen++] = id_len; /* length of data following */
32
r->req.aiocb = NULL;
36
- memcpy(outbuf + buflen, str, id_len);
33
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
37
- buflen += id_len;
34
+
38
+ if (id_len) {
35
if (scsi_disk_req_check_error(r, ret, true)) {
39
+ outbuf[buflen++] = 0x2; /* ASCII */
36
goto done;
40
+ outbuf[buflen++] = 0; /* not officially assigned */
37
}
41
+ outbuf[buflen++] = 0; /* reserved */
38
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
42
+ outbuf[buflen++] = id_len; /* length of data following */
39
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
43
+ memcpy(outbuf + buflen, str, id_len);
40
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
44
+ buflen += id_len;
41
45
+ }
42
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
46
43
+
47
if (s->qdev.wwn) {
44
assert(r->req.aiocb != NULL);
48
outbuf[buflen++] = 0x1; /* Binary */
45
r->req.aiocb = NULL;
46
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
48
if (ret < 0) {
49
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
50
} else {
51
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void *opaque, int ret)
52
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
53
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
54
55
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
56
+
57
assert(r->req.aiocb != NULL);
58
r->req.aiocb = NULL;
59
60
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
61
if (ret < 0) {
62
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
63
} else {
64
@@ -XXX,XX +XXX,XX @@ static void scsi_do_read_cb(void *opaque, int ret)
65
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
66
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
67
68
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
69
+
70
assert (r->req.aiocb != NULL);
71
r->req.aiocb = NULL;
72
73
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
74
if (ret < 0) {
75
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
76
} else {
77
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
78
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
79
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
80
81
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
82
+
83
assert (r->req.aiocb != NULL);
84
r->req.aiocb = NULL;
85
86
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
87
if (ret < 0) {
88
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
89
} else {
90
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
91
SCSIDiskReq *r = data->r;
92
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
93
94
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
95
+
96
assert(r->req.aiocb != NULL);
97
r->req.aiocb = NULL;
98
99
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
100
if (scsi_disk_req_check_error(r, ret, true)) {
101
scsi_req_unref(&r->req);
102
g_free(data);
103
@@ -XXX,XX +XXX,XX @@ static void scsi_write_same_complete(void *opaque, int ret)
104
SCSIDiskReq *r = data->r;
105
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
106
107
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
108
+
109
assert(r->req.aiocb != NULL);
110
r->req.aiocb = NULL;
111
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
112
+
113
if (scsi_disk_req_check_error(r, ret, true)) {
114
goto done;
115
}
116
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/scsi/scsi-generic.c
119
+++ b/hw/scsi/scsi-generic.c
120
@@ -XXX,XX +XXX,XX @@ static void scsi_command_complete(void *opaque, int ret)
121
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
122
SCSIDevice *s = r->req.dev;
123
124
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
125
+
126
assert(r->req.aiocb != NULL);
127
r->req.aiocb = NULL;
128
129
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
130
scsi_command_complete_noio(r, ret);
131
aio_context_release(blk_get_aio_context(s->conf.blk));
132
}
133
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
134
SCSIDevice *s = r->req.dev;
135
int len;
136
137
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
138
+
139
assert(r->req.aiocb != NULL);
140
r->req.aiocb = NULL;
141
142
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
143
-
144
if (ret || r->req.io_canceled) {
145
scsi_command_complete_noio(r, ret);
146
goto done;
147
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
148
149
trace_scsi_generic_write_complete(ret);
150
151
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
152
+
153
assert(r->req.aiocb != NULL);
154
r->req.aiocb = NULL;
155
156
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
157
-
158
if (ret || r->req.io_canceled) {
159
scsi_command_complete_noio(r, ret);
160
goto done;
49
--
161
--
50
2.20.1
162
2.39.2
51
52
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
This fixes a crash when attaching two disks with the same blockdev to
3
dma_blk_cb() only takes the AioContext lock around ->io_func(). That
4
a SCSI device that is using iothreads. Test case included.
4
means the rest of dma_blk_cb() is not protected. In particular, the
5
DMAAIOCB field accesses happen outside the lock.
5
6
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
There is a race when the main loop thread holds the AioContext lock and
8
invokes scsi_device_purge_requests() -> bdrv_aio_cancel() ->
9
dma_aio_cancel() while an IOThread executes dma_blk_cb(). The dbs->acb
10
field determines how cancellation proceeds. If dma_aio_cancel() sees
11
dbs->acb == NULL while dma_blk_cb() is still running, the request can be
12
completed twice (-ECANCELED and the actual return value).
13
14
The following assertion can occur with virtio-scsi when an IOThread is
15
used:
16
17
../hw/scsi/scsi-disk.c:368: scsi_dma_complete: Assertion `r->req.aiocb != NULL' failed.
18
19
Fix the race by holding the AioContext across dma_blk_cb(). Now
20
dma_aio_cancel() under the AioContext lock will not see
21
inconsistent/intermediate states.
22
23
Cc: Paolo Bonzini <pbonzini@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Message-Id: <20230221212218.1378734-3-stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
28
---
9
hw/scsi/scsi-disk.c | 23 ++++++++++++++++++++---
29
hw/scsi/scsi-disk.c | 4 +---
10
tests/qemu-iotests/240 | 18 ++++++++++++++++++
30
softmmu/dma-helpers.c | 12 +++++++-----
11
tests/qemu-iotests/240.out | 16 ++++++++++++++++
31
2 files changed, 8 insertions(+), 8 deletions(-)
12
3 files changed, 54 insertions(+), 3 deletions(-)
13
32
14
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
33
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
15
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/scsi/scsi-disk.c
35
--- a/hw/scsi/scsi-disk.c
17
+++ b/hw/scsi/scsi-disk.c
36
+++ b/hw/scsi/scsi-disk.c
18
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
37
@@ -XXX,XX +XXX,XX @@ done:
19
static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
38
scsi_req_unref(&r->req);
39
}
40
41
+/* Called with AioContext lock held */
42
static void scsi_dma_complete(void *opaque, int ret)
20
{
43
{
21
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
44
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
22
+ AioContext *ctx = NULL;
45
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
23
/* can happen for devices without drive. The error message for missing
46
24
* backend will be issued in scsi_realize
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
25
*/
48
-
26
if (s->qdev.conf.blk) {
49
assert(r->req.aiocb != NULL);
27
+ ctx = blk_get_aio_context(s->qdev.conf.blk);
50
r->req.aiocb = NULL;
28
+ aio_context_acquire(ctx);
51
29
blkconf_blocksizes(&s->qdev.conf);
52
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
53
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
30
}
54
}
31
s->qdev.blocksize = s->qdev.conf.logical_block_size;
55
scsi_dma_complete_noio(r, ret);
32
@@ -XXX,XX +XXX,XX @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
56
- aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
33
s->product = g_strdup("QEMU HARDDISK");
34
}
35
scsi_realize(&s->qdev, errp);
36
+ if (ctx) {
37
+ aio_context_release(ctx);
38
+ }
39
}
57
}
40
58
41
static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
59
static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
60
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/softmmu/dma-helpers.c
63
+++ b/softmmu/dma-helpers.c
64
@@ -XXX,XX +XXX,XX @@ static void dma_complete(DMAAIOCB *dbs, int ret)
65
static void dma_blk_cb(void *opaque, int ret)
42
{
66
{
43
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
67
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
44
+ AioContext *ctx;
68
+ AioContext *ctx = dbs->ctx;
45
int ret;
69
dma_addr_t cur_addr, cur_len;
46
70
void *mem;
47
if (!dev->conf.blk) {
71
48
@@ -XXX,XX +XXX,XX @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
72
trace_dma_blk_cb(dbs, ret);
49
assert(ret == 0);
73
50
}
51
52
+ ctx = blk_get_aio_context(dev->conf.blk);
53
+ aio_context_acquire(ctx);
74
+ aio_context_acquire(ctx);
54
s->qdev.blocksize = 2048;
75
dbs->acb = NULL;
55
s->qdev.type = TYPE_ROM;
76
dbs->offset += dbs->iov.size;
56
s->features |= 1 << SCSI_DISK_F_REMOVABLE;
77
57
@@ -XXX,XX +XXX,XX @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
78
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
58
s->product = g_strdup("QEMU CD-ROM");
79
dma_complete(dbs, ret);
59
}
60
scsi_realize(&s->qdev, errp);
61
+ aio_context_release(ctx);
62
}
63
64
static void scsi_disk_realize(SCSIDevice *dev, Error **errp)
65
@@ -XXX,XX +XXX,XX @@ static int get_device_type(SCSIDiskState *s)
66
static void scsi_block_realize(SCSIDevice *dev, Error **errp)
67
{
68
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
69
+ AioContext *ctx;
70
int sg_version;
71
int rc;
72
73
@@ -XXX,XX +XXX,XX @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp)
74
"be removed in a future version");
75
}
76
77
+ ctx = blk_get_aio_context(s->qdev.conf.blk);
78
+ aio_context_acquire(ctx);
79
+
80
/* check we are using a driver managing SG_IO (version 3 and after) */
81
rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version);
82
if (rc < 0) {
83
@@ -XXX,XX +XXX,XX @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp)
84
if (rc != -EPERM) {
85
error_append_hint(errp, "Is this a SCSI device?\n");
86
}
87
- return;
80
- return;
88
+ goto out;
81
+ goto out;
89
}
82
}
90
if (sg_version < 30000) {
83
dma_blk_unmap(dbs);
91
error_setg(errp, "scsi generic interface too old");
84
85
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
86
87
if (dbs->iov.size == 0) {
88
trace_dma_map_wait(dbs);
89
- dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs);
90
+ dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs);
91
cpu_register_map_client(dbs->bh);
92
- return;
92
- return;
93
+ goto out;
93
+ goto out;
94
}
94
}
95
95
96
/* get device type from INQUIRY data */
96
if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) {
97
rc = get_device_type(s);
97
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
98
if (rc < 0) {
98
QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align));
99
error_setg(errp, "INQUIRY failed");
100
- return;
101
+ goto out;
102
}
99
}
103
100
104
/* Make a guess for the block size, we'll fix it when the guest sends.
101
- aio_context_acquire(dbs->ctx);
105
@@ -XXX,XX +XXX,XX @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp)
102
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
106
103
dma_blk_cb, dbs, dbs->io_func_opaque);
107
scsi_realize(&s->qdev, errp);
104
- aio_context_release(dbs->ctx);
108
scsi_generic_read_device_inquiry(&s->qdev);
105
assert(dbs->acb);
109
+
110
+out:
106
+out:
111
+ aio_context_release(ctx);
107
+ aio_context_release(ctx);
112
}
108
}
113
109
114
typedef struct SCSIBlockReq {
110
static void dma_aio_cancel(BlockAIOCB *acb)
115
diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240
116
index XXXXXXX..XXXXXXX 100755
117
--- a/tests/qemu-iotests/240
118
+++ b/tests/qemu-iotests/240
119
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
120
{ "execute": "quit"}
121
EOF
122
123
+echo
124
+echo === Attach two SCSI disks using the same block device and the same iothread ===
125
+echo
126
+
127
+run_qemu <<EOF
128
+{ "execute": "qmp_capabilities" }
129
+{ "execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true}}
130
+{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread0"}}
131
+{ "execute": "device_add", "arguments": {"id": "scsi0", "driver": "${virtio_scsi}", "iothread": "iothread0"}}
132
+{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0"}}
133
+{ "execute": "device_add", "arguments": {"id": "scsi-hd1", "driver": "scsi-hd", "drive": "hd0"}}
134
+{ "execute": "device_del", "arguments": {"id": "scsi-hd0"}}
135
+{ "execute": "device_del", "arguments": {"id": "scsi-hd1"}}
136
+{ "execute": "device_del", "arguments": {"id": "scsi0"}}
137
+{ "execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
138
+{ "execute": "quit"}
139
+EOF
140
+
141
# success, all done
142
echo "*** done"
143
rm -f $seq.full
144
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
145
index XXXXXXX..XXXXXXX 100644
146
--- a/tests/qemu-iotests/240.out
147
+++ b/tests/qemu-iotests/240.out
148
@@ -XXX,XX +XXX,XX @@ QA output created by 240
149
150
=== Unplug a SCSI disk and then plug it again ===
151
152
+Testing:
153
+QMP_VERSION
154
+{"return": {}}
155
+{"return": {}}
156
+{"return": {}}
157
+{"return": {}}
158
+{"return": {}}
159
+{"return": {}}
160
+{"return": {}}
161
+{"return": {}}
162
+{"return": {}}
163
+{"return": {}}
164
+{"return": {}}
165
+
166
+=== Attach two SCSI disks using the same block device and the same iothread ===
167
+
168
Testing:
169
QMP_VERSION
170
{"return": {}}
171
--
111
--
172
2.20.1
112
2.39.2
173
174
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
This fixes a crash when attaching a disk to a SCSI device using
3
When an IOThread is configured, the ctrl virtqueue is processed in the
4
iothreads, then detaching it and reattaching it again. Test case
4
IOThread. TMFs that reset SCSI devices are currently called directly
5
included.
5
from the IOThread and trigger an assertion failure in blk_drain() from
6
6
the following call stack:
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
8
virtio_scsi_handle_ctrl_req -> virtio_scsi_do_tmf -> device_code_reset
9
-> scsi_disk_reset -> scsi_device_purge_requests -> blk_drain
10
11
../block/block-backend.c:1780: void blk_drain(BlockBackend *): Assertion `qemu_in_main_thread()' failed.
12
13
The blk_drain() function is not designed to be called from an IOThread
14
because it needs the Big QEMU Lock (BQL).
15
16
This patch defers TMFs that reset SCSI devices to a Bottom Half (BH)
17
that runs in the main loop thread under the BQL. This way it's safe to
18
call blk_drain() and the assertion failure is avoided.
19
20
Introduce s->tmf_bh_list for tracking TMF requests that have been
21
deferred to the BH. When the BH runs it will grab the entire list and
22
process all requests. Care must be taken to clear the list when the
23
virtio-scsi device is reset or unrealized. Otherwise deferred TMF
24
requests could execute later and lead to use-after-free or other
25
undefined behavior.
26
27
The s->resetting counter that's used by TMFs that reset SCSI devices is
28
accessed from multiple threads. This patch makes that explicit by using
29
atomic accessor functions. With this patch applied the counter is only
30
modified by the main loop thread under the BQL but can be read by any
31
thread.
32
33
Reported-by: Qing Wang <qinwang@redhat.com>
34
Cc: Paolo Bonzini <pbonzini@redhat.com>
35
Reviewed-by: Eric Blake <eblake@redhat.com>
36
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
37
Message-Id: <20230221212218.1378734-4-stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
39
---
10
hw/scsi/virtio-scsi.c | 6 +++
40
include/hw/virtio/virtio-scsi.h | 11 ++-
11
tests/qemu-iotests/240 | 89 ++++++++++++++++++++++++++++++++++++++
41
hw/scsi/virtio-scsi.c | 169 +++++++++++++++++++++++++-------
12
tests/qemu-iotests/240.out | 18 ++++++++
42
2 files changed, 143 insertions(+), 37 deletions(-)
13
tests/qemu-iotests/group | 1 +
43
14
4 files changed, 114 insertions(+)
44
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
15
create mode 100755 tests/qemu-iotests/240
45
index XXXXXXX..XXXXXXX 100644
16
create mode 100644 tests/qemu-iotests/240.out
46
--- a/include/hw/virtio/virtio-scsi.h
17
47
+++ b/include/hw/virtio/virtio-scsi.h
48
@@ -XXX,XX +XXX,XX @@ struct VirtIOSCSICommon {
49
VirtQueue **cmd_vqs;
50
};
51
52
+struct VirtIOSCSIReq;
53
+
54
struct VirtIOSCSI {
55
VirtIOSCSICommon parent_obj;
56
57
SCSIBus bus;
58
- int resetting;
59
+ int resetting; /* written from main loop thread, read from any thread */
60
bool events_dropped;
61
62
+ /*
63
+ * TMFs deferred to main loop BH. These fields are protected by
64
+ * virtio_scsi_acquire().
65
+ */
66
+ QEMUBH *tmf_bh;
67
+ QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list;
68
+
69
/* Fields for dataplane below */
70
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
71
18
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
72
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
19
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/scsi/virtio-scsi.c
74
--- a/hw/scsi/virtio-scsi.c
21
+++ b/hw/scsi/virtio-scsi.c
75
+++ b/hw/scsi/virtio-scsi.c
22
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
76
@@ -XXX,XX +XXX,XX @@ typedef struct VirtIOSCSIReq {
23
virtio_scsi_release(s);
77
QEMUSGList qsgl;
78
QEMUIOVector resp_iov;
79
80
- union {
81
- /* Used for two-stage request submission */
82
- QTAILQ_ENTRY(VirtIOSCSIReq) next;
83
+ /* Used for two-stage request submission and TMFs deferred to BH */
84
+ QTAILQ_ENTRY(VirtIOSCSIReq) next;
85
86
- /* Used for cancellation of request during TMFs */
87
- int remaining;
88
- };
89
+ /* Used for cancellation of request during TMFs */
90
+ int remaining;
91
92
SCSIRequest *sreq;
93
size_t resp_size;
94
@@ -XXX,XX +XXX,XX @@ static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
24
}
95
}
25
26
+ if (s->ctx) {
27
+ virtio_scsi_acquire(s);
28
+ blk_set_aio_context(sd->conf.blk, qemu_get_aio_context());
29
+ virtio_scsi_release(s);
30
+ }
31
+
32
qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
33
}
96
}
34
97
35
diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240
98
+static void virtio_scsi_do_one_tmf_bh(VirtIOSCSIReq *req)
36
new file mode 100755
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/tests/qemu-iotests/240
40
@@ -XXX,XX +XXX,XX @@
41
+#!/bin/bash
42
+#
43
+# Test hot plugging and unplugging with iothreads
44
+#
45
+# Copyright (C) 2019 Igalia, S.L.
46
+# Author: Alberto Garcia <berto@igalia.com>
47
+#
48
+# This program is free software; you can redistribute it and/or modify
49
+# it under the terms of the GNU General Public License as published by
50
+# the Free Software Foundation; either version 2 of the License, or
51
+# (at your option) any later version.
52
+#
53
+# This program is distributed in the hope that it will be useful,
54
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
55
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56
+# GNU General Public License for more details.
57
+#
58
+# You should have received a copy of the GNU General Public License
59
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
60
+#
61
+
62
+# creator
63
+owner=berto@igalia.com
64
+
65
+seq=`basename $0`
66
+echo "QA output created by $seq"
67
+
68
+status=1    # failure is the default!
69
+
70
+# get standard environment, filters and checks
71
+. ./common.rc
72
+. ./common.filter
73
+
74
+_supported_fmt generic
75
+_supported_proto generic
76
+_supported_os Linux
77
+
78
+do_run_qemu()
79
+{
99
+{
80
+ echo Testing: "$@"
100
+ VirtIOSCSI *s = req->dev;
81
+ $QEMU -nographic -qmp stdio -serial none "$@"
101
+ SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
82
+ echo
102
+ BusChild *kid;
103
+ int target;
104
+
105
+ switch (req->req.tmf.subtype) {
106
+ case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
107
+ if (!d) {
108
+ req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
109
+ goto out;
110
+ }
111
+ if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
112
+ req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
113
+ goto out;
114
+ }
115
+ qatomic_inc(&s->resetting);
116
+ device_cold_reset(&d->qdev);
117
+ qatomic_dec(&s->resetting);
118
+ break;
119
+
120
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
121
+ target = req->req.tmf.lun[1];
122
+ qatomic_inc(&s->resetting);
123
+
124
+ rcu_read_lock();
125
+ QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
126
+ SCSIDevice *d1 = SCSI_DEVICE(kid->child);
127
+ if (d1->channel == 0 && d1->id == target) {
128
+ device_cold_reset(&d1->qdev);
129
+ }
130
+ }
131
+ rcu_read_unlock();
132
+
133
+ qatomic_dec(&s->resetting);
134
+ break;
135
+
136
+ default:
137
+ g_assert_not_reached();
138
+ break;
139
+ }
140
+
141
+out:
142
+ object_unref(OBJECT(d));
143
+
144
+ virtio_scsi_acquire(s);
145
+ virtio_scsi_complete_req(req);
146
+ virtio_scsi_release(s);
83
+}
147
+}
84
+
148
+
85
+# Remove QMP events from (pretty-printed) output. Doesn't handle
149
+/* Some TMFs must be processed from the main loop thread */
86
+# nested dicts correctly, but we don't get any of those in this test.
150
+static void virtio_scsi_do_tmf_bh(void *opaque)
87
+_filter_qmp_events()
88
+{
151
+{
89
+ tr '\n' '\t' | sed -e \
152
+ VirtIOSCSI *s = opaque;
90
+    's/{\s*"timestamp":\s*{[^}]*},\s*"event":[^,}]*\(,\s*"data":\s*{[^}]*}\)\?\s*}\s*//g' \
153
+ QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
91
+    | tr '\t' '\n'
154
+ VirtIOSCSIReq *req;
155
+ VirtIOSCSIReq *tmp;
156
+
157
+ GLOBAL_STATE_CODE();
158
+
159
+ virtio_scsi_acquire(s);
160
+
161
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
162
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
163
+ QTAILQ_INSERT_TAIL(&reqs, req, next);
164
+ }
165
+
166
+ qemu_bh_delete(s->tmf_bh);
167
+ s->tmf_bh = NULL;
168
+
169
+ virtio_scsi_release(s);
170
+
171
+ QTAILQ_FOREACH_SAFE(req, &reqs, next, tmp) {
172
+ QTAILQ_REMOVE(&reqs, req, next);
173
+ virtio_scsi_do_one_tmf_bh(req);
174
+ }
92
+}
175
+}
93
+
176
+
94
+run_qemu()
177
+static void virtio_scsi_reset_tmf_bh(VirtIOSCSI *s)
95
+{
178
+{
96
+ do_run_qemu "$@" 2>&1 | _filter_qmp | _filter_qmp_events
179
+ VirtIOSCSIReq *req;
180
+ VirtIOSCSIReq *tmp;
181
+
182
+ GLOBAL_STATE_CODE();
183
+
184
+ virtio_scsi_acquire(s);
185
+
186
+ if (s->tmf_bh) {
187
+ qemu_bh_delete(s->tmf_bh);
188
+ s->tmf_bh = NULL;
189
+ }
190
+
191
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
192
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
193
+
194
+ /* SAM-6 6.3.2 Hard reset */
195
+ req->resp.tmf.response = VIRTIO_SCSI_S_TARGET_FAILURE;
196
+ virtio_scsi_complete_req(req);
197
+ }
198
+
199
+ virtio_scsi_release(s);
97
+}
200
+}
98
+
201
+
99
+case "$QEMU_DEFAULT_MACHINE" in
202
+static void virtio_scsi_defer_tmf_to_bh(VirtIOSCSIReq *req)
100
+ s390-ccw-virtio)
203
+{
101
+ virtio_scsi=virtio-scsi-ccw
204
+ VirtIOSCSI *s = req->dev;
102
+ ;;
205
+
103
+ *)
206
+ QTAILQ_INSERT_TAIL(&s->tmf_bh_list, req, next);
104
+ virtio_scsi=virtio-scsi-pci
207
+
105
+ ;;
208
+ if (!s->tmf_bh) {
106
+esac
209
+ s->tmf_bh = qemu_bh_new(virtio_scsi_do_tmf_bh, s);
107
+
210
+ qemu_bh_schedule(s->tmf_bh);
108
+echo
211
+ }
109
+echo === Unplug a SCSI disk and then plug it again ===
212
+}
110
+echo
213
+
111
+
214
/* Return 0 if the request is ready to be completed and return to guest;
112
+run_qemu <<EOF
215
* -EINPROGRESS if the request is submitted and will be completed later, in the
113
+{ "execute": "qmp_capabilities" }
216
* case of async cancellation. */
114
+{ "execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0"}}
217
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
115
+{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread0"}}
218
{
116
+{ "execute": "device_add", "arguments": {"id": "scsi0", "driver": "${virtio_scsi}", "iothread": "iothread0"}}
219
SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
117
+{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0"}}
220
SCSIRequest *r, *next;
118
+{ "execute": "device_del", "arguments": {"id": "scsi-hd0"}}
221
- BusChild *kid;
119
+{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0"}}
222
- int target;
120
+{ "execute": "device_del", "arguments": {"id": "scsi-hd0"}}
223
int ret = 0;
121
+{ "execute": "device_del", "arguments": {"id": "scsi0"}}
224
122
+{ "execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
225
virtio_scsi_ctx_check(s, d);
123
+{ "execute": "quit"}
226
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
124
+EOF
227
break;
125
+
228
126
+# success, all done
229
case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
127
+echo "*** done"
230
- if (!d) {
128
+rm -f $seq.full
231
- goto fail;
129
+status=0
232
- }
130
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
233
- if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
131
new file mode 100644
234
- goto incorrect_lun;
132
index XXXXXXX..XXXXXXX
235
- }
133
--- /dev/null
236
- s->resetting++;
134
+++ b/tests/qemu-iotests/240.out
237
- device_cold_reset(&d->qdev);
135
@@ -XXX,XX +XXX,XX @@
238
- s->resetting--;
136
+QA output created by 240
239
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
137
+
240
+ virtio_scsi_defer_tmf_to_bh(req);
138
+=== Unplug a SCSI disk and then plug it again ===
241
+ ret = -EINPROGRESS;
139
+
242
break;
140
+Testing:
243
141
+QMP_VERSION
244
case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
142
+{"return": {}}
245
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
143
+{"return": {}}
246
}
144
+{"return": {}}
247
break;
145
+{"return": {}}
248
146
+{"return": {}}
249
- case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
147
+{"return": {}}
250
- target = req->req.tmf.lun[1];
148
+{"return": {}}
251
- s->resetting++;
149
+{"return": {}}
252
-
150
+{"return": {}}
253
- rcu_read_lock();
151
+{"return": {}}
254
- QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
152
+{"return": {}}
255
- SCSIDevice *d1 = SCSI_DEVICE(kid->child);
153
+*** done
256
- if (d1->channel == 0 && d1->id == target) {
154
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
257
- device_cold_reset(&d1->qdev);
155
index XXXXXXX..XXXXXXX 100644
258
- }
156
--- a/tests/qemu-iotests/group
259
- }
157
+++ b/tests/qemu-iotests/group
260
- rcu_read_unlock();
158
@@ -XXX,XX +XXX,XX @@
261
-
159
237 rw auto quick
262
- s->resetting--;
160
238 auto quick
263
- break;
161
239 rw auto quick
264
-
162
+240 auto quick
265
case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
266
default:
267
req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
268
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_request_cancelled(SCSIRequest *r)
269
if (!req) {
270
return;
271
}
272
- if (req->dev->resetting) {
273
+ if (qatomic_read(&req->dev->resetting)) {
274
req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
275
} else {
276
req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
277
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_reset(VirtIODevice *vdev)
278
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
279
280
assert(!s->dataplane_started);
281
- s->resetting++;
282
+
283
+ virtio_scsi_reset_tmf_bh(s);
284
+
285
+ qatomic_inc(&s->resetting);
286
bus_cold_reset(BUS(&s->bus));
287
- s->resetting--;
288
+ qatomic_dec(&s->resetting);
289
290
vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
291
vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
292
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
293
VirtIOSCSI *s = VIRTIO_SCSI(dev);
294
Error *err = NULL;
295
296
+ QTAILQ_INIT(&s->tmf_bh_list);
297
+
298
virtio_scsi_common_realize(dev,
299
virtio_scsi_handle_ctrl,
300
virtio_scsi_handle_event,
301
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
302
{
303
VirtIOSCSI *s = VIRTIO_SCSI(dev);
304
305
+ virtio_scsi_reset_tmf_bh(s);
306
+
307
qbus_set_hotplug_handler(BUS(&s->bus), NULL);
308
virtio_scsi_common_unrealize(dev);
309
}
163
--
310
--
164
2.20.1
311
2.39.2
165
166
diff view generated by jsdifflib
1
From: yuchenlin <npes87184@gmail.com>
1
From: Or Ozeri <oro@il.ibm.com>
2
2
3
Recently, some bugs in dmg file have been fixed. To prevent reading dmg
3
Signed-off-by: Or Ozeri <oro@il.ibm.com>
4
is broken someday in the future, add a simple test which ensures the
4
Message-Id: <20230129113120.722708-2-oro@oro.sl.cloud9.ibm.com>
5
conversion from dmg to raw should not hang or face any I/O error.
5
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: yuchenlin <npes87184@gmail.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
8
---
11
tests/qemu-iotests/239 | 53 ++++++++++++++++++
9
block/rbd.c | 16 ++++++----------
12
tests/qemu-iotests/239.out | 4 ++
10
1 file changed, 6 insertions(+), 10 deletions(-)
13
tests/qemu-iotests/check | 7 +++
14
tests/qemu-iotests/group | 1 +
15
.../sample_images/simple-dmg.dmg.bz2 | Bin 0 -> 3479 bytes
16
5 files changed, 65 insertions(+)
17
create mode 100755 tests/qemu-iotests/239
18
create mode 100644 tests/qemu-iotests/239.out
19
create mode 100644 tests/qemu-iotests/sample_images/simple-dmg.dmg.bz2
20
11
21
diff --git a/tests/qemu-iotests/239 b/tests/qemu-iotests/239
12
diff --git a/block/rbd.c b/block/rbd.c
22
new file mode 100755
23
index XXXXXXX..XXXXXXX
24
--- /dev/null
25
+++ b/tests/qemu-iotests/239
26
@@ -XXX,XX +XXX,XX @@
27
+#!/bin/bash
28
+#
29
+# Test case for dmg
30
+#
31
+# Copyright (C) 2019 yuchenlin <npes87184@gmail.com>
32
+#
33
+# This program is free software; you can redistribute it and/or modify
34
+# it under the terms of the GNU General Public License as published by
35
+# the Free Software Foundation; either version 2 of the License, or
36
+# (at your option) any later version.
37
+#
38
+# This program is distributed in the hope that it will be useful,
39
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
+# GNU General Public License for more details.
42
+#
43
+# You should have received a copy of the GNU General Public License
44
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
45
+#
46
+
47
+# creator
48
+owner=npes87184@gmail.com
49
+
50
+seq=`basename $0`
51
+echo "QA output created by $seq"
52
+
53
+status=1    # failure is the default!
54
+
55
+_cleanup()
56
+{
57
+ rm -f "$TEST_IMG.raw"
58
+ _cleanup_test_img
59
+}
60
+trap "_cleanup; exit \$status" 0 1 2 3 15
61
+
62
+# get standard environment, filters and checks
63
+. ./common.rc
64
+
65
+_supported_fmt dmg
66
+_supported_proto file
67
+_supported_os Linux
68
+
69
+echo
70
+echo "== Testing conversion to raw should success =="
71
+_use_sample_img simple-dmg.dmg.bz2
72
+if ! $QEMU_IMG convert -f $IMGFMT -O raw "$TEST_IMG" "$TEST_IMG.raw" ; then
73
+ exit 1
74
+fi
75
+
76
+# success, all done
77
+echo "*** done"
78
+rm -f $seq.full
79
+status=0
80
diff --git a/tests/qemu-iotests/239.out b/tests/qemu-iotests/239.out
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/tests/qemu-iotests/239.out
85
@@ -XXX,XX +XXX,XX @@
86
+QA output created by 239
87
+
88
+== Testing conversion to raw should success ==
89
+*** done
90
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
91
index XXXXXXX..XXXXXXX 100755
92
--- a/tests/qemu-iotests/check
93
+++ b/tests/qemu-iotests/check
94
@@ -XXX,XX +XXX,XX @@ image format options
95
-vhdx test vhdx
96
-vmdk test vmdk
97
-luks test luks
98
+ -dmg test dmg
99
100
image protocol options
101
-file test file (default)
102
@@ -XXX,XX +XXX,XX @@ testlist options
103
xpand=false
104
;;
105
106
+ -dmg)
107
+ IMGFMT=dmg
108
+ IMGFMT_GENERIC=false
109
+ xpand=false
110
+ ;;
111
+
112
-qed)
113
IMGFMT=qed
114
xpand=false
115
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
116
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/qemu-iotests/group
14
--- a/block/rbd.c
118
+++ b/tests/qemu-iotests/group
15
+++ b/block/rbd.c
119
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
120
235 auto quick
17
{
121
236 auto quick
18
int r = 0;
122
238 auto quick
19
g_autofree char *passphrase = NULL;
123
+239 rw auto quick
20
- size_t passphrase_len;
124
diff --git a/tests/qemu-iotests/sample_images/simple-dmg.dmg.bz2 b/tests/qemu-iotests/sample_images/simple-dmg.dmg.bz2
21
rbd_encryption_format_t format;
125
new file mode 100644
22
rbd_encryption_options_t opts;
126
index XXXXXXX..XXXXXXX
23
rbd_encryption_luks1_format_options_t luks_opts;
127
GIT binary patch
24
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
128
literal 3479
25
opts_size = sizeof(luks_opts);
129
zcmV;I4QTR0T4*^jL0KkKS(36)s{k7pfB*mg|NsC0|NsC0|NsC0|NsC0|Ns5}|NsC0
26
r = qemu_rbd_convert_luks_create_options(
130
z|NsC0|Nr0#eji@i`+e|w_jjtUioUNn9=bhi?FYz+8lea^Pt`n6Q`GfM=uI^|rccqR
27
qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks),
131
z#)^4QQ(&j0^vx-<6U8+BMo&{rPgMO9KU6<bdYee{L&A*HX-%dfJg1{mX^f|mdZ(%S
28
- &luks_opts.alg, &passphrase, &passphrase_len, errp);
132
zYHDfZWgn$BPgL<R4Jqj~+M0TvOq0bPDe8Glf++<WdYU|=X+1Rn(<i9%Lp2zh4IZY3
29
+ &luks_opts.alg, &passphrase, &luks_opts.passphrase_size,
133
zjXgCzA?gg9Q$~!`&}h@t^qy1H^iL_WjXgCzK-!HSQ%^=sO&L8COn}g7>K>tx+G-x7
30
+ errp);
134
zKxhH7gFqfr)EbhWqfmN7Xqi0_(|U$T%^~Te(<9O!s(P57)gFnX(HMqCnW^apCLkWB
31
if (r < 0) {
135
zfB?c`7=Y8$P|yP*p{9YL8X6e}jSLZ{Kmat*Y9I=F1s<p9DB4Cq^#`bE4Ff^74GlCj
32
return r;
136
z05tUmngG$D8fXFP0MPXVMoj}i&;S4$8UdgN)B`|zgFpae5-JoYqMnhSqz_5zX!RaX
33
}
137
zN@?n8p`%8PJdIB%dW@MKrbdHIo}+1?O{io&O{DTNL5K|i44$J2gHSf0dW_JG15ZRS
34
luks_opts.passphrase = passphrase;
138
zO#>jv(V%IjnFNxA1T<(7k~Y;aPez3F!fB&IWZEW%)byHqn^PtYN0c*2G<pJPF%2|&
35
- luks_opts.passphrase_size = passphrase_len;
139
zjXg~oX{V%Vqb8bZplqPgw1%2w9-*VtQR*}r00xGQ4G24kA+jG=o`xW*WTQp80#*@D
36
break;
140
zGI^@e0Fq218g7gWKQ0-!!d?<+0Zg$VQi&#k#L$@->*ZllN2a;wYb5Z@K!FpiLKS04
37
}
141
zAXF_RNbYzNTvjprs6=NSa4=(xVBCm>1#>twBnc>5NRuJv+UXVcw)$K?45Ra5gMtys
38
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
142
z5#=tTi{6o_Dolm>AW0*9z$7i33Gt*7^pYSUXUfIy=|9=(Y5F2D)W#);#I!)dBq)W~
39
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
143
zrFlJ*pf<%<p!?|?K4A)WKmn>vEyY-2j;_z6FzSi8mQn!dfdGLU#z+u}O%{xk@FlI`
40
r = qemu_rbd_convert_luks_create_options(
144
z^B@Tz!-52v0~!WxwY>yM5j2L!wDW07lb>SjKuGF1Bv7*3#(>;&j=WH?%<2(%C(%mi
41
qapi_RbdEncryptionCreateOptionsLUKS2_base(
145
z3SK&{tsN6|F+h=$fRF|SAT&YV;=$CM8UPyf&KPGXD@;hw?Ie+ur$Ms`<R|DnF>?n=
42
&encrypt->u.luks2),
146
z=TVuCRg<`%CTS#rC3Rqi{8+-#G7{}$If&w>{u-}tqnXQGZ1vrDn(W+-ydtwD_5(m9
43
- &luks2_opts.alg, &passphrase, &passphrase_len, errp);
147
zUlJm4YF$|a547Ok)VNY_1&|O<rL!z~wcz}tQxE~Dj4cXB5;0mM5(lt%*IA;POn}RT
44
+ &luks2_opts.alg, &passphrase, &luks2_opts.passphrase_size,
148
z;6QRRmFhId9Am|k#g{Q@hX6cXxi&WKM_|eXL97PF^DAB*Vbz~zQKTvZ??`1m>?|T)
45
+ errp);
149
z42v8J{j@}JBoR7501!b0TQLa}5=%fGiZ01vc2PsfW3IL_R4y29^38$G<bvvm5nFd0
46
if (r < 0) {
150
zCwO?LU{=bViG0S0Zh^;{@n#!Kdu|V}*6A@n-bN2myQ=@_`vaVL_~0ObLdRRH{)&n2
47
return r;
151
zWjQqZq-v&|Sm)GU$5#3E-aM@MWEDTSJ=WXyvX!Ka^MIpH)wR_6>N@}eFEu8;#~W3O
48
}
152
zhYo*p2)1qo0FWCdNC$P6JWDI)lRL3RsCq~;CddNVfDeUAK|}zQbl`V}JlvEcUSn8M
49
luks2_opts.passphrase = passphrase;
153
zpVIf%kFZ>u>OO0J!nRehCj34b&G%X*%F`iNsN=6_pV&CdsRu0CM-x>qqFshZ5Cm<o
50
- luks2_opts.passphrase_size = passphrase_len;
154
zjS+4gAk-oc*IeI*Cm4uELVya|XwQV9;aJZ7Mzx<=On?m(0@tY~UQVHbY{wZn;D)7@
51
break;
155
z(k#N&X0YCEm2rAN!X56ASS+#z7ao9>#cE(tAoIY<O8RkL;gL@lE`rM`9JnB2CEx^z
52
}
156
z6c8i@0n%FhZje3Zxg#iF@R@T1Isa_wb*LjCgn+!DWDcYQh#WxZLepa#PQjgE{rMz?
53
default: {
157
zBq1<j2VVpX$Xd;K6V+q_hhHJtdWTbjuPi#R=(f&lykmQl$pDZgP%wm~nI*Ni#z^FO
54
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
158
zE-eT!OaQHD1y1DHB8`9}p<+T&reFk;4s}MH%)0IXH1auiL(e%0z#SY_Q4bA>;2;n;
55
{
159
z>6lWK8VC|iQ`TBT@eh_haUvW?s0F~|jWOEDBrNGaBoJh|LX9lsM4vqVlOYszX7pdA
56
int r = 0;
160
z{D&2t%ysWP&xa%2Q6LEk#Gf-=1UdvZ5a1%=kY@b_PJ?B`u>CaLI&B7em_7b|;n=Za
57
g_autofree char *passphrase = NULL;
161
zp~fR)pUI5+fvC#Km(lVCNpb=XW#mzCYrKf$7gM(TqYzYBKqz54qqz-xcv$fGQrdYy
58
- size_t passphrase_len;
162
zRD%pqsY(=-5JXlPYst2Xv=#sccTUb6A-KFq8XNZ`G)4wExi9zHxBO=zO;AbFM}`M!
59
rbd_encryption_luks1_format_options_t luks_opts;
163
zOk?+aXaO;H02oI0Bn>Mv09F(z2D>5BS#O#$P6Hjd6boVGU|fj(_>6Wj@RrKIn;8EB
60
rbd_encryption_luks2_format_options_t luks2_opts;
164
zble1^sy2Z1#DvynHzELF0f+`WC;nB6;l*sYRsG&{OT)PkEN{C-fC@>voA`)pYKBGR
61
rbd_encryption_format_t format;
165
zy0qd5hS(-IOAKl(iXY}a|K}p1?TmbyuKT-Qeer)gFKD88^Tpxr*kmLy;0FL}C&d#`
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
166
zQ|v00fv3#W*mSyZs|-K<h+d6pNO}MT^KN@JOgvk`m2@p1X~U$!#uswfANXB%a*2}d
63
opts_size = sizeof(luks_opts);
167
zwEVT6lZMv@K`D!LB_I^fo)latwZp8vy|3yBt&R41ACiQf!d~t-ftA7uBb30|`l#aR
64
r = qemu_rbd_convert_luks_options(
168
zSAZd~7y#5rmLOyX5*DtKB=1^~pw$7YjAzU-OkBe`h(K#GCV;6Q6}-9*#6ZQEesARr
65
qapi_RbdEncryptionOptionsLUKS_base(&encrypt->u.luks),
169
zwQh_HsY@9IS)I<~d1n7@4@41T%tXY@5h1NOcGB0n$$P2^q!Iwg96-Ypa~Me&Mkg03
66
- &passphrase, &passphrase_len, errp);
170
zx4>{zsMn+fmSxpq9<;PGzUke*7{Vc;ba?~~Fp@>uleN{!WoS8VmG%z%nuX9{w6QC^
67
+ &passphrase, &luks_opts.passphrase_size, errp);
171
z>cY}_BnH5wp)m6ur<d4axiRctR|XVPR-dd0=6w1P3>Z5+Eu`$-#pj&flXy9V9wq!p
68
if (r < 0) {
172
zo^)}9fQDYjW6Ab;cYA9~3Cm@szFUBpm=2bWB#w0?id*4t_2g7y|0*g1ylSPW9s834
69
return r;
173
ztjELX^xWJGpL*3Qc>%uRKQna>8~ayaq=0g~k?u90E|+R&pb}xi6sAxgk{0I9Tdk7g
70
}
174
zC&mCT7%%O`$bs$IGS?S?7$DVck$e==@QS_=nF(o3(InF7Dn=3k=Ls-^Fw9D7{(U3k
71
luks_opts.passphrase = passphrase;
175
zK*%{w#OE;-n}5J@QnW~k0W^>q6Frr!p|88#+Wy;ioe~<*h=i%&J;)%alO@Pegg+7j
72
- luks_opts.passphrase_size = passphrase_len;
176
zs``QTeEyD)x7p(92)N`E@8T8H#s^c%*24OW;aGvPuVQef*wBsRpU@6A_g9zdDt9$k
73
break;
177
z2zRm#rdLi0A^}Fb?sXZ{X@%WaZzShTNF-5=Fu)3i@t^qa`TwT<VRADXi9j*Cww!Bk
74
}
178
z$ofZn`qc*}gV@O>ucE88qh>EN`Jdw+s*<*u-@$9+o1#_6XJ989lqI=az!E}P5riY*
75
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
179
zHPwYH$BT`e?rVGc3nGpD(|bD_E!3{ti_*;NZZ0isXL2=SVRX$Ti~X!dedY#W1K<$#
76
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
180
zh_IvD035p;=Ek~DC$}ZJd(G3-dd#k6CG#xgT;mmS6+SLid1tQO-9<Sl@O^GuLUz-u
77
opts_size = sizeof(luks2_opts);
181
z417&euHAlM4ypAfeUp|&``-9llf#`5`nX06abKLfN@~l%nAq{U{u*UfSI+fFc$+Nq
78
r = qemu_rbd_convert_luks_options(
182
zjSkQ*mer2Rs5nuStK%0w;knBzMKh|{QO!^DPwP)t^4~w3qnO*hZDo{4^>~P#9iv%f
79
qapi_RbdEncryptionOptionsLUKS2_base(&encrypt->u.luks2),
183
zd!`qvbczBF)AAe0yE+WI*}DYOL2J~*ZCc}JWiu0LShw&6`-5`^SkNJY!gsi|e-MHy
80
- &passphrase, &passphrase_len, errp);
184
zZlN9Lb5NbuT7S&4oY6v}13BpeQ|?u0c*7n)Ku*p%ZDF?$7zjKXj(9#K?tO1dMW=8&
81
+ &passphrase, &luks2_opts.passphrase_size, errp);
185
z;MDsGo0=CLWp{b5$Kk0kxAl*^l^ziX<28c4->Ed%#N16IrySH$q`4%gn}5ksr>_0H
82
if (r < 0) {
186
zs-;Y4Bb7U_pNGMK075wJ%DahB2ArR=jC`2UWMe`ID;mPgA25l6GVc9>Rqybi7N6(i
83
return r;
187
z3BcjbfprP7Ivcy%+Vs~Z6Hw>JB!kJcD>mdTThTpO$(fg`Ds7pY<YTYWgmqU8=Xlve
84
}
188
zCriGy+iG;z+{{27v*;>N4BN<|%(+#T+h1sdgPjUAWN73ki+$-%j_&6PZ$I2$HnSEa
85
luks2_opts.passphrase = passphrase;
189
zQ?n{BB*A3zmlLHvH@o+ZJm1NSC9(?ka<7OppIcAi{V`Nj+^8SL!ywYLI$v(ivC_){
86
- luks2_opts.passphrase_size = passphrase_len;
190
z5anb)=MQS%<PN>hUHR@_HKDhdDPf*Hm`w^E{GT!Yq<}Hg8Ia{?PyA70;yx8nD^~B|
87
break;
191
zjuGESS<A^!S2=(y_Dz2Z3)U+>*z1(bcT1?|;LuVOg&xLebEk(1uB(fZJN&W3!xADj
88
}
192
zQD;ugVYYpOt=NBu$Bi07WcepgHm6q}1y>vxs^oJetK;=ix$9i9M#>O`?6X2pJoXi;
89
default: {
193
z#0mlFG2eK~z-yqErVC2`l5B&)s}jKZMRZxCyQ0^?cp$L5J>4{eoCysx+#X0J?r^+C
194
z#R8d5A5=5V#(QMr1?kT}qh|eQ8{a94K6_Sq=vcWz&WH@!TREj$F3%=NwMQ3YR-$or
195
zlXmr#8-D_(N;#e;g#CE1WYh8byF-ojSdtGh>P8pbz39Ew5qWHa^1-M77ji{7P>_<c
196
FP^-7hd6WPE
197
198
literal 0
199
HcmV?d00001
200
201
--
90
--
202
2.20.1
91
2.39.2
203
204
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Or Ozeri <oro@il.ibm.com>
2
2
3
This makes VMDK support blockdev-create. The implementation reuses the
3
Ceph RBD encryption API required specifying the encryption format
4
image creation code in vmdk_co_create_opts which now acceptes a callback
4
for loading encryption. The supported formats were LUKS (v1) and LUKS2.
5
pointer to "retrieve" BlockBackend pointers from the caller. This way we
6
separate the logic between file/extent acquisition and initialization.
7
5
8
The QAPI command parameters are mostly the same as the old create_opts
6
Starting from Reef release, RBD also supports loading with "luks-any" format,
9
except the dropped legacy @compat6 switch, which is redundant with
7
which works for both versions of LUKS.
10
@hwversion.
11
8
12
Signed-off-by: Fam Zheng <famz@redhat.com>
9
This commit extends the qemu rbd driver API to enable qemu users to use
13
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
this luks-any wildcard format.
11
12
Signed-off-by: Or Ozeri <oro@il.ibm.com>
13
Message-Id: <20230129113120.722708-3-oro@oro.sl.cloud9.ibm.com>
14
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
17
---
16
qapi/block-core.json | 70 +++++++
18
qapi/block-core.json | 16 ++++++++++++++--
17
qapi/qapi-schema.json | 16 +-
19
block/rbd.c | 19 +++++++++++++++++++
18
block/vmdk.c | 448 ++++++++++++++++++++++++++++++------------
20
2 files changed, 33 insertions(+), 2 deletions(-)
19
3 files changed, 400 insertions(+), 134 deletions(-)
20
21
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/block-core.json
24
--- a/qapi/block-core.json
24
+++ b/qapi/block-core.json
25
+++ b/qapi/block-core.json
25
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
26
'size': 'size',
27
##
27
'*cluster-size' : 'size' } }
28
# @RbdImageEncryptionFormat:
29
#
30
+# @luks-any: Used for opening either luks or luks2 (Since 8.0)
31
+#
32
# Since: 6.1
33
##
34
{ 'enum': 'RbdImageEncryptionFormat',
35
- 'data': [ 'luks', 'luks2' ] }
36
+ 'data': [ 'luks', 'luks2', 'luks-any' ] }
37
38
##
39
# @RbdEncryptionOptionsLUKSBase:
40
@@ -XXX,XX +XXX,XX @@
41
'base': 'RbdEncryptionOptionsLUKSBase',
42
'data': { } }
28
43
29
+##
44
+##
30
+# @BlockdevVmdkSubformat:
45
+# @RbdEncryptionOptionsLUKSAny:
31
+#
46
+#
32
+# Subformat options for VMDK images
47
+# Since: 8.0
33
+#
34
+# @monolithicSparse: Single file image with sparse cluster allocation
35
+#
36
+# @monolithicFlat: Single flat data image and a descriptor file
37
+#
38
+# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse extent
39
+# files, in addition to a descriptor file
40
+#
41
+# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat extent
42
+# files, in addition to a descriptor file
43
+#
44
+# @streamOptimized: Single file image sparse cluster allocation, optimized
45
+# for streaming over network.
46
+#
47
+# Since: 4.0
48
+##
48
+##
49
+{ 'enum': 'BlockdevVmdkSubformat',
49
+{ 'struct': 'RbdEncryptionOptionsLUKSAny',
50
+ 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse',
50
+ 'base': 'RbdEncryptionOptionsLUKSBase',
51
+ 'twoGbMaxExtentFlat', 'streamOptimized'] }
51
+ 'data': { } }
52
+
53
+##
54
+# @BlockdevVmdkAdapterType:
55
+#
56
+# Adapter type info for VMDK images
57
+#
58
+# Since: 4.0
59
+##
60
+{ 'enum': 'BlockdevVmdkAdapterType',
61
+ 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] }
62
+
63
+##
64
+# @BlockdevCreateOptionsVmdk:
65
+#
66
+# Driver specific image creation options for VMDK.
67
+#
68
+# @file Where to store the new image file. This refers to the image
69
+# file for monolithcSparse and streamOptimized format, or the
70
+# descriptor file for other formats.
71
+# @size Size of the virtual disk in bytes
72
+# @extents Where to store the data extents. Required for monolithcFlat,
73
+# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For
74
+# monolithicFlat, only one entry is required; for
75
+# twoGbMaxExtent* formats, the number of entries required is
76
+# calculated as extent_number = virtual_size / 2GB.
77
+# @subformat The subformat of the VMDK image. Default: "monolithicSparse".
78
+# @backing-file The path of backing file. Default: no backing file is used.
79
+# @adapter-type The adapter type used to fill in the descriptor. Default: ide.
80
+# @hwversion Hardware version. The meaningful options are "4" or "6".
81
+# Default: "4".
82
+# @zeroed-grain Whether to enable zeroed-grain feature for sparse subformats.
83
+# Default: false.
84
+#
85
+# Since: 4.0
86
+##
87
+{ 'struct': 'BlockdevCreateOptionsVmdk',
88
+ 'data': { 'file': 'BlockdevRef',
89
+ 'size': 'size',
90
+ '*extents': ['BlockdevRef'],
91
+ '*subformat': 'BlockdevVmdkSubformat',
92
+ '*backing-file': 'str',
93
+ '*adapter-type': 'BlockdevVmdkAdapterType',
94
+ '*hwversion': 'str',
95
+ '*zeroed-grain': 'bool' } }
96
+
97
+
52
+
98
##
53
##
99
# @SheepdogRedundancyType:
54
# @RbdEncryptionCreateOptionsLUKS:
100
#
55
#
101
@@ -XXX,XX +XXX,XX @@
56
@@ -XXX,XX +XXX,XX @@
102
'ssh': 'BlockdevCreateOptionsSsh',
57
'base': { 'format': 'RbdImageEncryptionFormat' },
103
'vdi': 'BlockdevCreateOptionsVdi',
58
'discriminator': 'format',
104
'vhdx': 'BlockdevCreateOptionsVhdx',
59
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
105
+ 'vmdk': 'BlockdevCreateOptionsVmdk',
60
- 'luks2': 'RbdEncryptionOptionsLUKS2' } }
106
'vpc': 'BlockdevCreateOptionsVpc'
61
+ 'luks2': 'RbdEncryptionOptionsLUKS2',
107
} }
62
+ 'luks-any': 'RbdEncryptionOptionsLUKSAny'} }
108
63
109
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
64
##
65
# @RbdEncryptionCreateOptions:
66
diff --git a/block/rbd.c b/block/rbd.c
110
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
111
--- a/qapi/qapi-schema.json
68
--- a/block/rbd.c
112
+++ b/qapi/qapi-schema.json
69
+++ b/block/rbd.c
113
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
114
'query-tpm-types',
71
g_autofree char *passphrase = NULL;
115
'ringbuf-read' ],
72
rbd_encryption_luks1_format_options_t luks_opts;
116
'name-case-whitelist': [
73
rbd_encryption_luks2_format_options_t luks2_opts;
117
- 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
118
- 'CpuInfoMIPS', # PC, visible through query-cpu
75
+ rbd_encryption_luks_format_options_t luks_any_opts;
119
- 'CpuInfoTricore', # PC, visible through query-cpu
76
+#endif
120
- 'QapiErrorClass', # all members, visible through errors
77
rbd_encryption_format_t format;
121
- 'UuidInfo', # UUID, visible through query-uuid
78
rbd_encryption_options_t opts;
122
- 'X86CPURegister32', # all members, visible indirectly through qom-get
79
size_t opts_size;
123
- 'q_obj_CpuInfo-base' # CPU, visible through query-cpu
80
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
124
+ 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
81
luks2_opts.passphrase = passphrase;
125
+ 'CpuInfoMIPS', # PC, visible through query-cpu
82
break;
126
+ 'CpuInfoTricore', # PC, visible through query-cpu
127
+ 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings
128
+ 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings
129
+ 'QapiErrorClass', # all members, visible through errors
130
+ 'UuidInfo', # UUID, visible through query-uuid
131
+ 'X86CPURegister32', # all members, visible indirectly through qom-get
132
+ 'q_obj_CpuInfo-base' # CPU, visible through query-cpu
133
] } }
134
135
# Documentation generated with qapi-gen.py is in source order, with
136
diff --git a/block/vmdk.c b/block/vmdk.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/block/vmdk.c
139
+++ b/block/vmdk.c
140
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
141
return VMDK_OK;
142
}
143
144
-static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts,
145
- Error **errp)
146
+/*
147
+ * idx == 0: get or create the descriptor file (also the image file if in a
148
+ * non-split format.
149
+ * idx >= 1: get the n-th extent if in a split subformat
150
+ */
151
+typedef BlockBackend *(*vmdk_create_extent_fn)(int64_t size,
152
+ int idx,
153
+ bool flat,
154
+ bool split,
155
+ bool compress,
156
+ bool zeroed_grain,
157
+ void *opaque,
158
+ Error **errp);
159
+
160
+static void vmdk_desc_add_extent(GString *desc,
161
+ const char *extent_line_fmt,
162
+ int64_t size, const char *filename)
163
+{
164
+ char *basename = g_path_get_basename(filename);
165
+
166
+ g_string_append_printf(desc, extent_line_fmt,
167
+ DIV_ROUND_UP(size, BDRV_SECTOR_SIZE), basename);
168
+ g_free(basename);
169
+}
170
+
171
+static int coroutine_fn vmdk_co_do_create(int64_t size,
172
+ BlockdevVmdkSubformat subformat,
173
+ BlockdevVmdkAdapterType adapter_type,
174
+ const char *backing_file,
175
+ const char *hw_version,
176
+ bool compat6,
177
+ bool zeroed_grain,
178
+ vmdk_create_extent_fn extent_fn,
179
+ void *opaque,
180
+ Error **errp)
181
{
182
- int idx = 0;
183
- BlockBackend *new_blk = NULL;
184
+ int extent_idx;
185
+ BlockBackend *blk = NULL;
186
Error *local_err = NULL;
187
char *desc = NULL;
188
- int64_t total_size = 0, filesize;
189
- char *adapter_type = NULL;
190
- char *backing_file = NULL;
191
- char *hw_version = NULL;
192
- char *fmt = NULL;
193
int ret = 0;
194
bool flat, split, compress;
195
GString *ext_desc_lines;
196
- char *path = g_malloc0(PATH_MAX);
197
- char *prefix = g_malloc0(PATH_MAX);
198
- char *postfix = g_malloc0(PATH_MAX);
199
- char *desc_line = g_malloc0(BUF_SIZE);
200
- char *ext_filename = g_malloc0(PATH_MAX);
201
- char *desc_filename = g_malloc0(PATH_MAX);
202
const int64_t split_size = 0x80000000; /* VMDK has constant split size */
203
- const char *desc_extent_line;
204
+ int64_t extent_size;
205
+ int64_t created_size = 0;
206
+ const char *extent_line_fmt;
207
char *parent_desc_line = g_malloc0(BUF_SIZE);
208
uint32_t parent_cid = 0xffffffff;
209
uint32_t number_heads = 16;
210
- bool zeroed_grain = false;
211
uint32_t desc_offset = 0, desc_len;
212
const char desc_template[] =
213
"# Disk DescriptorFile\n"
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
215
216
ext_desc_lines = g_string_new(NULL);
217
218
- if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
219
- ret = -EINVAL;
220
- goto exit;
221
- }
222
/* Read out options */
223
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
224
- BDRV_SECTOR_SIZE);
225
- adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
226
- backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
227
- hw_version = qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION);
228
- if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false)) {
229
- if (strcmp(hw_version, "undefined")) {
230
+ if (compat6) {
231
+ if (hw_version) {
232
error_setg(errp,
233
"compat6 cannot be enabled with hwversion set");
234
ret = -EINVAL;
235
goto exit;
236
}
83
}
237
- g_free(hw_version);
84
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
238
- hw_version = g_strdup("6");
85
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
239
- }
86
+ memset(&luks_any_opts, 0, sizeof(luks_any_opts));
240
- if (strcmp(hw_version, "undefined") == 0) {
87
+ format = RBD_ENCRYPTION_FORMAT_LUKS;
241
- g_free(hw_version);
88
+ opts = &luks_any_opts;
242
- hw_version = g_strdup("4");
89
+ opts_size = sizeof(luks_any_opts);
243
+ hw_version = "6";
90
+ r = qemu_rbd_convert_luks_options(
244
}
91
+ qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any),
245
- fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
92
+ &passphrase, &luks_any_opts.passphrase_size, errp);
246
- if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false)) {
93
+ if (r < 0) {
247
- zeroed_grain = true;
94
+ return r;
248
+ if (!hw_version) {
95
+ }
249
+ hw_version = "4";
96
+ luks_any_opts.passphrase = passphrase;
250
}
97
+ break;
251
252
- if (!adapter_type) {
253
- adapter_type = g_strdup("ide");
254
- } else if (strcmp(adapter_type, "ide") &&
255
- strcmp(adapter_type, "buslogic") &&
256
- strcmp(adapter_type, "lsilogic") &&
257
- strcmp(adapter_type, "legacyESX")) {
258
- error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
259
- ret = -EINVAL;
260
- goto exit;
261
- }
262
- if (strcmp(adapter_type, "ide") != 0) {
263
+ if (adapter_type != BLOCKDEV_VMDK_ADAPTER_TYPE_IDE) {
264
/* that's the number of heads with which vmware operates when
265
creating, exporting, etc. vmdk files with a non-ide adapter type */
266
number_heads = 255;
267
}
268
- if (!fmt) {
269
- /* Default format to monolithicSparse */
270
- fmt = g_strdup("monolithicSparse");
271
- } else if (strcmp(fmt, "monolithicFlat") &&
272
- strcmp(fmt, "monolithicSparse") &&
273
- strcmp(fmt, "twoGbMaxExtentSparse") &&
274
- strcmp(fmt, "twoGbMaxExtentFlat") &&
275
- strcmp(fmt, "streamOptimized")) {
276
- error_setg(errp, "Unknown subformat: '%s'", fmt);
277
- ret = -EINVAL;
278
- goto exit;
279
- }
280
- split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
281
- strcmp(fmt, "twoGbMaxExtentSparse"));
282
- flat = !(strcmp(fmt, "monolithicFlat") &&
283
- strcmp(fmt, "twoGbMaxExtentFlat"));
284
- compress = !strcmp(fmt, "streamOptimized");
285
+ split = (subformat == BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTFLAT) ||
286
+ (subformat == BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTSPARSE);
287
+ flat = (subformat == BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICFLAT) ||
288
+ (subformat == BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTFLAT);
289
+ compress = subformat == BLOCKDEV_VMDK_SUBFORMAT_STREAMOPTIMIZED;
290
+
291
if (flat) {
292
- desc_extent_line = "RW %" PRId64 " FLAT \"%s\" 0\n";
293
+ extent_line_fmt = "RW %" PRId64 " FLAT \"%s\" 0\n";
294
} else {
295
- desc_extent_line = "RW %" PRId64 " SPARSE \"%s\"\n";
296
+ extent_line_fmt = "RW %" PRId64 " SPARSE \"%s\"\n";
297
}
298
if (flat && backing_file) {
299
error_setg(errp, "Flat image can't have backing file");
300
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
301
ret = -ENOTSUP;
302
goto exit;
303
}
304
+
305
+ /* Create extents */
306
+ if (split) {
307
+ extent_size = split_size;
308
+ } else {
309
+ extent_size = size;
310
+ }
311
+ if (!split && !flat) {
312
+ created_size = extent_size;
313
+ } else {
314
+ created_size = 0;
315
+ }
316
+ /* Get the descriptor file BDS */
317
+ blk = extent_fn(created_size, 0, flat, split, compress, zeroed_grain,
318
+ opaque, errp);
319
+ if (!blk) {
320
+ ret = -EIO;
321
+ goto exit;
322
+ }
323
+ if (!split && !flat) {
324
+ vmdk_desc_add_extent(ext_desc_lines, extent_line_fmt, created_size,
325
+ blk_bs(blk)->filename);
326
+ }
327
+
328
if (backing_file) {
329
- BlockBackend *blk;
330
+ BlockBackend *backing;
331
char *full_backing = g_new0(char, PATH_MAX);
332
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
333
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
334
full_backing, PATH_MAX,
335
&local_err);
336
if (local_err) {
337
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
338
goto exit;
339
}
340
341
- blk = blk_new_open(full_backing, NULL, NULL,
342
- BDRV_O_NO_BACKING, errp);
343
+ backing = blk_new_open(full_backing, NULL, NULL,
344
+ BDRV_O_NO_BACKING, errp);
345
g_free(full_backing);
346
- if (blk == NULL) {
347
+ if (backing == NULL) {
348
ret = -EIO;
349
goto exit;
350
}
351
- if (strcmp(blk_bs(blk)->drv->format_name, "vmdk")) {
352
- blk_unref(blk);
353
+ if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) {
354
+ error_setg(errp, "Invalid backing file format: %s. Must be vmdk",
355
+ blk_bs(backing)->drv->format_name);
356
+ blk_unref(backing);
357
ret = -EINVAL;
358
goto exit;
359
}
360
- ret = vmdk_read_cid(blk_bs(blk), 0, &parent_cid);
361
- blk_unref(blk);
362
+ ret = vmdk_read_cid(blk_bs(backing), 0, &parent_cid);
363
+ blk_unref(backing);
364
if (ret) {
365
+ error_setg(errp, "Failed to read parent CID");
366
goto exit;
367
}
368
snprintf(parent_desc_line, BUF_SIZE,
369
"parentFileNameHint=\"%s\"", backing_file);
370
}
371
-
372
- /* Create extents */
373
- filesize = total_size;
374
- while (filesize > 0) {
375
- int64_t size = filesize;
376
-
377
- if (split && size > split_size) {
378
- size = split_size;
379
- }
380
- if (split) {
381
- snprintf(desc_filename, PATH_MAX, "%s-%c%03d%s",
382
- prefix, flat ? 'f' : 's', ++idx, postfix);
383
- } else if (flat) {
384
- snprintf(desc_filename, PATH_MAX, "%s-flat%s", prefix, postfix);
385
- } else {
386
- snprintf(desc_filename, PATH_MAX, "%s%s", prefix, postfix);
387
- }
388
- snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename);
389
-
390
- if (vmdk_create_extent(ext_filename, size,
391
- flat, compress, zeroed_grain, NULL, opts, errp)) {
392
+ extent_idx = 1;
393
+ while (created_size < size) {
394
+ BlockBackend *extent_blk;
395
+ int64_t cur_size = MIN(size - created_size, extent_size);
396
+ extent_blk = extent_fn(cur_size, extent_idx, flat, split, compress,
397
+ zeroed_grain, opaque, errp);
398
+ if (!extent_blk) {
399
ret = -EINVAL;
400
goto exit;
401
}
402
- filesize -= size;
403
-
404
- /* Format description line */
405
- snprintf(desc_line, BUF_SIZE,
406
- desc_extent_line, size / BDRV_SECTOR_SIZE, desc_filename);
407
- g_string_append(ext_desc_lines, desc_line);
408
+ vmdk_desc_add_extent(ext_desc_lines, extent_line_fmt, cur_size,
409
+ blk_bs(extent_blk)->filename);
410
+ created_size += cur_size;
411
+ extent_idx++;
412
+ blk_unref(extent_blk);
413
}
414
/* generate descriptor file */
415
desc = g_strdup_printf(desc_template,
416
g_random_int(),
417
parent_cid,
418
- fmt,
419
+ BlockdevVmdkSubformat_str(subformat),
420
parent_desc_line,
421
ext_desc_lines->str,
422
hw_version,
423
- total_size /
424
+ size /
425
(int64_t)(63 * number_heads * BDRV_SECTOR_SIZE),
426
number_heads,
427
- adapter_type);
428
+ BlockdevVmdkAdapterType_str(adapter_type));
429
desc_len = strlen(desc);
430
/* the descriptor offset = 0x200 */
431
if (!split && !flat) {
432
desc_offset = 0x200;
433
- } else {
434
- ret = bdrv_create_file(filename, opts, &local_err);
435
+ }
436
+
437
+ ret = blk_pwrite(blk, desc_offset, desc, desc_len, 0);
438
+ if (ret < 0) {
439
+ error_setg_errno(errp, -ret, "Could not write description");
440
+ goto exit;
441
+ }
442
+ /* bdrv_pwrite write padding zeros to align to sector, we don't need that
443
+ * for description file */
444
+ if (desc_offset == 0) {
445
+ ret = blk_truncate(blk, desc_len, PREALLOC_MODE_OFF, errp);
446
if (ret < 0) {
447
- error_propagate(errp, local_err);
448
goto exit;
449
}
450
}
451
+ ret = 0;
452
+exit:
453
+ if (blk) {
454
+ blk_unref(blk);
455
+ }
456
+ g_free(desc);
457
+ g_free(parent_desc_line);
458
+ g_string_free(ext_desc_lines, true);
459
+ return ret;
460
+}
461
462
- new_blk = blk_new_open(filename, NULL, NULL,
463
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
464
- &local_err);
465
- if (new_blk == NULL) {
466
- error_propagate(errp, local_err);
467
- ret = -EIO;
468
+typedef struct {
469
+ char *path;
470
+ char *prefix;
471
+ char *postfix;
472
+ QemuOpts *opts;
473
+} VMDKCreateOptsData;
474
+
475
+static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,
476
+ bool flat, bool split, bool compress,
477
+ bool zeroed_grain, void *opaque,
478
+ Error **errp)
479
+{
480
+ BlockBackend *blk = NULL;
481
+ BlockDriverState *bs = NULL;
482
+ VMDKCreateOptsData *data = opaque;
483
+ char *ext_filename = NULL;
484
+ char *rel_filename = NULL;
485
+
486
+ if (idx == 0) {
487
+ rel_filename = g_strdup_printf("%s%s", data->prefix, data->postfix);
488
+ } else if (split) {
489
+ rel_filename = g_strdup_printf("%s-%c%03d%s",
490
+ data->prefix,
491
+ flat ? 'f' : 's', idx, data->postfix);
492
+ } else {
493
+ assert(idx == 1);
494
+ rel_filename = g_strdup_printf("%s-flat%s", data->prefix, data->postfix);
495
+ }
496
+
497
+ ext_filename = g_strdup_printf("%s%s", data->path, rel_filename);
498
+ g_free(rel_filename);
499
+
500
+ if (vmdk_create_extent(ext_filename, size,
501
+ flat, compress, zeroed_grain, &blk, data->opts,
502
+ errp)) {
503
goto exit;
504
}
505
+ bdrv_unref(bs);
506
+exit:
507
+ g_free(ext_filename);
508
+ return blk;
509
+}
510
511
- blk_set_allow_write_beyond_eof(new_blk, true);
512
+static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts,
513
+ Error **errp)
514
+{
515
+ Error *local_err = NULL;
516
+ char *desc = NULL;
517
+ int64_t total_size = 0;
518
+ char *adapter_type = NULL;
519
+ BlockdevVmdkAdapterType adapter_type_enum;
520
+ char *backing_file = NULL;
521
+ char *hw_version = NULL;
522
+ char *fmt = NULL;
523
+ BlockdevVmdkSubformat subformat;
524
+ int ret = 0;
525
+ char *path = g_malloc0(PATH_MAX);
526
+ char *prefix = g_malloc0(PATH_MAX);
527
+ char *postfix = g_malloc0(PATH_MAX);
528
+ char *desc_line = g_malloc0(BUF_SIZE);
529
+ char *ext_filename = g_malloc0(PATH_MAX);
530
+ char *desc_filename = g_malloc0(PATH_MAX);
531
+ char *parent_desc_line = g_malloc0(BUF_SIZE);
532
+ bool zeroed_grain;
533
+ bool compat6;
534
+ VMDKCreateOptsData data;
535
536
- ret = blk_pwrite(new_blk, desc_offset, desc, desc_len, 0);
537
- if (ret < 0) {
538
- error_setg_errno(errp, -ret, "Could not write description");
539
+ if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
540
+ ret = -EINVAL;
541
goto exit;
542
}
543
- /* bdrv_pwrite write padding zeros to align to sector, we don't need that
544
- * for description file */
545
- if (desc_offset == 0) {
546
- ret = blk_truncate(new_blk, desc_len, PREALLOC_MODE_OFF, errp);
547
+ /* Read out options */
548
+ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
549
+ BDRV_SECTOR_SIZE);
550
+ adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
551
+ backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
552
+ hw_version = qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION);
553
+ compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
554
+ if (strcmp(hw_version, "undefined") == 0) {
555
+ g_free(hw_version);
556
+ hw_version = g_strdup("4");
557
}
558
-exit:
559
- if (new_blk) {
560
- blk_unref(new_blk);
561
+ fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
562
+ zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
563
+
564
+ if (adapter_type) {
565
+ adapter_type_enum = qapi_enum_parse(&BlockdevVmdkAdapterType_lookup,
566
+ adapter_type,
567
+ BLOCKDEV_VMDK_ADAPTER_TYPE_IDE,
568
+ &local_err);
569
+ if (local_err) {
570
+ error_propagate(errp, local_err);
571
+ ret = -EINVAL;
572
+ goto exit;
573
+ }
98
+ }
574
+ } else {
99
+#endif
575
+ adapter_type_enum = BLOCKDEV_VMDK_ADAPTER_TYPE_IDE;
100
default: {
576
}
101
r = -ENOTSUP;
577
+
102
error_setg_errno(
578
+ if (!fmt) {
579
+ /* Default format to monolithicSparse */
580
+ subformat = BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICSPARSE;
581
+ } else {
582
+ subformat = qapi_enum_parse(&BlockdevVmdkSubformat_lookup,
583
+ fmt,
584
+ BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICSPARSE,
585
+ &local_err);
586
+ if (local_err) {
587
+ error_propagate(errp, local_err);
588
+ ret = -EINVAL;
589
+ goto exit;
590
+ }
591
+ }
592
+ data = (VMDKCreateOptsData){
593
+ .prefix = prefix,
594
+ .postfix = postfix,
595
+ .path = path,
596
+ .opts = opts,
597
+ };
598
+ ret = vmdk_co_do_create(total_size, subformat, adapter_type_enum,
599
+ backing_file, hw_version, compat6, zeroed_grain,
600
+ vmdk_co_create_opts_cb, &data, errp);
601
+
602
+exit:
603
g_free(adapter_type);
604
g_free(backing_file);
605
g_free(hw_version);
606
@@ -XXX,XX +XXX,XX @@ exit:
607
g_free(ext_filename);
608
g_free(desc_filename);
609
g_free(parent_desc_line);
610
- g_string_free(ext_desc_lines, true);
611
+ return ret;
612
+}
613
+
614
+static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,
615
+ bool flat, bool split, bool compress,
616
+ bool zeroed_grain, void *opaque,
617
+ Error **errp)
618
+{
619
+ int ret;
620
+ BlockDriverState *bs;
621
+ BlockBackend *blk;
622
+ BlockdevCreateOptionsVmdk *opts = opaque;
623
+
624
+ if (idx == 0) {
625
+ bs = bdrv_open_blockdev_ref(opts->file, errp);
626
+ } else {
627
+ int i;
628
+ BlockdevRefList *list = opts->extents;
629
+ for (i = 1; i < idx; i++) {
630
+ if (!list || !list->next) {
631
+ error_setg(errp, "Extent [%d] not specified", i);
632
+ return NULL;
633
+ }
634
+ list = list->next;
635
+ }
636
+ if (!list) {
637
+ error_setg(errp, "Extent [%d] not specified", idx - 1);
638
+ return NULL;
639
+ }
640
+ bs = bdrv_open_blockdev_ref(list->value, errp);
641
+ }
642
+ if (!bs) {
643
+ return NULL;
644
+ }
645
+ blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
646
+ BLK_PERM_ALL);
647
+ if (blk_insert_bs(blk, bs, errp)) {
648
+ bdrv_unref(bs);
649
+ return NULL;
650
+ }
651
+ blk_set_allow_write_beyond_eof(blk, true);
652
+ bdrv_unref(bs);
653
+
654
+ ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
655
+ if (ret) {
656
+ blk_unref(blk);
657
+ blk = NULL;
658
+ }
659
+ return blk;
660
+}
661
+
662
+static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
663
+ Error **errp)
664
+{
665
+ int ret;
666
+ BlockdevCreateOptionsVmdk *opts;
667
+
668
+ opts = &create_options->u.vmdk;
669
+
670
+ /* Validate options */
671
+ if (!QEMU_IS_ALIGNED(opts->size, BDRV_SECTOR_SIZE)) {
672
+ error_setg(errp, "Image size must be a multiple of 512 bytes");
673
+ ret = -EINVAL;
674
+ goto out;
675
+ }
676
+
677
+ ret = vmdk_co_do_create(opts->size,
678
+ opts->subformat,
679
+ opts->adapter_type,
680
+ opts->backing_file,
681
+ opts->hwversion,
682
+ false,
683
+ opts->zeroed_grain,
684
+ vmdk_co_create_cb,
685
+ opts, errp);
686
+ return ret;
687
+
688
+out:
689
return ret;
690
}
691
692
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
693
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
694
.bdrv_close = vmdk_close,
695
.bdrv_co_create_opts = vmdk_co_create_opts,
696
+ .bdrv_co_create = vmdk_co_create,
697
.bdrv_co_flush_to_disk = vmdk_co_flush,
698
.bdrv_co_block_status = vmdk_co_block_status,
699
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
700
--
103
--
701
2.20.1
104
2.39.2
702
703
diff view generated by jsdifflib
1
Clarify that the number of extents provided in BlockdevCreateOptionsVmdk
1
From: Or Ozeri <oro@il.ibm.com>
2
must match the number of extents that will actually be used. Providing
2
3
more extents will result in an error now.
3
Starting from ceph Reef, RBD has built-in support for layered encryption,
4
4
where each ancestor image (in a cloned image setting) can be possibly
5
This requires adapting the test case to provide the right number of
5
encrypted using a unique passphrase.
6
extents.
6
7
7
A new function, rbd_encryption_load2, was added to librbd API.
8
This new function supports an array of passphrases (via "spec" structs).
9
10
This commit extends the qemu rbd driver API to use this new librbd API,
11
in order to support this new layered encryption feature.
12
13
Signed-off-by: Or Ozeri <oro@il.ibm.com>
14
Message-Id: <20230129113120.722708-4-oro@oro.sl.cloud9.ibm.com>
15
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
---
18
---
11
qapi/block-core.json | 3 ++-
19
qapi/block-core.json | 11 +++-
12
block/vmdk.c | 29 ++++++++++++++++++++++++-----
20
block/rbd.c | 153 ++++++++++++++++++++++++++++++++++++++++++-
13
tests/qemu-iotests/237 | 6 +++++-
21
2 files changed, 162 insertions(+), 2 deletions(-)
14
tests/qemu-iotests/237.out | 13 +++++++------
15
4 files changed, 38 insertions(+), 13 deletions(-)
16
22
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/qapi/block-core.json
25
--- a/qapi/block-core.json
20
+++ b/qapi/block-core.json
26
+++ b/qapi/block-core.json
21
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
22
# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For
28
##
23
# monolithicFlat, only one entry is required; for
29
# @RbdEncryptionOptions:
24
# twoGbMaxExtent* formats, the number of entries required is
30
#
25
-# calculated as extent_number = virtual_size / 2GB.
31
+# @format: Encryption format.
26
+# calculated as extent_number = virtual_size / 2GB. Providing
32
+#
27
+# more extents than will be used is an error.
33
+# @parent: Parent image encryption options (for cloned images).
28
# @subformat The subformat of the VMDK image. Default: "monolithicSparse".
34
+# Can be left unspecified if this cloned image is encrypted
29
# @backing-file The path of backing file. Default: no backing file is used.
35
+# using the same format and secret as its parent image (i.e.
30
# @adapter-type The adapter type used to fill in the descriptor. Default: ide.
36
+# not explicitly formatted) or if its parent image is not
31
diff --git a/block/vmdk.c b/block/vmdk.c
37
+# encrypted. (Since 8.0)
38
+#
39
# Since: 6.1
40
##
41
{ 'union': 'RbdEncryptionOptions',
42
- 'base': { 'format': 'RbdImageEncryptionFormat' },
43
+ 'base': { 'format': 'RbdImageEncryptionFormat',
44
+ '*parent': 'RbdEncryptionOptions' },
45
'discriminator': 'format',
46
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
47
'luks2': 'RbdEncryptionOptionsLUKS2',
48
diff --git a/block/rbd.c b/block/rbd.c
32
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
33
--- a/block/vmdk.c
50
--- a/block/rbd.c
34
+++ b/block/vmdk.c
51
+++ b/block/rbd.c
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
52
@@ -XXX,XX +XXX,XX @@ static const char rbd_luks2_header_verification[
36
{
53
'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
37
int extent_idx;
54
};
38
BlockBackend *blk = NULL;
55
39
+ BlockBackend *extent_blk;
56
+static const char rbd_layered_luks_header_verification[
40
Error *local_err = NULL;
57
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
41
char *desc = NULL;
58
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1
42
int ret = 0;
59
+};
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
60
+
61
+static const char rbd_layered_luks2_header_verification[
62
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
63
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2
64
+};
65
+
66
typedef enum {
67
RBD_AIO_READ,
68
RBD_AIO_WRITE,
69
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
70
71
return 0;
72
}
73
+
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
75
+static int qemu_rbd_encryption_load2(rbd_image_t image,
76
+ RbdEncryptionOptions *encrypt,
77
+ Error **errp)
78
+{
79
+ int r = 0;
80
+ int encrypt_count = 1;
81
+ int i;
82
+ RbdEncryptionOptions *curr_encrypt;
83
+ rbd_encryption_spec_t *specs;
84
+ rbd_encryption_luks1_format_options_t *luks_opts;
85
+ rbd_encryption_luks2_format_options_t *luks2_opts;
86
+ rbd_encryption_luks_format_options_t *luks_any_opts;
87
+
88
+ /* count encryption options */
89
+ for (curr_encrypt = encrypt->parent; curr_encrypt;
90
+ curr_encrypt = curr_encrypt->parent) {
91
+ ++encrypt_count;
92
+ }
93
+
94
+ specs = g_new0(rbd_encryption_spec_t, encrypt_count);
95
+
96
+ curr_encrypt = encrypt;
97
+ for (i = 0; i < encrypt_count; ++i) {
98
+ switch (curr_encrypt->format) {
99
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: {
100
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS1;
101
+
102
+ luks_opts = g_new0(rbd_encryption_luks1_format_options_t, 1);
103
+ specs[i].opts = luks_opts;
104
+ specs[i].opts_size = sizeof(*luks_opts);
105
+
106
+ r = qemu_rbd_convert_luks_options(
107
+ qapi_RbdEncryptionOptionsLUKS_base(
108
+ &curr_encrypt->u.luks),
109
+ (char **)&luks_opts->passphrase,
110
+ &luks_opts->passphrase_size,
111
+ errp);
112
+ break;
113
+ }
114
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
115
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS2;
116
+
117
+ luks2_opts = g_new0(rbd_encryption_luks2_format_options_t, 1);
118
+ specs[i].opts = luks2_opts;
119
+ specs[i].opts_size = sizeof(*luks2_opts);
120
+
121
+ r = qemu_rbd_convert_luks_options(
122
+ qapi_RbdEncryptionOptionsLUKS2_base(
123
+ &curr_encrypt->u.luks2),
124
+ (char **)&luks2_opts->passphrase,
125
+ &luks2_opts->passphrase_size,
126
+ errp);
127
+ break;
128
+ }
129
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
130
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS;
131
+
132
+ luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1);
133
+ specs[i].opts = luks_any_opts;
134
+ specs[i].opts_size = sizeof(*luks_any_opts);
135
+
136
+ r = qemu_rbd_convert_luks_options(
137
+ qapi_RbdEncryptionOptionsLUKSAny_base(
138
+ &curr_encrypt->u.luks_any),
139
+ (char **)&luks_any_opts->passphrase,
140
+ &luks_any_opts->passphrase_size,
141
+ errp);
142
+ break;
143
+ }
144
+ default: {
145
+ r = -ENOTSUP;
146
+ error_setg_errno(
147
+ errp, -r, "unknown image encryption format: %u",
148
+ curr_encrypt->format);
149
+ }
150
+ }
151
+
152
+ if (r < 0) {
153
+ goto exit;
154
+ }
155
+
156
+ curr_encrypt = curr_encrypt->parent;
157
+ }
158
+
159
+ r = rbd_encryption_load2(image, specs, encrypt_count);
160
+ if (r < 0) {
161
+ error_setg_errno(errp, -r, "layered encryption load fail");
162
+ goto exit;
163
+ }
164
+
165
+exit:
166
+ for (i = 0; i < encrypt_count; ++i) {
167
+ if (!specs[i].opts) {
168
+ break;
169
+ }
170
+
171
+ switch (specs[i].format) {
172
+ case RBD_ENCRYPTION_FORMAT_LUKS1: {
173
+ luks_opts = specs[i].opts;
174
+ g_free((void *)luks_opts->passphrase);
175
+ break;
176
+ }
177
+ case RBD_ENCRYPTION_FORMAT_LUKS2: {
178
+ luks2_opts = specs[i].opts;
179
+ g_free((void *)luks2_opts->passphrase);
180
+ break;
181
+ }
182
+ case RBD_ENCRYPTION_FORMAT_LUKS: {
183
+ luks_any_opts = specs[i].opts;
184
+ g_free((void *)luks_any_opts->passphrase);
185
+ break;
186
+ }
187
+ }
188
+
189
+ g_free(specs[i].opts);
190
+ }
191
+ g_free(specs);
192
+ return r;
193
+}
194
+#endif
195
#endif
196
197
/* FIXME Deprecate and remove keypairs or make it available in QMP. */
198
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
199
200
if (opts->encrypt) {
201
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
202
- r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
203
+ if (opts->encrypt->parent) {
204
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
205
+ r = qemu_rbd_encryption_load2(s->image, opts->encrypt, errp);
206
+#else
207
+ r = -ENOTSUP;
208
+ error_setg(errp, "RBD library does not support layered encryption");
209
+#endif
210
+ } else {
211
+ r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
212
+ }
213
if (r < 0) {
214
goto failed_post_open;
215
}
216
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs,
217
spec_info->u.rbd.data->encryption_format =
218
RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
219
spec_info->u.rbd.data->has_encryption_format = true;
220
+ } else if (memcmp(buf, rbd_layered_luks_header_verification,
221
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
222
+ spec_info->u.rbd.data->encryption_format =
223
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS;
224
+ spec_info->u.rbd.data->has_encryption_format = true;
225
+ } else if (memcmp(buf, rbd_layered_luks2_header_verification,
226
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
227
+ spec_info->u.rbd.data->encryption_format =
228
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
229
+ spec_info->u.rbd.data->has_encryption_format = true;
230
} else {
231
spec_info->u.rbd.data->has_encryption_format = false;
44
}
232
}
45
extent_idx = 1;
46
while (created_size < size) {
47
- BlockBackend *extent_blk;
48
int64_t cur_size = MIN(size - created_size, extent_size);
49
extent_blk = extent_fn(cur_size, extent_idx, flat, split, compress,
50
zeroed_grain, opaque, errp);
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
52
extent_idx++;
53
blk_unref(extent_blk);
54
}
55
+
56
+ /* Check whether we got excess extents */
57
+ extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain,
58
+ opaque, NULL);
59
+ if (extent_blk) {
60
+ blk_unref(extent_blk);
61
+ error_setg(errp, "List of extents contains unused extents");
62
+ ret = -EINVAL;
63
+ goto exit;
64
+ }
65
+
66
/* generate descriptor file */
67
desc = g_strdup_printf(desc_template,
68
g_random_int(),
69
@@ -XXX,XX +XXX,XX @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,
70
char *ext_filename = NULL;
71
char *rel_filename = NULL;
72
73
+ /* We're done, don't create excess extents. */
74
+ if (size == -1) {
75
+ assert(errp == NULL);
76
+ return NULL;
77
+ }
78
+
79
if (idx == 0) {
80
rel_filename = g_strdup_printf("%s%s", data->prefix, data->postfix);
81
} else if (split) {
82
@@ -XXX,XX +XXX,XX @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,
83
blk_set_allow_write_beyond_eof(blk, true);
84
bdrv_unref(bs);
85
86
- ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
87
- if (ret) {
88
- blk_unref(blk);
89
- blk = NULL;
90
+ if (size != -1) {
91
+ ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
92
+ if (ret) {
93
+ blk_unref(blk);
94
+ blk = NULL;
95
+ }
96
}
97
return blk;
98
}
99
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
100
index XXXXXXX..XXXXXXX 100755
101
--- a/tests/qemu-iotests/237
102
+++ b/tests/qemu-iotests/237
103
@@ -XXX,XX +XXX,XX @@
104
# along with this program. If not, see <http://www.gnu.org/licenses/>.
105
#
106
107
+import math
108
import iotests
109
from iotests import imgfmt
110
111
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
112
iotests.log("= %s %d =" % (subfmt, size))
113
iotests.log("")
114
115
+ num_extents = math.ceil(size / 2.0**31)
116
+ extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
117
+
118
vm.launch()
119
blockdev_create(vm, { 'driver': imgfmt,
120
'file': 'node0',
121
'size': size,
122
'subformat': subfmt,
123
- 'extents': ['ext1', 'ext2', 'ext3'] })
124
+ 'extents': extents })
125
vm.shutdown()
126
127
iotests.img_info_log(disk_path)
128
diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out
129
index XXXXXXX..XXXXXXX 100644
130
--- a/tests/qemu-iotests/237.out
131
+++ b/tests/qemu-iotests/237.out
132
@@ -XXX,XX +XXX,XX @@ Job failed: Extent [0] not specified
133
134
{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
135
{"return": {}}
136
+Job failed: List of extents contains unused extents
137
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
138
{"return": {}}
139
140
@@ -XXX,XX +XXX,XX @@ Job failed: Extent [0] not specified
141
142
= twoGbMaxExtentFlat 512 =
143
144
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
145
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
146
{"return": {}}
147
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
148
{"return": {}}
149
@@ -XXX,XX +XXX,XX @@ Format specific information:
150
151
= twoGbMaxExtentSparse 512 =
152
153
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
154
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
155
{"return": {}}
156
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
157
{"return": {}}
158
@@ -XXX,XX +XXX,XX @@ Format specific information:
159
160
= twoGbMaxExtentFlat 1073741824 =
161
162
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
163
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
164
{"return": {}}
165
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
166
{"return": {}}
167
@@ -XXX,XX +XXX,XX @@ Format specific information:
168
169
= twoGbMaxExtentSparse 1073741824 =
170
171
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
172
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
173
{"return": {}}
174
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
175
{"return": {}}
176
@@ -XXX,XX +XXX,XX @@ Format specific information:
177
178
= twoGbMaxExtentFlat 2147483648 =
179
180
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
181
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
182
{"return": {}}
183
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
184
{"return": {}}
185
@@ -XXX,XX +XXX,XX @@ Format specific information:
186
187
= twoGbMaxExtentSparse 2147483648 =
188
189
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
190
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
191
{"return": {}}
192
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
193
{"return": {}}
194
--
233
--
195
2.20.1
234
2.39.2
196
197
diff view generated by jsdifflib