1
The following changes since commit 0a301624c2f4ced3331ffd5bce85b4274fe132af:
1
The following changes since commit a51e5124a655b3dad80b36b18547cb1eca2c5eb2:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20220208' into staging (2022-02-08 11:40:08 +0000)
3
Merge tag 'pull-omnibus-111023-1' of https://gitlab.com/stsquad/qemu into staging (2023-10-11 09:43:10 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/kmwolf/qemu.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 fdb8541b2e4f6ff60f435fbb5a5e1df20c275a86:
9
for you to fetch changes up to e6e964b8b021446c8d3d1f91c0208f653e9ec92c:
10
10
11
hw/block/fdc-isa: Respect QOM properties when building AML (2022-02-11 17:37:26 +0100)
11
block: Add assertion for bdrv_graph_wrlock() (2023-10-12 16:31:33 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Fix crash in blockdev-reopen with iothreads
16
- Clean up coroutine versions of bdrv_{is_allocated,block_status}*
17
- fdc-isa: Respect QOM properties when building AML
17
- Graph locking part 5 (protect children/parent links)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
Bernhard Beschow (1):
20
Emanuele Giuseppe Esposito (1):
21
hw/block/fdc-isa: Respect QOM properties when building AML
21
block: Mark drain related functions GRAPH_RDLOCK
22
22
23
Kevin Wolf (2):
23
Kevin Wolf (21):
24
block: Lock AioContext for drain_end in blockdev-reopen
24
test-bdrv-drain: Don't call bdrv_graph_wrlock() in coroutine context
25
iotests: Test blockdev-reopen with iothreads and throttling
25
block-coroutine-wrapper: Add no_co_wrapper_bdrv_rdlock functions
26
block: Take graph rdlock in bdrv_inactivate_all()
27
block: Mark bdrv_first_blk() and bdrv_is_root_node() GRAPH_RDLOCK
28
block: Mark bdrv_parent_cb_resize() and callers GRAPH_RDLOCK
29
block: Mark bdrv_snapshot_fallback() and callers GRAPH_RDLOCK
30
block: Take graph rdlock in parts of reopen
31
block: Mark bdrv_get_xdbg_block_graph() and callers GRAPH_RDLOCK
32
block: Mark bdrv_refresh_filename() and callers GRAPH_RDLOCK
33
block: Mark bdrv_primary_child() and callers GRAPH_RDLOCK
34
block: Mark bdrv_get_parent_name() and callers GRAPH_RDLOCK
35
block: Mark bdrv_amend_options() and callers GRAPH_RDLOCK
36
qcow2: Mark qcow2_signal_corruption() and callers GRAPH_RDLOCK
37
qcow2: Mark qcow2_inactivate() and callers GRAPH_RDLOCK
38
qcow2: Mark check_constraints_on_bitmap() GRAPH_RDLOCK
39
block: Mark bdrv_op_is_blocked() and callers GRAPH_RDLOCK
40
block: Mark bdrv_apply_auto_read_only() and callers GRAPH_RDLOCK
41
block: Mark bdrv_get_specific_info() and callers GRAPH_RDLOCK
42
block: Protect bs->parents with graph_lock
43
block: Protect bs->children with graph_lock
44
block: Add assertion for bdrv_graph_wrlock()
26
45
27
blockdev.c | 11 ++++++++++-
46
Paolo Bonzini (4):
28
hw/block/fdc-isa.c | 11 +++++++----
47
block: rename the bdrv_co_block_status static function
29
tests/qemu-iotests/245 | 36 +++++++++++++++++++++++++++++++++---
48
block: complete public block status API
30
tests/qemu-iotests/245.out | 4 ++--
49
block: switch to co_wrapper for bdrv_is_allocated_*
31
4 files changed, 52 insertions(+), 10 deletions(-)
50
block: convert more bdrv_is_allocated* and bdrv_block_status* calls to coroutine versions
32
51
33
52
block/qcow2.h | 187 ++++++++++++++++------------
53
block/vhdx.h | 5 +-
54
include/block/block-common.h | 7 +-
55
include/block/block-global-state.h | 34 ++---
56
include/block/block-io.h | 71 +++++++----
57
include/block/block_int-common.h | 69 +++++-----
58
include/block/block_int-io.h | 7 +-
59
include/block/graph-lock.h | 3 +-
60
include/block/qapi.h | 23 ++--
61
include/block/snapshot.h | 24 ++--
62
include/sysemu/block-backend-global-state.h | 4 +-
63
block.c | 120 ++++++++++++------
64
block/backup.c | 1 +
65
block/block-backend.c | 9 +-
66
block/bochs.c | 2 +
67
block/cloop.c | 2 +
68
block/commit.c | 1 +
69
block/copy-before-write.c | 2 +-
70
block/copy-on-read.c | 8 +-
71
block/crypto.c | 4 +-
72
block/curl.c | 2 +
73
block/dmg.c | 2 +
74
block/export/export.c | 4 +
75
block/gluster.c | 2 +
76
block/graph-lock.c | 3 +-
77
block/io.c | 143 ++++++++++-----------
78
block/iscsi.c | 2 +
79
block/mirror.c | 10 +-
80
block/monitor/block-hmp-cmds.c | 5 +
81
block/nbd.c | 3 +-
82
block/nfs.c | 2 +-
83
block/parallels.c | 3 +
84
block/qapi-sysemu.c | 11 +-
85
block/qapi.c | 11 +-
86
block/qcow.c | 3 +
87
block/qcow2-bitmap.c | 38 +++---
88
block/qcow2-cache.c | 11 +-
89
block/qcow2-cluster.c | 62 ++++-----
90
block/qcow2-refcount.c | 80 ++++++------
91
block/qcow2.c | 77 +++++++-----
92
block/quorum.c | 4 +-
93
block/raw-format.c | 2 +
94
block/rbd.c | 4 +
95
block/replication.c | 29 +++--
96
block/snapshot.c | 54 ++++++--
97
block/stream.c | 8 +-
98
block/vdi.c | 3 +
99
block/vhdx.c | 4 +
100
block/vmdk.c | 53 +++++---
101
block/vpc.c | 3 +
102
block/vvfat.c | 20 +--
103
blockdev.c | 44 +++++++
104
blockjob.c | 1 +
105
migration/block.c | 2 +
106
migration/migration-hmp-cmds.c | 2 +
107
qemu-img.c | 16 +++
108
qemu-io-cmds.c | 3 +
109
tests/unit/test-bdrv-drain.c | 15 ++-
110
tests/unit/test-block-iothread.c | 8 ++
111
scripts/block-coroutine-wrapper.py | 10 +-
112
60 files changed, 843 insertions(+), 499 deletions(-)
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
bdrv_block_status exists as a wrapper for bdrv_block_status_above, but
4
the name of the (hypothetical) coroutine version, bdrv_co_block_status,
5
is squatted by a random static function. Rename it to
6
bdrv_co_do_block_status.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-ID: <20230904100306.156197-2-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/io.c | 21 +++++++++++----------
14
1 file changed, 11 insertions(+), 10 deletions(-)
15
16
diff --git a/block/io.c b/block/io.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/io.c
19
+++ b/block/io.c
20
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
21
* set to the host mapping and BDS corresponding to the guest offset.
22
*/
23
static int coroutine_fn GRAPH_RDLOCK
24
-bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
25
- int64_t offset, int64_t bytes,
26
- int64_t *pnum, int64_t *map, BlockDriverState **file)
27
+bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
28
+ int64_t offset, int64_t bytes,
29
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
30
{
31
int64_t total_size;
32
int64_t n; /* bytes */
33
@@ -XXX,XX +XXX,XX @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
34
35
if (ret & BDRV_BLOCK_RAW) {
36
assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
37
- ret = bdrv_co_block_status(local_file, want_zero, local_map,
38
- *pnum, pnum, &local_map, &local_file);
39
+ ret = bdrv_co_do_block_status(local_file, want_zero, local_map,
40
+ *pnum, pnum, &local_map, &local_file);
41
goto out;
42
}
43
44
@@ -XXX,XX +XXX,XX @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
45
int64_t file_pnum;
46
int ret2;
47
48
- ret2 = bdrv_co_block_status(local_file, want_zero, local_map,
49
- *pnum, &file_pnum, NULL, NULL);
50
+ ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map,
51
+ *pnum, &file_pnum, NULL, NULL);
52
if (ret2 >= 0) {
53
/* Ignore errors. This is just providing extra information, it
54
* is useful but not necessary.
55
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
56
return 0;
57
}
58
59
- ret = bdrv_co_block_status(bs, want_zero, offset, bytes, pnum, map, file);
60
+ ret = bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum,
61
+ map, file);
62
++*depth;
63
if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) {
64
return ret;
65
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
66
for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base;
67
p = bdrv_filter_or_cow_bs(p))
68
{
69
- ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map,
70
- file);
71
+ ret = bdrv_co_do_block_status(p, want_zero, offset, bytes, pnum,
72
+ map, file);
73
++*depth;
74
if (ret < 0) {
75
return ret;
76
--
77
2.41.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Include both coroutine and non-coroutine versions, the latter being
4
co_wrapper_mixed_bdrv_rdlock of the former.
5
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-ID: <20230904100306.156197-3-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block-io.h | 17 +++++++++++------
13
block/io.c | 18 +++++-------------
14
2 files changed, 16 insertions(+), 19 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 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_append(BlockDriverState *bs,
21
BdrvRequestFlags flags);
22
23
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
24
-int bdrv_block_status(BlockDriverState *bs, int64_t offset,
25
- int64_t bytes, int64_t *pnum, int64_t *map,
26
- BlockDriverState **file);
27
+
28
+int coroutine_fn GRAPH_RDLOCK
29
+bdrv_co_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
30
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
31
+int co_wrapper_mixed_bdrv_rdlock
32
+bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
33
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
34
35
int coroutine_fn GRAPH_RDLOCK
36
bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base,
37
int64_t offset, int64_t bytes, int64_t *pnum,
38
int64_t *map, BlockDriverState **file);
39
-int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
40
- int64_t offset, int64_t bytes, int64_t *pnum,
41
- int64_t *map, BlockDriverState **file);
42
+int co_wrapper_mixed_bdrv_rdlock
43
+bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
44
+ int64_t offset, int64_t bytes, int64_t *pnum,
45
+ int64_t *map, BlockDriverState **file);
46
47
int coroutine_fn GRAPH_RDLOCK
48
bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
49
diff --git a/block/io.c b/block/io.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/io.c
52
+++ b/block/io.c
53
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
54
bytes, pnum, map, file, NULL);
55
}
56
57
-int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
58
- int64_t offset, int64_t bytes, int64_t *pnum,
59
- int64_t *map, BlockDriverState **file)
60
+int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, int64_t offset,
61
+ int64_t bytes, int64_t *pnum,
62
+ int64_t *map, BlockDriverState **file)
63
{
64
IO_CODE();
65
- return bdrv_common_block_status_above(bs, base, false, true, offset, bytes,
66
- pnum, map, file, NULL);
67
-}
68
-
69
-int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
70
- int64_t *pnum, int64_t *map, BlockDriverState **file)
71
-{
72
- IO_CODE();
73
- return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
74
- offset, bytes, pnum, map, file);
75
+ return bdrv_co_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
76
+ offset, bytes, pnum, map, file);
77
}
78
79
/*
80
--
81
2.41.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-ID: <20230904100306.156197-4-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/block/block-io.h | 12 +++++----
10
block/io.c | 53 ++++++----------------------------------
11
2 files changed, 14 insertions(+), 51 deletions(-)
12
13
diff --git a/include/block/block-io.h b/include/block/block-io.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block-io.h
16
+++ b/include/block/block-io.h
17
@@ -XXX,XX +XXX,XX @@ bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
18
int coroutine_fn GRAPH_RDLOCK
19
bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
20
int64_t *pnum);
21
-int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
22
- int64_t *pnum);
23
+int co_wrapper_mixed_bdrv_rdlock
24
+bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
25
+ int64_t bytes, int64_t *pnum);
26
27
int coroutine_fn GRAPH_RDLOCK
28
bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
29
bool include_base, int64_t offset, int64_t bytes,
30
int64_t *pnum);
31
-int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
32
- bool include_base, int64_t offset, int64_t bytes,
33
- int64_t *pnum);
34
+int co_wrapper_mixed_bdrv_rdlock
35
+bdrv_is_allocated_above(BlockDriverState *bs, BlockDriverState *base,
36
+ bool include_base, int64_t offset,
37
+ int64_t bytes, int64_t *pnum);
38
39
int coroutine_fn GRAPH_RDLOCK
40
bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
41
diff --git a/block/io.c b/block/io.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/io.c
44
+++ b/block/io.c
45
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
46
return !!(ret & BDRV_BLOCK_ALLOCATED);
47
}
48
49
-int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
50
- int64_t *pnum)
51
-{
52
- int ret;
53
- int64_t dummy;
54
- IO_CODE();
55
-
56
- ret = bdrv_common_block_status_above(bs, bs, true, false, offset,
57
- bytes, pnum ? pnum : &dummy, NULL,
58
- NULL, NULL);
59
- if (ret < 0) {
60
- return ret;
61
- }
62
- return !!(ret & BDRV_BLOCK_ALLOCATED);
63
-}
64
-
65
-/* See bdrv_is_allocated_above for documentation */
66
-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
67
- BlockDriverState *base,
68
- bool include_base, int64_t offset,
69
- int64_t bytes, int64_t *pnum)
70
-{
71
- int depth;
72
- int ret;
73
- IO_CODE();
74
-
75
- ret = bdrv_co_common_block_status_above(top, base, include_base, false,
76
- offset, bytes, pnum, NULL, NULL,
77
- &depth);
78
- if (ret < 0) {
79
- return ret;
80
- }
81
-
82
- if (ret & BDRV_BLOCK_ALLOCATED) {
83
- return depth;
84
- }
85
- return 0;
86
-}
87
-
88
/*
89
* Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP]
90
*
91
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
92
* words, the result is not necessarily the maximum possible range);
93
* but 'pnum' will only be 0 when end of file is reached.
94
*/
95
-int bdrv_is_allocated_above(BlockDriverState *top,
96
- BlockDriverState *base,
97
- bool include_base, int64_t offset,
98
- int64_t bytes, int64_t *pnum)
99
+int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *bs,
100
+ BlockDriverState *base,
101
+ bool include_base, int64_t offset,
102
+ int64_t bytes, int64_t *pnum)
103
{
104
int depth;
105
int ret;
106
IO_CODE();
107
108
- ret = bdrv_common_block_status_above(top, base, include_base, false,
109
- offset, bytes, pnum, NULL, NULL,
110
- &depth);
111
+ ret = bdrv_co_common_block_status_above(bs, base, include_base, false,
112
+ offset, bytes, pnum, NULL, NULL,
113
+ &depth);
114
if (ret < 0) {
115
return ret;
116
}
117
--
118
2.41.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-ID: <20230904100306.156197-5-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/copy-before-write.c | 2 +-
10
block/copy-on-read.c | 8 ++++----
11
block/io.c | 6 +++---
12
block/mirror.c | 10 +++++-----
13
block/qcow2.c | 5 +++--
14
block/replication.c | 8 ++++----
15
block/stream.c | 8 ++++----
16
block/vvfat.c | 18 +++++++++---------
17
8 files changed, 33 insertions(+), 32 deletions(-)
18
19
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/copy-before-write.c
22
+++ b/block/copy-before-write.c
23
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
24
return -EACCES;
25
}
26
27
- ret = bdrv_block_status(child->bs, offset, cur_bytes, pnum, map, file);
28
+ ret = bdrv_co_block_status(child->bs, offset, cur_bytes, pnum, map, file);
29
if (child == s->target) {
30
/*
31
* We refer to s->target only for areas that we've written to it.
32
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/copy-on-read.c
35
+++ b/block/copy-on-read.c
36
@@ -XXX,XX +XXX,XX @@ cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
37
local_flags = flags;
38
39
/* In case of failure, try to copy-on-read anyway */
40
- ret = bdrv_is_allocated(bs->file->bs, offset, bytes, &n);
41
+ ret = bdrv_co_is_allocated(bs->file->bs, offset, bytes, &n);
42
if (ret <= 0) {
43
- ret = bdrv_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
44
- state->bottom_bs, true, offset,
45
- n, &n);
46
+ ret = bdrv_co_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
47
+ state->bottom_bs, true, offset,
48
+ n, &n);
49
if (ret > 0 || ret < 0) {
50
local_flags |= BDRV_REQ_COPY_ON_READ;
51
}
52
diff --git a/block/io.c b/block/io.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/io.c
55
+++ b/block/io.c
56
@@ -XXX,XX +XXX,XX @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
57
ret = 1; /* "already allocated", so nothing will be copied */
58
pnum = MIN(align_bytes, max_transfer);
59
} else {
60
- ret = bdrv_is_allocated(bs, align_offset,
61
- MIN(align_bytes, max_transfer), &pnum);
62
+ ret = bdrv_co_is_allocated(bs, align_offset,
63
+ MIN(align_bytes, max_transfer), &pnum);
64
if (ret < 0) {
65
/*
66
* Safe to treat errors in querying allocation as if
67
@@ -XXX,XX +XXX,XX @@ bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
68
/* The flag BDRV_REQ_COPY_ON_READ has reached its addressee */
69
flags &= ~BDRV_REQ_COPY_ON_READ;
70
71
- ret = bdrv_is_allocated(bs, offset, bytes, &pnum);
72
+ ret = bdrv_co_is_allocated(bs, offset, bytes, &pnum);
73
if (ret < 0) {
74
goto out;
75
}
76
diff --git a/block/mirror.c b/block/mirror.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/mirror.c
79
+++ b/block/mirror.c
80
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
81
82
assert(!(offset % s->granularity));
83
WITH_GRAPH_RDLOCK_GUARD() {
84
- ret = bdrv_block_status_above(source, NULL, offset,
85
- nb_chunks * s->granularity,
86
- &io_bytes, NULL, NULL);
87
+ ret = bdrv_co_block_status_above(source, NULL, offset,
88
+ nb_chunks * s->granularity,
89
+ &io_bytes, NULL, NULL);
90
}
91
if (ret < 0) {
92
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
94
}
95
96
WITH_GRAPH_RDLOCK_GUARD() {
97
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
98
- bytes, &count);
99
+ ret = bdrv_co_is_allocated_above(bs, s->base_overlay, true, offset,
100
+ bytes, &count);
101
}
102
if (ret < 0) {
103
return ret;
104
diff --git a/block/qcow2.c b/block/qcow2.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/block/qcow2.c
107
+++ b/block/qcow2.c
108
@@ -XXX,XX +XXX,XX @@ finish:
109
}
110
111
112
-static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
113
+static bool coroutine_fn GRAPH_RDLOCK
114
+is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
115
{
116
int64_t nr;
117
int res;
118
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
119
* backing file. So, we need a loop.
120
*/
121
do {
122
- res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
123
+ res = bdrv_co_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
124
offset += nr;
125
bytes -= nr;
126
} while (res >= 0 && (res & BDRV_BLOCK_ZERO) && nr && bytes);
127
diff --git a/block/replication.c b/block/replication.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/block/replication.c
130
+++ b/block/replication.c
131
@@ -XXX,XX +XXX,XX @@ replication_co_writev(BlockDriverState *bs, int64_t sector_num,
132
while (remaining_sectors > 0) {
133
int64_t count;
134
135
- ret = bdrv_is_allocated_above(top->bs, base->bs, false,
136
- sector_num * BDRV_SECTOR_SIZE,
137
- remaining_sectors * BDRV_SECTOR_SIZE,
138
- &count);
139
+ ret = bdrv_co_is_allocated_above(top->bs, base->bs, false,
140
+ sector_num * BDRV_SECTOR_SIZE,
141
+ remaining_sectors * BDRV_SECTOR_SIZE,
142
+ &count);
143
if (ret < 0) {
144
goto out1;
145
}
146
diff --git a/block/stream.c b/block/stream.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/stream.c
149
+++ b/block/stream.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
151
copy = false;
152
153
WITH_GRAPH_RDLOCK_GUARD() {
154
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
155
+ ret = bdrv_co_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
156
if (ret == 1) {
157
/* Allocated in the top, no need to copy. */
158
} else if (ret >= 0) {
159
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
160
* Copy if allocated in the intermediate images. Limit to the
161
* known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).
162
*/
163
- ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
164
- s->base_overlay, true,
165
- offset, n, &n);
166
+ ret = bdrv_co_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
167
+ s->base_overlay, true,
168
+ offset, n, &n);
169
/* Finish early if end of backing file has been reached */
170
if (ret == 0 && n == 0) {
171
n = len - offset;
172
diff --git a/block/vvfat.c b/block/vvfat.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vvfat.c
175
+++ b/block/vvfat.c
176
@@ -XXX,XX +XXX,XX @@ vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sector
177
if (s->qcow) {
178
int64_t n;
179
int ret;
180
- ret = bdrv_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
181
- (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
182
+ ret = bdrv_co_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
183
+ (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
184
if (ret < 0) {
185
return ret;
186
}
187
@@ -XXX,XX +XXX,XX @@ cluster_was_modified(BDRVVVFATState *s, uint32_t cluster_num)
188
}
189
190
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
191
- was_modified = bdrv_is_allocated(s->qcow->bs,
192
- (cluster2sector(s, cluster_num) +
193
- i) * BDRV_SECTOR_SIZE,
194
- BDRV_SECTOR_SIZE, NULL);
195
+ was_modified = bdrv_co_is_allocated(s->qcow->bs,
196
+ (cluster2sector(s, cluster_num) +
197
+ i) * BDRV_SECTOR_SIZE,
198
+ BDRV_SECTOR_SIZE, NULL);
199
}
200
201
/*
202
@@ -XXX,XX +XXX,XX @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch
203
for (i = 0; i < s->sectors_per_cluster; i++) {
204
int res;
205
206
- res = bdrv_is_allocated(s->qcow->bs,
207
- (offs + i) * BDRV_SECTOR_SIZE,
208
- BDRV_SECTOR_SIZE, NULL);
209
+ res = bdrv_co_is_allocated(s->qcow->bs,
210
+ (offs + i) * BDRV_SECTOR_SIZE,
211
+ BDRV_SECTOR_SIZE, NULL);
212
if (res < 0) {
213
return -1;
214
}
215
--
216
2.41.0
diff view generated by jsdifflib
New patch
1
AIO callbacks are effectively coroutine_mixed_fn. If AIO requests don't
2
return immediately, their callback is called from the request coroutine.
3
This means that in AIO callbacks, we can't call no_coroutine_fns such as
4
bdrv_graph_wrlock(). Unfortunately test-bdrv-drain does so.
1
5
6
Change the test to use a BH to drop out of coroutine context, and add
7
coroutine_mixed_fn and no_coroutine_fn markers to clarify the context
8
each function runs in.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-ID: <20230929145157.45443-2-kwolf@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
tests/unit/test-bdrv-drain.c | 7 ++++---
16
1 file changed, 4 insertions(+), 3 deletions(-)
17
18
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/unit/test-bdrv-drain.c
21
+++ b/tests/unit/test-bdrv-drain.c
22
@@ -XXX,XX +XXX,XX @@ struct detach_by_parent_data {
23
};
24
static struct detach_by_parent_data detach_by_parent_data;
25
26
-static void detach_indirect_bh(void *opaque)
27
+static void no_coroutine_fn detach_indirect_bh(void *opaque)
28
{
29
struct detach_by_parent_data *data = opaque;
30
31
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
32
bdrv_graph_wrunlock();
33
}
34
35
-static void detach_by_parent_aio_cb(void *opaque, int ret)
36
+static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
37
{
38
struct detach_by_parent_data *data = &detach_by_parent_data;
39
40
g_assert_cmpint(ret, ==, 0);
41
if (data->by_parent_cb) {
42
bdrv_inc_in_flight(data->child_b->bs);
43
- detach_indirect_bh(data);
44
+ aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
45
+ detach_indirect_bh, &detach_by_parent_data);
46
}
47
}
48
49
--
50
2.41.0
diff view generated by jsdifflib
New patch
1
Add a new wrapper type for GRAPH_RDLOCK functions that should be called
2
from coroutine context.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-ID: <20230929145157.45443-3-kwolf@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/block/block-common.h | 7 +++++--
10
scripts/block-coroutine-wrapper.py | 10 +++++++---
11
2 files changed, 12 insertions(+), 5 deletions(-)
12
13
diff --git a/include/block/block-common.h b/include/block/block-common.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block-common.h
16
+++ b/include/block/block-common.h
17
@@ -XXX,XX +XXX,XX @@
18
* function. The coroutine yields after scheduling the BH and is reentered when
19
* the wrapped function returns.
20
*
21
- * A no_co_wrapper_bdrv_wrlock function is a no_co_wrapper function that
22
- * automatically takes the graph wrlock when calling the wrapped function.
23
+ * A no_co_wrapper_bdrv_rdlock function is a no_co_wrapper function that
24
+ * automatically takes the graph rdlock when calling the wrapped function. In
25
+ * the same way, no_co_wrapper_bdrv_wrlock functions automatically take the
26
+ * graph wrlock.
27
*
28
* If the first parameter of the function is a BlockDriverState, BdrvChild or
29
* BlockBackend pointer, the AioContext lock for it is taken in the wrapper.
30
*/
31
#define no_co_wrapper
32
+#define no_co_wrapper_bdrv_rdlock
33
#define no_co_wrapper_bdrv_wrlock
34
35
#include "block/blockjob.h"
36
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
37
index XXXXXXX..XXXXXXX 100644
38
--- a/scripts/block-coroutine-wrapper.py
39
+++ b/scripts/block-coroutine-wrapper.py
40
@@ -XXX,XX +XXX,XX @@ def __init__(self, wrapper_type: str, return_type: str, name: str,
41
raise ValueError(f"Invalid no_co function name: {self.name}")
42
if not self.create_only_co:
43
raise ValueError(f"no_co function can't be mixed: {self.name}")
44
- if self.graph_rdlock:
45
- raise ValueError(f"no_co function can't be rdlock: {self.name}")
46
+ if self.graph_rdlock and self.graph_wrlock:
47
+ raise ValueError("function can't be both rdlock and wrlock: "
48
+ f"{self.name}")
49
self.target_name = f'{subsystem}_{subname}'
50
51
self.ctx = self.gen_ctx()
52
@@ -XXX,XX +XXX,XX @@ def gen_no_co_wrapper(func: FuncDecl) -> str:
53
54
graph_lock=''
55
graph_unlock=''
56
- if func.graph_wrlock:
57
+ if func.graph_rdlock:
58
+ graph_lock=' bdrv_graph_rdlock_main_loop();'
59
+ graph_unlock=' bdrv_graph_rdunlock_main_loop();'
60
+ elif func.graph_wrlock:
61
graph_lock=' bdrv_graph_wrlock(NULL);'
62
graph_unlock=' bdrv_graph_wrunlock();'
63
64
--
65
2.41.0
diff view generated by jsdifflib
New patch
1
The function reads the parents list, so it needs to hold the graph lock.
1
2
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Message-ID: <20230929145157.45443-4-kwolf@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
block.c | 7 ++++---
9
1 file changed, 4 insertions(+), 3 deletions(-)
10
11
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
14
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
16
}
17
}
18
19
-static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
20
+static bool GRAPH_RDLOCK
21
+bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
22
{
23
BdrvChild *parent;
24
GLOBAL_STATE_CODE();
25
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
26
return false;
27
}
28
29
-static int bdrv_inactivate_recurse(BlockDriverState *bs)
30
+static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs)
31
{
32
BdrvChild *child, *parent;
33
int ret;
34
uint64_t cumulative_perms, cumulative_shared_perms;
35
36
GLOBAL_STATE_CODE();
37
- GRAPH_RDLOCK_GUARD_MAINLOOP();
38
39
if (!bs->drv) {
40
return -ENOMEDIUM;
41
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
42
GSList *aio_ctxs = NULL, *ctx;
43
44
GLOBAL_STATE_CODE();
45
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
46
47
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
48
AioContext *aio_context = bdrv_get_aio_context(bs);
49
--
50
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_first_blk() and bdrv_is_root_node() need to hold a reader lock
3
for the graph. These functions are the only functions in block-backend.c
4
that access the parent list of a node.
1
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-ID: <20230929145157.45443-5-kwolf@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 9 +++++----
12
include/sysemu/block-backend-global-state.h | 4 ++--
13
block.c | 1 +
14
block/block-backend.c | 6 +++++-
15
block/export/export.c | 4 ++++
16
block/io.c | 1 +
17
block/monitor/block-hmp-cmds.c | 2 ++
18
block/qapi-sysemu.c | 2 ++
19
block/replication.c | 10 ++++++++--
20
block/snapshot.c | 15 +++++++++++----
21
blockdev.c | 5 +++++
22
migration/block.c | 2 ++
23
migration/migration-hmp-cmds.c | 2 ++
24
tests/unit/test-block-iothread.c | 3 +++
25
14 files changed, 53 insertions(+), 13 deletions(-)
26
27
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block-global-state.h
30
+++ b/include/block/block-global-state.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState * GRAPH_RDLOCK
32
check_to_replace_node(BlockDriverState *parent_bs, const char *node_name,
33
Error **errp);
34
35
-int no_coroutine_fn bdrv_activate(BlockDriverState *bs, Error **errp);
36
+int no_coroutine_fn GRAPH_RDLOCK
37
+bdrv_activate(BlockDriverState *bs, Error **errp);
38
39
-int coroutine_fn no_co_wrapper
40
+int coroutine_fn no_co_wrapper_bdrv_rdlock
41
bdrv_co_activate(BlockDriverState *bs, Error **errp);
42
43
void bdrv_activate_all(Error **errp);
44
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvNextIterator {
45
BlockDriverState *bs;
46
} BdrvNextIterator;
47
48
-BlockDriverState *bdrv_first(BdrvNextIterator *it);
49
-BlockDriverState *bdrv_next(BdrvNextIterator *it);
50
+BlockDriverState * GRAPH_RDLOCK bdrv_first(BdrvNextIterator *it);
51
+BlockDriverState * GRAPH_RDLOCK bdrv_next(BdrvNextIterator *it);
52
void bdrv_next_cleanup(BdrvNextIterator *it);
53
54
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
55
diff --git a/include/sysemu/block-backend-global-state.h b/include/sysemu/block-backend-global-state.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/sysemu/block-backend-global-state.h
58
+++ b/include/sysemu/block-backend-global-state.h
59
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public);
60
void blk_remove_bs(BlockBackend *blk);
61
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp);
62
int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp);
63
-bool bdrv_has_blk(BlockDriverState *bs);
64
-bool bdrv_is_root_node(BlockDriverState *bs);
65
+bool GRAPH_RDLOCK bdrv_has_blk(BlockDriverState *bs);
66
+bool GRAPH_RDLOCK bdrv_is_root_node(BlockDriverState *bs);
67
int GRAPH_UNLOCKED blk_set_perm(BlockBackend *blk, uint64_t perm,
68
uint64_t shared_perm, Error **errp);
69
void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm);
70
diff --git a/block.c b/block.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block.c
73
+++ b/block.c
74
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
75
BdrvNextIterator it;
76
77
GLOBAL_STATE_CODE();
78
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
79
80
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
81
AioContext *aio_context = bdrv_get_aio_context(bs);
82
diff --git a/block/block-backend.c b/block/block-backend.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/block/block-backend.c
85
+++ b/block/block-backend.c
86
@@ -XXX,XX +XXX,XX @@ BlockDriverState *blk_bs(BlockBackend *blk)
87
return blk->root ? blk->root->bs : NULL;
88
}
89
90
-static BlockBackend *bdrv_first_blk(BlockDriverState *bs)
91
+static BlockBackend * GRAPH_RDLOCK bdrv_first_blk(BlockDriverState *bs)
92
{
93
BdrvChild *child;
94
95
GLOBAL_STATE_CODE();
96
+ assert_bdrv_graph_readable();
97
98
QLIST_FOREACH(child, &bs->parents, next_parent) {
99
if (child->klass == &child_root) {
100
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_root_node(BlockDriverState *bs)
101
BdrvChild *c;
102
103
GLOBAL_STATE_CODE();
104
+ assert_bdrv_graph_readable();
105
+
106
QLIST_FOREACH(c, &bs->parents, next_parent) {
107
if (c->klass != &child_root) {
108
return false;
109
@@ -XXX,XX +XXX,XX @@ void blk_activate(BlockBackend *blk, Error **errp)
110
if (qemu_in_coroutine()) {
111
bdrv_co_activate(bs, errp);
112
} else {
113
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
114
bdrv_activate(bs, errp);
115
}
116
}
117
diff --git a/block/export/export.c b/block/export/export.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/export/export.c
120
+++ b/block/export/export.c
121
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
122
uint64_t perm;
123
int ret;
124
125
+ GLOBAL_STATE_CODE();
126
+
127
if (!id_wellformed(export->id)) {
128
error_setg(errp, "Invalid block export id");
129
return NULL;
130
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
131
* access since the export could be available before migration handover.
132
* ctx was acquired in the caller.
133
*/
134
+ bdrv_graph_rdlock_main_loop();
135
bdrv_activate(bs, NULL);
136
+ bdrv_graph_rdunlock_main_loop();
137
138
perm = BLK_PERM_CONSISTENT_READ;
139
if (export->writable) {
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 @@ int bdrv_flush_all(void)
145
int result = 0;
146
147
GLOBAL_STATE_CODE();
148
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
149
150
/*
151
* bdrv queue is managed by record/replay,
152
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/monitor/block-hmp-cmds.c
155
+++ b/block/monitor/block-hmp-cmds.c
156
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
157
SnapshotEntry *snapshot_entry;
158
Error *err = NULL;
159
160
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
161
+
162
bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, &err);
163
if (!bs) {
164
error_report_err(err);
165
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qapi-sysemu.c
168
+++ b/block/qapi-sysemu.c
169
@@ -XXX,XX +XXX,XX @@ static void blockdev_insert_medium(const char *device, const char *id,
170
BlockBackend *blk;
171
BlockDriverState *bs;
172
173
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
174
+
175
blk = qmp_get_blk(device, id, errp);
176
if (!blk) {
177
return;
178
diff --git a/block/replication.c b/block/replication.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/replication.c
181
+++ b/block/replication.c
182
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
183
Error *local_err = NULL;
184
BackupPerf perf = { .use_copy_range = true, .max_workers = 1 };
185
186
+ GLOBAL_STATE_CODE();
187
+
188
aio_context = bdrv_get_aio_context(bs);
189
aio_context_acquire(aio_context);
190
s = bs->opaque;
191
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
192
return;
193
}
194
195
+ bdrv_graph_rdlock_main_loop();
196
secondary_disk = hidden_disk->bs->backing;
197
if (!secondary_disk->bs || !bdrv_has_blk(secondary_disk->bs)) {
198
error_setg(errp, "The secondary disk doesn't have block backend");
199
+ bdrv_graph_rdunlock_main_loop();
200
aio_context_release(aio_context);
201
return;
202
}
203
+ bdrv_graph_rdunlock_main_loop();
204
205
/* verify the length */
206
active_length = bdrv_getlength(active_disk->bs);
207
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
208
return;
209
}
210
211
- bdrv_graph_wrunlock();
212
-
213
/* start backup job now */
214
error_setg(&s->blocker,
215
"Block device is in use by internal backup job");
216
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
217
if (!top_bs || !bdrv_is_root_node(top_bs) ||
218
!check_top_bs(top_bs, bs)) {
219
error_setg(errp, "No top_bs or it is invalid");
220
+ bdrv_graph_wrunlock();
221
reopen_backing_file(bs, false, NULL);
222
aio_context_release(aio_context);
223
return;
224
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
225
bdrv_op_block_all(top_bs, s->blocker);
226
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
227
228
+ bdrv_graph_wrunlock();
229
+
230
s->backup_job = backup_job_create(
231
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
232
0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL,
233
diff --git a/block/snapshot.c b/block/snapshot.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/block/snapshot.c
236
+++ b/block/snapshot.c
237
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
238
}
239
240
241
-static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
242
- GList **all_bdrvs,
243
- Error **errp)
244
+static int GRAPH_RDLOCK
245
+bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
246
+ GList **all_bdrvs, Error **errp)
247
{
248
g_autoptr(GList) bdrvs = NULL;
249
250
@@ -XXX,XX +XXX,XX @@ static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
251
}
252
253
254
-static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
255
+static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
256
{
257
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
258
return false;
259
@@ -XXX,XX +XXX,XX @@ bool bdrv_all_can_snapshot(bool has_devices, strList *devices,
260
GList *iterbdrvs;
261
262
GLOBAL_STATE_CODE();
263
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
264
265
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
266
return false;
267
@@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name,
268
GList *iterbdrvs;
269
270
GLOBAL_STATE_CODE();
271
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
272
273
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
274
return -1;
275
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
276
GList *iterbdrvs;
277
278
GLOBAL_STATE_CODE();
279
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
280
281
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
282
return -1;
283
@@ -XXX,XX +XXX,XX @@ int bdrv_all_has_snapshot(const char *name,
284
GList *iterbdrvs;
285
286
GLOBAL_STATE_CODE();
287
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
288
289
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
290
return -1;
291
@@ -XXX,XX +XXX,XX @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
292
{
293
g_autoptr(GList) bdrvs = NULL;
294
GList *iterbdrvs;
295
+
296
GLOBAL_STATE_CODE();
297
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
298
299
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
300
return -1;
301
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_all_find_vmstate_bs(const char *vmstate_bs,
302
GList *iterbdrvs;
303
304
GLOBAL_STATE_CODE();
305
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
306
307
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
308
return NULL;
309
diff --git a/blockdev.c b/blockdev.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/blockdev.c
312
+++ b/blockdev.c
313
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
314
BlockDriverState *bs;
315
AioContext *aio_context;
316
317
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
318
+
319
bs = bdrv_lookup_bs(name, name, errp);
320
if (bs == NULL) {
321
return NULL;
322
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_del(const char *node_name, Error **errp)
323
BlockDriverState *bs;
324
325
GLOBAL_STATE_CODE();
326
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
327
328
bs = bdrv_find_node(node_name);
329
if (!bs) {
330
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
331
AioContext *new_context;
332
BlockDriverState *bs;
333
334
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
335
+
336
bs = bdrv_find_node(node_name);
337
if (!bs) {
338
error_setg(errp, "Failed to find node with node-name='%s'", node_name);
339
diff --git a/migration/block.c b/migration/block.c
340
index XXXXXXX..XXXXXXX 100644
341
--- a/migration/block.c
342
+++ b/migration/block.c
343
@@ -XXX,XX +XXX,XX @@ static int init_blk_migration(QEMUFile *f)
344
Error *local_err = NULL;
345
int ret;
346
347
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
348
+
349
block_mig_state.submitted = 0;
350
block_mig_state.read_done = 0;
351
block_mig_state.transferred = 0;
352
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
353
index XXXXXXX..XXXXXXX 100644
354
--- a/migration/migration-hmp-cmds.c
355
+++ b/migration/migration-hmp-cmds.c
356
@@ -XXX,XX +XXX,XX @@ static void vm_completion(ReadLineState *rs, const char *str)
357
BlockDriverState *bs;
358
BdrvNextIterator it;
359
360
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
361
+
362
len = strlen(str);
363
readline_set_completion_index(rs, len);
364
365
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
366
index XXXXXXX..XXXXXXX 100644
367
--- a/tests/unit/test-block-iothread.c
368
+++ b/tests/unit/test-block-iothread.c
369
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_check(BdrvChild *c)
370
371
static void test_sync_op_activate(BdrvChild *c)
372
{
373
+ GLOBAL_STATE_CODE();
374
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
375
+
376
/* Early success: Image is not inactive */
377
bdrv_activate(c->bs, NULL);
378
}
379
--
380
2.41.0
diff view generated by jsdifflib
New patch
1
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
3
Draining recursively traverses the graph, therefore we need to make sure
4
that also such accesses to the graph are protected by the graph rdlock.
5
6
There are 3 different drain callers to consider:
7
1. drain in the main loop: no issue at all, rdlock is nop.
8
2. drain in an iothread: rdlock only works in main loop or coroutines,
9
so disallow it.
10
3. drain in a coroutine (regardless of AioContext): the drain mechanism
11
takes care of scheduling a BH in the bs->aio_context that will
12
then take care of perform the actual draining. This is wrong,
13
because as pointed in (2) if bs->aio_context is an iothread then
14
rdlock won't work. Therefore change bdrv_co_yield_to_drain to
15
schedule the BH in the main loop.
16
17
Caller (2) also implies that we need to modify test-bdrv-drain.c to
18
disallow draining in the iothreads.
19
20
For some places, we know that they will hold the lock, but we don't have
21
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
22
with a FIXME comment. These places will be removed once everything is
23
properly annotated.
24
25
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Message-ID: <20230929145157.45443-6-kwolf@redhat.com>
28
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
---
31
include/block/block-io.h | 23 ++++++++++++++++++-----
32
include/block/block_int-common.h | 6 +++---
33
block.c | 6 +++---
34
block/io.c | 32 ++++++++++++++++++++++++++++----
35
tests/unit/test-bdrv-drain.c | 4 ++--
36
5 files changed, 54 insertions(+), 17 deletions(-)
37
38
diff --git a/include/block/block-io.h b/include/block/block-io.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block-io.h
41
+++ b/include/block/block-io.h
42
@@ -XXX,XX +XXX,XX @@ bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
43
*
44
* Begin a quiesced section for the parent of @c.
45
*/
46
-void bdrv_parent_drained_begin_single(BdrvChild *c);
47
+void GRAPH_RDLOCK bdrv_parent_drained_begin_single(BdrvChild *c);
48
49
/**
50
* bdrv_parent_drained_poll_single:
51
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c);
52
* Returns true if there is any pending activity to cease before @c can be
53
* called quiesced, false otherwise.
54
*/
55
-bool bdrv_parent_drained_poll_single(BdrvChild *c);
56
+bool GRAPH_RDLOCK bdrv_parent_drained_poll_single(BdrvChild *c);
57
58
/**
59
* bdrv_parent_drained_end_single:
60
*
61
* End a quiesced section for the parent of @c.
62
*/
63
-void bdrv_parent_drained_end_single(BdrvChild *c);
64
+void GRAPH_RDLOCK bdrv_parent_drained_end_single(BdrvChild *c);
65
66
/**
67
* bdrv_drain_poll:
68
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c);
69
*
70
* This is part of bdrv_drained_begin.
71
*/
72
-bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
73
- bool ignore_bds_parents);
74
+bool GRAPH_RDLOCK
75
+bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
76
+ bool ignore_bds_parents);
77
78
/**
79
* bdrv_drained_begin:
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
81
* Begin a quiesced section for exclusive access to the BDS, by disabling
82
* external request sources including NBD server, block jobs, and device model.
83
*
84
+ * This function can only be invoked by the main loop or a coroutine
85
+ * (regardless of the AioContext where it is running).
86
+ * If the coroutine is running in an Iothread AioContext, this function will
87
+ * just schedule a BH to run in the main loop.
88
+ * However, it cannot be directly called by an Iothread.
89
+ *
90
* This function can be recursive.
91
*/
92
void bdrv_drained_begin(BlockDriverState *bs);
93
@@ -XXX,XX +XXX,XX @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, BdrvChild *parent);
94
* bdrv_drained_end:
95
*
96
* End a quiescent section started by bdrv_drained_begin().
97
+ *
98
+ * This function can only be invoked by the main loop or a coroutine
99
+ * (regardless of the AioContext where it is running).
100
+ * If the coroutine is running in an Iothread AioContext, this function will
101
+ * just schedule a BH to run in the main loop.
102
+ * However, it cannot be directly called by an Iothread.
103
*/
104
void bdrv_drained_end(BlockDriverState *bs);
105
106
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
107
index XXXXXXX..XXXXXXX 100644
108
--- a/include/block/block_int-common.h
109
+++ b/include/block/block_int-common.h
110
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
111
* Note that this can be nested. If drained_begin() was called twice, new
112
* I/O is allowed only after drained_end() was called twice, too.
113
*/
114
- void (*drained_begin)(BdrvChild *child);
115
- void (*drained_end)(BdrvChild *child);
116
+ void GRAPH_RDLOCK_PTR (*drained_begin)(BdrvChild *child);
117
+ void GRAPH_RDLOCK_PTR (*drained_end)(BdrvChild *child);
118
119
/*
120
* Returns whether the parent has pending requests for the child. This
121
* callback is polled after .drained_begin() has been called until all
122
* activity on the child has stopped.
123
*/
124
- bool (*drained_poll)(BdrvChild *child);
125
+ bool GRAPH_RDLOCK_PTR (*drained_poll)(BdrvChild *child);
126
127
/*
128
* Notifies the parent that the filename of its child has changed (e.g.
129
diff --git a/block.c b/block.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block.c
132
+++ b/block.c
133
@@ -XXX,XX +XXX,XX @@ static char *bdrv_child_get_parent_desc(BdrvChild *c)
134
return g_strdup_printf("node '%s'", bdrv_get_node_name(parent));
135
}
136
137
-static void bdrv_child_cb_drained_begin(BdrvChild *child)
138
+static void GRAPH_RDLOCK bdrv_child_cb_drained_begin(BdrvChild *child)
139
{
140
BlockDriverState *bs = child->opaque;
141
bdrv_do_drained_begin_quiesce(bs, NULL);
142
}
143
144
-static bool bdrv_child_cb_drained_poll(BdrvChild *child)
145
+static bool GRAPH_RDLOCK bdrv_child_cb_drained_poll(BdrvChild *child)
146
{
147
BlockDriverState *bs = child->opaque;
148
return bdrv_drain_poll(bs, NULL, false);
149
}
150
151
-static void bdrv_child_cb_drained_end(BdrvChild *child)
152
+static void GRAPH_RDLOCK bdrv_child_cb_drained_end(BdrvChild *child)
153
{
154
BlockDriverState *bs = child->opaque;
155
bdrv_drained_end(bs);
156
diff --git a/block/io.c b/block/io.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/io.c
159
+++ b/block/io.c
160
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs);
161
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
162
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
163
164
-static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
165
+static void GRAPH_RDLOCK
166
+bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
167
{
168
BdrvChild *c, *next;
169
+ IO_OR_GS_CODE();
170
+ assert_bdrv_graph_readable();
171
172
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
173
if (c == ignore) {
174
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c)
175
}
176
}
177
178
-static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
179
+static void GRAPH_RDLOCK
180
+bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
181
{
182
BdrvChild *c;
183
+ IO_OR_GS_CODE();
184
+ assert_bdrv_graph_readable();
185
186
QLIST_FOREACH(c, &bs->parents, next_parent) {
187
if (c == ignore) {
188
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
189
190
bool bdrv_parent_drained_poll_single(BdrvChild *c)
191
{
192
+ IO_OR_GS_CODE();
193
+
194
if (c->klass->drained_poll) {
195
return c->klass->drained_poll(c);
196
}
197
return false;
198
}
199
200
-static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
201
- bool ignore_bds_parents)
202
+static bool GRAPH_RDLOCK
203
+bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
204
+ bool ignore_bds_parents)
205
{
206
BdrvChild *c, *next;
207
bool busy = false;
208
+ IO_OR_GS_CODE();
209
+ assert_bdrv_graph_readable();
210
211
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
212
if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
213
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c)
214
c->quiesced_parent = true;
215
216
if (c->klass->drained_begin) {
217
+ /* called with rdlock taken, but it doesn't really need it. */
218
c->klass->drained_begin(c);
219
}
220
}
221
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
222
static bool bdrv_drain_poll_top_level(BlockDriverState *bs,
223
BdrvChild *ignore_parent)
224
{
225
+ GLOBAL_STATE_CODE();
226
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
227
+
228
return bdrv_drain_poll(bs, ignore_parent, false);
229
}
230
231
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent,
232
233
/* Stop things in parent-to-child order */
234
if (qatomic_fetch_inc(&bs->quiesce_counter) == 0) {
235
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
236
bdrv_parent_drained_begin(bs, parent);
237
if (bs->drv && bs->drv->bdrv_drain_begin) {
238
bs->drv->bdrv_drain_begin(bs);
239
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
240
bdrv_co_yield_to_drain(bs, false, parent, false);
241
return;
242
}
243
+
244
+ /* At this point, we should be always running in the main loop. */
245
+ GLOBAL_STATE_CODE();
246
assert(bs->quiesce_counter > 0);
247
GLOBAL_STATE_CODE();
248
249
/* Re-enable things in child-to-parent order */
250
old_quiesce_counter = qatomic_fetch_dec(&bs->quiesce_counter);
251
if (old_quiesce_counter == 1) {
252
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
253
if (bs->drv && bs->drv->bdrv_drain_end) {
254
bs->drv->bdrv_drain_end(bs);
255
}
256
@@ -XXX,XX +XXX,XX @@ void bdrv_drain(BlockDriverState *bs)
257
static void bdrv_drain_assert_idle(BlockDriverState *bs)
258
{
259
BdrvChild *child, *next;
260
+ GLOBAL_STATE_CODE();
261
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
262
263
assert(qatomic_read(&bs->in_flight) == 0);
264
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
265
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_all_poll(void)
266
{
267
BlockDriverState *bs = NULL;
268
bool result = false;
269
+
270
GLOBAL_STATE_CODE();
271
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
272
273
/* bdrv_drain_poll() can't make changes to the graph and we are holding the
274
* main AioContext lock, so iterating bdrv_next_all_states() is safe. */
275
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/tests/unit/test-bdrv-drain.c
278
+++ b/tests/unit/test-bdrv-drain.c
279
@@ -XXX,XX +XXX,XX @@ static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
280
}
281
}
282
283
-static void detach_by_driver_cb_drained_begin(BdrvChild *child)
284
+static void GRAPH_RDLOCK detach_by_driver_cb_drained_begin(BdrvChild *child)
285
{
286
struct detach_by_parent_data *data = &detach_by_parent_data;
287
288
@@ -XXX,XX +XXX,XX @@ static BdrvChildClass detach_by_driver_cb_class;
289
* state is messed up, but if it is only polled in the single
290
* BDRV_POLL_WHILE() at the end of the drain, this should work fine.
291
*/
292
-static void test_detach_indirect(bool by_parent_cb)
293
+static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb)
294
{
295
BlockBackend *blk;
296
BlockDriverState *parent_a, *parent_b, *a, *b, *c;
297
--
298
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_parent_cb_resize() need to hold a reader lock for the graph.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-ID: <20230929145157.45443-7-kwolf@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/io.c | 12 +++++++++---
10
1 file changed, 9 insertions(+), 3 deletions(-)
11
12
diff --git a/block/io.c b/block/io.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/io.c
15
+++ b/block/io.c
16
@@ -XXX,XX +XXX,XX @@
17
/* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */
18
#define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
19
20
-static void bdrv_parent_cb_resize(BlockDriverState *bs);
21
+static void coroutine_fn GRAPH_RDLOCK
22
+bdrv_parent_cb_resize(BlockDriverState *bs);
23
+
24
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
25
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
26
27
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
28
}
29
}
30
31
-static inline void coroutine_fn
32
+static inline void coroutine_fn GRAPH_RDLOCK
33
bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
34
BdrvTrackedRequest *req, int ret)
35
{
36
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
37
bytes, read_flags, write_flags);
38
}
39
40
-static void bdrv_parent_cb_resize(BlockDriverState *bs)
41
+static void coroutine_fn GRAPH_RDLOCK
42
+bdrv_parent_cb_resize(BlockDriverState *bs)
43
{
44
BdrvChild *c;
45
+
46
+ assert_bdrv_graph_readable();
47
+
48
QLIST_FOREACH(c, &bs->parents, next_parent) {
49
if (c->klass->resize) {
50
c->klass->resize(c);
51
--
52
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_snapshot_fallback() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-8-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int-common.h | 18 ++++++++--------
11
include/block/snapshot.h | 24 +++++++++++++---------
12
block/snapshot.c | 35 ++++++++++++++++++++++++++------
13
blockdev.c | 9 ++++++++
14
qemu-img.c | 5 +++++
15
5 files changed, 67 insertions(+), 24 deletions(-)
16
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int-common.h
20
+++ b/include/block/block_int-common.h
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
23
int GRAPH_RDLOCK_PTR (*bdrv_inactivate)(BlockDriverState *bs);
24
25
- int (*bdrv_snapshot_create)(BlockDriverState *bs,
26
- QEMUSnapshotInfo *sn_info);
27
- int (*bdrv_snapshot_goto)(BlockDriverState *bs,
28
- const char *snapshot_id);
29
- int (*bdrv_snapshot_delete)(BlockDriverState *bs,
30
- const char *snapshot_id,
31
- const char *name,
32
- Error **errp);
33
+ int GRAPH_RDLOCK_PTR (*bdrv_snapshot_create)(
34
+ BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
35
+
36
+ int GRAPH_UNLOCKED_PTR (*bdrv_snapshot_goto)(
37
+ BlockDriverState *bs, const char *snapshot_id);
38
+
39
+ int GRAPH_RDLOCK_PTR (*bdrv_snapshot_delete)(
40
+ BlockDriverState *bs, const char *snapshot_id, const char *name,
41
+ Error **errp);
42
+
43
int (*bdrv_snapshot_list)(BlockDriverState *bs,
44
QEMUSnapshotInfo **psn_info);
45
int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
46
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/block/snapshot.h
49
+++ b/include/block/snapshot.h
50
@@ -XXX,XX +XXX,XX @@
51
#ifndef SNAPSHOT_H
52
#define SNAPSHOT_H
53
54
+#include "block/graph-lock.h"
55
#include "qapi/qapi-builtin-types.h"
56
57
#define SNAPSHOT_OPT_BASE "snapshot."
58
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
59
const char *name,
60
QEMUSnapshotInfo *sn_info,
61
Error **errp);
62
-int bdrv_can_snapshot(BlockDriverState *bs);
63
-int bdrv_snapshot_create(BlockDriverState *bs,
64
- QEMUSnapshotInfo *sn_info);
65
-int bdrv_snapshot_goto(BlockDriverState *bs,
66
- const char *snapshot_id,
67
- Error **errp);
68
-int bdrv_snapshot_delete(BlockDriverState *bs,
69
- const char *snapshot_id,
70
- const char *name,
71
- Error **errp);
72
+
73
+int GRAPH_RDLOCK bdrv_can_snapshot(BlockDriverState *bs);
74
+
75
+int GRAPH_RDLOCK
76
+bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
77
+
78
+int GRAPH_UNLOCKED
79
+bdrv_snapshot_goto(BlockDriverState *bs, const char *snapshot_id, Error **errp);
80
+
81
+int GRAPH_RDLOCK
82
+bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
83
+ const char *name, Error **errp);
84
+
85
int bdrv_snapshot_list(BlockDriverState *bs,
86
QEMUSnapshotInfo **psn_info);
87
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
88
diff --git a/block/snapshot.c b/block/snapshot.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/snapshot.c
91
+++ b/block/snapshot.c
92
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
93
* back if the given BDS does not support snapshots.
94
* Return NULL if there is no BDS to (safely) fall back to.
95
*/
96
-static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
97
+static BdrvChild * GRAPH_RDLOCK
98
+bdrv_snapshot_fallback_child(BlockDriverState *bs)
99
{
100
BdrvChild *fallback = bdrv_primary_child(bs);
101
BdrvChild *child;
102
103
+ GLOBAL_STATE_CODE();
104
+ assert_bdrv_graph_readable();
105
+
106
/* We allow fallback only to primary child */
107
if (!fallback) {
108
return NULL;
109
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
110
return fallback;
111
}
112
113
-static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
114
+static BlockDriverState * GRAPH_RDLOCK
115
+bdrv_snapshot_fallback(BlockDriverState *bs)
116
{
117
+ GLOBAL_STATE_CODE();
118
return child_bs(bdrv_snapshot_fallback_child(bs));
119
}
120
121
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
122
return ret;
123
}
124
125
+ bdrv_graph_rdlock_main_loop();
126
fallback = bdrv_snapshot_fallback_child(bs);
127
+ bdrv_graph_rdunlock_main_loop();
128
+
129
if (fallback) {
130
QDict *options;
131
QDict *file_options;
132
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
133
int bdrv_snapshot_list(BlockDriverState *bs,
134
QEMUSnapshotInfo **psn_info)
135
{
136
+ GLOBAL_STATE_CODE();
137
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
138
+
139
BlockDriver *drv = bs->drv;
140
BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
141
142
- GLOBAL_STATE_CODE();
143
if (!drv) {
144
return -ENOMEDIUM;
145
}
146
@@ -XXX,XX +XXX,XX @@ bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
147
148
static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
149
{
150
+ GLOBAL_STATE_CODE();
151
+ assert_bdrv_graph_readable();
152
+
153
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
154
return false;
155
}
156
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
157
{
158
g_autoptr(GList) bdrvs = NULL;
159
GList *iterbdrvs;
160
+ int ret;
161
162
GLOBAL_STATE_CODE();
163
- GRAPH_RDLOCK_GUARD_MAINLOOP();
164
165
- if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
166
+ bdrv_graph_rdlock_main_loop();
167
+ ret = bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp);
168
+ bdrv_graph_rdunlock_main_loop();
169
+
170
+ if (ret < 0) {
171
return -1;
172
}
173
174
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
175
BlockDriverState *bs = iterbdrvs->data;
176
AioContext *ctx = bdrv_get_aio_context(bs);
177
int ret = 0;
178
+ bool all_snapshots_includes_bs;
179
180
aio_context_acquire(ctx);
181
- if (devices || bdrv_all_snapshots_includes_bs(bs)) {
182
+ bdrv_graph_rdlock_main_loop();
183
+ all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
184
+ bdrv_graph_rdunlock_main_loop();
185
+
186
+ if (devices || all_snapshots_includes_bs) {
187
ret = bdrv_snapshot_goto(bs, name, errp);
188
}
189
aio_context_release(ctx);
190
diff --git a/blockdev.c b/blockdev.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/blockdev.c
193
+++ b/blockdev.c
194
@@ -XXX,XX +XXX,XX @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
195
SnapshotInfo *info = NULL;
196
int ret;
197
198
+ GLOBAL_STATE_CODE();
199
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
200
+
201
bs = qmp_get_root_bs(device, errp);
202
if (!bs) {
203
return NULL;
204
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_action(BlockdevSnapshotInternal *internal,
205
AioContext *aio_context;
206
int ret1;
207
208
+ GLOBAL_STATE_CODE();
209
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
210
+
211
tran_add(tran, &internal_snapshot_drv, state);
212
213
device = internal->device;
214
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(void *opaque)
215
AioContext *aio_context;
216
Error *local_error = NULL;
217
218
+ GLOBAL_STATE_CODE();
219
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
220
+
221
if (!state->created) {
222
return;
223
}
224
diff --git a/qemu-img.c b/qemu-img.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/qemu-img.c
227
+++ b/qemu-img.c
228
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
229
sn.date_sec = rt / G_USEC_PER_SEC;
230
sn.date_nsec = (rt % G_USEC_PER_SEC) * 1000;
231
232
+ bdrv_graph_rdlock_main_loop();
233
ret = bdrv_snapshot_create(bs, &sn);
234
+ bdrv_graph_rdunlock_main_loop();
235
+
236
if (ret) {
237
error_report("Could not create snapshot '%s': %s",
238
snapshot_name, strerror(-ret));
239
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
240
break;
241
242
case SNAPSHOT_DELETE:
243
+ bdrv_graph_rdlock_main_loop();
244
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
245
if (ret < 0) {
246
error_report("Could not delete snapshot '%s': snapshot not "
247
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
248
ret = 1;
249
}
250
}
251
+ bdrv_graph_rdunlock_main_loop();
252
break;
253
}
254
255
--
256
2.41.0
diff view generated by jsdifflib
New patch
1
Reopen isn't easy with respect to locking because many of its functions
2
need to iterate the graph, some change it, and then you get some drains
3
in the middle where you can't hold any locks.
1
4
5
Therefore just documents most of the functions to be unlocked, and take
6
locks internally before accessing the graph.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-ID: <20230929145157.45443-9-kwolf@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
include/block/block_int-common.h | 13 +++++---
14
block.c | 57 ++++++++++++++++++++------------
15
2 files changed, 43 insertions(+), 27 deletions(-)
16
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int-common.h
20
+++ b/include/block/block_int-common.h
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
Error **errp);
23
24
/* For handling image reopen for split or non-split files. */
25
- int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
26
- BlockReopenQueue *queue, Error **errp);
27
- void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
28
- void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state);
29
- void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
30
+ int GRAPH_UNLOCKED_PTR (*bdrv_reopen_prepare)(
31
+ BDRVReopenState *reopen_state, BlockReopenQueue *queue, Error **errp);
32
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_commit)(
33
+ BDRVReopenState *reopen_state);
34
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_commit_post)(
35
+ BDRVReopenState *reopen_state);
36
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_abort)(
37
+ BDRVReopenState *reopen_state);
38
void (*bdrv_join_options)(QDict *options, QDict *old_options);
39
40
int GRAPH_UNLOCKED_PTR (*bdrv_open)(
41
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
44
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int bdrv_reset_options_allowed(BlockDriverState *bs,
46
/*
47
* Returns true if @child can be reached recursively from @bs
48
*/
49
-static bool bdrv_recurse_has_child(BlockDriverState *bs,
50
- BlockDriverState *child)
51
+static bool GRAPH_RDLOCK
52
+bdrv_recurse_has_child(BlockDriverState *bs, BlockDriverState *child)
53
{
54
BdrvChild *c;
55
56
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
57
*
58
* To be called with bs->aio_context locked.
59
*/
60
-static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
61
- BlockDriverState *bs,
62
- QDict *options,
63
- const BdrvChildClass *klass,
64
- BdrvChildRole role,
65
- bool parent_is_format,
66
- QDict *parent_options,
67
- int parent_flags,
68
- bool keep_old_opts)
69
+static BlockReopenQueue * GRAPH_RDLOCK
70
+bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, BlockDriverState *bs,
71
+ QDict *options, const BdrvChildClass *klass,
72
+ BdrvChildRole role, bool parent_is_format,
73
+ QDict *parent_options, int parent_flags,
74
+ bool keep_old_opts)
75
{
76
assert(bs != NULL);
77
78
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
79
80
GLOBAL_STATE_CODE();
81
82
+ /*
83
+ * Strictly speaking, draining is illegal under GRAPH_RDLOCK. We know that
84
+ * we've been called with bdrv_graph_rdlock_main_loop(), though, so it's ok
85
+ * in practice.
86
+ */
87
bdrv_drained_begin(bs);
88
89
if (bs_queue == NULL) {
90
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
91
QDict *options, bool keep_old_opts)
92
{
93
GLOBAL_STATE_CODE();
94
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
95
96
return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
97
NULL, 0, keep_old_opts);
98
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
99
* Callers must make sure that their AioContext locking is still correct after
100
* this.
101
*/
102
-static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
103
- bool is_backing, Transaction *tran,
104
- Error **errp)
105
+static int GRAPH_UNLOCKED
106
+bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
107
+ bool is_backing, Transaction *tran,
108
+ Error **errp)
109
{
110
BlockDriverState *bs = reopen_state->bs;
111
BlockDriverState *new_child_bs;
112
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
113
QObject *value;
114
const char *str;
115
AioContext *ctx, *old_ctx;
116
+ bool has_child;
117
int ret;
118
119
GLOBAL_STATE_CODE();
120
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
121
new_child_bs = bdrv_lookup_bs(NULL, str, errp);
122
if (new_child_bs == NULL) {
123
return -EINVAL;
124
- } else if (bdrv_recurse_has_child(new_child_bs, bs)) {
125
+ }
126
+
127
+ bdrv_graph_rdlock_main_loop();
128
+ has_child = bdrv_recurse_has_child(new_child_bs, bs);
129
+ bdrv_graph_rdunlock_main_loop();
130
+
131
+ if (has_child) {
132
error_setg(errp, "Making '%s' a %s child of '%s' would create a "
133
"cycle", str, child_name, bs->node_name);
134
return -EINVAL;
135
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
136
* After calling this function, the transaction @change_child_tran may only be
137
* completed while holding a writer lock for the graph.
138
*/
139
-static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
140
- BlockReopenQueue *queue,
141
- Transaction *change_child_tran, Error **errp)
142
+static int GRAPH_UNLOCKED
143
+bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
144
+ Transaction *change_child_tran, Error **errp)
145
{
146
int ret = -1;
147
int old_flags;
148
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
149
if (qdict_size(reopen_state->options)) {
150
const QDictEntry *entry = qdict_first(reopen_state->options);
151
152
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
153
+
154
do {
155
QObject *new = entry->value;
156
QObject *old = qdict_get(reopen_state->bs->options, entry->key);
157
@@ -XXX,XX +XXX,XX @@ error:
158
* makes them final by swapping the staging BlockDriverState contents into
159
* the active BlockDriverState contents.
160
*/
161
-static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
162
+static void GRAPH_UNLOCKED bdrv_reopen_commit(BDRVReopenState *reopen_state)
163
{
164
BlockDriver *drv;
165
BlockDriverState *bs;
166
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
167
drv->bdrv_reopen_commit(reopen_state);
168
}
169
170
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
171
+
172
/* set BDS specific flags now */
173
qobject_unref(bs->explicit_options);
174
qobject_unref(bs->options);
175
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
176
qdict_del(bs->explicit_options, "backing");
177
qdict_del(bs->options, "backing");
178
179
- bdrv_graph_rdlock_main_loop();
180
bdrv_refresh_limits(bs, NULL, NULL);
181
- bdrv_graph_rdunlock_main_loop();
182
bdrv_refresh_total_sectors(bs, bs->total_sectors);
183
}
184
185
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
186
* Abort the reopen, and delete and free the staged changes in
187
* reopen_state
188
*/
189
-static void bdrv_reopen_abort(BDRVReopenState *reopen_state)
190
+static void GRAPH_UNLOCKED bdrv_reopen_abort(BDRVReopenState *reopen_state)
191
{
192
BlockDriver *drv;
193
194
--
195
2.41.0
diff view generated by jsdifflib
1
bdrv_subtree_drained_end() requires the caller to hold the AioContext
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
lock for the drained node. Not doing this for nodes outside of the main
2
bdrv_get_xdbg_block_graph() need to hold a reader lock for the graph
3
AioContext leads to crashes when AIO_WAIT_WHILE() needs to wait and
3
because it accesses the children list of a node.
4
tries to temporarily release the lock.
5
4
6
Fixes: 3908b7a8994fa5ef7a89aa58cd5a02fc58141592
7
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2046659
8
Reported-by: Qing Wang <qinwang@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20220203140534.36522-2-kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-10-kwolf@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
9
---
14
blockdev.c | 11 ++++++++++-
10
include/block/block-global-state.h | 2 +-
15
1 file changed, 10 insertions(+), 1 deletion(-)
11
blockdev.c | 2 ++
12
2 files changed, 3 insertions(+), 1 deletion(-)
16
13
14
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block-global-state.h
17
+++ b/include/block/block-global-state.h
18
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init_1(BlockDriverState *bs);
19
int bdrv_has_zero_init(BlockDriverState *bs);
20
BlockDriverState *bdrv_find_node(const char *node_name);
21
BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp);
22
-XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp);
23
+XDbgBlockGraph * GRAPH_RDLOCK bdrv_get_xdbg_block_graph(Error **errp);
24
BlockDriverState *bdrv_lookup_bs(const char *device,
25
const char *node_name,
26
Error **errp);
17
diff --git a/blockdev.c b/blockdev.c
27
diff --git a/blockdev.c b/blockdev.c
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/blockdev.c
29
--- a/blockdev.c
20
+++ b/blockdev.c
30
+++ b/blockdev.c
21
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
31
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfoList *qmp_query_named_block_nodes(bool has_flat,
32
33
XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
22
{
34
{
23
BlockReopenQueue *queue = NULL;
35
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
24
GSList *drained = NULL;
25
+ GSList *p;
26
27
/* Add each one of the BDS that we want to reopen to the queue */
28
for (; reopen_list != NULL; reopen_list = reopen_list->next) {
29
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
30
31
fail:
32
bdrv_reopen_queue_free(queue);
33
- g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
34
+ for (p = drained; p; p = p->next) {
35
+ BlockDriverState *bs = p->data;
36
+ AioContext *ctx = bdrv_get_aio_context(bs);
37
+
36
+
38
+ aio_context_acquire(ctx);
37
return bdrv_get_xdbg_block_graph(errp);
39
+ bdrv_subtree_drained_end(bs);
40
+ aio_context_release(ctx);
41
+ }
42
+ g_slist_free(drained);
43
}
38
}
44
39
45
void qmp_blockdev_del(const char *node_name, Error **errp)
46
--
40
--
47
2.34.1
41
2.41.0
48
49
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_refresh_filename() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-11-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/vhdx.h | 5 +--
11
include/block/block-global-state.h | 9 ++++--
12
include/block/block_int-common.h | 8 ++---
13
include/block/qapi.h | 16 ++++------
14
block.c | 23 +++++++++++---
15
block/nfs.c | 2 +-
16
block/qapi.c | 11 ++++---
17
block/raw-format.c | 2 ++
18
block/vhdx.c | 4 +++
19
block/vmdk.c | 51 +++++++++++++++++++-----------
20
blockdev.c | 13 ++++++++
21
qemu-img.c | 4 +++
22
12 files changed, 101 insertions(+), 47 deletions(-)
23
24
diff --git a/block/vhdx.h b/block/vhdx.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/vhdx.h
27
+++ b/block/vhdx.h
28
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
29
30
bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
31
32
-int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
33
- Error **errp);
34
+int GRAPH_RDLOCK
35
+vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
36
+ Error **errp);
37
38
int coroutine_fn GRAPH_RDLOCK
39
vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
40
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block-global-state.h
43
+++ b/include/block/block-global-state.h
44
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
45
Error **errp);
46
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
47
const char *backing_file);
48
-void bdrv_refresh_filename(BlockDriverState *bs);
49
+void GRAPH_RDLOCK bdrv_refresh_filename(BlockDriverState *bs);
50
51
void GRAPH_RDLOCK
52
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
53
@@ -XXX,XX +XXX,XX @@ void bdrv_next_cleanup(BdrvNextIterator *it);
54
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
55
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
56
void *opaque, bool read_only);
57
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
58
-char *bdrv_dirname(BlockDriverState *bs, Error **errp);
59
+
60
+char * GRAPH_RDLOCK
61
+bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
62
+
63
+char * GRAPH_RDLOCK bdrv_dirname(BlockDriverState *bs, Error **errp);
64
65
void bdrv_img_create(const char *filename, const char *fmt,
66
const char *base_filename, const char *base_fmt,
67
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/include/block/block_int-common.h
70
+++ b/include/block/block_int-common.h
71
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
72
* Refreshes the bs->exact_filename field. If that is impossible,
73
* bs->exact_filename has to be left empty.
74
*/
75
- void (*bdrv_refresh_filename)(BlockDriverState *bs);
76
+ void GRAPH_RDLOCK_PTR (*bdrv_refresh_filename)(BlockDriverState *bs);
77
78
/*
79
* Gathers the open options for all children into @target.
80
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
81
* block driver which implements it is probably doing something
82
* shady regarding its runtime option structure.
83
*/
84
- void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
85
- bool backing_overridden);
86
+ void GRAPH_RDLOCK_PTR (*bdrv_gather_child_options)(
87
+ BlockDriverState *bs, QDict *target, bool backing_overridden);
88
89
/*
90
* Returns an allocated string which is the directory name of this BDS: It
91
* will be used to make relative filenames absolute by prepending this
92
* function's return value to them.
93
*/
94
- char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
95
+ char * GRAPH_RDLOCK_PTR (*bdrv_dirname)(BlockDriverState *bs, Error **errp);
96
97
/*
98
* This informs the driver that we are no longer interested in the result
99
diff --git a/include/block/qapi.h b/include/block/qapi.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/block/qapi.h
102
+++ b/include/block/qapi.h
103
@@ -XXX,XX +XXX,XX @@
104
#include "block/snapshot.h"
105
#include "qapi/qapi-types-block-core.h"
106
107
-BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
108
- BlockDriverState *bs,
109
- bool flat,
110
- Error **errp);
111
+BlockDeviceInfo * GRAPH_RDLOCK
112
+bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
113
+ bool flat, Error **errp);
114
+
115
int bdrv_query_snapshot_info_list(BlockDriverState *bs,
116
SnapshotInfoList **p_list,
117
Error **errp);
118
-void bdrv_query_image_info(BlockDriverState *bs,
119
- ImageInfo **p_info,
120
- bool flat,
121
- bool skip_implicit_filters,
122
- Error **errp);
123
+void GRAPH_RDLOCK
124
+bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
125
+ bool skip_implicit_filters, Error **errp);
126
void GRAPH_RDLOCK
127
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
128
Error **errp);
129
diff --git a/block.c b/block.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block.c
132
+++ b/block.c
133
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
134
* setting @errp. In all other cases, NULL will only be returned with
135
* @errp set.
136
*/
137
-static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
138
- const char *filename, Error **errp)
139
+static char * GRAPH_RDLOCK
140
+bdrv_make_absolute_filename(BlockDriverState *relative_to,
141
+ const char *filename, Error **errp)
142
{
143
char *dir, *full_name;
144
145
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
146
*child_flags &= ~BDRV_O_NATIVE_AIO;
147
}
148
149
-static void bdrv_backing_attach(BdrvChild *c)
150
+static void GRAPH_WRLOCK bdrv_backing_attach(BdrvChild *c)
151
{
152
BlockDriverState *parent = c->opaque;
153
BlockDriverState *backing_hd = c->bs;
154
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
155
}
156
157
if (file != NULL) {
158
+ bdrv_graph_rdlock_main_loop();
159
bdrv_refresh_filename(blk_bs(file));
160
+ bdrv_graph_rdunlock_main_loop();
161
+
162
filename = blk_bs(file)->filename;
163
} else {
164
/*
165
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
166
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
167
}
168
169
+ bdrv_graph_rdlock_main_loop();
170
backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
171
+ bdrv_graph_rdunlock_main_loop();
172
+
173
if (local_err) {
174
ret = -EINVAL;
175
error_propagate(errp, local_err);
176
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
177
}
178
179
if (implicit_backing) {
180
+ bdrv_graph_rdlock_main_loop();
181
bdrv_refresh_filename(backing_hd);
182
+ bdrv_graph_rdunlock_main_loop();
183
pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
184
backing_hd->filename);
185
}
186
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
187
if (local_err != NULL) {
188
error_propagate(errp, local_err);
189
} else {
190
+ bdrv_graph_rdlock_main_loop();
191
bdrv_refresh_filename(reopen_state->bs);
192
+ bdrv_graph_rdunlock_main_loop();
193
error_setg(errp, "failed while preparing to reopen image '%s'",
194
reopen_state->bs->filename);
195
}
196
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
197
198
bdrv_ref(top);
199
bdrv_drained_begin(base);
200
+ bdrv_graph_rdlock_main_loop();
201
202
if (!top->drv || !base->drv) {
203
goto exit;
204
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
205
backing_file_str = base->filename;
206
}
207
208
- bdrv_graph_rdlock_main_loop();
209
QLIST_FOREACH(c, &top->parents, next_parent) {
210
updated_children = g_slist_prepend(updated_children, c);
211
}
212
- bdrv_graph_rdunlock_main_loop();
213
214
/*
215
* It seems correct to pass detach_subchain=true here, but it triggers
216
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
217
218
ret = 0;
219
exit:
220
+ bdrv_graph_rdunlock_main_loop();
221
bdrv_drained_end(base);
222
bdrv_unref(top);
223
return ret;
224
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfoList *bdrv_named_nodes_list(bool flat,
225
BlockDriverState *bs;
226
227
GLOBAL_STATE_CODE();
228
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
229
230
list = NULL;
231
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
232
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
233
BlockDriverState *bs_below;
234
235
GLOBAL_STATE_CODE();
236
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
237
238
if (!bs || !bs->drv || !backing_file) {
239
return NULL;
240
diff --git a/block/nfs.c b/block/nfs.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/nfs.c
243
+++ b/block/nfs.c
244
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs)
245
}
246
}
247
248
-static char *nfs_dirname(BlockDriverState *bs, Error **errp)
249
+static char * GRAPH_RDLOCK nfs_dirname(BlockDriverState *bs, Error **errp)
250
{
251
NFSClient *client = bs->opaque;
252
253
diff --git a/block/qapi.c b/block/qapi.c
254
index XXXXXXX..XXXXXXX 100644
255
--- a/block/qapi.c
256
+++ b/block/qapi.c
257
@@ -XXX,XX +XXX,XX @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
258
* Helper function for other query info functions. Store information about @bs
259
* in @info, setting @errp on error.
260
*/
261
-static void bdrv_do_query_node_info(BlockDriverState *bs,
262
- BlockNodeInfo *info,
263
- Error **errp)
264
+static void GRAPH_RDLOCK
265
+bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
266
{
267
int64_t size;
268
const char *backing_filename;
269
@@ -XXX,XX +XXX,XX @@ fail:
270
}
271
272
/* @p_info will be set only on success. */
273
-static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
274
- Error **errp)
275
+static void GRAPH_RDLOCK
276
+bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, Error **errp)
277
{
278
BlockInfo *info = g_malloc0(sizeof(*info));
279
BlockDriverState *bs = blk_bs(blk);
280
@@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp)
281
BlockBackend *blk;
282
Error *local_err = NULL;
283
284
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
285
+
286
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
287
BlockInfoList *info;
288
289
diff --git a/block/raw-format.c b/block/raw-format.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/raw-format.c
292
+++ b/block/raw-format.c
293
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
294
BDRV_REQ_ZERO_WRITE;
295
296
if (bs->probed && !bdrv_is_read_only(bs)) {
297
+ bdrv_graph_rdlock_main_loop();
298
bdrv_refresh_filename(bs->file->bs);
299
+ bdrv_graph_rdunlock_main_loop();
300
fprintf(stderr,
301
"WARNING: Image format was not specified for '%s' and probing "
302
"guessed raw.\n"
303
diff --git a/block/vhdx.c b/block/vhdx.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/block/vhdx.c
306
+++ b/block/vhdx.c
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
308
uint64_t signature;
309
Error *local_err = NULL;
310
311
+ GLOBAL_STATE_CODE();
312
+
313
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
314
if (ret < 0) {
315
return ret;
316
}
317
318
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
319
+
320
s->bat = NULL;
321
s->first_visible_write = true;
322
323
diff --git a/block/vmdk.c b/block/vmdk.c
324
index XXXXXXX..XXXXXXX 100644
325
--- a/block/vmdk.c
326
+++ b/block/vmdk.c
327
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
328
return 0;
329
}
330
331
-static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
332
- Error **errp)
333
+static int GRAPH_RDLOCK
334
+vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, Error **errp)
335
{
336
int ret;
337
size_t l1_size;
338
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
339
return ret;
340
}
341
342
-static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
343
- BdrvChild *file,
344
- int flags, Error **errp)
345
+static int GRAPH_RDLOCK
346
+vmdk_open_vmfs_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
347
+ Error **errp)
348
{
349
int ret;
350
uint32_t magic;
351
@@ -XXX,XX +XXX,XX @@ static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
352
return 0;
353
}
354
355
-static int vmdk_open_se_sparse(BlockDriverState *bs,
356
- BdrvChild *file,
357
- int flags, Error **errp)
358
+static int GRAPH_RDLOCK
359
+vmdk_open_se_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
360
+ Error **errp)
361
{
362
int ret;
363
VMDKSESparseConstHeader const_header;
364
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
365
return buf;
366
}
367
368
-static int vmdk_open_vmdk4(BlockDriverState *bs,
369
- BdrvChild *file,
370
- int flags, QDict *options, Error **errp)
371
+static int GRAPH_RDLOCK
372
+vmdk_open_vmdk4(BlockDriverState *bs, BdrvChild *file, int flags,
373
+ QDict *options, Error **errp)
374
{
375
int ret;
376
uint32_t magic;
377
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
378
}
379
380
/* Open an extent file and append to bs array */
381
-static int vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
382
- char *buf, QDict *options, Error **errp)
383
+static int GRAPH_RDLOCK
384
+vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
385
+ char *buf, QDict *options, Error **errp)
386
{
387
uint32_t magic;
388
389
@@ -XXX,XX +XXX,XX @@ static const char *next_line(const char *s)
390
return s;
391
}
392
393
-static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
394
- QDict *options, Error **errp)
395
+static int GRAPH_RDLOCK
396
+vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
397
+ Error **errp)
398
{
399
int ret;
400
int matches;
401
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
402
char extent_opt_prefix[32];
403
Error *local_err = NULL;
404
405
+ GLOBAL_STATE_CODE();
406
+
407
for (p = desc; *p; p = next_line(p)) {
408
/* parse extent line in one of below formats:
409
*
410
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
411
ret = vmdk_add_extent(bs, extent_file, true, sectors,
412
0, 0, 0, 0, 0, &extent, errp);
413
if (ret < 0) {
414
+ bdrv_graph_rdunlock_main_loop();
415
bdrv_graph_wrlock(NULL);
416
bdrv_unref_child(bs, extent_file);
417
bdrv_graph_wrunlock();
418
+ bdrv_graph_rdlock_main_loop();
419
goto out;
420
}
421
extent->flat_start_offset = flat_offset << 9;
422
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
423
}
424
g_free(buf);
425
if (ret) {
426
+ bdrv_graph_rdunlock_main_loop();
427
bdrv_graph_wrlock(NULL);
428
bdrv_unref_child(bs, extent_file);
429
bdrv_graph_wrunlock();
430
+ bdrv_graph_rdlock_main_loop();
431
goto out;
432
}
433
extent = &s->extents[s->num_extents - 1];
434
} else if (!strcmp(type, "SESPARSE")) {
435
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
436
if (ret) {
437
+ bdrv_graph_rdunlock_main_loop();
438
bdrv_graph_wrlock(NULL);
439
bdrv_unref_child(bs, extent_file);
440
bdrv_graph_wrunlock();
441
+ bdrv_graph_rdlock_main_loop();
442
goto out;
443
}
444
extent = &s->extents[s->num_extents - 1];
445
} else {
446
error_setg(errp, "Unsupported extent type '%s'", type);
447
+ bdrv_graph_rdunlock_main_loop();
448
bdrv_graph_wrlock(NULL);
449
bdrv_unref_child(bs, extent_file);
450
bdrv_graph_wrunlock();
451
+ bdrv_graph_rdlock_main_loop();
452
ret = -ENOTSUP;
453
goto out;
454
}
455
@@ -XXX,XX +XXX,XX @@ out:
456
return ret;
457
}
458
459
-static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
460
- QDict *options, Error **errp)
461
+static int GRAPH_RDLOCK
462
+vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf, QDict *options,
463
+ Error **errp)
464
{
465
int ret;
466
char ct[128];
467
@@ -XXX,XX +XXX,XX @@ static int vmdk_has_zero_init(BlockDriverState *bs)
468
return 1;
469
}
470
471
-static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
472
+static VmdkExtentInfo * GRAPH_RDLOCK vmdk_get_extent_info(VmdkExtent *extent)
473
{
474
VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);
475
476
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
477
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
478
VmdkExtentInfoList **tail;
479
480
+ assume_graph_lock(); /* FIXME */
481
+
482
*spec_info = (ImageInfoSpecific){
483
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
484
.u = {
485
diff --git a/blockdev.c b/blockdev.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/blockdev.c
488
+++ b/blockdev.c
489
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
490
bool set_backing_hd = false;
491
int ret;
492
493
+ GLOBAL_STATE_CODE();
494
+
495
tran_add(tran, &drive_backup_drv, state);
496
497
if (!backup->has_mode) {
498
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
499
BlockDriverState *explicit_backing =
500
bdrv_skip_implicit_filters(source);
501
502
+ bdrv_graph_rdlock_main_loop();
503
bdrv_refresh_filename(explicit_backing);
504
+ bdrv_graph_rdunlock_main_loop();
505
+
506
bdrv_img_create(backup->target, format,
507
explicit_backing->filename,
508
explicit_backing->drv->format_name, NULL,
509
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
510
Error *local_err = NULL;
511
int job_flags = JOB_DEFAULT;
512
513
+ GLOBAL_STATE_CODE();
514
+
515
if (base && base_node) {
516
error_setg(errp, "'base' and 'base-node' cannot be specified "
517
"at the same time");
518
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
519
goto out;
520
}
521
assert(bdrv_get_aio_context(base_bs) == aio_context);
522
+
523
+ bdrv_graph_rdlock_main_loop();
524
bdrv_refresh_filename(base_bs);
525
+ bdrv_graph_rdunlock_main_loop();
526
}
527
528
if (bottom) {
529
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
530
break;
531
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
532
/* create new image with backing file */
533
+ bdrv_graph_rdlock_main_loop();
534
bdrv_refresh_filename(explicit_backing);
535
+ bdrv_graph_rdunlock_main_loop();
536
+
537
bdrv_img_create(arg->target, format,
538
explicit_backing->filename,
539
explicit_backing->drv->format_name,
540
diff --git a/qemu-img.c b/qemu-img.c
541
index XXXXXXX..XXXXXXX 100644
542
--- a/qemu-img.c
543
+++ b/qemu-img.c
544
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
545
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
546
547
if (file && has_offset) {
548
+ bdrv_graph_rdlock_main_loop();
549
bdrv_refresh_filename(file);
550
+ bdrv_graph_rdunlock_main_loop();
551
filename = file->filename;
552
}
553
554
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
555
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
556
}
557
558
+ bdrv_graph_rdlock_main_loop();
559
bdrv_refresh_filename(bs);
560
+ bdrv_graph_rdunlock_main_loop();
561
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
562
: bs->filename;
563
out_real_path =
564
--
565
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_primary_child() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-12-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int-io.h | 5 +++--
11
block.c | 11 ++++++++++-
12
block/snapshot.c | 3 +++
13
3 files changed, 16 insertions(+), 3 deletions(-)
14
15
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block_int-io.h
18
+++ b/include/block/block_int-io.h
19
@@ -XXX,XX +XXX,XX @@ bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
20
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
21
BdrvChild *bdrv_filter_child(BlockDriverState *bs);
22
BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs);
23
-BdrvChild *bdrv_primary_child(BlockDriverState *bs);
24
+BdrvChild * GRAPH_RDLOCK bdrv_primary_child(BlockDriverState *bs);
25
BlockDriverState *bdrv_skip_filters(BlockDriverState *bs);
26
BlockDriverState *bdrv_backing_chain_next(BlockDriverState *bs);
27
28
@@ -XXX,XX +XXX,XX @@ static inline BlockDriverState *bdrv_filter_or_cow_bs(BlockDriverState *bs)
29
return child_bs(bdrv_filter_or_cow_child(bs));
30
}
31
32
-static inline BlockDriverState *bdrv_primary_bs(BlockDriverState *bs)
33
+static inline BlockDriverState * GRAPH_RDLOCK
34
+bdrv_primary_bs(BlockDriverState *bs)
35
{
36
IO_CODE();
37
return child_bs(bdrv_primary_child(bs));
38
diff --git a/block.c b/block.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block.c
41
+++ b/block.c
42
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
43
bs->drv->bdrv_co_debug_event(bs, event);
44
}
45
46
-static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
47
+static BlockDriverState * GRAPH_RDLOCK
48
+bdrv_find_debug_node(BlockDriverState *bs)
49
{
50
GLOBAL_STATE_CODE();
51
while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
52
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
53
const char *tag)
54
{
55
GLOBAL_STATE_CODE();
56
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
57
+
58
bs = bdrv_find_debug_node(bs);
59
if (bs) {
60
return bs->drv->bdrv_debug_breakpoint(bs, event, tag);
61
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
62
int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
63
{
64
GLOBAL_STATE_CODE();
65
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
66
+
67
bs = bdrv_find_debug_node(bs);
68
if (bs) {
69
return bs->drv->bdrv_debug_remove_breakpoint(bs, tag);
70
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
71
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
72
{
73
GLOBAL_STATE_CODE();
74
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
75
+
76
while (bs && (!bs->drv || !bs->drv->bdrv_debug_resume)) {
77
bs = bdrv_primary_bs(bs);
78
}
79
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
80
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
81
{
82
GLOBAL_STATE_CODE();
83
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
84
+
85
while (bs && bs->drv && !bs->drv->bdrv_debug_is_suspended) {
86
bs = bdrv_primary_bs(bs);
87
}
88
diff --git a/block/snapshot.c b/block/snapshot.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/snapshot.c
91
+++ b/block/snapshot.c
92
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
93
* respective option (with the qdict_put_str() call above).
94
* Assert that .bdrv_open() has attached the right BDS as primary child.
95
*/
96
+ bdrv_graph_rdlock_main_loop();
97
assert(bdrv_primary_bs(bs) == fallback_bs);
98
+ bdrv_graph_rdunlock_main_loop();
99
+
100
bdrv_unref(fallback_bs);
101
return ret;
102
}
103
--
104
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_get_parent_name() need to hold a reader lock for the graph
3
because it accesses the parents list of a node.
1
4
5
For some places, we know that they will hold the lock, but we don't have
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
7
with a FIXME comment. These places will be removed once everything is
8
properly annotated.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-ID: <20230929145157.45443-13-kwolf@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/qcow2.h | 7 +++----
16
include/block/block-io.h | 8 ++++++--
17
include/block/block_int-io.h | 2 +-
18
include/block/qapi.h | 7 ++++---
19
block.c | 14 ++++++++++++--
20
block/backup.c | 1 +
21
block/parallels.c | 3 +++
22
block/qcow.c | 3 +++
23
block/qcow2-bitmap.c | 2 ++
24
block/qcow2.c | 4 ++++
25
block/quorum.c | 4 ++--
26
block/rbd.c | 2 ++
27
block/snapshot.c | 3 +++
28
block/vdi.c | 3 +++
29
block/vpc.c | 3 +++
30
block/vvfat.c | 2 ++
31
blockjob.c | 1 +
32
17 files changed, 55 insertions(+), 14 deletions(-)
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 @@ int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp
39
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
40
bool release_stored, Error **errp);
41
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
42
-bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
43
- const char *name,
44
- uint32_t granularity,
45
- Error **errp);
46
+bool coroutine_fn GRAPH_RDLOCK
47
+qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
48
+ uint32_t granularity, Error **errp);
49
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
50
const char *name,
51
Error **errp);
52
diff --git a/include/block/block-io.h b/include/block/block-io.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/include/block/block-io.h
55
+++ b/include/block/block-io.h
56
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_format_name(BlockDriverState *bs);
57
58
bool bdrv_supports_compressed_writes(BlockDriverState *bs);
59
const char *bdrv_get_node_name(const BlockDriverState *bs);
60
-const char *bdrv_get_device_name(const BlockDriverState *bs);
61
-const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
62
+
63
+const char * GRAPH_RDLOCK
64
+bdrv_get_device_name(const BlockDriverState *bs);
65
+
66
+const char * GRAPH_RDLOCK
67
+bdrv_get_device_or_node_name(const BlockDriverState *bs);
68
69
int coroutine_fn GRAPH_RDLOCK
70
bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
71
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-io.h
74
+++ b/include/block/block_int-io.h
75
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
76
*/
77
void bdrv_wakeup(BlockDriverState *bs);
78
79
-const char *bdrv_get_parent_name(const BlockDriverState *bs);
80
+const char * GRAPH_RDLOCK bdrv_get_parent_name(const BlockDriverState *bs);
81
bool blk_dev_has_tray(BlockBackend *blk);
82
bool blk_dev_is_tray_open(BlockBackend *blk);
83
84
diff --git a/include/block/qapi.h b/include/block/qapi.h
85
index XXXXXXX..XXXXXXX 100644
86
--- a/include/block/qapi.h
87
+++ b/include/block/qapi.h
88
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo * GRAPH_RDLOCK
89
bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
90
bool flat, Error **errp);
91
92
-int bdrv_query_snapshot_info_list(BlockDriverState *bs,
93
- SnapshotInfoList **p_list,
94
- Error **errp);
95
+int GRAPH_RDLOCK
96
+bdrv_query_snapshot_info_list(BlockDriverState *bs,
97
+ SnapshotInfoList **p_list,
98
+ Error **errp);
99
void GRAPH_RDLOCK
100
bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
101
bool skip_implicit_filters, Error **errp);
102
diff --git a/block.c b/block.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block.c
105
+++ b/block.c
106
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
107
return !(bs->open_flags & BDRV_O_RDWR);
108
}
109
110
-static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
111
- bool ignore_allow_rdw, Error **errp)
112
+static int GRAPH_RDLOCK
113
+bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
114
+ bool ignore_allow_rdw, Error **errp)
115
{
116
IO_CODE();
117
118
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
119
int ret = 0;
120
IO_CODE();
121
122
+ assume_graph_lock(); /* FIXME */
123
+
124
if (!(bs->open_flags & BDRV_O_RDWR)) {
125
return 0;
126
}
127
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
128
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
129
* not set, or if the BDS still has copy_on_read enabled */
130
read_only = !(reopen_state->flags & BDRV_O_RDWR);
131
+
132
+ bdrv_graph_rdlock_main_loop();
133
ret = bdrv_can_set_read_only(reopen_state->bs, read_only, true, &local_err);
134
+ bdrv_graph_rdunlock_main_loop();
135
if (local_err) {
136
error_propagate(errp, local_err);
137
goto error;
138
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
139
} else {
140
/* It is currently mandatory to have a bdrv_reopen_prepare()
141
* handler for each supported drv. */
142
+ bdrv_graph_rdlock_main_loop();
143
error_setg(errp, "Block format '%s' used by node '%s' "
144
"does not support reopening files", drv->format_name,
145
bdrv_get_device_or_node_name(reopen_state->bs));
146
+ bdrv_graph_rdunlock_main_loop();
147
ret = -1;
148
goto error;
149
}
150
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
151
{
152
BdrvOpBlocker *blocker;
153
GLOBAL_STATE_CODE();
154
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
155
+
156
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
157
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
158
blocker = QLIST_FIRST(&bs->op_blockers[op]);
159
diff --git a/block/backup.c b/block/backup.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/backup.c
162
+++ b/block/backup.c
163
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
164
assert(bs);
165
assert(target);
166
GLOBAL_STATE_CODE();
167
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
168
169
/* QMP interface protects us from these cases */
170
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
171
diff --git a/block/parallels.c b/block/parallels.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/block/parallels.c
174
+++ b/block/parallels.c
175
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
176
bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
177
178
/* Disable migration until bdrv_activate method is added */
179
+ bdrv_graph_rdlock_main_loop();
180
error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
181
"does not support live migration",
182
bdrv_get_device_or_node_name(bs));
183
+ bdrv_graph_rdunlock_main_loop();
184
+
185
ret = migrate_add_blocker(s->migration_blocker, errp);
186
if (ret < 0) {
187
error_setg(errp, "Migration blocker error");
188
diff --git a/block/qcow.c b/block/qcow.c
189
index XXXXXXX..XXXXXXX 100644
190
--- a/block/qcow.c
191
+++ b/block/qcow.c
192
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
193
}
194
195
/* Disable migration when qcow images are used */
196
+ bdrv_graph_rdlock_main_loop();
197
error_setg(&s->migration_blocker, "The qcow format used by node '%s' "
198
"does not support live migration",
199
bdrv_get_device_or_node_name(bs));
200
+ bdrv_graph_rdunlock_main_loop();
201
+
202
ret = migrate_add_blocker(s->migration_blocker, errp);
203
if (ret < 0) {
204
error_free(s->migration_blocker);
205
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/block/qcow2-bitmap.c
208
+++ b/block/qcow2-bitmap.c
209
@@ -XXX,XX +XXX,XX @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
210
int64_t len = bdrv_getlength(bs);
211
int64_t bitmap_bytes;
212
213
+ assume_graph_lock(); /* FIXME */
214
+
215
assert(granularity > 0);
216
assert((granularity & (granularity - 1)) == 0);
217
218
diff --git a/block/qcow2.c b/block/qcow2.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/block/qcow2.c
221
+++ b/block/qcow2.c
222
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
223
int ret, result = 0;
224
Error *local_err = NULL;
225
226
+ assume_graph_lock(); /* FIXME */
227
+
228
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
229
if (local_err != NULL) {
230
result = -EINVAL;
231
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
232
char *message;
233
va_list ap;
234
235
+ assume_graph_lock(); /* FIXME */
236
+
237
fatal = fatal && bdrv_is_writable(bs);
238
239
if (s->signaled_corruption &&
240
diff --git a/block/quorum.c b/block/quorum.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/quorum.c
243
+++ b/block/quorum.c
244
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad(QuorumOpType type, uint64_t offset,
245
end_sector - start_sector);
246
}
247
248
-static void quorum_report_failure(QuorumAIOCB *acb)
249
+static void GRAPH_RDLOCK quorum_report_failure(QuorumAIOCB *acb)
250
{
251
const char *reference = bdrv_get_device_or_node_name(acb->bs);
252
int64_t start_sector = acb->offset / BDRV_SECTOR_SIZE;
253
@@ -XXX,XX +XXX,XX @@ static void quorum_report_failure(QuorumAIOCB *acb)
254
255
static int quorum_vote_error(QuorumAIOCB *acb);
256
257
-static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
258
+static bool GRAPH_RDLOCK quorum_has_too_much_io_failed(QuorumAIOCB *acb)
259
{
260
BDRVQuorumState *s = acb->bs->opaque;
261
262
diff --git a/block/rbd.c b/block/rbd.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/block/rbd.c
265
+++ b/block/rbd.c
266
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
267
BDRVRBDState *s = state->bs->opaque;
268
int ret = 0;
269
270
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
271
+
272
if (s->snap && state->flags & BDRV_O_RDWR) {
273
error_setg(errp,
274
"Cannot change node '%s' to r/w when using RBD snapshot",
275
diff --git a/block/snapshot.c b/block/snapshot.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/block/snapshot.c
278
+++ b/block/snapshot.c
279
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
280
BlockDriver *drv = bs->drv;
281
282
GLOBAL_STATE_CODE();
283
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
284
285
if (!drv) {
286
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
287
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
288
}
289
aio_context_release(ctx);
290
if (ret < 0) {
291
+ bdrv_graph_rdlock_main_loop();
292
error_prepend(errp, "Could not load snapshot '%s' on '%s': ",
293
name, bdrv_get_device_or_node_name(bs));
294
+ bdrv_graph_rdunlock_main_loop();
295
return -1;
296
}
297
298
diff --git a/block/vdi.c b/block/vdi.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/block/vdi.c
301
+++ b/block/vdi.c
302
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
303
}
304
305
/* Disable migration when vdi images are used */
306
+ bdrv_graph_rdlock_main_loop();
307
error_setg(&s->migration_blocker, "The vdi format used by node '%s' "
308
"does not support live migration",
309
bdrv_get_device_or_node_name(bs));
310
+ bdrv_graph_rdunlock_main_loop();
311
+
312
ret = migrate_add_blocker(s->migration_blocker, errp);
313
if (ret < 0) {
314
error_free(s->migration_blocker);
315
diff --git a/block/vpc.c b/block/vpc.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/block/vpc.c
318
+++ b/block/vpc.c
319
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
320
}
321
322
/* Disable migration when VHD images are used */
323
+ bdrv_graph_rdlock_main_loop();
324
error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
325
"does not support live migration",
326
bdrv_get_device_or_node_name(bs));
327
+ bdrv_graph_rdunlock_main_loop();
328
+
329
ret = migrate_add_blocker(s->migration_blocker, errp);
330
if (ret < 0) {
331
error_free(s->migration_blocker);
332
diff --git a/block/vvfat.c b/block/vvfat.c
333
index XXXXXXX..XXXXXXX 100644
334
--- a/block/vvfat.c
335
+++ b/block/vvfat.c
336
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
337
QemuOpts *opts;
338
int ret;
339
340
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
341
+
342
#ifdef DEBUG
343
vvv = s;
344
#endif
345
diff --git a/blockjob.c b/blockjob.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/blockjob.c
348
+++ b/blockjob.c
349
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
350
BlockJob *job;
351
int ret;
352
GLOBAL_STATE_CODE();
353
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
354
355
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
356
job_id = bdrv_get_device_name(bs);
357
--
358
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_amend_options() need to hold a reader lock for the graph. This
3
removes an assume_graph_lock() call in crypto's implementation.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-14-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-global-state.h | 8 ++++----
11
include/block/block_int-common.h | 10 ++++------
12
block/crypto.c | 4 +---
13
qemu-img.c | 7 +++++++
14
4 files changed, 16 insertions(+), 13 deletions(-)
15
16
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-global-state.h
19
+++ b/include/block/block-global-state.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
21
*/
22
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
23
int64_t total_work_size, void *opaque);
24
-int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
25
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
26
- bool force,
27
- Error **errp);
28
+int GRAPH_RDLOCK
29
+bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
30
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
31
+ bool force, Error **errp);
32
33
/* check if a named node can be replaced when doing drive-mirror */
34
BlockDriverState * GRAPH_RDLOCK
35
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int-common.h
38
+++ b/include/block/block_int-common.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
int coroutine_fn GRAPH_UNLOCKED_PTR (*bdrv_co_create_opts)(
41
BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
42
43
- int (*bdrv_amend_options)(BlockDriverState *bs,
44
- QemuOpts *opts,
45
- BlockDriverAmendStatusCB *status_cb,
46
- void *cb_opaque,
47
- bool force,
48
- Error **errp);
49
+ int GRAPH_RDLOCK_PTR (*bdrv_amend_options)(
50
+ BlockDriverState *bs, QemuOpts *opts,
51
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
52
+ bool force, Error **errp);
53
54
int (*bdrv_make_empty)(BlockDriverState *bs);
55
56
diff --git a/block/crypto.c b/block/crypto.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/crypto.c
59
+++ b/block/crypto.c
60
@@ -XXX,XX +XXX,XX @@ block_crypto_amend_options_generic_luks(BlockDriverState *bs,
61
errp);
62
}
63
64
-static int
65
+static int GRAPH_RDLOCK
66
block_crypto_amend_options_luks(BlockDriverState *bs,
67
QemuOpts *opts,
68
BlockDriverAmendStatusCB *status_cb,
69
@@ -XXX,XX +XXX,XX @@ block_crypto_amend_options_luks(BlockDriverState *bs,
70
QCryptoBlockAmendOptions *amend_options = NULL;
71
int ret = -EINVAL;
72
73
- assume_graph_lock(); /* FIXME */
74
-
75
assert(crypto);
76
assert(crypto->block);
77
78
diff --git a/qemu-img.c b/qemu-img.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/qemu-img.c
81
+++ b/qemu-img.c
82
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
83
{
84
BlockDriver *drv;
85
86
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
87
+
88
/* Find driver and parse its options */
89
drv = bdrv_find_format(format);
90
if (!drv) {
91
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
92
goto out;
93
}
94
95
+ bdrv_graph_rdlock_main_loop();
96
if (!bs->drv->bdrv_amend_options) {
97
error_report("Format driver '%s' does not support option amendment",
98
fmt);
99
+ bdrv_graph_rdunlock_main_loop();
100
ret = -1;
101
goto out;
102
}
103
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
104
"This option is only supported for image creation\n");
105
}
106
107
+ bdrv_graph_rdunlock_main_loop();
108
error_report_err(err);
109
ret = -1;
110
goto out;
111
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
112
qemu_progress_print(0.f, 0);
113
ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, force, &err);
114
qemu_progress_print(100.f, 0);
115
+ bdrv_graph_rdunlock_main_loop();
116
+
117
if (ret < 0) {
118
error_report_err(err);
119
goto out;
120
--
121
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
qcow2_signal_corruption() need to hold a reader lock for the graph
3
because it calls bdrv_get_node_name(), which accesses the parents list
4
of a node.
1
5
6
For some places, we know that they will hold the lock, but we don't have
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: <20230929145157.45443-15-kwolf@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/qcow2.h | 180 +++++++++++++++++------------
17
include/block/block-global-state.h | 2 +-
18
include/block/block_int-common.h | 2 +-
19
block.c | 3 +-
20
block/block-backend.c | 2 +
21
block/qcow2-bitmap.c | 31 ++---
22
block/qcow2-cache.c | 11 +-
23
block/qcow2-cluster.c | 62 +++++-----
24
block/qcow2-refcount.c | 80 ++++++-------
25
block/qcow2.c | 61 +++++-----
26
block/replication.c | 8 +-
27
11 files changed, 250 insertions(+), 192 deletions(-)
28
29
diff --git a/block/qcow2.h b/block/qcow2.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2.h
32
+++ b/block/qcow2.h
33
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs);
34
int qcow2_mark_corrupt(BlockDriverState *bs);
35
int qcow2_update_header(BlockDriverState *bs);
36
37
-void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
38
- int64_t size, const char *message_format, ...)
39
- G_GNUC_PRINTF(5, 6);
40
+void GRAPH_RDLOCK
41
+qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
42
+ int64_t size, const char *message_format, ...)
43
+ G_GNUC_PRINTF(5, 6);
44
45
int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
46
uint64_t entries, size_t entry_len,
47
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
48
int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs);
49
void qcow2_refcount_close(BlockDriverState *bs);
50
51
-int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
52
- uint64_t *refcount);
53
+int GRAPH_RDLOCK qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
54
+ uint64_t *refcount);
55
56
-int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
57
- uint64_t addend, bool decrease,
58
- enum qcow2_discard_type type);
59
+int GRAPH_RDLOCK
60
+qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
61
+ uint64_t addend, bool decrease,
62
+ enum qcow2_discard_type type);
63
64
-int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
65
- uint64_t additional_clusters, bool exact_size,
66
- int new_refblock_index,
67
- uint64_t new_refblock_offset);
68
+int64_t GRAPH_RDLOCK
69
+qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
70
+ uint64_t additional_clusters, bool exact_size,
71
+ int new_refblock_index,
72
+ uint64_t new_refblock_offset);
73
74
-int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
75
-int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
76
- int64_t nb_clusters);
77
-int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size);
78
-void qcow2_free_clusters(BlockDriverState *bs,
79
- int64_t offset, int64_t size,
80
- enum qcow2_discard_type type);
81
-void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
82
- enum qcow2_discard_type type);
83
+int64_t GRAPH_RDLOCK
84
+qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
85
86
-int qcow2_update_snapshot_refcount(BlockDriverState *bs,
87
- int64_t l1_table_offset, int l1_size, int addend);
88
+int64_t GRAPH_RDLOCK coroutine_fn
89
+qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
90
+ int64_t nb_clusters);
91
92
-int qcow2_flush_caches(BlockDriverState *bs);
93
-int qcow2_write_caches(BlockDriverState *bs);
94
+int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size);
95
+void GRAPH_RDLOCK qcow2_free_clusters(BlockDriverState *bs,
96
+ int64_t offset, int64_t size,
97
+ enum qcow2_discard_type type);
98
+void GRAPH_RDLOCK
99
+qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
100
+ enum qcow2_discard_type type);
101
+
102
+int GRAPH_RDLOCK
103
+qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset,
104
+ int l1_size, int addend);
105
+
106
+int GRAPH_RDLOCK qcow2_flush_caches(BlockDriverState *bs);
107
+int GRAPH_RDLOCK qcow2_write_caches(BlockDriverState *bs);
108
int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
109
BdrvCheckMode fix);
110
111
@@ -XXX,XX +XXX,XX @@ void qcow2_process_discards(BlockDriverState *bs, int ret);
112
113
int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
114
int64_t size);
115
-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
116
- int64_t size, bool data_file);
117
+int GRAPH_RDLOCK
118
+qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
119
+ int64_t size, bool data_file);
120
+
121
int coroutine_fn qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
122
void **refcount_table,
123
int64_t *refcount_table_size,
124
int64_t offset, int64_t size);
125
126
-int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
127
- BlockDriverAmendStatusCB *status_cb,
128
- void *cb_opaque, Error **errp);
129
+int GRAPH_RDLOCK
130
+qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
131
+ BlockDriverAmendStatusCB *status_cb,
132
+ void *cb_opaque, Error **errp);
133
int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
134
-int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
135
+
136
+int64_t coroutine_fn GRAPH_RDLOCK
137
+qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
138
139
int coroutine_fn GRAPH_RDLOCK
140
qcow2_detect_metadata_preallocation(BlockDriverState *bs);
141
142
/* qcow2-cluster.c functions */
143
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
144
- bool exact_size);
145
+int GRAPH_RDLOCK
146
+qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size);
147
148
int coroutine_fn GRAPH_RDLOCK
149
qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
150
151
-int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
152
+int GRAPH_RDLOCK qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
153
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
154
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
155
156
-int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
157
- unsigned int *bytes, uint64_t *host_offset,
158
- QCow2SubclusterType *subcluster_type);
159
-int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
160
- unsigned int *bytes,
161
- uint64_t *host_offset, QCowL2Meta **m);
162
+int GRAPH_RDLOCK
163
+qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
164
+ unsigned int *bytes, uint64_t *host_offset,
165
+ QCow2SubclusterType *subcluster_type);
166
+
167
+int coroutine_fn GRAPH_RDLOCK
168
+qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
169
+ unsigned int *bytes, uint64_t *host_offset,
170
+ QCowL2Meta **m);
171
+
172
int coroutine_fn GRAPH_RDLOCK
173
qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset,
174
int compressed_size, uint64_t *host_offset);
175
@@ -XXX,XX +XXX,XX @@ void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
176
int coroutine_fn GRAPH_RDLOCK
177
qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
178
179
-void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
180
-int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
181
- uint64_t bytes, enum qcow2_discard_type type,
182
- bool full_discard);
183
+void coroutine_fn GRAPH_RDLOCK
184
+qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
185
+
186
+int GRAPH_RDLOCK
187
+qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
188
+ enum qcow2_discard_type type, bool full_discard);
189
190
int coroutine_fn GRAPH_RDLOCK
191
qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
192
int flags);
193
194
-int qcow2_expand_zero_clusters(BlockDriverState *bs,
195
- BlockDriverAmendStatusCB *status_cb,
196
- void *cb_opaque);
197
+int GRAPH_RDLOCK
198
+qcow2_expand_zero_clusters(BlockDriverState *bs,
199
+ BlockDriverAmendStatusCB *status_cb,
200
+ void *cb_opaque);
201
202
/* qcow2-snapshot.c functions */
203
-int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
204
-int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
205
-int qcow2_snapshot_delete(BlockDriverState *bs,
206
- const char *snapshot_id,
207
- const char *name,
208
- Error **errp);
209
+int GRAPH_RDLOCK
210
+qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
211
+
212
+int GRAPH_RDLOCK
213
+qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
214
+
215
+int GRAPH_RDLOCK
216
+qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
217
+ const char *name, Error **errp);
218
+
219
int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab);
220
int qcow2_snapshot_load_tmp(BlockDriverState *bs,
221
const char *snapshot_id,
222
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
223
void qcow2_free_snapshots(BlockDriverState *bs);
224
int coroutine_fn GRAPH_RDLOCK
225
qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
226
-int qcow2_write_snapshots(BlockDriverState *bs);
227
+int GRAPH_RDLOCK qcow2_write_snapshots(BlockDriverState *bs);
228
229
int coroutine_fn GRAPH_RDLOCK
230
qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
231
BdrvCheckMode fix);
232
233
-int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
234
- BdrvCheckResult *result,
235
- BdrvCheckMode fix);
236
+int coroutine_fn GRAPH_RDLOCK
237
+qcow2_check_fix_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
238
+ BdrvCheckMode fix);
239
240
/* qcow2-cache.c functions */
241
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
242
@@ -XXX,XX +XXX,XX @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
243
int qcow2_cache_destroy(Qcow2Cache *c);
244
245
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
246
-int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
247
-int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
248
-int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
249
- Qcow2Cache *dependency);
250
+int GRAPH_RDLOCK qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
251
+int GRAPH_RDLOCK qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
252
+int GRAPH_RDLOCK qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
253
+ Qcow2Cache *dependency);
254
void qcow2_cache_depends_on_flush(Qcow2Cache *c);
255
256
void qcow2_cache_clean_unused(Qcow2Cache *c);
257
-int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c);
258
+int GRAPH_RDLOCK qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c);
259
+
260
+int GRAPH_RDLOCK
261
+qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
262
+ void **table);
263
+
264
+int GRAPH_RDLOCK
265
+qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
266
+ void **table);
267
268
-int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
269
- void **table);
270
-int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
271
- void **table);
272
void qcow2_cache_put(Qcow2Cache *c, void **table);
273
void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset);
274
void qcow2_cache_discard(Qcow2Cache *c, void *table);
275
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn GRAPH_RDLOCK
276
qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp);
277
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
278
Qcow2BitmapInfoList **info_list, Error **errp);
279
-int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
280
+int GRAPH_RDLOCK qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
281
+int GRAPH_RDLOCK qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
282
int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
283
-bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
284
- bool release_stored, Error **errp);
285
-int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
286
+
287
+bool GRAPH_RDLOCK
288
+qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, bool release_stored,
289
+ Error **errp);
290
+
291
bool coroutine_fn GRAPH_RDLOCK
292
qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
293
uint32_t granularity, Error **errp);
294
-int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
295
- const char *name,
296
- Error **errp);
297
+
298
+int coroutine_fn GRAPH_RDLOCK
299
+qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
300
+ Error **errp);
301
+
302
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
303
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
304
uint32_t cluster_size);
305
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
306
index XXXXXXX..XXXXXXX 100644
307
--- a/include/block/block-global-state.h
308
+++ b/include/block/block-global-state.h
309
@@ -XXX,XX +XXX,XX @@ void GRAPH_RDLOCK
310
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
311
312
int bdrv_commit(BlockDriverState *bs);
313
-int bdrv_make_empty(BdrvChild *c, Error **errp);
314
+int GRAPH_RDLOCK bdrv_make_empty(BdrvChild *c, Error **errp);
315
int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
316
const char *backing_fmt, bool warn);
317
void bdrv_register(BlockDriver *bdrv);
318
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
319
index XXXXXXX..XXXXXXX 100644
320
--- a/include/block/block_int-common.h
321
+++ b/include/block/block_int-common.h
322
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
323
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
324
bool force, Error **errp);
325
326
- int (*bdrv_make_empty)(BlockDriverState *bs);
327
+ int GRAPH_RDLOCK_PTR (*bdrv_make_empty)(BlockDriverState *bs);
328
329
/*
330
* Refreshes the bs->exact_filename field. If that is impossible,
331
diff --git a/block.c b/block.c
332
index XXXXXXX..XXXXXXX 100644
333
--- a/block.c
334
+++ b/block.c
335
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
336
{
337
BdrvOpBlocker *blocker;
338
GLOBAL_STATE_CODE();
339
- GRAPH_RDLOCK_GUARD_MAINLOOP();
340
+
341
+ assume_graph_lock(); /* FIXME */
342
343
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
344
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
345
diff --git a/block/block-backend.c b/block/block-backend.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/block/block-backend.c
348
+++ b/block/block-backend.c
349
@@ -XXX,XX +XXX,XX @@ const BdrvChild *blk_root(BlockBackend *blk)
350
int blk_make_empty(BlockBackend *blk, Error **errp)
351
{
352
GLOBAL_STATE_CODE();
353
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
354
+
355
if (!blk_is_available(blk)) {
356
error_setg(errp, "No medium inserted");
357
return -ENOMEDIUM;
358
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
359
index XXXXXXX..XXXXXXX 100644
360
--- a/block/qcow2-bitmap.c
361
+++ b/block/qcow2-bitmap.c
362
@@ -XXX,XX +XXX,XX @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
363
return 0;
364
}
365
366
-static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
367
- uint32_t bitmap_table_size)
368
+static void GRAPH_RDLOCK
369
+clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
370
+ uint32_t bitmap_table_size)
371
{
372
BDRVQcow2State *s = bs->opaque;
373
int i;
374
@@ -XXX,XX +XXX,XX @@ fail:
375
return ret;
376
}
377
378
-static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
379
+static int GRAPH_RDLOCK
380
+free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
381
{
382
int ret;
383
uint64_t *bitmap_table;
384
@@ -XXX,XX +XXX,XX @@ out:
385
* Store bitmap list to qcow2 image as a bitmap directory.
386
* Everything is checked.
387
*/
388
-static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
389
- uint64_t *offset, uint64_t *size, bool in_place)
390
+static int GRAPH_RDLOCK
391
+bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
392
+ uint64_t *offset, uint64_t *size, bool in_place)
393
{
394
int ret;
395
uint8_t *dir;
396
@@ -XXX,XX +XXX,XX @@ fail:
397
* Bitmap List end
398
*/
399
400
-static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
401
- Qcow2BitmapList *bm_list)
402
+static int GRAPH_RDLOCK
403
+update_ext_header_and_dir_in_place(BlockDriverState *bs,
404
+ Qcow2BitmapList *bm_list)
405
{
406
BDRVQcow2State *s = bs->opaque;
407
int ret;
408
@@ -XXX,XX +XXX,XX @@ static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
409
*/
410
}
411
412
-static int update_ext_header_and_dir(BlockDriverState *bs,
413
- Qcow2BitmapList *bm_list)
414
+static int GRAPH_RDLOCK
415
+update_ext_header_and_dir(BlockDriverState *bs, Qcow2BitmapList *bm_list)
416
{
417
BDRVQcow2State *s = bs->opaque;
418
int ret;
419
@@ -XXX,XX +XXX,XX @@ out:
420
/* store_bitmap_data()
421
* Store bitmap to image, filling bitmap table accordingly.
422
*/
423
-static uint64_t *store_bitmap_data(BlockDriverState *bs,
424
- BdrvDirtyBitmap *bitmap,
425
- uint32_t *bitmap_table_size, Error **errp)
426
+static uint64_t * GRAPH_RDLOCK
427
+store_bitmap_data(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
428
+ uint32_t *bitmap_table_size, Error **errp)
429
{
430
int ret;
431
BDRVQcow2State *s = bs->opaque;
432
@@ -XXX,XX +XXX,XX @@ fail:
433
* Store bm->dirty_bitmap to qcow2.
434
* Set bm->table_offset and bm->table_size accordingly.
435
*/
436
-static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
437
+static int GRAPH_RDLOCK
438
+store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
439
{
440
int ret;
441
uint64_t *tb;
442
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
443
index XXXXXXX..XXXXXXX 100644
444
--- a/block/qcow2-cache.c
445
+++ b/block/qcow2-cache.c
446
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_destroy(Qcow2Cache *c)
447
return 0;
448
}
449
450
-static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
451
+static int GRAPH_RDLOCK
452
+qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
453
{
454
int ret;
455
456
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
457
return 0;
458
}
459
460
-static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
461
+static int GRAPH_RDLOCK
462
+qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
463
{
464
BDRVQcow2State *s = bs->opaque;
465
int ret = 0;
466
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c)
467
return 0;
468
}
469
470
-static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
471
- uint64_t offset, void **table, bool read_from_disk)
472
+static int GRAPH_RDLOCK
473
+qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
474
+ void **table, bool read_from_disk)
475
{
476
BDRVQcow2State *s = bs->opaque;
477
int i;
478
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
479
index XXXXXXX..XXXXXXX 100644
480
--- a/block/qcow2-cluster.c
481
+++ b/block/qcow2-cluster.c
482
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
483
* the cache is used; otherwise the L2 slice is loaded from the image
484
* file.
485
*/
486
-static int l2_load(BlockDriverState *bs, uint64_t offset,
487
- uint64_t l2_offset, uint64_t **l2_slice)
488
+static int GRAPH_RDLOCK
489
+l2_load(BlockDriverState *bs, uint64_t offset,
490
+ uint64_t l2_offset, uint64_t **l2_slice)
491
{
492
BDRVQcow2State *s = bs->opaque;
493
int start_of_slice = l2_entry_size(s) *
494
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
495
*
496
*/
497
498
-static int l2_allocate(BlockDriverState *bs, int l1_index)
499
+static int GRAPH_RDLOCK l2_allocate(BlockDriverState *bs, int l1_index)
500
{
501
BDRVQcow2State *s = bs->opaque;
502
uint64_t old_l2_offset;
503
@@ -XXX,XX +XXX,XX @@ fail:
504
*
505
* Returns 0 on success, -errno in failure case
506
*/
507
-static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
508
- uint64_t **new_l2_slice,
509
- int *new_l2_index)
510
+static int GRAPH_RDLOCK
511
+get_cluster_table(BlockDriverState *bs, uint64_t offset,
512
+ uint64_t **new_l2_slice, int *new_l2_index)
513
{
514
BDRVQcow2State *s = bs->opaque;
515
unsigned int l2_index;
516
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
517
*
518
* Returns 0 on success, -errno on failure.
519
*/
520
-static int coroutine_fn calculate_l2_meta(BlockDriverState *bs,
521
- uint64_t host_cluster_offset,
522
- uint64_t guest_offset, unsigned bytes,
523
- uint64_t *l2_slice, QCowL2Meta **m,
524
- bool keep_old)
525
+static int coroutine_fn GRAPH_RDLOCK
526
+calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
527
+ uint64_t guest_offset, unsigned bytes, uint64_t *l2_slice,
528
+ QCowL2Meta **m, bool keep_old)
529
{
530
BDRVQcow2State *s = bs->opaque;
531
int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
532
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
533
*
534
* -errno: in error cases
535
*/
536
-static int coroutine_fn handle_copied(BlockDriverState *bs,
537
- uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
538
- QCowL2Meta **m)
539
+static int coroutine_fn GRAPH_RDLOCK
540
+handle_copied(BlockDriverState *bs, uint64_t guest_offset,
541
+ uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
542
{
543
BDRVQcow2State *s = bs->opaque;
544
int l2_index;
545
@@ -XXX,XX +XXX,XX @@ out:
546
* function has been waiting for another request and the allocation must be
547
* restarted, but the whole request should not be failed.
548
*/
549
-static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
550
- uint64_t guest_offset,
551
- uint64_t *host_offset,
552
- uint64_t *nb_clusters)
553
+static int coroutine_fn GRAPH_RDLOCK
554
+do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
555
+ uint64_t *host_offset, uint64_t *nb_clusters)
556
{
557
BDRVQcow2State *s = bs->opaque;
558
559
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
560
*
561
* -errno: in error cases
562
*/
563
-static int coroutine_fn handle_alloc(BlockDriverState *bs,
564
- uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
565
- QCowL2Meta **m)
566
+static int coroutine_fn GRAPH_RDLOCK
567
+handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
568
+ uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
569
{
570
BDRVQcow2State *s = bs->opaque;
571
int l2_index;
572
@@ -XXX,XX +XXX,XX @@ again:
573
* all clusters in the same L2 slice) and returns the number of discarded
574
* clusters.
575
*/
576
-static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
577
- uint64_t nb_clusters,
578
- enum qcow2_discard_type type, bool full_discard)
579
+static int GRAPH_RDLOCK
580
+discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters,
581
+ enum qcow2_discard_type type, bool full_discard)
582
{
583
BDRVQcow2State *s = bs->opaque;
584
uint64_t *l2_slice;
585
@@ -XXX,XX +XXX,XX @@ fail:
586
* all clusters in the same L2 slice) and returns the number of zeroed
587
* clusters.
588
*/
589
-static int coroutine_fn
590
+static int coroutine_fn GRAPH_RDLOCK
591
zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
592
uint64_t nb_clusters, int flags)
593
{
594
@@ -XXX,XX +XXX,XX @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
595
return nb_clusters;
596
}
597
598
-static int coroutine_fn
599
+static int coroutine_fn GRAPH_RDLOCK
600
zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
601
unsigned nb_subclusters)
602
{
603
@@ -XXX,XX +XXX,XX @@ fail:
604
* status_cb(). l1_entries contains the total number of L1 entries and
605
* *visited_l1_entries counts all visited L1 entries.
606
*/
607
-static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
608
- int l1_size, int64_t *visited_l1_entries,
609
- int64_t l1_entries,
610
- BlockDriverAmendStatusCB *status_cb,
611
- void *cb_opaque)
612
+static int GRAPH_RDLOCK
613
+expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
614
+ int l1_size, int64_t *visited_l1_entries,
615
+ int64_t l1_entries,
616
+ BlockDriverAmendStatusCB *status_cb,
617
+ void *cb_opaque)
618
{
619
BDRVQcow2State *s = bs->opaque;
620
bool is_active_l1 = (l1_table == s->l1_table);
621
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
622
index XXXXXXX..XXXXXXX 100644
623
--- a/block/qcow2-refcount.c
624
+++ b/block/qcow2-refcount.c
625
@@ -XXX,XX +XXX,XX @@ static void set_refcount_ro6(void *refcount_array, uint64_t index,
626
}
627
628
629
-static int load_refcount_block(BlockDriverState *bs,
630
- int64_t refcount_block_offset,
631
- void **refcount_block)
632
+static int GRAPH_RDLOCK
633
+load_refcount_block(BlockDriverState *bs, int64_t refcount_block_offset,
634
+ void **refcount_block)
635
{
636
BDRVQcow2State *s = bs->opaque;
637
638
@@ -XXX,XX +XXX,XX @@ static int in_same_refcount_block(BDRVQcow2State *s, uint64_t offset_a,
639
*
640
* Returns 0 on success or -errno in error case
641
*/
642
-static int alloc_refcount_block(BlockDriverState *bs,
643
- int64_t cluster_index, void **refcount_block)
644
+static int GRAPH_RDLOCK
645
+alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index,
646
+ void **refcount_block)
647
{
648
BDRVQcow2State *s = bs->opaque;
649
unsigned int refcount_table_index;
650
@@ -XXX,XX +XXX,XX @@ found:
651
/* XXX: cache several refcount block clusters ? */
652
/* @addend is the absolute value of the addend; if @decrease is set, @addend
653
* will be subtracted from the current refcount, otherwise it will be added */
654
-static int update_refcount(BlockDriverState *bs,
655
- int64_t offset,
656
- int64_t length,
657
- uint64_t addend,
658
- bool decrease,
659
- enum qcow2_discard_type type)
660
+static int GRAPH_RDLOCK
661
+update_refcount(BlockDriverState *bs, int64_t offset, int64_t length,
662
+ uint64_t addend, bool decrease, enum qcow2_discard_type type)
663
{
664
BDRVQcow2State *s = bs->opaque;
665
int64_t start, last, cluster_offset;
666
@@ -XXX,XX +XXX,XX @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
667
668
669
/* return < 0 if error */
670
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
671
- uint64_t max)
672
+static int64_t GRAPH_RDLOCK
673
+alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max)
674
{
675
BDRVQcow2State *s = bs->opaque;
676
uint64_t i, nb_clusters, refcount;
677
@@ -XXX,XX +XXX,XX @@ calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
678
* Compares the actual reference count for each cluster in the image against the
679
* refcount as reported by the refcount structures on-disk.
680
*/
681
-static void coroutine_fn
682
+static void coroutine_fn GRAPH_RDLOCK
683
compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
684
BdrvCheckMode fix, bool *rebuild,
685
int64_t *highest_cluster,
686
@@ -XXX,XX +XXX,XX @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
687
*
688
* @allocated should be set to true if a new cluster has been allocated.
689
*/
690
-typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
691
- uint64_t reftable_index, uint64_t *reftable_size,
692
- void *refblock, bool refblock_empty,
693
- bool *allocated, Error **errp);
694
+typedef int /* GRAPH_RDLOCK_PTR */
695
+ (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
696
+ uint64_t reftable_index, uint64_t *reftable_size,
697
+ void *refblock, bool refblock_empty,
698
+ bool *allocated, Error **errp);
699
700
/**
701
* This "operation" for walk_over_reftable() allocates the refblock on disk (if
702
* it is not empty) and inserts its offset into the new reftable. The size of
703
* this new reftable is increased as required.
704
*/
705
-static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
706
- uint64_t reftable_index, uint64_t *reftable_size,
707
- void *refblock, bool refblock_empty, bool *allocated,
708
- Error **errp)
709
+static int GRAPH_RDLOCK
710
+alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
711
+ uint64_t reftable_index, uint64_t *reftable_size,
712
+ void *refblock, bool refblock_empty, bool *allocated,
713
+ Error **errp)
714
{
715
BDRVQcow2State *s = bs->opaque;
716
int64_t offset;
717
@@ -XXX,XX +XXX,XX @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
718
* offset specified by the new reftable's entry. It does not modify the new
719
* reftable or change any refcounts.
720
*/
721
-static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
722
- uint64_t reftable_index, uint64_t *reftable_size,
723
- void *refblock, bool refblock_empty, bool *allocated,
724
- Error **errp)
725
+static int GRAPH_RDLOCK
726
+flush_refblock(BlockDriverState *bs, uint64_t **reftable,
727
+ uint64_t reftable_index, uint64_t *reftable_size,
728
+ void *refblock, bool refblock_empty, bool *allocated,
729
+ Error **errp)
730
{
731
BDRVQcow2State *s = bs->opaque;
732
int64_t offset;
733
@@ -XXX,XX +XXX,XX @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
734
*
735
* @allocated is set to true if a new cluster has been allocated.
736
*/
737
-static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
738
- uint64_t *new_reftable_index,
739
- uint64_t *new_reftable_size,
740
- void *new_refblock, int new_refblock_size,
741
- int new_refcount_bits,
742
- RefblockFinishOp *operation, bool *allocated,
743
- Qcow2SetRefcountFunc *new_set_refcount,
744
- BlockDriverAmendStatusCB *status_cb,
745
- void *cb_opaque, int index, int total,
746
- Error **errp)
747
+static int GRAPH_RDLOCK
748
+walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
749
+ uint64_t *new_reftable_index,
750
+ uint64_t *new_reftable_size,
751
+ void *new_refblock, int new_refblock_size,
752
+ int new_refcount_bits,
753
+ RefblockFinishOp *operation, bool *allocated,
754
+ Qcow2SetRefcountFunc *new_set_refcount,
755
+ BlockDriverAmendStatusCB *status_cb,
756
+ void *cb_opaque, int index, int total,
757
+ Error **errp)
758
{
759
BDRVQcow2State *s = bs->opaque;
760
uint64_t reftable_index;
761
@@ -XXX,XX +XXX,XX @@ done:
762
return ret;
763
}
764
765
-static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
766
- uint64_t offset)
767
+static int64_t coroutine_fn GRAPH_RDLOCK
768
+get_refblock_offset(BlockDriverState *bs, uint64_t offset)
769
{
770
BDRVQcow2State *s = bs->opaque;
771
uint32_t index = offset_to_reftable_index(s, offset);
772
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
773
return covering_refblock_offset;
774
}
775
776
-static int coroutine_fn
777
+static int coroutine_fn GRAPH_RDLOCK
778
qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
779
{
780
BDRVQcow2State *s = bs->opaque;
781
diff --git a/block/qcow2.c b/block/qcow2.c
782
index XXXXXXX..XXXXXXX 100644
783
--- a/block/qcow2.c
784
+++ b/block/qcow2.c
785
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
786
* function when there are no pending requests, it does not guard against
787
* concurrent requests dirtying the image.
788
*/
789
-static int qcow2_mark_clean(BlockDriverState *bs)
790
+static int GRAPH_RDLOCK qcow2_mark_clean(BlockDriverState *bs)
791
{
792
BDRVQcow2State *s = bs->opaque;
793
794
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_corrupt(BlockDriverState *bs)
795
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
796
* before if necessary.
797
*/
798
-static int coroutine_fn qcow2_mark_consistent(BlockDriverState *bs)
799
+static int coroutine_fn GRAPH_RDLOCK
800
+qcow2_mark_consistent(BlockDriverState *bs)
801
{
802
BDRVQcow2State *s = bs->opaque;
803
804
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2ReopenState {
805
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
806
} Qcow2ReopenState;
807
808
-static int qcow2_update_options_prepare(BlockDriverState *bs,
809
- Qcow2ReopenState *r,
810
- QDict *options, int flags,
811
- Error **errp)
812
+static int GRAPH_RDLOCK
813
+qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r,
814
+ QDict *options, int flags, Error **errp)
815
{
816
BDRVQcow2State *s = bs->opaque;
817
QemuOpts *opts = NULL;
818
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
819
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
820
}
821
822
-static int coroutine_fn
823
+static int coroutine_fn GRAPH_RDLOCK
824
qcow2_update_options(BlockDriverState *bs, QDict *options, int flags,
825
Error **errp)
826
{
827
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
828
bs->bl.pdiscard_alignment = s->cluster_size;
829
}
830
831
-static int qcow2_reopen_prepare(BDRVReopenState *state,
832
- BlockReopenQueue *queue, Error **errp)
833
+static int GRAPH_UNLOCKED
834
+qcow2_reopen_prepare(BDRVReopenState *state,BlockReopenQueue *queue,
835
+ Error **errp)
836
{
837
BDRVQcow2State *s = state->bs->opaque;
838
Qcow2ReopenState *r;
839
int ret;
840
841
+ GLOBAL_STATE_CODE();
842
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
843
+
844
r = g_new0(Qcow2ReopenState, 1);
845
state->opaque = r;
846
847
@@ -XXX,XX +XXX,XX @@ static void qcow2_reopen_commit(BDRVReopenState *state)
848
849
static void qcow2_reopen_commit_post(BDRVReopenState *state)
850
{
851
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
852
+
853
if (state->flags & BDRV_O_RDWR) {
854
Error *local_err = NULL;
855
856
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
857
return ret;
858
}
859
860
-static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
861
- int64_t offset, int64_t bytes)
862
+static int coroutine_fn GRAPH_RDLOCK
863
+qcow2_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
864
{
865
int ret;
866
BDRVQcow2State *s = bs->opaque;
867
@@ -XXX,XX +XXX,XX @@ fail:
868
return ret;
869
}
870
871
-static int make_completely_empty(BlockDriverState *bs)
872
+static int GRAPH_RDLOCK make_completely_empty(BlockDriverState *bs)
873
{
874
BDRVQcow2State *s = bs->opaque;
875
Error *local_err = NULL;
876
@@ -XXX,XX +XXX,XX @@ fail:
877
return ret;
878
}
879
880
-static int qcow2_make_empty(BlockDriverState *bs)
881
+static int GRAPH_RDLOCK qcow2_make_empty(BlockDriverState *bs)
882
{
883
BDRVQcow2State *s = bs->opaque;
884
uint64_t offset, end_offset;
885
@@ -XXX,XX +XXX,XX @@ static int qcow2_make_empty(BlockDriverState *bs)
886
return ret;
887
}
888
889
-static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
890
+static coroutine_fn GRAPH_RDLOCK int qcow2_co_flush_to_os(BlockDriverState *bs)
891
{
892
BDRVQcow2State *s = bs->opaque;
893
int ret;
894
@@ -XXX,XX +XXX,XX @@ qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
895
return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0);
896
}
897
898
-static int qcow2_has_compressed_clusters(BlockDriverState *bs)
899
+static int GRAPH_RDLOCK qcow2_has_compressed_clusters(BlockDriverState *bs)
900
{
901
int64_t offset = 0;
902
int64_t bytes = bdrv_getlength(bs);
903
@@ -XXX,XX +XXX,XX @@ static int qcow2_has_compressed_clusters(BlockDriverState *bs)
904
* Downgrades an image's version. To achieve this, any incompatible features
905
* have to be removed.
906
*/
907
-static int qcow2_downgrade(BlockDriverState *bs, int target_version,
908
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
909
- Error **errp)
910
+static int GRAPH_RDLOCK
911
+qcow2_downgrade(BlockDriverState *bs, int target_version,
912
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
913
+ Error **errp)
914
{
915
BDRVQcow2State *s = bs->opaque;
916
int current_version = s->qcow_version;
917
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
918
* features of older versions, some things may have to be presented
919
* differently.
920
*/
921
-static int qcow2_upgrade(BlockDriverState *bs, int target_version,
922
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
923
- Error **errp)
924
+static int GRAPH_RDLOCK
925
+qcow2_upgrade(BlockDriverState *bs, int target_version,
926
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
927
+ Error **errp)
928
{
929
BDRVQcow2State *s = bs->opaque;
930
bool need_snapshot_update;
931
@@ -XXX,XX +XXX,XX @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
932
info->original_cb_opaque);
933
}
934
935
-static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
936
- BlockDriverAmendStatusCB *status_cb,
937
- void *cb_opaque,
938
- bool force,
939
- Error **errp)
940
+static int GRAPH_RDLOCK
941
+qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
942
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
943
+ bool force, Error **errp)
944
{
945
BDRVQcow2State *s = bs->opaque;
946
int old_version = s->qcow_version, new_version = old_version;
947
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
948
char *message;
949
va_list ap;
950
951
- assume_graph_lock(); /* FIXME */
952
-
953
fatal = fatal && bdrv_is_writable(bs);
954
955
if (s->signaled_corruption &&
956
diff --git a/block/replication.c b/block/replication.c
957
index XXXXXXX..XXXXXXX 100644
958
--- a/block/replication.c
959
+++ b/block/replication.c
960
@@ -XXX,XX +XXX,XX @@ out:
961
return ret;
962
}
963
964
-static void secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
965
+static void GRAPH_UNLOCKED
966
+secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
967
{
968
BDRVReplicationState *s = bs->opaque;
969
BdrvChild *active_disk = bs->file;
970
Error *local_err = NULL;
971
int ret;
972
973
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
974
+
975
if (!s->backup_job) {
976
error_setg(errp, "Backup job was cancelled unexpectedly");
977
return;
978
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
979
/* Must be true, or the bdrv_getlength() calls would have failed */
980
assert(active_disk->bs->drv && hidden_disk->bs->drv);
981
982
+ bdrv_graph_rdlock_main_loop();
983
if (!active_disk->bs->drv->bdrv_make_empty ||
984
!hidden_disk->bs->drv->bdrv_make_empty) {
985
error_setg(errp,
986
"Active disk or hidden disk doesn't support make_empty");
987
aio_context_release(aio_context);
988
+ bdrv_graph_rdunlock_main_loop();
989
return;
990
}
991
+ bdrv_graph_rdunlock_main_loop();
992
993
/* reopen the backing file in r/w mode */
994
reopen_backing_file(bs, true, &local_err);
995
--
996
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
qcow2_inactivate() need to hold a reader lock for the graph because it
3
calls bdrv_get_device_or_node_name(), which accesses the parents list of
4
a node.
1
5
6
qcow2_do_close() is a bit strange because it is called from different
7
contexts. If close_data_file = true, we know that we were called from
8
non-coroutine main loop context (more specifically, we're coming from
9
qcow2_close()) and can safely drop the reader lock temporarily with
10
bdrv_graph_rdunlock_main_loop() and acquire the writer lock.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-ID: <20230929145157.45443-16-kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/qcow2.c | 15 ++++++++++-----
18
1 file changed, 10 insertions(+), 5 deletions(-)
19
20
diff --git a/block/qcow2.c b/block/qcow2.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2.c
23
+++ b/block/qcow2.c
24
@@ -XXX,XX +XXX,XX @@ fail_nometa:
25
return ret;
26
}
27
28
-static int qcow2_inactivate(BlockDriverState *bs)
29
+static int GRAPH_RDLOCK qcow2_inactivate(BlockDriverState *bs)
30
{
31
BDRVQcow2State *s = bs->opaque;
32
int ret, result = 0;
33
Error *local_err = NULL;
34
35
- assume_graph_lock(); /* FIXME */
36
-
37
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
38
if (local_err != NULL) {
39
result = -EINVAL;
40
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
41
return result;
42
}
43
44
-static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
45
+static void coroutine_mixed_fn GRAPH_RDLOCK
46
+qcow2_do_close(BlockDriverState *bs, bool close_data_file)
47
{
48
BDRVQcow2State *s = bs->opaque;
49
qemu_vfree(s->l1_table);
50
@@ -XXX,XX +XXX,XX @@ static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
51
g_free(s->image_backing_format);
52
53
if (close_data_file && has_data_file(bs)) {
54
+ GLOBAL_STATE_CODE();
55
+ bdrv_graph_rdunlock_main_loop();
56
bdrv_graph_wrlock(NULL);
57
bdrv_unref_child(bs, s->data_file);
58
bdrv_graph_wrunlock();
59
s->data_file = NULL;
60
+ bdrv_graph_rdlock_main_loop();
61
}
62
63
qcow2_refcount_close(bs);
64
qcow2_free_snapshots(bs);
65
}
66
67
-static void qcow2_close(BlockDriverState *bs)
68
+static void GRAPH_UNLOCKED qcow2_close(BlockDriverState *bs)
69
{
70
+ GLOBAL_STATE_CODE();
71
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
72
+
73
qcow2_do_close(bs, true);
74
}
75
76
--
77
2.41.0
diff view generated by jsdifflib
New patch
1
It still has an assume_graph_lock() call, but all of its callers are now
2
properly annotated to hold the graph lock. Update the function to be
3
GRAPH_RDLOCK as well and remove the assume_graph_lock().
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-17-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/qcow2-bitmap.c | 9 +++------
11
1 file changed, 3 insertions(+), 6 deletions(-)
12
13
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2-bitmap.c
16
+++ b/block/qcow2-bitmap.c
17
@@ -XXX,XX +XXX,XX @@ static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity)
18
return DIV_ROUND_UP(num_bits, 8);
19
}
20
21
-static int check_constraints_on_bitmap(BlockDriverState *bs,
22
- const char *name,
23
- uint32_t granularity,
24
- Error **errp)
25
+static int GRAPH_RDLOCK
26
+check_constraints_on_bitmap(BlockDriverState *bs, const char *name,
27
+ uint32_t granularity, Error **errp)
28
{
29
BDRVQcow2State *s = bs->opaque;
30
int granularity_bits = ctz32(granularity);
31
int64_t len = bdrv_getlength(bs);
32
int64_t bitmap_bytes;
33
34
- assume_graph_lock(); /* FIXME */
35
-
36
assert(granularity > 0);
37
assert((granularity & (granularity - 1)) == 0);
38
39
--
40
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_op_is_blocked() need to hold a reader lock for the graph
3
because it calls bdrv_get_device_or_node_name(), which accesses the
4
parents list of a node.
1
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-ID: <20230929145157.45443-18-kwolf@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 4 +++-
12
block.c | 2 --
13
block/block-backend.c | 1 +
14
block/commit.c | 1 +
15
block/monitor/block-hmp-cmds.c | 3 +++
16
block/qapi-sysemu.c | 9 +++++++--
17
blockdev.c | 15 +++++++++++++++
18
7 files changed, 30 insertions(+), 5 deletions(-)
19
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block-global-state.h
23
+++ b/include/block/block-global-state.h
24
@@ -XXX,XX +XXX,XX @@ bdrv_attach_child(BlockDriverState *parent_bs,
25
BdrvChildRole child_role,
26
Error **errp);
27
28
-bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
29
+bool GRAPH_RDLOCK
30
+bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
31
+
32
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
33
void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason);
34
void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
35
diff --git a/block.c b/block.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block.c
38
+++ b/block.c
39
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
40
BdrvOpBlocker *blocker;
41
GLOBAL_STATE_CODE();
42
43
- assume_graph_lock(); /* FIXME */
44
-
45
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
46
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
47
blocker = QLIST_FIRST(&bs->op_blockers[op]);
48
diff --git a/block/block-backend.c b/block/block-backend.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/block-backend.c
51
+++ b/block/block-backend.c
52
@@ -XXX,XX +XXX,XX @@ bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
53
{
54
BlockDriverState *bs = blk_bs(blk);
55
GLOBAL_STATE_CODE();
56
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
57
58
if (!bs) {
59
return false;
60
diff --git a/block/commit.c b/block/commit.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/commit.c
63
+++ b/block/commit.c
64
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
65
Error *local_err = NULL;
66
67
GLOBAL_STATE_CODE();
68
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
69
70
if (!drv)
71
return -ENOMEDIUM;
72
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/monitor/block-hmp-cmds.c
75
+++ b/block/monitor/block-hmp-cmds.c
76
@@ -XXX,XX +XXX,XX @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
77
AioContext *aio_context;
78
Error *local_err = NULL;
79
80
+ GLOBAL_STATE_CODE();
81
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
82
+
83
bs = bdrv_find_node(id);
84
if (bs) {
85
qmp_blockdev_del(id, &local_err);
86
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/qapi-sysemu.c
89
+++ b/block/qapi-sysemu.c
90
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_close_tray(const char *device,
91
}
92
}
93
94
-static void blockdev_remove_medium(const char *device, const char *id,
95
- Error **errp)
96
+static void GRAPH_UNLOCKED
97
+blockdev_remove_medium(const char *device, const char *id, Error **errp)
98
{
99
BlockBackend *blk;
100
BlockDriverState *bs;
101
AioContext *aio_context;
102
bool has_attached_device;
103
104
+ GLOBAL_STATE_CODE();
105
+
106
blk = qmp_get_blk(device, id, errp);
107
if (!blk) {
108
return;
109
@@ -XXX,XX +XXX,XX @@ static void blockdev_remove_medium(const char *device, const char *id,
110
aio_context = bdrv_get_aio_context(bs);
111
aio_context_acquire(aio_context);
112
113
+ bdrv_graph_rdlock_main_loop();
114
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
115
+ bdrv_graph_rdunlock_main_loop();
116
goto out;
117
}
118
+ bdrv_graph_rdunlock_main_loop();
119
120
blk_remove_bs(blk);
121
122
diff --git a/blockdev.c b/blockdev.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/blockdev.c
125
+++ b/blockdev.c
126
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
127
}
128
129
/* Early check to avoid creating target */
130
+ bdrv_graph_rdlock_main_loop();
131
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
132
+ bdrv_graph_rdunlock_main_loop();
133
goto out;
134
}
135
+ bdrv_graph_rdunlock_main_loop();
136
137
flags = bs->open_flags | BDRV_O_RDWR;
138
139
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
140
return;
141
}
142
143
+ bdrv_graph_co_rdlock();
144
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
145
error_setg(errp, QERR_DEVICE_IN_USE, device);
146
+ bdrv_graph_co_rdunlock();
147
return;
148
}
149
+ bdrv_graph_co_rdunlock();
150
151
blk = blk_co_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
152
if (!blk) {
153
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
154
* Check for op blockers in the whole chain between bs and base (or bottom)
155
*/
156
iter_end = bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
157
+ bdrv_graph_rdlock_main_loop();
158
for (iter = bs; iter && iter != iter_end;
159
iter = bdrv_filter_or_cow_bs(iter))
160
{
161
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
162
+ bdrv_graph_rdunlock_main_loop();
163
goto out;
164
}
165
}
166
+ bdrv_graph_rdunlock_main_loop();
167
168
/* if we are streaming the entire chain, the result will have no backing
169
* file, and specifying one is therefore an error */
170
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
171
}
172
173
/* Early check to avoid creating target */
174
+ bdrv_graph_rdlock_main_loop();
175
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
176
+ bdrv_graph_rdunlock_main_loop();
177
return;
178
}
179
+ bdrv_graph_rdunlock_main_loop();
180
181
aio_context = bdrv_get_aio_context(bs);
182
aio_context_acquire(aio_context);
183
@@ -XXX,XX +XXX,XX @@ void qmp_change_backing_file(const char *device,
184
185
/* even though we are not necessarily operating on bs, we need it to
186
* determine if block ops are currently prohibited on the chain */
187
+ bdrv_graph_rdlock_main_loop();
188
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
189
+ bdrv_graph_rdunlock_main_loop();
190
goto out;
191
}
192
+ bdrv_graph_rdunlock_main_loop();
193
194
/* final sanity check */
195
if (!bdrv_chain_contains(bs, image_bs)) {
196
--
197
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_apply_auto_read_only() need to hold a reader lock for the graph
3
because it calls bdrv_can_set_read_only(), which indirectly accesses the
4
parents list of a node.
1
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-ID: <20230929145157.45443-19-kwolf@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-io.h | 6 ++++--
12
block.c | 4 ++--
13
block/bochs.c | 2 ++
14
block/cloop.c | 2 ++
15
block/curl.c | 2 ++
16
block/dmg.c | 2 ++
17
block/gluster.c | 2 ++
18
block/iscsi.c | 2 ++
19
block/nbd.c | 3 ++-
20
block/rbd.c | 2 ++
21
10 files changed, 22 insertions(+), 5 deletions(-)
22
23
diff --git a/include/block/block-io.h b/include/block/block-io.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block-io.h
26
+++ b/include/block/block-io.h
27
@@ -XXX,XX +XXX,XX @@ bdrv_is_allocated_above(BlockDriverState *bs, BlockDriverState *base,
28
int coroutine_fn GRAPH_RDLOCK
29
bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
30
31
-int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
32
- Error **errp);
33
+int GRAPH_RDLOCK
34
+bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
35
+ Error **errp);
36
+
37
bool bdrv_is_read_only(BlockDriverState *bs);
38
bool bdrv_is_writable(BlockDriverState *bs);
39
bool bdrv_is_sg(BlockDriverState *bs);
40
diff --git a/block.c b/block.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block.c
43
+++ b/block.c
44
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
45
int ret = 0;
46
IO_CODE();
47
48
- assume_graph_lock(); /* FIXME */
49
-
50
if (!(bs->open_flags & BDRV_O_RDWR)) {
51
return 0;
52
}
53
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
54
55
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, ro)) {
56
if (!ro && bdrv_is_whitelisted(drv, true)) {
57
+ bdrv_graph_rdlock_main_loop();
58
ret = bdrv_apply_auto_read_only(bs, NULL, NULL);
59
+ bdrv_graph_rdunlock_main_loop();
60
} else {
61
ret = -ENOTSUP;
62
}
63
diff --git a/block/bochs.c b/block/bochs.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/bochs.c
66
+++ b/block/bochs.c
67
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
68
int ret;
69
70
/* No write support yet */
71
+ bdrv_graph_rdlock_main_loop();
72
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
73
+ bdrv_graph_rdunlock_main_loop();
74
if (ret < 0) {
75
return ret;
76
}
77
diff --git a/block/cloop.c b/block/cloop.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/cloop.c
80
+++ b/block/cloop.c
81
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
82
uint32_t offsets_size, max_compressed_block_size = 1, i;
83
int ret;
84
85
+ bdrv_graph_rdlock_main_loop();
86
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
87
+ bdrv_graph_rdunlock_main_loop();
88
if (ret < 0) {
89
return ret;
90
}
91
diff --git a/block/curl.c b/block/curl.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/block/curl.c
94
+++ b/block/curl.c
95
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
96
const char *protocol_delimiter;
97
int ret;
98
99
+ bdrv_graph_rdlock_main_loop();
100
ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
101
errp);
102
+ bdrv_graph_rdunlock_main_loop();
103
if (ret < 0) {
104
return ret;
105
}
106
diff --git a/block/dmg.c b/block/dmg.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/dmg.c
109
+++ b/block/dmg.c
110
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
111
int64_t offset;
112
int ret;
113
114
+ bdrv_graph_rdlock_main_loop();
115
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
116
+ bdrv_graph_rdunlock_main_loop();
117
if (ret < 0) {
118
return ret;
119
}
120
diff --git a/block/gluster.c b/block/gluster.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/gluster.c
123
+++ b/block/gluster.c
124
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
125
if (ret == -EACCES || ret == -EROFS) {
126
/* Try to degrade to read-only, but if it doesn't work, still use the
127
* normal error message. */
128
+ bdrv_graph_rdlock_main_loop();
129
if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
130
open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
131
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
132
ret = s->fd ? 0 : -errno;
133
}
134
+ bdrv_graph_rdunlock_main_loop();
135
}
136
137
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
143
/* Check the write protect flag of the LUN if we want to write */
144
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
145
iscsilun->write_protected) {
146
+ bdrv_graph_rdlock_main_loop();
147
ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
148
+ bdrv_graph_rdunlock_main_loop();
149
if (ret < 0) {
150
goto out;
151
}
152
diff --git a/block/nbd.c b/block/nbd.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/nbd.c
155
+++ b/block/nbd.c
156
@@ -XXX,XX +XXX,XX @@ static bool nbd_client_will_reconnect(BDRVNBDState *s)
157
* Return failure if the server's advertised options are incompatible with the
158
* client's needs.
159
*/
160
-static int nbd_handle_updated_info(BlockDriverState *bs, Error **errp)
161
+static int coroutine_fn GRAPH_RDLOCK
162
+nbd_handle_updated_info(BlockDriverState *bs, Error **errp)
163
{
164
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
165
int ret;
166
diff --git a/block/rbd.c b/block/rbd.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/rbd.c
169
+++ b/block/rbd.c
170
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
171
/* If we are using an rbd snapshot, we must be r/o, otherwise
172
* leave as-is */
173
if (s->snap != NULL) {
174
+ bdrv_graph_rdlock_main_loop();
175
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
176
+ bdrv_graph_rdunlock_main_loop();
177
if (r < 0) {
178
goto failed_post_open;
179
}
180
--
181
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_get_specific_info() need to hold a reader lock for the graph.
3
This removes an assume_graph_lock() call in vmdk's implementation.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-20-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-io.h | 5 +++--
11
include/block/block_int-common.h | 4 ++--
12
block/vmdk.c | 6 ++----
13
qemu-io-cmds.c | 3 +++
14
4 files changed, 10 insertions(+), 8 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 @@ bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
21
int co_wrapper_mixed_bdrv_rdlock
22
bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
23
24
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
25
- Error **errp);
26
+ImageInfoSpecific * GRAPH_RDLOCK
27
+bdrv_get_specific_info(BlockDriverState *bs, Error **errp);
28
+
29
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
30
void bdrv_round_to_subclusters(BlockDriverState *bs,
31
int64_t offset, int64_t bytes,
32
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int-common.h
35
+++ b/include/block/block_int-common.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_get_info)(
38
BlockDriverState *bs, BlockDriverInfo *bdi);
39
40
- ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
41
- Error **errp);
42
+ ImageInfoSpecific * GRAPH_RDLOCK_PTR (*bdrv_get_specific_info)(
43
+ BlockDriverState *bs, Error **errp);
44
BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
45
46
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)(
47
diff --git a/block/vmdk.c b/block/vmdk.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/vmdk.c
50
+++ b/block/vmdk.c
51
@@ -XXX,XX +XXX,XX @@ vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
52
return ret;
53
}
54
55
-static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
56
- Error **errp)
57
+static ImageInfoSpecific * GRAPH_RDLOCK
58
+vmdk_get_specific_info(BlockDriverState *bs, Error **errp)
59
{
60
int i;
61
BDRVVmdkState *s = bs->opaque;
62
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
63
VmdkExtentInfoList **tail;
64
65
- assume_graph_lock(); /* FIXME */
66
-
67
*spec_info = (ImageInfoSpecific){
68
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
69
.u = {
70
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qemu-io-cmds.c
73
+++ b/qemu-io-cmds.c
74
@@ -XXX,XX +XXX,XX @@ static int info_f(BlockBackend *blk, int argc, char **argv)
75
char s1[64], s2[64];
76
int ret;
77
78
+ GLOBAL_STATE_CODE();
79
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
80
+
81
if (bs->drv && bs->drv->format_name) {
82
printf("format name: %s\n", bs->drv->format_name);
83
}
84
--
85
2.41.0
diff view generated by jsdifflib
New patch
1
Almost all functions that access the parent link already take the graph
2
lock now. Add locking to the remaining user in a test case and finally
3
annotate the struct field itself as protected by the graph lock.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-21-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int-common.h | 4 ++--
11
tests/unit/test-block-iothread.c | 5 +++++
12
2 files changed, 7 insertions(+), 2 deletions(-)
13
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int-common.h
17
+++ b/include/block/block_int-common.h
18
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
19
bool quiesced_parent;
20
21
QLIST_ENTRY(BdrvChild) next;
22
- QLIST_ENTRY(BdrvChild) next_parent;
23
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
24
};
25
26
/*
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
28
BdrvChild *backing;
29
BdrvChild *file;
30
31
- QLIST_HEAD(, BdrvChild) parents;
32
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) parents;
33
34
QDict *options;
35
QDict *explicit_options;
36
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/unit/test-block-iothread.c
39
+++ b/tests/unit/test-block-iothread.c
40
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
41
BlockDriverState *bs;
42
BdrvChild *c;
43
44
+ GLOBAL_STATE_CODE();
45
+
46
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
47
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
48
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
49
blk_insert_bs(blk, bs, &error_abort);
50
+
51
+ bdrv_graph_rdlock_main_loop();
52
c = QLIST_FIRST(&bs->parents);
53
+ bdrv_graph_rdunlock_main_loop();
54
55
blk_set_aio_context(blk, ctx, &error_abort);
56
aio_context_acquire(ctx);
57
--
58
2.41.0
diff view generated by jsdifflib
1
From: Bernhard Beschow <shentey@gmail.com>
1
Almost all functions that access the child links already take the graph
2
lock now. Add locking to the remaining users and finally annotate the
3
struct field itself as protected by the graph lock.
2
4
3
Other ISA devices such as serial-isa use the properties in their
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
build_aml functions. fdc-isa not using them is probably an oversight.
6
Message-ID: <20230929145157.45443-22-kwolf@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-Id: <20220209191558.30393-1-shentey@gmail.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
hw/block/fdc-isa.c | 11 +++++++----
10
include/block/block_int-common.h | 4 ++--
12
1 file changed, 7 insertions(+), 4 deletions(-)
11
block.c | 2 ++
12
block/replication.c | 3 ++-
13
tests/unit/test-bdrv-drain.c | 4 ++++
14
4 files changed, 10 insertions(+), 3 deletions(-)
13
15
14
diff --git a/hw/block/fdc-isa.c b/hw/block/fdc-isa.c
16
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/block/fdc-isa.c
18
--- a/include/block/block_int-common.h
17
+++ b/hw/block/fdc-isa.c
19
+++ b/include/block/block_int-common.h
18
@@ -XXX,XX +XXX,XX @@ int cmos_get_fd_drive_type(FloppyDriveType fd0)
20
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
19
21
*/
20
static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope)
22
bool quiesced_parent;
23
24
- QLIST_ENTRY(BdrvChild) next;
25
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next;
26
QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
27
};
28
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
30
* See also comment in include/block/block.h, to learn how backing and file
31
* are connected with BdrvChildRole.
32
*/
33
- QLIST_HEAD(, BdrvChild) children;
34
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) children;
35
BdrvChild *backing;
36
BdrvChild *file;
37
38
diff --git a/block.c b/block.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block.c
41
+++ b/block.c
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
21
{
43
{
22
+ FDCtrlISABus *isa = ISA_FDC(isadev);
44
assert(!child->bs);
23
Aml *dev;
45
GLOBAL_STATE_CODE();
24
Aml *crs;
46
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
25
int i;
47
+
26
@@ -XXX,XX +XXX,XX @@ static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope)
48
assert(!child->next.le_prev); /* not in children list */
27
};
49
28
50
g_free(child->name);
29
crs = aml_resource_template();
51
diff --git a/block/replication.c b/block/replication.c
30
- aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04));
52
index XXXXXXX..XXXXXXX 100644
31
- aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01));
53
--- a/block/replication.c
32
- aml_append(crs, aml_irq_no_flags(6));
54
+++ b/block/replication.c
33
aml_append(crs,
55
@@ -XXX,XX +XXX,XX @@ static void backup_job_completed(void *opaque, int ret)
34
- aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
56
backup_job_cleanup(bs);
35
+ aml_io(AML_DECODE16, isa->iobase + 2, isa->iobase + 2, 0x00, 0x04));
57
}
36
+ aml_append(crs,
58
37
+ aml_io(AML_DECODE16, isa->iobase + 7, isa->iobase + 7, 0x00, 0x01));
59
-static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
38
+ aml_append(crs, aml_irq_no_flags(isa->irq));
60
+static bool GRAPH_RDLOCK
39
+ aml_append(crs,
61
+check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
40
+ aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, isa->dma));
62
{
41
63
BdrvChild *child;
42
dev = aml_device("FDC0");
64
43
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
65
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/tests/unit/test-bdrv-drain.c
68
+++ b/tests/unit/test-bdrv-drain.c
69
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
70
blk_co_unref(blk);
71
} else {
72
BdrvChild *c, *next_c;
73
+ bdrv_graph_co_rdlock();
74
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
75
+ bdrv_graph_co_rdunlock();
76
bdrv_co_unref_child(bs, c);
77
+ bdrv_graph_co_rdlock();
78
}
79
+ bdrv_graph_co_rdunlock();
80
}
81
82
dbdd->done = true;
44
--
83
--
45
2.34.1
84
2.41.0
46
47
diff view generated by jsdifflib
1
The 'throttle' block driver implements .bdrv_co_drain_end, so
1
bdrv_graph_wrlock() can't run in a coroutine (because it polls) and
2
blockdev-reopen will have to wait for it to complete in the polling
2
requires holding the BQL. We already have GLOBAL_STATE_CODE() to assert
3
loop at the end of qmp_blockdev_reopen(). This makes AIO_WAIT_WHILE()
3
the latter. Assert the former as well and add a no_coroutine_fn marker.
4
release the AioContext lock, which causes a crash if the lock hasn't
5
correctly been taken.
6
4
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20220203140534.36522-3-kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-23-kwolf@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
9
---
12
tests/qemu-iotests/245 | 36 +++++++++++++++++++++++++++++++++---
10
include/block/graph-lock.h | 3 ++-
13
tests/qemu-iotests/245.out | 4 ++--
11
block/graph-lock.c | 3 ++-
14
2 files changed, 35 insertions(+), 5 deletions(-)
12
2 files changed, 4 insertions(+), 2 deletions(-)
15
13
16
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
14
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/245
19
+++ b/tests/qemu-iotests/245
20
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
21
self.assertEqual(self.get_node('hd1'), None)
22
self.assert_qmp(self.get_node('hd2'), 'ro', True)
23
24
- def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None):
25
- opts = hd_opts(0)
26
+ def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None,
27
+ opts_a = None, opts_b = None):
28
+ opts = opts_a or hd_opts(0)
29
result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
30
self.assert_qmp(result, 'return', {})
31
32
- opts2 = hd_opts(2)
33
+ opts2 = opts_b or hd_opts(2)
34
result = self.vm.qmp('blockdev-add', conv_keys = False, **opts2)
35
self.assert_qmp(result, 'return', {})
36
37
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
38
def test_iothreads_switch_overlay(self):
39
self.run_test_iothreads('', 'iothread0')
40
41
+ def test_iothreads_with_throttling(self):
42
+ # Create a throttle-group object
43
+ opts = { 'qom-type': 'throttle-group', 'id': 'group0',
44
+ 'limits': { 'iops-total': 1000 } }
45
+ result = self.vm.qmp('object-add', conv_keys = False, **opts)
46
+ self.assert_qmp(result, 'return', {})
47
+
48
+ # Options with a throttle filter between format and protocol
49
+ opts = [
50
+ {
51
+ 'driver': iotests.imgfmt,
52
+ 'node-name': f'hd{idx}',
53
+ 'file' : {
54
+ 'node-name': f'hd{idx}-throttle',
55
+ 'driver': 'throttle',
56
+ 'throttle-group': 'group0',
57
+ 'file': {
58
+ 'driver': 'file',
59
+ 'node-name': f'hd{idx}-file',
60
+ 'filename': hd_path[idx],
61
+ },
62
+ },
63
+ }
64
+ for idx in (0, 2)
65
+ ]
66
+
67
+ self.run_test_iothreads('iothread0', 'iothread0', None,
68
+ opts[0], opts[1])
69
+
70
if __name__ == '__main__':
71
iotests.activate_logging()
72
iotests.main(supported_fmts=["qcow2"],
73
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
74
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
75
--- a/tests/qemu-iotests/245.out
16
--- a/include/block/graph-lock.h
76
+++ b/tests/qemu-iotests/245.out
17
+++ b/include/block/graph-lock.h
77
@@ -XXX,XX +XXX,XX @@ read 1/1 bytes at offset 262152
18
@@ -XXX,XX +XXX,XX @@ void unregister_aiocontext(AioContext *ctx);
78
read 1/1 bytes at offset 262160
19
* This function polls. Callers must not hold the lock of any AioContext other
79
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
20
* than the current one and the one of @bs.
80
21
*/
81
-...............
22
-void bdrv_graph_wrlock(BlockDriverState *bs) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
82
+................
23
+void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
83
----------------------------------------------------------------------
24
+bdrv_graph_wrlock(BlockDriverState *bs);
84
-Ran 25 tests
25
85
+Ran 26 tests
26
/*
86
27
* bdrv_graph_wrunlock:
87
OK
28
diff --git a/block/graph-lock.c b/block/graph-lock.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/graph-lock.c
31
+++ b/block/graph-lock.c
32
@@ -XXX,XX +XXX,XX @@ static uint32_t reader_count(void)
33
return rd;
34
}
35
36
-void bdrv_graph_wrlock(BlockDriverState *bs)
37
+void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs)
38
{
39
AioContext *ctx = NULL;
40
41
GLOBAL_STATE_CODE();
42
assert(!qatomic_read(&has_writer));
43
+ assert(!qemu_in_coroutine());
44
45
/*
46
* Release only non-mainloop AioContext. The mainloop often relies on the
88
--
47
--
89
2.34.1
48
2.41.0
90
91
diff view generated by jsdifflib