1
The following changes since commit 9964e96dc9999cf7f7c936ee854a795415d19b60:
1
The following changes since commit a51e5124a655b3dad80b36b18547cb1eca2c5eb2:
2
2
3
Merge remote-tracking branch 'jasowang/tags/net-pull-request' into staging (2017-05-23 15:01:31 +0100)
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://repo.or.cz/qemu/kevin.git tags/for-upstream
7
8
8
git://repo.or.cz/qemu/kevin.git tags/for-upstream
9
for you to fetch changes up to e6e964b8b021446c8d3d1f91c0208f653e9ec92c:
9
10
10
for you to fetch changes up to 42a48128417b3bfade93d1a4721348cc480e9e50:
11
block: Add assertion for bdrv_graph_wrlock() (2023-10-12 16:31:33 +0200)
11
12
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-05-29-v3' into queue-block (2017-05-29 16:34:27 +0200)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
16
Block layer patches
14
Block layer patches
17
15
16
- Clean up coroutine versions of bdrv_{is_allocated,block_status}*
17
- Graph locking part 5 (protect children/parent links)
18
18
----------------------------------------------------------------
19
----------------------------------------------------------------
19
Alberto Garcia (2):
20
Emanuele Giuseppe Esposito (1):
20
stream: fix crash in stream_start() when block_job_create() fails
21
block: Mark drain related functions GRAPH_RDLOCK
21
qcow2: remove extra local_error variable
22
22
23
Daniel P. Berrange (4):
23
Kevin Wolf (21):
24
qemu-img: add support for --object with 'dd' command
24
test-bdrv-drain: Don't call bdrv_graph_wrlock() in coroutine context
25
qemu-img: fix --image-opts usage with dd command
25
block-coroutine-wrapper: Add no_co_wrapper_bdrv_rdlock functions
26
qemu-img: introduce --target-image-opts for 'convert' command
26
block: Take graph rdlock in bdrv_inactivate_all()
27
qemu-img: copy *key-secret opts when opening newly created files
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()
28
45
29
Eric Blake (1):
46
Paolo Bonzini (4):
30
block: Tweak error message related to qemu-img amend
47
block: rename the bdrv_co_block_status static function
48
block: complete public block status API
49
block: switch to co_wrapper for bdrv_is_allocated_*
50
block: convert more bdrv_is_allocated* and bdrv_block_status* calls to coroutine versions
31
51
32
Fam Zheng (3):
52
block/qcow2.h | 187 ++++++++++++++++------------
33
iotests: 147: Don't test inet6 if not available
53
block/vhdx.h | 5 +-
34
qemu-img: Fix documentation of convert
54
include/block/block-common.h | 7 +-
35
qemu-img: Fix leakage of options on error
55
include/block/block-global-state.h | 34 ++---
36
56
include/block/block-io.h | 71 +++++++----
37
Kevin Wolf (3):
57
include/block/block_int-common.h | 69 +++++-----
38
qemu-iotests: Test streaming with missing job ID
58
include/block/block_int-io.h | 7 +-
39
mirror: Drop permissions on s->target on completion
59
include/block/graph-lock.h | 3 +-
40
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-05-29-v3' into queue-block
60
include/block/qapi.h | 23 ++--
41
61
include/block/snapshot.h | 24 ++--
42
Max Reitz (2):
62
include/sysemu/block-backend-global-state.h | 4 +-
43
block: Fix backing paths for filenames with colons
63
block.c | 120 ++++++++++++------
44
block/file-*: *_parse_filename() and colons
64
block/backup.c | 1 +
45
65
block/block-backend.c | 9 +-
46
Stephen Bates (1):
66
block/bochs.c | 2 +
47
nvme: Add support for Controller Memory Buffers
67
block/cloop.c | 2 +
48
68
block/commit.c | 1 +
49
block.c | 50 +++++++++++++--
69
block/copy-before-write.c | 2 +-
50
block/file-posix.c | 17 +-----
70
block/copy-on-read.c | 8 +-
51
block/file-win32.c | 12 +---
71
block/crypto.c | 4 +-
52
block/mirror.c | 7 ++-
72
block/curl.c | 2 +
53
block/qcow2-cluster.c | 3 +-
73
block/dmg.c | 2 +
54
block/qcow2.c | 5 +-
74
block/export/export.c | 4 +
55
block/stream.c | 2 +-
75
block/gluster.c | 2 +
56
hw/block/nvme.c | 75 +++++++++++++++++++++--
76
block/graph-lock.c | 3 +-
57
hw/block/nvme.h | 73 ++++++++++++++++++++++
77
block/io.c | 143 ++++++++++-----------
58
include/block/block_int.h | 3 +
78
block/iscsi.c | 2 +
59
qemu-img-cmds.hx | 4 +-
79
block/mirror.c | 10 +-
60
qemu-img.c | 148 +++++++++++++++++++++++++++++++++++----------
80
block/monitor/block-hmp-cmds.c | 5 +
61
qemu-img.texi | 12 +++-
81
block/nbd.c | 3 +-
62
tests/qemu-iotests/030 | 4 ++
82
block/nfs.c | 2 +-
63
tests/qemu-iotests/030.out | 4 +-
83
block/parallels.c | 3 +
64
tests/qemu-iotests/060.out | 2 +-
84
block/qapi-sysemu.c | 11 +-
65
tests/qemu-iotests/147 | 7 +++
85
block/qapi.c | 11 +-
66
17 files changed, 351 insertions(+), 77 deletions(-)
86
block/qcow.c | 3 +
67
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
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The --image-opts flag can only be used to affect the parsing
3
bdrv_block_status exists as a wrapper for bdrv_block_status_above, but
4
of the source image. The target image has to be specified in
4
the name of the (hypothetical) coroutine version, bdrv_co_block_status,
5
the traditional style regardless, since it needs to be passed
5
is squatted by a random static function. Rename it to
6
to the bdrv_create() API which does not support the new style
6
bdrv_co_do_block_status.
7
opts.
8
7
9
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-ID: <20230904100306.156197-2-pbonzini@redhat.com>
11
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Message-id: 20170515164712.6643-3-berrange@redhat.com
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
12
---
15
qemu-img.c | 9 +++++++--
13
block/io.c | 21 +++++++++++----------
16
1 file changed, 7 insertions(+), 2 deletions(-)
14
1 file changed, 11 insertions(+), 10 deletions(-)
17
15
18
diff --git a/qemu-img.c b/qemu-img.c
16
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/qemu-img.c
18
--- a/block/io.c
21
+++ b/qemu-img.c
19
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
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);
23
goto out;
41
goto out;
24
}
42
}
25
43
26
- blk2 = img_open(image_opts, out.filename, out_fmt, BDRV_O_RDWR,
44
@@ -XXX,XX +XXX,XX @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
27
- false, false, false);
45
int64_t file_pnum;
28
+ /* TODO, we can't honour --image-opts for the target,
46
int ret2;
29
+ * since it needs to be given in a format compatible
47
30
+ * with the bdrv_create() call above which does not
48
- ret2 = bdrv_co_block_status(local_file, want_zero, local_map,
31
+ * support image-opts style.
49
- *pnum, &file_pnum, NULL, NULL);
32
+ */
50
+ ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map,
33
+ blk2 = img_open_file(out.filename, out_fmt, BDRV_O_RDWR,
51
+ *pnum, &file_pnum, NULL, NULL);
34
+ false, false, false);
52
if (ret2 >= 0) {
35
53
/* Ignore errors. This is just providing extra information, it
36
if (!blk2) {
54
* is useful but not necessary.
37
ret = -1;
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;
38
--
76
--
39
1.8.3.1
77
2.41.0
40
41
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
1
From: Alberto Garcia <berto@igalia.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The code that tries to reopen a BlockDriverState in stream_start()
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
when the creation of a new block job fails crashes because it attempts
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
to dereference a pointer that is known to be NULL.
5
Message-ID: <20230904100306.156197-5-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
This is a regression introduced in a170a91fd3eab6155da39e740381867e,
8
likely because the code was copied from stream_complete().
9
10
Cc: qemu-stable@nongnu.org
11
Reported-by: Kashyap Chamarthy <kchamart@redhat.com>
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Tested-by: Kashyap Chamarthy <kchamart@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
8
---
16
block/stream.c | 2 +-
9
block/copy-before-write.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
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
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
}
19
diff --git a/block/stream.c b/block/stream.c
146
diff --git a/block/stream.c b/block/stream.c
20
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
21
--- a/block/stream.c
148
--- a/block/stream.c
22
+++ b/block/stream.c
149
+++ b/block/stream.c
23
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
24
151
copy = false;
25
fail:
152
26
if (orig_bs_flags != bdrv_get_flags(bs)) {
153
WITH_GRAPH_RDLOCK_GUARD() {
27
- bdrv_reopen(bs, s->bs_flags, NULL);
154
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
28
+ bdrv_reopen(bs, orig_bs_flags, NULL);
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)
29
}
188
}
30
}
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
}
31
--
215
--
32
1.8.3.1
216
2.41.0
33
34
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
1
From: Max Reitz <mreitz@redhat.com>
1
The function reads the parents list, so it needs to hold the graph lock.
2
2
3
The file drivers' *_parse_filename() implementations just strip the
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
optional protocol prefix off the filename. However, for e.g.
4
Message-ID: <20230929145157.45443-4-kwolf@redhat.com>
5
"file:foo:bar", this would lead to "foo:bar" being stored as the BDS's
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
filename which looks like it should be managed using the "foo" protocol.
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
This is especially troublesome if you then try to resolve a backing
8
filename based on "foo:bar".
9
10
This issue can only occur if the stripped part is a relative filename
11
("file:/foo:bar" will be shortened to "/foo:bar" and having a slash
12
before the first colon means that "/foo" is not recognized as a protocol
13
part). Therefore, we can easily fix it by prepending "./" to such
14
filenames.
15
16
Before this patch:
17
$ ./qemu-img create -f qcow2 backing.qcow2 64M
18
Formatting 'backing.qcow2', fmt=qcow2 size=67108864 encryption=off
19
cluster_size=65536 lazy_refcounts=off refcount_bits=16
20
$ ./qemu-img create -f qcow2 -b backing.qcow2 file:top:image.qcow2
21
Formatting 'file:top:image.qcow2', fmt=qcow2 size=67108864
22
backing_file=backing.qcow2 encryption=off cluster_size=65536
23
lazy_refcounts=off refcount_bits=16
24
$ ./qemu-io file:top:image.qcow2
25
can't open device file:top:image.qcow2: Could not open backing file:
26
Unknown protocol 'top'
27
28
After this patch:
29
$ ./qemu-io file:top:image.qcow2
30
[no error]
31
32
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
Message-id: 20170522195217.12991-3-mreitz@redhat.com
34
Reviewed-by: Eric Blake <eblake@redhat.com>
35
Signed-off-by: Max Reitz <mreitz@redhat.com>
36
---
7
---
37
block.c | 35 +++++++++++++++++++++++++++++++++++
8
block.c | 7 ++++---
38
block/file-posix.c | 17 +++--------------
9
1 file changed, 4 insertions(+), 3 deletions(-)
39
block/file-win32.c | 12 ++----------
40
include/block/block_int.h | 3 +++
41
4 files changed, 43 insertions(+), 24 deletions(-)
42
10
43
diff --git a/block.c b/block.c
11
diff --git a/block.c b/block.c
44
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
45
--- a/block.c
13
--- a/block.c
46
+++ b/block.c
14
+++ b/block.c
47
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
15
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
48
}
16
}
49
}
17
}
50
18
51
+/*
19
-static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
52
+ * Helper function for bdrv_parse_filename() implementations to remove optional
20
+static bool GRAPH_RDLOCK
53
+ * protocol prefixes (especially "file:") from a filename and for putting the
21
+bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
54
+ * stripped filename into the options QDict if there is such a prefix.
55
+ */
56
+void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
57
+ QDict *options)
58
+{
59
+ if (strstart(filename, prefix, &filename)) {
60
+ /* Stripping the explicit protocol prefix may result in a protocol
61
+ * prefix being (wrongly) detected (if the filename contains a colon) */
62
+ if (path_has_protocol(filename)) {
63
+ QString *fat_filename;
64
+
65
+ /* This means there is some colon before the first slash; therefore,
66
+ * this cannot be an absolute path */
67
+ assert(!path_is_absolute(filename));
68
+
69
+ /* And we can thus fix the protocol detection issue by prefixing it
70
+ * by "./" */
71
+ fat_filename = qstring_from_str("./");
72
+ qstring_append(fat_filename, filename);
73
+
74
+ assert(!path_has_protocol(qstring_get_str(fat_filename)));
75
+
76
+ qdict_put(options, "filename", fat_filename);
77
+ } else {
78
+ /* If no protocol prefix was detected, we can use the shortened
79
+ * filename as-is */
80
+ qdict_put_str(options, "filename", filename);
81
+ }
82
+ }
83
+}
84
+
85
+
86
/* Returns whether the image file is opened as read-only. Note that this can
87
* return false and writing to the image file is still not possible because the
88
* image is inactivated. */
89
diff --git a/block/file-posix.c b/block/file-posix.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/file-posix.c
92
+++ b/block/file-posix.c
93
@@ -XXX,XX +XXX,XX @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
94
static void raw_parse_filename(const char *filename, QDict *options,
95
Error **errp)
96
{
22
{
97
- /* The filename does not have to be prefixed by the protocol name, since
23
BdrvChild *parent;
98
- * "file" is the default protocol; therefore, the return value of this
24
GLOBAL_STATE_CODE();
99
- * function call can be ignored. */
25
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
100
- strstart(filename, "file:", &filename);
26
return false;
101
-
102
- qdict_put_str(options, "filename", filename);
103
+ bdrv_parse_filename_strip_prefix(filename, "file:", options);
104
}
27
}
105
28
106
static QemuOptsList raw_runtime_opts = {
29
-static int bdrv_inactivate_recurse(BlockDriverState *bs)
107
@@ -XXX,XX +XXX,XX @@ static int check_hdev_writable(BDRVRawState *s)
30
+static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs)
108
static void hdev_parse_filename(const char *filename, QDict *options,
109
Error **errp)
110
{
31
{
111
- /* The prefix is optional, just as for "file". */
32
BdrvChild *child, *parent;
112
- strstart(filename, "host_device:", &filename);
33
int ret;
113
-
34
uint64_t cumulative_perms, cumulative_shared_perms;
114
- qdict_put_str(options, "filename", filename);
35
115
+ bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
36
GLOBAL_STATE_CODE();
116
}
37
- GRAPH_RDLOCK_GUARD_MAINLOOP();
117
38
118
static bool hdev_is_sg(BlockDriverState *bs)
39
if (!bs->drv) {
119
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
40
return -ENOMEDIUM;
120
static void cdrom_parse_filename(const char *filename, QDict *options,
41
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
121
Error **errp)
42
GSList *aio_ctxs = NULL, *ctx;
122
{
43
123
- /* The prefix is optional, just as for "file". */
44
GLOBAL_STATE_CODE();
124
- strstart(filename, "host_cdrom:", &filename);
45
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
125
-
46
126
- qdict_put_str(options, "filename", filename);
47
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
127
+ bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options);
48
AioContext *aio_context = bdrv_get_aio_context(bs);
128
}
129
#endif
130
131
diff --git a/block/file-win32.c b/block/file-win32.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/block/file-win32.c
134
+++ b/block/file-win32.c
135
@@ -XXX,XX +XXX,XX @@ static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
136
static void raw_parse_filename(const char *filename, QDict *options,
137
Error **errp)
138
{
139
- /* The filename does not have to be prefixed by the protocol name, since
140
- * "file" is the default protocol; therefore, the return value of this
141
- * function call can be ignored. */
142
- strstart(filename, "file:", &filename);
143
-
144
- qdict_put_str(options, "filename", filename);
145
+ bdrv_parse_filename_strip_prefix(filename, "file:", options);
146
}
147
148
static QemuOptsList raw_runtime_opts = {
149
@@ -XXX,XX +XXX,XX @@ static int hdev_probe_device(const char *filename)
150
static void hdev_parse_filename(const char *filename, QDict *options,
151
Error **errp)
152
{
153
- /* The prefix is optional, just as for "file". */
154
- strstart(filename, "host_device:", &filename);
155
-
156
- qdict_put_str(options, "filename", filename);
157
+ bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
158
}
159
160
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
161
diff --git a/include/block/block_int.h b/include/block/block_int.h
162
index XXXXXXX..XXXXXXX 100644
163
--- a/include/block/block_int.h
164
+++ b/include/block/block_int.h
165
@@ -XXX,XX +XXX,XX @@ int get_tmp_filename(char *filename, int size);
166
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
167
const char *filename);
168
169
+void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
170
+ QDict *options);
171
+
172
173
/**
174
* bdrv_add_before_write_notifier:
175
--
49
--
176
1.8.3.1
50
2.41.0
177
178
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
1
From: "Daniel P. Berrange" <berrange@redhat.com>
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.
2
4
3
The qemu-img dd command added --image-opts support, but missed
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
the corresponding --object support. This prevented passing
6
Message-ID: <20230929145157.45443-8-kwolf@redhat.com>
5
secrets (eg auth passwords) needed by certain disk images.
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(-)
6
16
7
Reviewed-by: Fam Zheng <famz@redhat.com>
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
index XXXXXXX..XXXXXXX 100644
9
Reviewed-by: Eric Blake <eblake@redhat.com>
19
--- a/include/block/block_int-common.h
10
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
20
+++ b/include/block/block_int-common.h
11
Message-id: 20170515164712.6643-2-berrange@redhat.com
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
13
---
23
int GRAPH_RDLOCK_PTR (*bdrv_inactivate)(BlockDriverState *bs);
14
qemu-img.c | 18 ++++++++++++++++++
24
15
1 file changed, 18 insertions(+)
25
- int (*bdrv_snapshot_create)(BlockDriverState *bs,
16
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
}
17
diff --git a/qemu-img.c b/qemu-img.c
224
diff --git a/qemu-img.c b/qemu-img.c
18
index XXXXXXX..XXXXXXX 100644
225
index XXXXXXX..XXXXXXX 100644
19
--- a/qemu-img.c
226
--- a/qemu-img.c
20
+++ b/qemu-img.c
227
+++ b/qemu-img.c
21
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
228
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
22
};
229
sn.date_sec = rt / G_USEC_PER_SEC;
23
const struct option long_options[] = {
230
sn.date_nsec = (rt % G_USEC_PER_SEC) * 1000;
24
{ "help", no_argument, 0, 'h'},
231
25
+ { "object", required_argument, 0, OPTION_OBJECT},
232
+ bdrv_graph_rdlock_main_loop();
26
{ "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
233
ret = bdrv_snapshot_create(bs, &sn);
27
{ "force-share", no_argument, 0, 'U'},
234
+ bdrv_graph_rdunlock_main_loop();
28
{ 0, 0, 0, 0 }
235
+
29
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
236
if (ret) {
30
case 'U':
237
error_report("Could not create snapshot '%s': %s",
31
force_share = true;
238
snapshot_name, strerror(-ret));
32
break;
239
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
33
+ case OPTION_OBJECT: {
240
break;
34
+ QemuOpts *opts;
241
35
+ opts = qemu_opts_parse_noisily(&qemu_object_opts,
242
case SNAPSHOT_DELETE:
36
+ optarg, true);
243
+ bdrv_graph_rdlock_main_loop();
37
+ if (!opts) {
244
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
38
+ ret = -1;
245
if (ret < 0) {
39
+ goto out;
246
error_report("Could not delete snapshot '%s': snapshot not "
40
+ }
247
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
41
+ } break;
248
ret = 1;
42
case OPTION_IMAGE_OPTS:
249
}
43
image_opts = true;
250
}
44
break;
251
+ bdrv_graph_rdunlock_main_loop();
45
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
252
break;
46
ret = -1;
253
}
47
goto out;
48
}
49
+
50
+ if (qemu_opts_foreach(&qemu_object_opts,
51
+ user_creatable_add_opts_foreach,
52
+ NULL, NULL)) {
53
+ ret = -1;
54
+ goto out;
55
+ }
56
+
57
blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
58
force_share);
59
254
60
--
255
--
61
1.8.3.1
256
2.41.0
62
63
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
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_get_xdbg_block_graph() 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-10-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 | 2 +-
11
blockdev.c | 2 ++
12
2 files changed, 3 insertions(+), 1 deletion(-)
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);
27
diff --git a/blockdev.c b/blockdev.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/blockdev.c
30
+++ b/blockdev.c
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)
34
{
35
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
36
+
37
return bdrv_get_xdbg_block_graph(errp);
38
}
39
40
--
41
2.41.0
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
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.
2
4
3
Reported by Coverity.
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(-)
4
23
5
Signed-off-by: Fam Zheng <famz@redhat.com>
24
diff --git a/block/vhdx.h b/block/vhdx.h
6
Message-id: 20170515141014.25793-1-famz@redhat.com
25
index XXXXXXX..XXXXXXX 100644
7
Reviewed-by: Eric Blake <eblake@redhat.com>
26
--- a/block/vhdx.h
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
+++ b/block/vhdx.h
9
---
28
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
10
qemu-img.c | 1 +
29
11
1 file changed, 1 insertion(+)
30
bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
12
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,
13
diff --git a/qemu-img.c b/qemu-img.c
540
diff --git a/qemu-img.c b/qemu-img.c
14
index XXXXXXX..XXXXXXX 100644
541
index XXXXXXX..XXXXXXX 100644
15
--- a/qemu-img.c
542
--- a/qemu-img.c
16
+++ b/qemu-img.c
543
+++ b/qemu-img.c
17
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_opts(const char *optstr,
544
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
18
if (qdict_haskey(options, BDRV_OPT_FORCE_SHARE)
545
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
19
&& !qdict_get_bool(options, BDRV_OPT_FORCE_SHARE)) {
546
20
error_report("--force-share/-U conflicts with image options");
547
if (file && has_offset) {
21
+ QDECREF(options);
548
+ bdrv_graph_rdlock_main_loop();
22
return NULL;
549
bdrv_refresh_filename(file);
23
}
550
+ bdrv_graph_rdunlock_main_loop();
24
qdict_put(options, BDRV_OPT_FORCE_SHARE, qbool_from_bool(true));
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 =
25
--
564
--
26
1.8.3.1
565
2.41.0
27
28
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
1
From: Stephen Bates <sbates@raithlin.com>
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.
2
4
3
Implement NVMe Controller Memory Buffers (CMBs) which were added in
5
For some places, we know that they will hold the lock, but we don't have
4
version 1.2 of the NVMe Specification. This patch adds an optional
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
argument (cmb_size_mb) which indicates the size of the CMB (in
7
with a FIXME comment. These places will be removed once everything is
6
MB). Currently only the Submission Queue Support (SQS) is enabled
8
properly annotated.
7
which aligns with the current Linux driver for NVMe.
8
9
9
Signed-off-by: Stephen Bates <sbates@raithlin.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Acked-by: Keith Busch <keith.busch@intel.com>
11
Message-ID: <20230929145157.45443-13-kwolf@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
hw/block/nvme.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
15
block/qcow2.h | 7 +++----
14
hw/block/nvme.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
include/block/block-io.h | 8 ++++++--
15
2 files changed, 144 insertions(+), 4 deletions(-)
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(-)
16
33
17
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
34
diff --git a/block/qcow2.h b/block/qcow2.h
18
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/block/nvme.c
36
--- a/block/qcow2.h
20
+++ b/hw/block/nvme.c
37
+++ b/block/qcow2.h
21
@@ -XXX,XX +XXX,XX @@
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,
22
*/
76
*/
23
77
void bdrv_wakeup(BlockDriverState *bs);
24
/**
78
25
- * Reference Specs: http://www.nvmexpress.org, 1.1, 1.0e
79
-const char *bdrv_get_parent_name(const BlockDriverState *bs);
26
+ * Reference Specs: http://www.nvmexpress.org, 1.2, 1.1, 1.0e
80
+const char * GRAPH_RDLOCK bdrv_get_parent_name(const BlockDriverState *bs);
27
*
81
bool blk_dev_has_tray(BlockBackend *blk);
28
* http://www.nvmexpress.org/resources/
82
bool blk_dev_is_tray_open(BlockBackend *blk);
29
*/
83
30
@@ -XXX,XX +XXX,XX @@
84
diff --git a/include/block/qapi.h b/include/block/qapi.h
31
/**
85
index XXXXXXX..XXXXXXX 100644
32
* Usage: add options:
86
--- a/include/block/qapi.h
33
* -drive file=<file>,if=none,id=<drive_id>
87
+++ b/include/block/qapi.h
34
- * -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>
88
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo * GRAPH_RDLOCK
35
+ * -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
89
bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
36
+ * cmb_size_mb=<cmb_size_mb[optional]>
90
bool flat, Error **errp);
37
+ *
91
38
+ * Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
92
-int bdrv_query_snapshot_info_list(BlockDriverState *bs,
39
+ * offset 0 in BAR2 and supports SQS only for now.
93
- SnapshotInfoList **p_list,
40
*/
94
- Error **errp);
41
95
+int GRAPH_RDLOCK
42
#include "qemu/osdep.h"
96
+bdrv_query_snapshot_info_list(BlockDriverState *bs,
43
@@ -XXX,XX +XXX,XX @@
97
+ SnapshotInfoList **p_list,
44
98
+ Error **errp);
45
static void nvme_process_sq(void *opaque);
99
void GRAPH_RDLOCK
46
100
bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
47
+static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
101
bool skip_implicit_filters, Error **errp);
48
+{
102
diff --git a/block.c b/block.c
49
+ if (n->cmbsz && addr >= n->ctrl_mem.addr &&
103
index XXXXXXX..XXXXXXX 100644
50
+ addr < (n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size))) {
104
--- a/block.c
51
+ memcpy(buf, (void *)&n->cmbuf[addr - n->ctrl_mem.addr], size);
105
+++ b/block.c
52
+ } else {
106
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
53
+ pci_dma_read(&n->parent_obj, addr, buf, size);
107
return !(bs->open_flags & BDRV_O_RDWR);
54
+ }
108
}
55
+}
109
56
+
110
-static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
57
static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid)
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)
58
{
115
{
59
return sqid < n->num_queues && n->sq[sqid] != NULL ? 0 : -1;
116
IO_CODE();
60
@@ -XXX,XX +XXX,XX @@ static void nvme_process_sq(void *opaque)
117
61
118
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
62
while (!(nvme_sq_empty(sq) || QTAILQ_EMPTY(&sq->req_list))) {
119
int ret = 0;
63
addr = sq->dma_addr + sq->head * n->sqe_size;
120
IO_CODE();
64
- pci_dma_read(&n->parent_obj, addr, (void *)&cmd, sizeof(cmd));
121
65
+ nvme_addr_read(n, addr, (void *)&cmd, sizeof(cmd));
122
+ assume_graph_lock(); /* FIXME */
66
nvme_inc_sq_head(sq);
123
+
67
124
if (!(bs->open_flags & BDRV_O_RDWR)) {
68
req = QTAILQ_FIRST(&sq->req_list);
125
return 0;
69
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvme_mmio_ops = {
126
}
70
},
127
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
71
};
128
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
72
129
* not set, or if the BDS still has copy_on_read enabled */
73
+static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data,
130
read_only = !(reopen_state->flags & BDRV_O_RDWR);
74
+ unsigned size)
131
+
75
+{
132
+ bdrv_graph_rdlock_main_loop();
76
+ NvmeCtrl *n = (NvmeCtrl *)opaque;
133
ret = bdrv_can_set_read_only(reopen_state->bs, read_only, true, &local_err);
77
+ memcpy(&n->cmbuf[addr], &data, size);
134
+ bdrv_graph_rdunlock_main_loop();
78
+}
135
if (local_err) {
79
+
136
error_propagate(errp, local_err);
80
+static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
137
goto error;
81
+{
138
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
82
+ uint64_t val;
139
} else {
83
+ NvmeCtrl *n = (NvmeCtrl *)opaque;
140
/* It is currently mandatory to have a bdrv_reopen_prepare()
84
+
141
* handler for each supported drv. */
85
+ memcpy(&val, &n->cmbuf[addr], size);
142
+ bdrv_graph_rdlock_main_loop();
86
+ return val;
143
error_setg(errp, "Block format '%s' used by node '%s' "
87
+}
144
"does not support reopening files", drv->format_name,
88
+
145
bdrv_get_device_or_node_name(reopen_state->bs));
89
+static const MemoryRegionOps nvme_cmb_ops = {
146
+ bdrv_graph_rdunlock_main_loop();
90
+ .read = nvme_cmb_read,
147
ret = -1;
91
+ .write = nvme_cmb_write,
148
goto error;
92
+ .endianness = DEVICE_LITTLE_ENDIAN,
149
}
93
+ .impl = {
150
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
94
+ .min_access_size = 2,
95
+ .max_access_size = 8,
96
+ },
97
+};
98
+
99
static int nvme_init(PCIDevice *pci_dev)
100
{
151
{
101
NvmeCtrl *n = NVME(pci_dev);
152
BdrvOpBlocker *blocker;
102
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
153
GLOBAL_STATE_CODE();
103
NVME_CAP_SET_CSS(n->bar.cap, 1);
154
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
104
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
155
+
105
156
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
106
- n->bar.vs = 0x00010100;
157
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
107
+ n->bar.vs = 0x00010200;
158
blocker = QLIST_FIRST(&bs->op_blockers[op]);
108
n->bar.intmc = n->bar.intms = 0;
159
diff --git a/block/backup.c b/block/backup.c
109
160
index XXXXXXX..XXXXXXX 100644
110
+ if (n->cmb_size_mb) {
161
--- a/block/backup.c
111
+
162
+++ b/block/backup.c
112
+ NVME_CMBLOC_SET_BIR(n->bar.cmbloc, 2);
163
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
113
+ NVME_CMBLOC_SET_OFST(n->bar.cmbloc, 0);
164
assert(bs);
114
+
165
assert(target);
115
+ NVME_CMBSZ_SET_SQS(n->bar.cmbsz, 1);
166
GLOBAL_STATE_CODE();
116
+ NVME_CMBSZ_SET_CQS(n->bar.cmbsz, 0);
167
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
117
+ NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 0);
168
118
+ NVME_CMBSZ_SET_RDS(n->bar.cmbsz, 0);
169
/* QMP interface protects us from these cases */
119
+ NVME_CMBSZ_SET_WDS(n->bar.cmbsz, 0);
170
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
120
+ NVME_CMBSZ_SET_SZU(n->bar.cmbsz, 2); /* MBs */
171
diff --git a/block/parallels.c b/block/parallels.c
121
+ NVME_CMBSZ_SET_SZ(n->bar.cmbsz, n->cmb_size_mb);
172
index XXXXXXX..XXXXXXX 100644
122
+
173
--- a/block/parallels.c
123
+ n->cmbuf = g_malloc0(NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
174
+++ b/block/parallels.c
124
+ memory_region_init_io(&n->ctrl_mem, OBJECT(n), &nvme_cmb_ops, n,
175
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
125
+ "nvme-cmb", NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
176
bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
126
+ pci_register_bar(&n->parent_obj, NVME_CMBLOC_BIR(n->bar.cmbloc),
177
127
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
178
/* Disable migration until bdrv_activate method is added */
128
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
179
+ bdrv_graph_rdlock_main_loop();
129
+
180
error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
130
+ }
181
"does not support live migration",
131
+
182
bdrv_get_device_or_node_name(bs));
132
for (i = 0; i < n->num_namespaces; i++) {
183
+ bdrv_graph_rdunlock_main_loop();
133
NvmeNamespace *ns = &n->namespaces[i];
184
+
134
NvmeIdNs *id_ns = &ns->id_ns;
185
ret = migrate_add_blocker(s->migration_blocker, errp);
135
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
186
if (ret < 0) {
136
g_free(n->namespaces);
187
error_setg(errp, "Migration blocker error");
137
g_free(n->cq);
188
diff --git a/block/qcow.c b/block/qcow.c
138
g_free(n->sq);
189
index XXXXXXX..XXXXXXX 100644
139
+ if (n->cmbsz) {
190
--- a/block/qcow.c
140
+ memory_region_unref(&n->ctrl_mem);
191
+++ b/block/qcow.c
141
+ }
192
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
142
+
193
}
143
msix_uninit_exclusive_bar(pci_dev);
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);
144
}
246
}
145
247
146
static Property nvme_props[] = {
248
-static void quorum_report_failure(QuorumAIOCB *acb)
147
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
249
+static void GRAPH_RDLOCK quorum_report_failure(QuorumAIOCB *acb)
148
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
250
{
149
+ DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
251
const char *reference = bdrv_get_device_or_node_name(acb->bs);
150
DEFINE_PROP_END_OF_LIST(),
252
int64_t start_sector = acb->offset / BDRV_SECTOR_SIZE;
151
};
253
@@ -XXX,XX +XXX,XX @@ static void quorum_report_failure(QuorumAIOCB *acb)
152
254
153
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
255
static int quorum_vote_error(QuorumAIOCB *acb);
154
index XXXXXXX..XXXXXXX 100644
256
155
--- a/hw/block/nvme.h
257
-static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
156
+++ b/hw/block/nvme.h
258
+static bool GRAPH_RDLOCK quorum_has_too_much_io_failed(QuorumAIOCB *acb)
157
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
259
{
158
uint32_t aqa;
260
BDRVQuorumState *s = acb->bs->opaque;
159
uint64_t asq;
261
160
uint64_t acq;
262
diff --git a/block/rbd.c b/block/rbd.c
161
+ uint32_t cmbloc;
263
index XXXXXXX..XXXXXXX 100644
162
+ uint32_t cmbsz;
264
--- a/block/rbd.c
163
} NvmeBar;
265
+++ b/block/rbd.c
164
266
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
165
enum NvmeCapShift {
267
BDRVRBDState *s = state->bs->opaque;
166
@@ -XXX,XX +XXX,XX @@ enum NvmeAqaMask {
268
int ret = 0;
167
#define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK)
269
168
#define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK)
270
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
169
271
+
170
+enum NvmeCmblocShift {
272
if (s->snap && state->flags & BDRV_O_RDWR) {
171
+ CMBLOC_BIR_SHIFT = 0,
273
error_setg(errp,
172
+ CMBLOC_OFST_SHIFT = 12,
274
"Cannot change node '%s' to r/w when using RBD snapshot",
173
+};
275
diff --git a/block/snapshot.c b/block/snapshot.c
174
+
276
index XXXXXXX..XXXXXXX 100644
175
+enum NvmeCmblocMask {
277
--- a/block/snapshot.c
176
+ CMBLOC_BIR_MASK = 0x7,
278
+++ b/block/snapshot.c
177
+ CMBLOC_OFST_MASK = 0xfffff,
279
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
178
+};
280
BlockDriver *drv = bs->drv;
179
+
281
180
+#define NVME_CMBLOC_BIR(cmbloc) ((cmbloc >> CMBLOC_BIR_SHIFT) & \
282
GLOBAL_STATE_CODE();
181
+ CMBLOC_BIR_MASK)
283
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
182
+#define NVME_CMBLOC_OFST(cmbloc)((cmbloc >> CMBLOC_OFST_SHIFT) & \
284
183
+ CMBLOC_OFST_MASK)
285
if (!drv) {
184
+
286
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
185
+#define NVME_CMBLOC_SET_BIR(cmbloc, val) \
287
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
186
+ (cmbloc |= (uint64_t)(val & CMBLOC_BIR_MASK) << CMBLOC_BIR_SHIFT)
288
}
187
+#define NVME_CMBLOC_SET_OFST(cmbloc, val) \
289
aio_context_release(ctx);
188
+ (cmbloc |= (uint64_t)(val & CMBLOC_OFST_MASK) << CMBLOC_OFST_SHIFT)
290
if (ret < 0) {
189
+
291
+ bdrv_graph_rdlock_main_loop();
190
+enum NvmeCmbszShift {
292
error_prepend(errp, "Could not load snapshot '%s' on '%s': ",
191
+ CMBSZ_SQS_SHIFT = 0,
293
name, bdrv_get_device_or_node_name(bs));
192
+ CMBSZ_CQS_SHIFT = 1,
294
+ bdrv_graph_rdunlock_main_loop();
193
+ CMBSZ_LISTS_SHIFT = 2,
295
return -1;
194
+ CMBSZ_RDS_SHIFT = 3,
296
}
195
+ CMBSZ_WDS_SHIFT = 4,
297
196
+ CMBSZ_SZU_SHIFT = 8,
298
diff --git a/block/vdi.c b/block/vdi.c
197
+ CMBSZ_SZ_SHIFT = 12,
299
index XXXXXXX..XXXXXXX 100644
198
+};
300
--- a/block/vdi.c
199
+
301
+++ b/block/vdi.c
200
+enum NvmeCmbszMask {
302
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
201
+ CMBSZ_SQS_MASK = 0x1,
303
}
202
+ CMBSZ_CQS_MASK = 0x1,
304
203
+ CMBSZ_LISTS_MASK = 0x1,
305
/* Disable migration when vdi images are used */
204
+ CMBSZ_RDS_MASK = 0x1,
306
+ bdrv_graph_rdlock_main_loop();
205
+ CMBSZ_WDS_MASK = 0x1,
307
error_setg(&s->migration_blocker, "The vdi format used by node '%s' "
206
+ CMBSZ_SZU_MASK = 0xf,
308
"does not support live migration",
207
+ CMBSZ_SZ_MASK = 0xfffff,
309
bdrv_get_device_or_node_name(bs));
208
+};
310
+ bdrv_graph_rdunlock_main_loop();
209
+
311
+
210
+#define NVME_CMBSZ_SQS(cmbsz) ((cmbsz >> CMBSZ_SQS_SHIFT) & CMBSZ_SQS_MASK)
312
ret = migrate_add_blocker(s->migration_blocker, errp);
211
+#define NVME_CMBSZ_CQS(cmbsz) ((cmbsz >> CMBSZ_CQS_SHIFT) & CMBSZ_CQS_MASK)
313
if (ret < 0) {
212
+#define NVME_CMBSZ_LISTS(cmbsz)((cmbsz >> CMBSZ_LISTS_SHIFT) & CMBSZ_LISTS_MASK)
314
error_free(s->migration_blocker);
213
+#define NVME_CMBSZ_RDS(cmbsz) ((cmbsz >> CMBSZ_RDS_SHIFT) & CMBSZ_RDS_MASK)
315
diff --git a/block/vpc.c b/block/vpc.c
214
+#define NVME_CMBSZ_WDS(cmbsz) ((cmbsz >> CMBSZ_WDS_SHIFT) & CMBSZ_WDS_MASK)
316
index XXXXXXX..XXXXXXX 100644
215
+#define NVME_CMBSZ_SZU(cmbsz) ((cmbsz >> CMBSZ_SZU_SHIFT) & CMBSZ_SZU_MASK)
317
--- a/block/vpc.c
216
+#define NVME_CMBSZ_SZ(cmbsz) ((cmbsz >> CMBSZ_SZ_SHIFT) & CMBSZ_SZ_MASK)
318
+++ b/block/vpc.c
217
+
319
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
218
+#define NVME_CMBSZ_SET_SQS(cmbsz, val) \
320
}
219
+ (cmbsz |= (uint64_t)(val & CMBSZ_SQS_MASK) << CMBSZ_SQS_SHIFT)
321
220
+#define NVME_CMBSZ_SET_CQS(cmbsz, val) \
322
/* Disable migration when VHD images are used */
221
+ (cmbsz |= (uint64_t)(val & CMBSZ_CQS_MASK) << CMBSZ_CQS_SHIFT)
323
+ bdrv_graph_rdlock_main_loop();
222
+#define NVME_CMBSZ_SET_LISTS(cmbsz, val) \
324
error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
223
+ (cmbsz |= (uint64_t)(val & CMBSZ_LISTS_MASK) << CMBSZ_LISTS_SHIFT)
325
"does not support live migration",
224
+#define NVME_CMBSZ_SET_RDS(cmbsz, val) \
326
bdrv_get_device_or_node_name(bs));
225
+ (cmbsz |= (uint64_t)(val & CMBSZ_RDS_MASK) << CMBSZ_RDS_SHIFT)
327
+ bdrv_graph_rdunlock_main_loop();
226
+#define NVME_CMBSZ_SET_WDS(cmbsz, val) \
328
+
227
+ (cmbsz |= (uint64_t)(val & CMBSZ_WDS_MASK) << CMBSZ_WDS_SHIFT)
329
ret = migrate_add_blocker(s->migration_blocker, errp);
228
+#define NVME_CMBSZ_SET_SZU(cmbsz, val) \
330
if (ret < 0) {
229
+ (cmbsz |= (uint64_t)(val & CMBSZ_SZU_MASK) << CMBSZ_SZU_SHIFT)
331
error_free(s->migration_blocker);
230
+#define NVME_CMBSZ_SET_SZ(cmbsz, val) \
332
diff --git a/block/vvfat.c b/block/vvfat.c
231
+ (cmbsz |= (uint64_t)(val & CMBSZ_SZ_MASK) << CMBSZ_SZ_SHIFT)
333
index XXXXXXX..XXXXXXX 100644
232
+
334
--- a/block/vvfat.c
233
+#define NVME_CMBSZ_GETSIZE(cmbsz) \
335
+++ b/block/vvfat.c
234
+ (NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
336
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
235
+
337
QemuOpts *opts;
236
typedef struct NvmeCmd {
338
int ret;
237
uint8_t opcode;
339
238
uint8_t fuse;
340
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
239
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeNamespace {
341
+
240
typedef struct NvmeCtrl {
342
#ifdef DEBUG
241
PCIDevice parent_obj;
343
vvv = s;
242
MemoryRegion iomem;
344
#endif
243
+ MemoryRegion ctrl_mem;
345
diff --git a/blockjob.c b/blockjob.c
244
NvmeBar bar;
346
index XXXXXXX..XXXXXXX 100644
245
BlockConf conf;
347
--- a/blockjob.c
246
348
+++ b/blockjob.c
247
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
349
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
248
uint32_t num_queues;
350
BlockJob *job;
249
uint32_t max_q_ents;
351
int ret;
250
uint64_t ns_size;
352
GLOBAL_STATE_CODE();
251
+ uint32_t cmb_size_mb;
353
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
252
+ uint32_t cmbsz;
354
253
+ uint32_t cmbloc;
355
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
254
+ uint8_t *cmbuf;
356
job_id = bdrv_get_device_name(bs);
255
256
char *serial;
257
NvmeNamespace *namespaces;
258
--
357
--
259
1.8.3.1
358
2.41.0
260
261
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
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.
2
4
3
The '--image-opts' flag indicates whether the source filename
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
includes options. The target filename has to remain in the
6
Message-ID: <20230929145157.45443-14-kwolf@redhat.com>
5
plain filename format though, since it needs to be passed to
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
bdrv_create(). When using --skip-create though, it would be
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
possible to use image-opts syntax. This adds --target-image-opts
9
---
8
to indicate that the target filename includes options. Currently
10
include/block/block-global-state.h | 8 ++++----
9
this mandates use of the --skip-create flag too.
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(-)
10
15
11
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
16
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
12
Message-id: 20170515164712.6643-4-berrange@redhat.com
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
qemu-img-cmds.hx | 4 +--
18
qemu-img.c | 84 ++++++++++++++++++++++++++++++++++++++------------------
19
qemu-img.texi | 12 ++++++--
20
3 files changed, 69 insertions(+), 31 deletions(-)
21
22
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-img-cmds.hx
18
--- a/include/block/block-global-state.h
25
+++ b/qemu-img-cmds.hx
19
+++ b/include/block/block-global-state.h
26
@@ -XXX,XX +XXX,XX @@ STEXI
20
@@ -XXX,XX +XXX,XX @@ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
27
ETEXI
21
*/
28
22
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
29
DEF("convert", img_convert,
23
int64_t total_work_size, void *opaque);
30
- "convert [--object objectdef] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
24
-int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
31
+ "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
25
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
32
STEXI
26
- bool force,
33
-@item convert [--object @var{objectdef}] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
27
- Error **errp);
34
+@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
28
+int GRAPH_RDLOCK
35
ETEXI
29
+bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
36
30
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
37
DEF("dd", img_dd,
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
38
diff --git a/qemu-img.c b/qemu-img.c
78
diff --git a/qemu-img.c b/qemu-img.c
39
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
40
--- a/qemu-img.c
80
--- a/qemu-img.c
41
+++ b/qemu-img.c
81
+++ b/qemu-img.c
42
@@ -XXX,XX +XXX,XX @@ enum {
82
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
43
OPTION_PATTERN = 260,
44
OPTION_FLUSH_INTERVAL = 261,
45
OPTION_NO_DRAIN = 262,
46
+ OPTION_TARGET_IMAGE_OPTS = 263,
47
};
48
49
typedef enum OutputFormat {
50
@@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s)
51
static int img_convert(int argc, char **argv)
52
{
83
{
53
int c, bs_i, flags, src_flags = 0;
84
BlockDriver *drv;
54
- const char *fmt = NULL, *out_fmt = "raw", *cache = "unsafe",
85
55
+ const char *fmt = NULL, *out_fmt = NULL, *cache = "unsafe",
86
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
56
*src_cache = BDRV_DEFAULT_CACHE, *out_baseimg = NULL,
57
*out_filename, *out_baseimg_param, *snapshot_name = NULL;
58
- BlockDriver *drv, *proto_drv;
59
+ BlockDriver *drv = NULL, *proto_drv = NULL;
60
BlockDriverInfo bdi;
61
BlockDriverState *out_bs;
62
QemuOpts *opts = NULL, *sn_opts = NULL;
63
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
64
char *options = NULL;
65
Error *local_err = NULL;
66
bool writethrough, src_writethrough, quiet = false, image_opts = false,
67
- skip_create = false, progress = false;
68
+ skip_create = false, progress = false, tgt_image_opts = false;
69
int64_t ret = -EINVAL;
70
bool force_share = false;
71
72
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
73
{"object", required_argument, 0, OPTION_OBJECT},
74
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
75
{"force-share", no_argument, 0, 'U'},
76
+ {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
77
{0, 0, 0, 0}
78
};
79
c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:WU",
80
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
81
case OPTION_IMAGE_OPTS:
82
image_opts = true;
83
break;
84
+ case OPTION_TARGET_IMAGE_OPTS:
85
+ tgt_image_opts = true;
86
+ break;
87
}
88
}
89
90
+ if (!out_fmt && !tgt_image_opts) {
91
+ out_fmt = "raw";
92
+ }
93
+
87
+
94
if (qemu_opts_foreach(&qemu_object_opts,
88
/* Find driver and parse its options */
95
user_creatable_add_opts_foreach,
89
drv = bdrv_find_format(format);
96
NULL, NULL)) {
90
if (!drv) {
97
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
91
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
98
goto fail_getopt;
99
}
100
101
+ if (tgt_image_opts && !skip_create) {
102
+ error_report("--target-image-opts requires use of -n flag");
103
+ goto fail_getopt;
104
+ }
105
+
106
s.src_num = argc - optind - 1;
107
out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL;
108
109
if (options && has_help_option(options)) {
110
- ret = print_block_option_help(out_filename, out_fmt);
111
- goto fail_getopt;
112
+ if (out_fmt) {
113
+ ret = print_block_option_help(out_filename, out_fmt);
114
+ goto fail_getopt;
115
+ } else {
116
+ error_report("Option help requires a format be specified");
117
+ goto fail_getopt;
118
+ }
119
}
120
121
if (s.src_num < 1) {
122
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
123
goto out;
92
goto out;
124
}
93
}
125
94
126
- /* Find driver and parse its options */
95
+ bdrv_graph_rdlock_main_loop();
127
- drv = bdrv_find_format(out_fmt);
96
if (!bs->drv->bdrv_amend_options) {
128
- if (!drv) {
97
error_report("Format driver '%s' does not support option amendment",
129
- error_report("Unknown file format '%s'", out_fmt);
98
fmt);
130
- ret = -1;
99
+ bdrv_graph_rdunlock_main_loop();
131
- goto out;
132
- }
133
+ if (!skip_create) {
134
+ /* Find driver and parse its options */
135
+ drv = bdrv_find_format(out_fmt);
136
+ if (!drv) {
137
+ error_report("Unknown file format '%s'", out_fmt);
138
+ ret = -1;
139
+ goto out;
140
+ }
141
142
- proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
143
- if (!proto_drv) {
144
- error_report_err(local_err);
145
- ret = -1;
146
- goto out;
147
- }
148
+ proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
149
+ if (!proto_drv) {
150
+ error_report_err(local_err);
151
+ ret = -1;
152
+ goto out;
153
+ }
154
155
- if (!skip_create) {
156
if (!drv->create_opts) {
157
error_report("Format driver '%s' does not support image creation",
158
drv->format_name);
159
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
160
const char *preallocation =
161
qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
162
163
- if (!drv->bdrv_co_pwritev_compressed) {
164
+ if (drv && !drv->bdrv_co_pwritev_compressed) {
165
error_report("Compression not supported for this file format");
166
ret = -1;
167
goto out;
168
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
169
goto out;
170
}
171
172
- /* XXX we should allow --image-opts to trigger use of
173
- * img_open() here, but then we have trouble with
174
- * the bdrv_create() call which takes different params.
175
- * Not critical right now, so fix can wait...
176
- */
177
- s.target = img_open_file(out_filename, out_fmt, flags, writethrough, quiet,
178
- false);
179
+ if (skip_create) {
180
+ s.target = img_open(tgt_image_opts, out_filename, out_fmt,
181
+ flags, writethrough, quiet, false);
182
+ } else {
183
+ /* TODO ultimately we should allow --target-image-opts
184
+ * to be used even when -n is not given.
185
+ * That has to wait for bdrv_create to be improved
186
+ * to allow filenames in option syntax
187
+ */
188
+ s.target = img_open_file(out_filename, out_fmt, flags,
189
+ writethrough, quiet, false);
190
+ }
191
if (!s.target) {
192
ret = -1;
100
ret = -1;
193
goto out;
101
goto out;
194
}
102
}
195
out_bs = blk_bs(s.target);
103
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
196
104
"This option is only supported for image creation\n");
197
+ if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) {
105
}
198
+ error_report("Compression not supported for this file format");
106
199
+ ret = -1;
107
+ bdrv_graph_rdunlock_main_loop();
200
+ goto out;
108
error_report_err(err);
201
+ }
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();
202
+
116
+
203
/* increase bufsectors from the default 4096 (2M) if opt_transfer
117
if (ret < 0) {
204
* or discard_alignment of the out_bs is greater. Limit to 32768 (16MB)
118
error_report_err(err);
205
* as maximum. */
119
goto out;
206
diff --git a/qemu-img.texi b/qemu-img.texi
207
index XXXXXXX..XXXXXXX 100644
208
--- a/qemu-img.texi
209
+++ b/qemu-img.texi
210
@@ -XXX,XX +XXX,XX @@ keys.
211
212
@item --image-opts
213
214
-Indicates that the @var{filename} parameter is to be interpreted as a
215
+Indicates that the source @var{filename} parameter is to be interpreted as a
216
full option string, not a plain filename. This parameter is mutually
217
-exclusive with the @var{-f} and @var{-F} parameters.
218
+exclusive with the @var{-f} parameter.
219
+
220
+@item --target-image-opts
221
+
222
+Indicates that the @var{output_filename} parameter(s) are to be interpreted as
223
+a full option string, not a plain filename. This parameter is mutually
224
+exclusive with the @var{-O} parameters. It is currently required to also use
225
+the @var{-n} parameter to skip image creation. This restriction may be relaxed
226
+in a future release.
227
228
@item fmt
229
is the disk image format. It is guessed automatically in most cases. See below
230
--
120
--
231
1.8.3.1
121
2.41.0
232
233
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
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.
2
5
3
When converting a 1.1 image down to 0.10, qemu-iotests 060 forces
6
For some places, we know that they will hold the lock, but we don't have
4
a contrived failure where allocating a cluster used to replace a
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
zero cluster reads unaligned data. Since it is a zero cluster
8
with a FIXME comment. These places will be removed once everything is
6
rather than a data cluster being converted, changing the error
9
properly annotated.
7
message to match our earlier change in 'qcow2: Make distinction
8
between zero cluster types obvious' is worthwhile.
9
10
10
Suggested-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Message-ID: <20230929145157.45443-15-kwolf@redhat.com>
12
Message-id: 20170508171302.17805-1-eblake@redhat.com
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
[mreitz: Commit message fixes]
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
15
---
16
block/qcow2-cluster.c | 3 ++-
16
block/qcow2.h | 180 +++++++++++++++++------------
17
tests/qemu-iotests/060.out | 2 +-
17
include/block/block-global-state.h | 2 +-
18
2 files changed, 3 insertions(+), 2 deletions(-)
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(-)
19
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;
20
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
478
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
21
index XXXXXXX..XXXXXXX 100644
479
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2-cluster.c
480
--- a/block/qcow2-cluster.c
23
+++ b/block/qcow2-cluster.c
481
+++ b/block/qcow2-cluster.c
24
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
482
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
25
}
483
* the cache is used; otherwise the L2 slice is loaded from the image
26
484
* file.
27
if (offset_into_cluster(s, offset)) {
485
*/
28
- qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset "
486
-static int l2_load(BlockDriverState *bs, uint64_t offset,
29
+ qcow2_signal_corruption(bs, true, -1, -1,
487
- uint64_t l2_offset, uint64_t **l2_slice)
30
+ "Cluster allocation offset "
488
+static int GRAPH_RDLOCK
31
"%#" PRIx64 " unaligned (L2 offset: %#"
489
+l2_load(BlockDriverState *bs, uint64_t offset,
32
PRIx64 ", L2 index: %#x)", offset,
490
+ uint64_t l2_offset, uint64_t **l2_slice)
33
l2_offset, j);
491
{
34
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
492
BDRVQcow2State *s = bs->opaque;
35
index XXXXXXX..XXXXXXX 100644
493
int start_of_slice = l2_entry_size(s) *
36
--- a/tests/qemu-iotests/060.out
494
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
37
+++ b/tests/qemu-iotests/060.out
495
*
38
@@ -XXX,XX +XXX,XX @@ read failed: Input/output error
496
*/
39
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
497
40
wrote 65536/65536 bytes at offset 0
498
-static int l2_allocate(BlockDriverState *bs, int l1_index)
41
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
499
+static int GRAPH_RDLOCK l2_allocate(BlockDriverState *bs, int l1_index)
42
-qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
500
{
43
+qcow2: Marking image as corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
501
BDRVQcow2State *s = bs->opaque;
44
qemu-img: Error while amending options: Input/output error
502
uint64_t old_l2_offset;
45
503
@@ -XXX,XX +XXX,XX @@ fail:
46
=== Testing unaligned reftable entry ===
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);
47
--
995
--
48
1.8.3.1
996
2.41.0
49
50
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
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.
2
5
3
Commit d7086422b1c1e75e320519cfe26176db6ec97a37 added a local_err
6
qcow2_do_close() is a bit strange because it is called from different
4
variable global to the qcow2_amend_options() function, so there's no
7
contexts. If close_data_file = true, we know that we were called from
5
need to have this other one.
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.
6
11
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-id: 20170511150337.21470-1-berto@igalia.com
13
Message-ID: <20230929145157.45443-16-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
16
---
12
block/qcow2.c | 5 ++---
17
block/qcow2.c | 15 ++++++++++-----
13
1 file changed, 2 insertions(+), 3 deletions(-)
18
1 file changed, 10 insertions(+), 5 deletions(-)
14
19
15
diff --git a/block/qcow2.c b/block/qcow2.c
20
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
22
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
23
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
24
@@ -XXX,XX +XXX,XX @@ fail_nometa:
20
25
return ret;
21
if (s->refcount_bits != refcount_bits) {
26
}
22
int refcount_order = ctz32(refcount_bits);
27
23
- Error *local_error = NULL;
28
-static int qcow2_inactivate(BlockDriverState *bs)
24
29
+static int GRAPH_RDLOCK qcow2_inactivate(BlockDriverState *bs)
25
if (new_version < 3 && refcount_bits != 16) {
30
{
26
error_report("Different refcount widths than 16 bits require "
31
BDRVQcow2State *s = bs->opaque;
27
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
32
int ret, result = 0;
28
helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
33
Error *local_err = NULL;
29
ret = qcow2_change_refcount_order(bs, refcount_order,
34
30
&qcow2_amend_helper_cb,
35
- assume_graph_lock(); /* FIXME */
31
- &helper_cb_info, &local_error);
36
-
32
+ &helper_cb_info, &local_err);
37
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
33
if (ret < 0) {
38
if (local_err != NULL) {
34
- error_report_err(local_error);
39
result = -EINVAL;
35
+ error_report_err(local_err);
40
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
36
return ret;
41
return result;
37
}
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();
38
}
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
39
--
76
--
40
1.8.3.1
77
2.41.0
41
42
diff view generated by jsdifflib
1
This fixes an assertion failure that was triggered by qemu-iotests 129
1
It still has an assume_graph_lock() call, but all of its callers are now
2
on some CI host, while the same test case didn't seem to fail on other
2
properly annotated to hold the graph lock. Update the function to be
3
hosts.
3
GRAPH_RDLOCK as well and remove the assume_graph_lock().
4
4
5
Essentially the problem is that the blk_unref(s->target) in
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
mirror_exit() doesn't necessarily mean that the BlockBackend goes away
6
Message-ID: <20230929145157.45443-17-kwolf@redhat.com>
7
immediately. It is possible that the job completion was triggered nested
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
in mirror_drain(), which looks like this:
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/qcow2-bitmap.c | 9 +++------
11
1 file changed, 3 insertions(+), 6 deletions(-)
9
12
10
BlockBackend *target = s->target;
13
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
11
blk_ref(target);
12
blk_drain(target);
13
blk_unref(target);
14
15
In this case, the write permissions for s->target are retained until
16
after blk_drain(), which makes removing mirror_top_bs fail for the
17
active commit case (can't have a writable backing file in the chain
18
without the filter driver).
19
20
Explicitly dropping the permissions first means that the additional
21
reference doesn't hurt and the job can complete successfully even if
22
called from the nested blk_drain().
23
24
Cc: qemu-stable@nongnu.org
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
27
Reviewed-by: Max Reitz <mreitz@redhat.com>
28
---
29
block/mirror.c | 7 ++++++-
30
1 file changed, 6 insertions(+), 1 deletion(-)
31
32
diff --git a/block/mirror.c b/block/mirror.c
33
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
34
--- a/block/mirror.c
15
--- a/block/qcow2-bitmap.c
35
+++ b/block/mirror.c
16
+++ b/block/qcow2-bitmap.c
36
@@ -XXX,XX +XXX,XX @@ static void mirror_exit(BlockJob *job, void *opaque)
17
@@ -XXX,XX +XXX,XX @@ static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity)
37
18
return DIV_ROUND_UP(num_bits, 8);
38
/* Remove target parent that still uses BLK_PERM_WRITE/RESIZE before
19
}
39
* inserting target_bs at s->to_replace, where we might not be able to get
20
40
- * these permissions. */
21
-static int check_constraints_on_bitmap(BlockDriverState *bs,
41
+ * these permissions.
22
- const char *name,
42
+ *
23
- uint32_t granularity,
43
+ * Note that blk_unref() alone doesn't necessarily drop permissions because
24
- Error **errp)
44
+ * we might be running nested inside mirror_drain(), which takes an extra
25
+static int GRAPH_RDLOCK
45
+ * reference, so use an explicit blk_set_perm() first. */
26
+check_constraints_on_bitmap(BlockDriverState *bs, const char *name,
46
+ blk_set_perm(s->target, 0, BLK_PERM_ALL, &error_abort);
27
+ uint32_t granularity, Error **errp)
47
blk_unref(s->target);
28
{
48
s->target = NULL;
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);
49
38
50
--
39
--
51
1.8.3.1
40
2.41.0
52
53
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
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.
2
5
3
The qemu-img dd/convert commands will create an image file and
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
then try to open it. Historically it has been possible to open
7
Message-ID: <20230929145157.45443-18-kwolf@redhat.com>
5
new files without passing any options. With encrypted files
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
though, the *key-secret options are mandatory, so we need to
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
provide those options when opening the newly created file.
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(-)
8
19
9
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
10
Message-id: 20170515164712.6643-5-berrange@redhat.com
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
qemu-img.c | 42 +++++++++++++++++++++++++++++++++++++-----
15
1 file changed, 37 insertions(+), 5 deletions(-)
16
17
diff --git a/qemu-img.c b/qemu-img.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/qemu-img.c
22
--- a/include/block/block-global-state.h
20
+++ b/qemu-img.c
23
+++ b/include/block/block-global-state.h
21
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_opts(const char *optstr,
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
}
22
}
92
}
23
93
24
static BlockBackend *img_open_file(const char *filename,
94
-static void blockdev_remove_medium(const char *device, const char *id,
25
+ QDict *options,
95
- Error **errp)
26
const char *fmt, int flags,
96
+static void GRAPH_UNLOCKED
27
bool writethrough, bool quiet,
97
+blockdev_remove_medium(const char *device, const char *id, Error **errp)
28
bool force_share)
29
{
98
{
30
BlockBackend *blk;
99
BlockBackend *blk;
31
Error *local_err = NULL;
100
BlockDriverState *bs;
32
- QDict *options = qdict_new();
101
AioContext *aio_context;
33
102
bool has_attached_device;
34
+ if (!options) {
103
35
+ options = qdict_new();
104
+ GLOBAL_STATE_CODE();
36
+ }
105
+
37
if (fmt) {
106
blk = qmp_get_blk(device, id, errp);
38
qdict_put_str(options, "driver", fmt);
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;
39
}
117
}
40
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_file(const char *filename,
118
+ bdrv_graph_rdunlock_main_loop();
41
}
119
42
120
blk_remove_bs(blk);
43
121
44
+static int img_add_key_secrets(void *opaque,
122
diff --git a/blockdev.c b/blockdev.c
45
+ const char *name, const char *value,
123
index XXXXXXX..XXXXXXX 100644
46
+ Error **errp)
124
--- a/blockdev.c
47
+{
125
+++ b/blockdev.c
48
+ QDict *options = opaque;
126
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
49
+
50
+ if (g_str_has_suffix(name, "key-secret")) {
51
+ qdict_put(options, name, qstring_from_str(value));
52
+ }
53
+
54
+ return 0;
55
+}
56
+
57
+static BlockBackend *img_open_new_file(const char *filename,
58
+ QemuOpts *create_opts,
59
+ const char *fmt, int flags,
60
+ bool writethrough, bool quiet,
61
+ bool force_share)
62
+{
63
+ QDict *options = NULL;
64
+
65
+ options = qdict_new();
66
+ qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort);
67
+
68
+ return img_open_file(filename, options, fmt, flags, writethrough, quiet,
69
+ force_share);
70
+}
71
+
72
+
73
static BlockBackend *img_open(bool image_opts,
74
const char *filename,
75
const char *fmt, int flags, bool writethrough,
76
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open(bool image_opts,
77
blk = img_open_opts(filename, opts, flags, writethrough, quiet,
78
force_share);
79
} else {
80
- blk = img_open_file(filename, fmt, flags, writethrough, quiet,
81
+ blk = img_open_file(filename, NULL, fmt, flags, writethrough, quiet,
82
force_share);
83
}
127
}
84
return blk;
128
85
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
129
/* Early check to avoid creating target */
86
* That has to wait for bdrv_create to be improved
130
+ bdrv_graph_rdlock_main_loop();
87
* to allow filenames in option syntax
131
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
88
*/
132
+ bdrv_graph_rdunlock_main_loop();
89
- s.target = img_open_file(out_filename, out_fmt, flags,
133
goto out;
90
- writethrough, quiet, false);
91
+ s.target = img_open_new_file(out_filename, opts, out_fmt,
92
+ flags, writethrough, quiet, false);
93
}
134
}
94
if (!s.target) {
135
+ bdrv_graph_rdunlock_main_loop();
95
ret = -1;
136
96
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
137
flags = bs->open_flags | BDRV_O_RDWR;
97
* with the bdrv_create() call above which does not
138
98
* support image-opts style.
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)
99
*/
155
*/
100
- blk2 = img_open_file(out.filename, out_fmt, BDRV_O_RDWR,
156
iter_end = bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
101
+ blk2 = img_open_file(out.filename, NULL, out_fmt, BDRV_O_RDWR,
157
+ bdrv_graph_rdlock_main_loop();
102
false, false, false);
158
for (iter = bs; iter && iter != iter_end;
103
159
iter = bdrv_filter_or_cow_bs(iter))
104
if (!blk2) {
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)) {
105
--
196
--
106
1.8.3.1
197
2.41.0
107
108
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
1
From: Fam Zheng <famz@redhat.com>
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.
2
4
3
It got lost in commit a8d16f9ca "qemu-img: Update documentation for -U".
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(-)
4
15
5
Reported-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Message-id: 20170515103551.31313-1-famz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
qemu-img-cmds.hx | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img-cmds.hx
18
--- a/include/block/block-io.h
17
+++ b/qemu-img-cmds.hx
19
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ STEXI
20
@@ -XXX,XX +XXX,XX @@ bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
19
ETEXI
21
int co_wrapper_mixed_bdrv_rdlock
20
22
bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
21
DEF("convert", img_convert,
23
22
- "convert [--object objectdef] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
24
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
23
+ "convert [--object objectdef] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
25
- Error **errp);
24
STEXI
26
+ImageInfoSpecific * GRAPH_RDLOCK
25
-@item convert [--object @var{objectdef}] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
27
+bdrv_get_specific_info(BlockDriverState *bs, Error **errp);
26
+@item convert [--object @var{objectdef}] [--image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
28
+
27
ETEXI
29
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
28
30
void bdrv_round_to_subclusters(BlockDriverState *bs,
29
DEF("dd", img_dd,
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
}
30
--
84
--
31
1.8.3.1
85
2.41.0
32
33
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
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.
2
4
3
This is the case in our docker tests, as we use --net=none there. Skip
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
this method.
6
Message-ID: <20230929145157.45443-21-kwolf@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
---
9
tests/qemu-iotests/147 | 7 +++++++
10
include/block/block_int-common.h | 4 ++--
10
1 file changed, 7 insertions(+)
11
tests/unit/test-block-iothread.c | 5 +++++
12
2 files changed, 7 insertions(+), 2 deletions(-)
11
13
12
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
13
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/147
16
--- a/include/block/block_int-common.h
15
+++ b/tests/qemu-iotests/147
17
+++ b/include/block/block_int-common.h
16
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
18
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
17
self._server_down()
19
bool quiesced_parent;
18
20
19
def test_inet6(self):
21
QLIST_ENTRY(BdrvChild) next;
20
+ try:
22
- QLIST_ENTRY(BdrvChild) next_parent;
21
+ socket.getaddrinfo("::0", "0", socket.AF_INET6,
23
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
22
+ socket.SOCK_STREAM, socket.IPPROTO_TCP,
24
};
23
+ socket.AI_ADDRCONFIG | socket.AI_CANONNAME)
25
24
+ except socket.gaierror:
26
/*
25
+ # IPv6 not available, skip
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
26
+ return
28
BdrvChild *backing;
27
address = { 'type': 'inet',
29
BdrvChild *file;
28
'data': {
30
29
'host': '::1',
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);
30
--
57
--
31
1.8.3.1
58
2.41.0
32
33
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.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
path_combine() naturally tries to preserve a protocol prefix. However,
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
it recognizes such a prefix by scanning for the first colon; which is
6
Message-ID: <20230929145157.45443-22-kwolf@redhat.com>
5
different from what path_has_protocol() does: There only is a protocol
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
prefix if there is a colon before the first slash.
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int-common.h | 4 ++--
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(-)
7
15
8
A protocol prefix that is not recognized by path_has_protocol() is none,
16
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
9
and should thus not be taken as one.
17
index XXXXXXX..XXXXXXX 100644
10
18
--- a/include/block/block_int-common.h
11
Case in point, before this patch:
19
+++ b/include/block/block_int-common.h
12
$ ./qemu-img create -f qcow2 -b backing.qcow2 ./top:image.qcow2
20
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
13
qemu-img: ./top:image.qcow2: Could not open './top:backing.qcow2':
21
*/
14
No such file or directory
22
bool quiesced_parent;
15
23
16
Afterwards:
24
- QLIST_ENTRY(BdrvChild) next;
17
$ ./qemu-img create -f qcow2 -b backing.qcow2 ./top:image.qcow2
25
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next;
18
qemu-img: ./top:image.qcow2: Could not open './backing.qcow2':
26
QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
19
No such file or directory
27
};
20
28
21
Reported-by: yangyang <yangyang@redhat.com>
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
30
* See also comment in include/block/block.h, to learn how backing and file
23
Reviewed-by: Eric Blake <eblake@redhat.com>
31
* are connected with BdrvChildRole.
24
Message-id: 20170522195217.12991-2-mreitz@redhat.com
32
*/
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
- QLIST_HEAD(, BdrvChild) children;
26
---
34
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) children;
27
block.c | 15 ++++++++++-----
35
BdrvChild *backing;
28
1 file changed, 10 insertions(+), 5 deletions(-)
36
BdrvChild *file;
29
37
30
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
40
--- a/block.c
33
+++ b/block.c
41
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
35
if (path_is_absolute(filename)) {
43
{
36
pstrcpy(dest, dest_size, filename);
44
assert(!child->bs);
45
GLOBAL_STATE_CODE();
46
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
47
+
48
assert(!child->next.le_prev); /* not in children list */
49
50
g_free(child->name);
51
diff --git a/block/replication.c b/block/replication.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/replication.c
54
+++ b/block/replication.c
55
@@ -XXX,XX +XXX,XX @@ static void backup_job_completed(void *opaque, int ret)
56
backup_job_cleanup(bs);
57
}
58
59
-static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
60
+static bool GRAPH_RDLOCK
61
+check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
62
{
63
BdrvChild *child;
64
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);
37
} else {
71
} else {
38
- p = strchr(base_path, ':');
72
BdrvChild *c, *next_c;
39
- if (p)
73
+ bdrv_graph_co_rdlock();
40
- p++;
74
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
41
- else
75
+ bdrv_graph_co_rdunlock();
42
- p = base_path;
76
bdrv_co_unref_child(bs, c);
43
+ const char *protocol_stripped = NULL;
77
+ bdrv_graph_co_rdlock();
44
+
78
}
45
+ if (path_has_protocol(base_path)) {
79
+ bdrv_graph_co_rdunlock();
46
+ protocol_stripped = strchr(base_path, ':');
80
}
47
+ if (protocol_stripped) {
81
48
+ protocol_stripped++;
82
dbdd->done = true;
49
+ }
50
+ }
51
+ p = protocol_stripped ?: base_path;
52
+
53
p1 = strrchr(base_path, '/');
54
#ifdef _WIN32
55
{
56
--
83
--
57
1.8.3.1
84
2.41.0
58
59
diff view generated by jsdifflib
1
This adds a small test for the image streaming error path for failing
1
bdrv_graph_wrlock() can't run in a coroutine (because it polls) and
2
block_job_create(), which would have found the null pointer dereference
2
requires holding the BQL. We already have GLOBAL_STATE_CODE() to assert
3
in commit a170a91f.
3
the latter. Assert the former as well and add a no_coroutine_fn marker.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Message-ID: <20230929145157.45443-23-kwolf@redhat.com>
7
Reviewed-by: Kashyap Chamarthy <kchamart@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
tests/qemu-iotests/030 | 4 ++++
10
include/block/graph-lock.h | 3 ++-
12
tests/qemu-iotests/030.out | 4 ++--
11
block/graph-lock.c | 3 ++-
13
2 files changed, 6 insertions(+), 2 deletions(-)
12
2 files changed, 4 insertions(+), 2 deletions(-)
14
13
15
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
14
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/030
18
+++ b/tests/qemu-iotests/030
19
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
20
result = self.vm.qmp('block-stream', device='nonexistent')
21
self.assert_qmp(result, 'error/class', 'GenericError')
22
23
+ def test_job_id_missing(self):
24
+ result = self.vm.qmp('block-stream', device='mid')
25
+ self.assert_qmp(result, 'error/class', 'GenericError')
26
+
27
28
class TestParallelOps(iotests.QMPTestCase):
29
num_ops = 4 # Number of parallel block-stream operations
30
diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
31
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
32
--- a/tests/qemu-iotests/030.out
16
--- a/include/block/graph-lock.h
33
+++ b/tests/qemu-iotests/030.out
17
+++ b/include/block/graph-lock.h
34
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void unregister_aiocontext(AioContext *ctx);
35
-......................
19
* This function polls. Callers must not hold the lock of any AioContext other
36
+.......................
20
* than the current one and the one of @bs.
37
----------------------------------------------------------------------
21
*/
38
-Ran 22 tests
22
-void bdrv_graph_wrlock(BlockDriverState *bs) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
39
+Ran 23 tests
23
+void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
40
24
+bdrv_graph_wrlock(BlockDriverState *bs);
41
OK
25
26
/*
27
* bdrv_graph_wrunlock:
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
42
--
47
--
43
1.8.3.1
48
2.41.0
44
45
diff view generated by jsdifflib