1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
1
The following changes since commit a51e5124a655b3dad80b36b18547cb1eca2c5eb2:
2
2
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +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
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
9
for you to fetch changes up to e6e964b8b021446c8d3d1f91c0208f653e9ec92c:
10
10
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
11
block: Add assertion for bdrv_graph_wrlock() (2023-10-12 16:31:33 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Fix resize (extending) of short overlays
16
- Clean up coroutine versions of bdrv_{is_allocated,block_status}*
17
- nvme: introduce PMR support from NVMe 1.4 spec
17
- Graph locking part 5 (protect children/parent links)
18
- qemu-storage-daemon: Fix non-string --object properties
19
18
20
----------------------------------------------------------------
19
----------------------------------------------------------------
21
Alberto Garcia (1):
20
Emanuele Giuseppe Esposito (1):
22
qcow2: Add incompatibility note between backing files and raw external data files
21
block: Mark drain related functions GRAPH_RDLOCK
23
22
24
Andrzej Jakowski (1):
23
Kevin Wolf (21):
25
nvme: introduce PMR support from NVMe 1.4 spec
24
test-bdrv-drain: Don't call bdrv_graph_wrlock() in coroutine context
25
block-coroutine-wrapper: Add no_co_wrapper_bdrv_rdlock functions
26
block: Take graph rdlock in bdrv_inactivate_all()
27
block: Mark bdrv_first_blk() and bdrv_is_root_node() GRAPH_RDLOCK
28
block: Mark bdrv_parent_cb_resize() and callers GRAPH_RDLOCK
29
block: Mark bdrv_snapshot_fallback() and callers GRAPH_RDLOCK
30
block: Take graph rdlock in parts of reopen
31
block: Mark bdrv_get_xdbg_block_graph() and callers GRAPH_RDLOCK
32
block: Mark bdrv_refresh_filename() and callers GRAPH_RDLOCK
33
block: Mark bdrv_primary_child() and callers GRAPH_RDLOCK
34
block: Mark bdrv_get_parent_name() and callers GRAPH_RDLOCK
35
block: Mark bdrv_amend_options() and callers GRAPH_RDLOCK
36
qcow2: Mark qcow2_signal_corruption() and callers GRAPH_RDLOCK
37
qcow2: Mark qcow2_inactivate() and callers GRAPH_RDLOCK
38
qcow2: Mark check_constraints_on_bitmap() GRAPH_RDLOCK
39
block: Mark bdrv_op_is_blocked() and callers GRAPH_RDLOCK
40
block: Mark bdrv_apply_auto_read_only() and callers GRAPH_RDLOCK
41
block: Mark bdrv_get_specific_info() and callers GRAPH_RDLOCK
42
block: Protect bs->parents with graph_lock
43
block: Protect bs->children with graph_lock
44
block: Add assertion for bdrv_graph_wrlock()
26
45
27
Kevin Wolf (12):
46
Paolo Bonzini (4):
28
block: Add flags to BlockDriver.bdrv_co_truncate()
47
block: rename the bdrv_co_block_status static function
29
block: Add flags to bdrv(_co)_truncate()
48
block: complete public block status API
30
block-backend: Add flags to blk_truncate()
49
block: switch to co_wrapper for bdrv_is_allocated_*
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
50
block: convert more bdrv_is_allocated* and bdrv_block_status* calls to coroutine versions
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: truncate: Don't make backing file data visible
35
iotests: Filter testfiles out in filter_img_info()
36
iotests: Test committing to short backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
40
51
41
Paolo Bonzini (1):
52
block/qcow2.h | 187 ++++++++++++++++------------
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
53
block/vhdx.h | 5 +-
43
54
include/block/block-common.h | 7 +-
44
docs/interop/qcow2.txt | 3 +
55
include/block/block-global-state.h | 34 ++---
45
hw/block/nvme.h | 2 +
56
include/block/block-io.h | 71 +++++++----
46
include/block/block.h | 5 +-
57
include/block/block_int-common.h | 69 +++++-----
47
include/block/block_int.h | 10 +-
58
include/block/block_int-io.h | 7 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
59
include/block/graph-lock.h | 3 +-
49
include/qom/object_interfaces.h | 16 +++
60
include/block/qapi.h | 23 ++--
50
include/sysemu/block-backend.h | 2 +-
61
include/block/snapshot.h | 24 ++--
51
block.c | 3 +-
62
include/sysemu/block-backend-global-state.h | 4 +-
52
block/block-backend.c | 4 +-
63
block.c | 120 ++++++++++++------
53
block/commit.c | 4 +-
64
block/backup.c | 1 +
54
block/crypto.c | 7 +-
65
block/block-backend.c | 9 +-
55
block/file-posix.c | 6 +-
66
block/bochs.c | 2 +
56
block/file-win32.c | 2 +-
67
block/cloop.c | 2 +
57
block/gluster.c | 1 +
68
block/commit.c | 1 +
58
block/io.c | 43 ++++++-
69
block/copy-before-write.c | 2 +-
59
block/iscsi.c | 2 +-
70
block/copy-on-read.c | 8 +-
60
block/mirror.c | 2 +-
71
block/crypto.c | 4 +-
61
block/nfs.c | 3 +-
72
block/curl.c | 2 +
62
block/parallels.c | 6 +-
73
block/dmg.c | 2 +
63
block/qcow.c | 4 +-
74
block/export/export.c | 4 +
64
block/qcow2-cluster.c | 2 +-
75
block/gluster.c | 2 +
65
block/qcow2-refcount.c | 2 +-
76
block/graph-lock.c | 3 +-
66
block/qcow2.c | 73 +++++++++--
77
block/io.c | 143 ++++++++++-----------
67
block/qed.c | 3 +-
78
block/iscsi.c | 2 +
68
block/raw-format.c | 6 +-
79
block/mirror.c | 10 +-
69
block/rbd.c | 1 +
80
block/monitor/block-hmp-cmds.c | 5 +
70
block/sheepdog.c | 4 +-
81
block/nbd.c | 3 +-
71
block/ssh.c | 2 +-
82
block/nfs.c | 2 +-
72
block/vdi.c | 2 +-
83
block/parallels.c | 3 +
73
block/vhdx-log.c | 2 +-
84
block/qapi-sysemu.c | 11 +-
74
block/vhdx.c | 6 +-
85
block/qapi.c | 11 +-
75
block/vmdk.c | 8 +-
86
block/qcow.c | 3 +
76
block/vpc.c | 2 +-
87
block/qcow2-bitmap.c | 38 +++---
77
blockdev.c | 2 +-
88
block/qcow2-cache.c | 11 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
89
block/qcow2-cluster.c | 62 ++++-----
79
qemu-img.c | 2 +-
90
block/qcow2-refcount.c | 80 ++++++------
80
qemu-io-cmds.c | 2 +-
91
block/qcow2.c | 77 +++++++-----
81
qemu-storage-daemon.c | 4 +-
92
block/quorum.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
93
block/raw-format.c | 2 +
83
qom/qom-qmp-cmds.c | 24 +---
94
block/rbd.c | 4 +
84
tests/test-block-iothread.c | 9 +-
95
block/replication.c | 29 +++--
85
tests/qemu-iotests/iotests.py | 5 +-
96
block/snapshot.c | 54 ++++++--
86
hw/block/Makefile.objs | 2 +-
97
block/stream.c | 8 +-
87
hw/block/trace-events | 4 +
98
block/vdi.c | 3 +
88
tests/qemu-iotests/244 | 10 +-
99
block/vhdx.c | 4 +
89
tests/qemu-iotests/244.out | 9 +-
100
block/vmdk.c | 53 +++++---
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
101
block/vpc.c | 3 +
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
102
block/vvfat.c | 20 +--
92
tests/qemu-iotests/group | 1 +
103
blockdev.c | 44 +++++++
93
49 files changed, 951 insertions(+), 96 deletions(-)
104
blockjob.c | 1 +
94
create mode 100755 tests/qemu-iotests/274
105
migration/block.c | 2 +
95
create mode 100644 tests/qemu-iotests/274.out
106
migration/migration-hmp-cmds.c | 2 +
96
107
qemu-img.c | 16 +++
97
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
When extending the size of an image that has a backing file larger than
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
4
2
5
Consider the following scenario where the overlay is shorter than its
3
bdrv_block_status exists as a wrapper for bdrv_block_status_above, but
6
backing file:
4
the name of the (hypothetical) coroutine version, bdrv_co_block_status,
5
is squatted by a random static function. Rename it to
6
bdrv_co_do_block_status.
7
7
8
base.qcow2: AAAAAAAA
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
overlay.qcow2: BBBB
9
Message-ID: <20230904100306.156197-2-pbonzini@redhat.com>
10
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
12
---
36
block/io.c | 25 +++++++++++++++++++++++++
13
block/io.c | 21 +++++++++++----------
37
1 file changed, 25 insertions(+)
14
1 file changed, 11 insertions(+), 10 deletions(-)
38
15
39
diff --git a/block/io.c b/block/io.c
16
diff --git a/block/io.c b/block/io.c
40
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
41
--- a/block/io.c
18
--- a/block/io.c
42
+++ b/block/io.c
19
+++ b/block/io.c
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
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);
44
goto out;
41
goto out;
45
}
42
}
46
43
47
+ /*
44
@@ -XXX,XX +XXX,XX @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
48
+ * If the image has a backing file that is large enough that it would
45
int64_t file_pnum;
49
+ * provide data for the new area, we cannot leave it unallocated because
46
int ret2;
50
+ * then the backing file content would become visible. Instead, zero-fill
47
51
+ * the new area.
48
- ret2 = bdrv_co_block_status(local_file, want_zero, local_map,
52
+ *
49
- *pnum, &file_pnum, NULL, NULL);
53
+ * Note that if the image has a backing file, but was opened without the
50
+ ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map,
54
+ * backing file, taking care of keeping things consistent with that backing
51
+ *pnum, &file_pnum, NULL, NULL);
55
+ * file is the user's responsibility.
52
if (ret2 >= 0) {
56
+ */
53
/* Ignore errors. This is just providing extra information, it
57
+ if (new_bytes && bs->backing) {
54
* is useful but not necessary.
58
+ int64_t backing_len;
55
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
59
+
56
return 0;
60
+ backing_len = bdrv_getlength(backing_bs(bs));
57
}
61
+ if (backing_len < 0) {
58
62
+ ret = backing_len;
59
- ret = bdrv_co_block_status(bs, want_zero, offset, bytes, pnum, map, file);
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
60
+ ret = bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum,
64
+ goto out;
61
+ map, file);
65
+ }
62
++*depth;
66
+
63
if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) {
67
+ if (backing_len > old_size) {
64
return ret;
68
+ flags |= BDRV_REQ_ZERO_WRITE;
65
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
69
+ }
66
for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base;
70
+ }
67
p = bdrv_filter_or_cow_bs(p))
71
+
68
{
72
if (drv->bdrv_co_truncate) {
69
- ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map,
73
if (flags & ~bs->supported_truncate_flags) {
70
- file);
74
error_setg(errp, "Block driver does not support requested flags");
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;
75
--
76
--
76
2.25.3
77
2.41.0
77
78
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: Paolo Bonzini <pbonzini@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Test 244 checks the expected behavior of qcow2 external data files
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
with respect to zero and discarded clusters. Filesystems however
5
are free to ignore discard requests, and this seems to be the
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
9
10
This fixes docker tests on RHEL8.
11
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
5
Message-ID: <20230904100306.156197-5-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
8
---
18
tests/qemu-iotests/244 | 10 ++++++++--
9
block/copy-before-write.c | 2 +-
19
tests/qemu-iotests/244.out | 9 ++++++---
10
block/copy-on-read.c | 8 ++++----
20
2 files changed, 14 insertions(+), 5 deletions(-)
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(-)
21
18
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
19
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
23
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qemu-iotests/244
21
--- a/block/copy-before-write.c
25
+++ b/tests/qemu-iotests/244
22
+++ b/block/copy-before-write.c
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
23
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
27
echo
24
return -EACCES;
28
$QEMU_IO -c 'read -P 0 0 1M' \
25
}
29
-c 'read -P 0x11 1M 1M' \
26
30
- -c 'read -P 0 2M 2M' \
27
- ret = bdrv_block_status(child->bs, offset, cur_bytes, pnum, map, file);
31
-c 'read -P 0x11 4M 1M' \
28
+ ret = bdrv_co_block_status(child->bs, offset, cur_bytes, pnum, map, file);
32
-c 'read -P 0 5M 1M' \
29
if (child == s->target) {
33
-f raw "$TEST_IMG.data" |
30
/*
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
31
* We refer to s->target only for areas that we've written to it.
35
-f $IMGFMT "$TEST_IMG" |
32
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
36
_filter_qemu_io
33
index XXXXXXX..XXXXXXX 100644
37
34
--- a/block/copy-on-read.c
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
35
+++ b/block/copy-on-read.c
39
+# they can contain stale data in the external data file. Instead, zero
36
@@ -XXX,XX +XXX,XX @@ cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
40
+# clusters must be zeroed in the external data file too.
37
local_flags = flags;
41
echo
38
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
39
/* In case of failure, try to copy-on-read anyway */
43
+$QEMU_IO -c 'read -P 0 0 1M' \
40
- ret = bdrv_is_allocated(bs->file->bs, offset, bytes, &n);
44
+ -c 'read -P 0x11 1M 1M' \
41
+ ret = bdrv_co_is_allocated(bs->file->bs, offset, bytes, &n);
45
+ -c 'read -P 0 3M 3M' \
42
if (ret <= 0) {
46
+ -f raw "$TEST_IMG".data |
43
- ret = bdrv_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
47
+ _filter_qemu_io
44
- state->bottom_bs, true, offset,
48
45
- n, &n);
49
echo -n "qcow2 file size after I/O: "
46
+ ret = bdrv_co_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
50
du -b $TEST_IMG | cut -f1
47
+ state->bottom_bs, true, offset,
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
48
+ n, &n);
52
index XXXXXXX..XXXXXXX 100644
49
if (ret > 0 || ret < 0) {
53
--- a/tests/qemu-iotests/244.out
50
local_flags |= BDRV_REQ_COPY_ON_READ;
54
+++ b/tests/qemu-iotests/244.out
51
}
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
52
diff --git a/block/io.c b/block/io.c
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
index XXXXXXX..XXXXXXX 100644
57
read 1048576/1048576 bytes at offset 1048576
54
--- a/block/io.c
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
55
+++ b/block/io.c
59
-read 2097152/2097152 bytes at offset 2097152
56
@@ -XXX,XX +XXX,XX @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
57
ret = 1; /* "already allocated", so nothing will be copied */
61
read 1048576/1048576 bytes at offset 4194304
58
pnum = MIN(align_bytes, max_transfer);
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
59
} else {
63
read 1048576/1048576 bytes at offset 5242880
60
- ret = bdrv_is_allocated(bs, align_offset,
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
61
- MIN(align_bytes, max_transfer), &pnum);
65
read 4194304/4194304 bytes at offset 2097152
62
+ ret = bdrv_co_is_allocated(bs, align_offset,
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
+ MIN(align_bytes, max_transfer), &pnum);
67
64
if (ret < 0) {
68
-Images are identical.
65
/*
69
+read 1048576/1048576 bytes at offset 0
66
* Safe to treat errors in querying allocation as if
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
@@ -XXX,XX +XXX,XX @@ bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
71
+read 1048576/1048576 bytes at offset 1048576
68
/* The flag BDRV_REQ_COPY_ON_READ has reached its addressee */
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
69
flags &= ~BDRV_REQ_COPY_ON_READ;
73
+read 3145728/3145728 bytes at offset 3145728
70
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
- ret = bdrv_is_allocated(bs, offset, bytes, &pnum);
75
qcow2 file size after I/O: 327680
72
+ ret = bdrv_co_is_allocated(bs, offset, bytes, &pnum);
76
73
if (ret < 0) {
77
=== bdrv_co_block_status test for file and offset=0 ===
74
goto out;
75
}
76
diff --git a/block/mirror.c b/block/mirror.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/mirror.c
79
+++ b/block/mirror.c
80
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
81
82
assert(!(offset % s->granularity));
83
WITH_GRAPH_RDLOCK_GUARD() {
84
- ret = bdrv_block_status_above(source, NULL, offset,
85
- nb_chunks * s->granularity,
86
- &io_bytes, NULL, NULL);
87
+ ret = bdrv_co_block_status_above(source, NULL, offset,
88
+ nb_chunks * s->granularity,
89
+ &io_bytes, NULL, NULL);
90
}
91
if (ret < 0) {
92
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
94
}
95
96
WITH_GRAPH_RDLOCK_GUARD() {
97
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
98
- bytes, &count);
99
+ ret = bdrv_co_is_allocated_above(bs, s->base_overlay, true, offset,
100
+ bytes, &count);
101
}
102
if (ret < 0) {
103
return ret;
104
diff --git a/block/qcow2.c b/block/qcow2.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/block/qcow2.c
107
+++ b/block/qcow2.c
108
@@ -XXX,XX +XXX,XX @@ finish:
109
}
110
111
112
-static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
113
+static bool coroutine_fn GRAPH_RDLOCK
114
+is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
115
{
116
int64_t nr;
117
int res;
118
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
119
* backing file. So, we need a loop.
120
*/
121
do {
122
- res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
123
+ res = bdrv_co_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
124
offset += nr;
125
bytes -= nr;
126
} while (res >= 0 && (res & BDRV_BLOCK_ZERO) && nr && bytes);
127
diff --git a/block/replication.c b/block/replication.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/block/replication.c
130
+++ b/block/replication.c
131
@@ -XXX,XX +XXX,XX @@ replication_co_writev(BlockDriverState *bs, int64_t sector_num,
132
while (remaining_sectors > 0) {
133
int64_t count;
134
135
- ret = bdrv_is_allocated_above(top->bs, base->bs, false,
136
- sector_num * BDRV_SECTOR_SIZE,
137
- remaining_sectors * BDRV_SECTOR_SIZE,
138
- &count);
139
+ ret = bdrv_co_is_allocated_above(top->bs, base->bs, false,
140
+ sector_num * BDRV_SECTOR_SIZE,
141
+ remaining_sectors * BDRV_SECTOR_SIZE,
142
+ &count);
143
if (ret < 0) {
144
goto out1;
145
}
146
diff --git a/block/stream.c b/block/stream.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/stream.c
149
+++ b/block/stream.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
151
copy = false;
152
153
WITH_GRAPH_RDLOCK_GUARD() {
154
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
155
+ ret = bdrv_co_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
156
if (ret == 1) {
157
/* Allocated in the top, no need to copy. */
158
} else if (ret >= 0) {
159
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
160
* Copy if allocated in the intermediate images. Limit to the
161
* known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).
162
*/
163
- ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
164
- s->base_overlay, true,
165
- offset, n, &n);
166
+ ret = bdrv_co_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
167
+ s->base_overlay, true,
168
+ offset, n, &n);
169
/* Finish early if end of backing file has been reached */
170
if (ret == 0 && n == 0) {
171
n = len - offset;
172
diff --git a/block/vvfat.c b/block/vvfat.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vvfat.c
175
+++ b/block/vvfat.c
176
@@ -XXX,XX +XXX,XX @@ vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sector
177
if (s->qcow) {
178
int64_t n;
179
int ret;
180
- ret = bdrv_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
181
- (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
182
+ ret = bdrv_co_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
183
+ (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
184
if (ret < 0) {
185
return ret;
186
}
187
@@ -XXX,XX +XXX,XX @@ cluster_was_modified(BDRVVVFATState *s, uint32_t cluster_num)
188
}
189
190
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
191
- was_modified = bdrv_is_allocated(s->qcow->bs,
192
- (cluster2sector(s, cluster_num) +
193
- i) * BDRV_SECTOR_SIZE,
194
- BDRV_SECTOR_SIZE, NULL);
195
+ was_modified = bdrv_co_is_allocated(s->qcow->bs,
196
+ (cluster2sector(s, cluster_num) +
197
+ i) * BDRV_SECTOR_SIZE,
198
+ BDRV_SECTOR_SIZE, NULL);
199
}
200
201
/*
202
@@ -XXX,XX +XXX,XX @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch
203
for (i = 0; i < s->sectors_per_cluster; i++) {
204
int res;
205
206
- res = bdrv_is_allocated(s->qcow->bs,
207
- (offs + i) * BDRV_SECTOR_SIZE,
208
- BDRV_SECTOR_SIZE, NULL);
209
+ res = bdrv_co_is_allocated(s->qcow->bs,
210
+ (offs + i) * BDRV_SECTOR_SIZE,
211
+ BDRV_SECTOR_SIZE, NULL);
212
if (res < 0) {
213
return -1;
214
}
78
--
215
--
79
2.25.3
216
2.41.0
80
81
diff view generated by jsdifflib
New patch
1
AIO callbacks are effectively coroutine_mixed_fn. If AIO requests don't
2
return immediately, their callback is called from the request coroutine.
3
This means that in AIO callbacks, we can't call no_coroutine_fns such as
4
bdrv_graph_wrlock(). Unfortunately test-bdrv-drain does so.
1
5
6
Change the test to use a BH to drop out of coroutine context, and add
7
coroutine_mixed_fn and no_coroutine_fn markers to clarify the context
8
each function runs in.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-ID: <20230929145157.45443-2-kwolf@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
tests/unit/test-bdrv-drain.c | 7 ++++---
16
1 file changed, 4 insertions(+), 3 deletions(-)
17
18
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/unit/test-bdrv-drain.c
21
+++ b/tests/unit/test-bdrv-drain.c
22
@@ -XXX,XX +XXX,XX @@ struct detach_by_parent_data {
23
};
24
static struct detach_by_parent_data detach_by_parent_data;
25
26
-static void detach_indirect_bh(void *opaque)
27
+static void no_coroutine_fn detach_indirect_bh(void *opaque)
28
{
29
struct detach_by_parent_data *data = opaque;
30
31
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
32
bdrv_graph_wrunlock();
33
}
34
35
-static void detach_by_parent_aio_cb(void *opaque, int ret)
36
+static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
37
{
38
struct detach_by_parent_data *data = &detach_by_parent_data;
39
40
g_assert_cmpint(ret, ==, 0);
41
if (data->by_parent_cb) {
42
bdrv_inc_in_flight(data->child_b->bs);
43
- detach_indirect_bh(data);
44
+ aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
45
+ detach_indirect_bh, &detach_by_parent_data);
46
}
47
}
48
49
--
50
2.41.0
diff view generated by jsdifflib
New patch
1
Add a new wrapper type for GRAPH_RDLOCK functions that should be called
2
from coroutine context.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-ID: <20230929145157.45443-3-kwolf@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/block/block-common.h | 7 +++++--
10
scripts/block-coroutine-wrapper.py | 10 +++++++---
11
2 files changed, 12 insertions(+), 5 deletions(-)
12
13
diff --git a/include/block/block-common.h b/include/block/block-common.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block-common.h
16
+++ b/include/block/block-common.h
17
@@ -XXX,XX +XXX,XX @@
18
* function. The coroutine yields after scheduling the BH and is reentered when
19
* the wrapped function returns.
20
*
21
- * A no_co_wrapper_bdrv_wrlock function is a no_co_wrapper function that
22
- * automatically takes the graph wrlock when calling the wrapped function.
23
+ * A no_co_wrapper_bdrv_rdlock function is a no_co_wrapper function that
24
+ * automatically takes the graph rdlock when calling the wrapped function. In
25
+ * the same way, no_co_wrapper_bdrv_wrlock functions automatically take the
26
+ * graph wrlock.
27
*
28
* If the first parameter of the function is a BlockDriverState, BdrvChild or
29
* BlockBackend pointer, the AioContext lock for it is taken in the wrapper.
30
*/
31
#define no_co_wrapper
32
+#define no_co_wrapper_bdrv_rdlock
33
#define no_co_wrapper_bdrv_wrlock
34
35
#include "block/blockjob.h"
36
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
37
index XXXXXXX..XXXXXXX 100644
38
--- a/scripts/block-coroutine-wrapper.py
39
+++ b/scripts/block-coroutine-wrapper.py
40
@@ -XXX,XX +XXX,XX @@ def __init__(self, wrapper_type: str, return_type: str, name: str,
41
raise ValueError(f"Invalid no_co function name: {self.name}")
42
if not self.create_only_co:
43
raise ValueError(f"no_co function can't be mixed: {self.name}")
44
- if self.graph_rdlock:
45
- raise ValueError(f"no_co function can't be rdlock: {self.name}")
46
+ if self.graph_rdlock and self.graph_wrlock:
47
+ raise ValueError("function can't be both rdlock and wrlock: "
48
+ f"{self.name}")
49
self.target_name = f'{subsystem}_{subname}'
50
51
self.ctx = self.gen_ctx()
52
@@ -XXX,XX +XXX,XX @@ def gen_no_co_wrapper(func: FuncDecl) -> str:
53
54
graph_lock=''
55
graph_unlock=''
56
- if func.graph_wrlock:
57
+ if func.graph_rdlock:
58
+ graph_lock=' bdrv_graph_rdlock_main_loop();'
59
+ graph_unlock=' bdrv_graph_rdunlock_main_loop();'
60
+ elif func.graph_wrlock:
61
graph_lock=' bdrv_graph_wrlock(NULL);'
62
graph_unlock=' bdrv_graph_wrunlock();'
63
64
--
65
2.41.0
diff view generated by jsdifflib
New patch
1
The function reads the parents list, so it needs to hold the graph lock.
1
2
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Message-ID: <20230929145157.45443-4-kwolf@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
block.c | 7 ++++---
9
1 file changed, 4 insertions(+), 3 deletions(-)
10
11
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
14
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
16
}
17
}
18
19
-static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
20
+static bool GRAPH_RDLOCK
21
+bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
22
{
23
BdrvChild *parent;
24
GLOBAL_STATE_CODE();
25
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
26
return false;
27
}
28
29
-static int bdrv_inactivate_recurse(BlockDriverState *bs)
30
+static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs)
31
{
32
BdrvChild *child, *parent;
33
int ret;
34
uint64_t cumulative_perms, cumulative_shared_perms;
35
36
GLOBAL_STATE_CODE();
37
- GRAPH_RDLOCK_GUARD_MAINLOOP();
38
39
if (!bs->drv) {
40
return -ENOMEDIUM;
41
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
42
GSList *aio_ctxs = NULL, *ctx;
43
44
GLOBAL_STATE_CODE();
45
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
46
47
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
48
AioContext *aio_context = bdrv_get_aio_context(bs);
49
--
50
2.41.0
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_first_blk() and bdrv_is_root_node() need to hold a reader lock
3
for the graph. These functions are the only functions in block-backend.c
4
that access the parent list of a node.
1
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-ID: <20230929145157.45443-5-kwolf@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 9 +++++----
12
include/sysemu/block-backend-global-state.h | 4 ++--
13
block.c | 1 +
14
block/block-backend.c | 6 +++++-
15
block/export/export.c | 4 ++++
16
block/io.c | 1 +
17
block/monitor/block-hmp-cmds.c | 2 ++
18
block/qapi-sysemu.c | 2 ++
19
block/replication.c | 10 ++++++++--
20
block/snapshot.c | 15 +++++++++++----
21
blockdev.c | 5 +++++
22
migration/block.c | 2 ++
23
migration/migration-hmp-cmds.c | 2 ++
24
tests/unit/test-block-iothread.c | 3 +++
25
14 files changed, 53 insertions(+), 13 deletions(-)
26
27
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block-global-state.h
30
+++ b/include/block/block-global-state.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState * GRAPH_RDLOCK
32
check_to_replace_node(BlockDriverState *parent_bs, const char *node_name,
33
Error **errp);
34
35
-int no_coroutine_fn bdrv_activate(BlockDriverState *bs, Error **errp);
36
+int no_coroutine_fn GRAPH_RDLOCK
37
+bdrv_activate(BlockDriverState *bs, Error **errp);
38
39
-int coroutine_fn no_co_wrapper
40
+int coroutine_fn no_co_wrapper_bdrv_rdlock
41
bdrv_co_activate(BlockDriverState *bs, Error **errp);
42
43
void bdrv_activate_all(Error **errp);
44
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvNextIterator {
45
BlockDriverState *bs;
46
} BdrvNextIterator;
47
48
-BlockDriverState *bdrv_first(BdrvNextIterator *it);
49
-BlockDriverState *bdrv_next(BdrvNextIterator *it);
50
+BlockDriverState * GRAPH_RDLOCK bdrv_first(BdrvNextIterator *it);
51
+BlockDriverState * GRAPH_RDLOCK bdrv_next(BdrvNextIterator *it);
52
void bdrv_next_cleanup(BdrvNextIterator *it);
53
54
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
55
diff --git a/include/sysemu/block-backend-global-state.h b/include/sysemu/block-backend-global-state.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/sysemu/block-backend-global-state.h
58
+++ b/include/sysemu/block-backend-global-state.h
59
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public);
60
void blk_remove_bs(BlockBackend *blk);
61
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp);
62
int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp);
63
-bool bdrv_has_blk(BlockDriverState *bs);
64
-bool bdrv_is_root_node(BlockDriverState *bs);
65
+bool GRAPH_RDLOCK bdrv_has_blk(BlockDriverState *bs);
66
+bool GRAPH_RDLOCK bdrv_is_root_node(BlockDriverState *bs);
67
int GRAPH_UNLOCKED blk_set_perm(BlockBackend *blk, uint64_t perm,
68
uint64_t shared_perm, Error **errp);
69
void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm);
70
diff --git a/block.c b/block.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block.c
73
+++ b/block.c
74
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
75
BdrvNextIterator it;
76
77
GLOBAL_STATE_CODE();
78
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
79
80
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
81
AioContext *aio_context = bdrv_get_aio_context(bs);
82
diff --git a/block/block-backend.c b/block/block-backend.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/block/block-backend.c
85
+++ b/block/block-backend.c
86
@@ -XXX,XX +XXX,XX @@ BlockDriverState *blk_bs(BlockBackend *blk)
87
return blk->root ? blk->root->bs : NULL;
88
}
89
90
-static BlockBackend *bdrv_first_blk(BlockDriverState *bs)
91
+static BlockBackend * GRAPH_RDLOCK bdrv_first_blk(BlockDriverState *bs)
92
{
93
BdrvChild *child;
94
95
GLOBAL_STATE_CODE();
96
+ assert_bdrv_graph_readable();
97
98
QLIST_FOREACH(child, &bs->parents, next_parent) {
99
if (child->klass == &child_root) {
100
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_root_node(BlockDriverState *bs)
101
BdrvChild *c;
102
103
GLOBAL_STATE_CODE();
104
+ assert_bdrv_graph_readable();
105
+
106
QLIST_FOREACH(c, &bs->parents, next_parent) {
107
if (c->klass != &child_root) {
108
return false;
109
@@ -XXX,XX +XXX,XX @@ void blk_activate(BlockBackend *blk, Error **errp)
110
if (qemu_in_coroutine()) {
111
bdrv_co_activate(bs, errp);
112
} else {
113
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
114
bdrv_activate(bs, errp);
115
}
116
}
117
diff --git a/block/export/export.c b/block/export/export.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/export/export.c
120
+++ b/block/export/export.c
121
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
122
uint64_t perm;
123
int ret;
124
125
+ GLOBAL_STATE_CODE();
126
+
127
if (!id_wellformed(export->id)) {
128
error_setg(errp, "Invalid block export id");
129
return NULL;
130
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
131
* access since the export could be available before migration handover.
132
* ctx was acquired in the caller.
133
*/
134
+ bdrv_graph_rdlock_main_loop();
135
bdrv_activate(bs, NULL);
136
+ bdrv_graph_rdunlock_main_loop();
137
138
perm = BLK_PERM_CONSISTENT_READ;
139
if (export->writable) {
140
diff --git a/block/io.c b/block/io.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/io.c
143
+++ b/block/io.c
144
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
145
int result = 0;
146
147
GLOBAL_STATE_CODE();
148
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
149
150
/*
151
* bdrv queue is managed by record/replay,
152
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/monitor/block-hmp-cmds.c
155
+++ b/block/monitor/block-hmp-cmds.c
156
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
157
SnapshotEntry *snapshot_entry;
158
Error *err = NULL;
159
160
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
161
+
162
bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, &err);
163
if (!bs) {
164
error_report_err(err);
165
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qapi-sysemu.c
168
+++ b/block/qapi-sysemu.c
169
@@ -XXX,XX +XXX,XX @@ static void blockdev_insert_medium(const char *device, const char *id,
170
BlockBackend *blk;
171
BlockDriverState *bs;
172
173
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
174
+
175
blk = qmp_get_blk(device, id, errp);
176
if (!blk) {
177
return;
178
diff --git a/block/replication.c b/block/replication.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/replication.c
181
+++ b/block/replication.c
182
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
183
Error *local_err = NULL;
184
BackupPerf perf = { .use_copy_range = true, .max_workers = 1 };
185
186
+ GLOBAL_STATE_CODE();
187
+
188
aio_context = bdrv_get_aio_context(bs);
189
aio_context_acquire(aio_context);
190
s = bs->opaque;
191
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
192
return;
193
}
194
195
+ bdrv_graph_rdlock_main_loop();
196
secondary_disk = hidden_disk->bs->backing;
197
if (!secondary_disk->bs || !bdrv_has_blk(secondary_disk->bs)) {
198
error_setg(errp, "The secondary disk doesn't have block backend");
199
+ bdrv_graph_rdunlock_main_loop();
200
aio_context_release(aio_context);
201
return;
202
}
203
+ bdrv_graph_rdunlock_main_loop();
204
205
/* verify the length */
206
active_length = bdrv_getlength(active_disk->bs);
207
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
208
return;
209
}
210
211
- bdrv_graph_wrunlock();
212
-
213
/* start backup job now */
214
error_setg(&s->blocker,
215
"Block device is in use by internal backup job");
216
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
217
if (!top_bs || !bdrv_is_root_node(top_bs) ||
218
!check_top_bs(top_bs, bs)) {
219
error_setg(errp, "No top_bs or it is invalid");
220
+ bdrv_graph_wrunlock();
221
reopen_backing_file(bs, false, NULL);
222
aio_context_release(aio_context);
223
return;
224
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
225
bdrv_op_block_all(top_bs, s->blocker);
226
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
227
228
+ bdrv_graph_wrunlock();
229
+
230
s->backup_job = backup_job_create(
231
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
232
0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL,
233
diff --git a/block/snapshot.c b/block/snapshot.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/block/snapshot.c
236
+++ b/block/snapshot.c
237
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
238
}
239
240
241
-static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
242
- GList **all_bdrvs,
243
- Error **errp)
244
+static int GRAPH_RDLOCK
245
+bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
246
+ GList **all_bdrvs, Error **errp)
247
{
248
g_autoptr(GList) bdrvs = NULL;
249
250
@@ -XXX,XX +XXX,XX @@ static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
251
}
252
253
254
-static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
255
+static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
256
{
257
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
258
return false;
259
@@ -XXX,XX +XXX,XX @@ bool bdrv_all_can_snapshot(bool has_devices, strList *devices,
260
GList *iterbdrvs;
261
262
GLOBAL_STATE_CODE();
263
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
264
265
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
266
return false;
267
@@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name,
268
GList *iterbdrvs;
269
270
GLOBAL_STATE_CODE();
271
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
272
273
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
274
return -1;
275
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
276
GList *iterbdrvs;
277
278
GLOBAL_STATE_CODE();
279
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
280
281
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
282
return -1;
283
@@ -XXX,XX +XXX,XX @@ int bdrv_all_has_snapshot(const char *name,
284
GList *iterbdrvs;
285
286
GLOBAL_STATE_CODE();
287
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
288
289
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
290
return -1;
291
@@ -XXX,XX +XXX,XX @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
292
{
293
g_autoptr(GList) bdrvs = NULL;
294
GList *iterbdrvs;
295
+
296
GLOBAL_STATE_CODE();
297
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
298
299
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
300
return -1;
301
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_all_find_vmstate_bs(const char *vmstate_bs,
302
GList *iterbdrvs;
303
304
GLOBAL_STATE_CODE();
305
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
306
307
if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
308
return NULL;
309
diff --git a/blockdev.c b/blockdev.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/blockdev.c
312
+++ b/blockdev.c
313
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
314
BlockDriverState *bs;
315
AioContext *aio_context;
316
317
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
318
+
319
bs = bdrv_lookup_bs(name, name, errp);
320
if (bs == NULL) {
321
return NULL;
322
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_del(const char *node_name, Error **errp)
323
BlockDriverState *bs;
324
325
GLOBAL_STATE_CODE();
326
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
327
328
bs = bdrv_find_node(node_name);
329
if (!bs) {
330
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
331
AioContext *new_context;
332
BlockDriverState *bs;
333
334
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
335
+
336
bs = bdrv_find_node(node_name);
337
if (!bs) {
338
error_setg(errp, "Failed to find node with node-name='%s'", node_name);
339
diff --git a/migration/block.c b/migration/block.c
340
index XXXXXXX..XXXXXXX 100644
341
--- a/migration/block.c
342
+++ b/migration/block.c
343
@@ -XXX,XX +XXX,XX @@ static int init_blk_migration(QEMUFile *f)
344
Error *local_err = NULL;
345
int ret;
346
347
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
348
+
349
block_mig_state.submitted = 0;
350
block_mig_state.read_done = 0;
351
block_mig_state.transferred = 0;
352
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
353
index XXXXXXX..XXXXXXX 100644
354
--- a/migration/migration-hmp-cmds.c
355
+++ b/migration/migration-hmp-cmds.c
356
@@ -XXX,XX +XXX,XX @@ static void vm_completion(ReadLineState *rs, const char *str)
357
BlockDriverState *bs;
358
BdrvNextIterator it;
359
360
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
361
+
362
len = strlen(str);
363
readline_set_completion_index(rs, len);
364
365
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
366
index XXXXXXX..XXXXXXX 100644
367
--- a/tests/unit/test-block-iothread.c
368
+++ b/tests/unit/test-block-iothread.c
369
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_check(BdrvChild *c)
370
371
static void test_sync_op_activate(BdrvChild *c)
372
{
373
+ GLOBAL_STATE_CODE();
374
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
375
+
376
/* Early success: Image is not inactive */
377
bdrv_activate(c->bs, NULL);
378
}
379
--
380
2.41.0
diff view generated by jsdifflib
New patch
1
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
3
Draining recursively traverses the graph, therefore we need to make sure
4
that also such accesses to the graph are protected by the graph rdlock.
5
6
There are 3 different drain callers to consider:
7
1. drain in the main loop: no issue at all, rdlock is nop.
8
2. drain in an iothread: rdlock only works in main loop or coroutines,
9
so disallow it.
10
3. drain in a coroutine (regardless of AioContext): the drain mechanism
11
takes care of scheduling a BH in the bs->aio_context that will
12
then take care of perform the actual draining. This is wrong,
13
because as pointed in (2) if bs->aio_context is an iothread then
14
rdlock won't work. Therefore change bdrv_co_yield_to_drain to
15
schedule the BH in the main loop.
16
17
Caller (2) also implies that we need to modify test-bdrv-drain.c to
18
disallow draining in the iothreads.
19
20
For some places, we know that they will hold the lock, but we don't have
21
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
22
with a FIXME comment. These places will be removed once everything is
23
properly annotated.
24
25
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Message-ID: <20230929145157.45443-6-kwolf@redhat.com>
28
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
---
31
include/block/block-io.h | 23 ++++++++++++++++++-----
32
include/block/block_int-common.h | 6 +++---
33
block.c | 6 +++---
34
block/io.c | 32 ++++++++++++++++++++++++++++----
35
tests/unit/test-bdrv-drain.c | 4 ++--
36
5 files changed, 54 insertions(+), 17 deletions(-)
37
38
diff --git a/include/block/block-io.h b/include/block/block-io.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block-io.h
41
+++ b/include/block/block-io.h
42
@@ -XXX,XX +XXX,XX @@ bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
43
*
44
* Begin a quiesced section for the parent of @c.
45
*/
46
-void bdrv_parent_drained_begin_single(BdrvChild *c);
47
+void GRAPH_RDLOCK bdrv_parent_drained_begin_single(BdrvChild *c);
48
49
/**
50
* bdrv_parent_drained_poll_single:
51
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c);
52
* Returns true if there is any pending activity to cease before @c can be
53
* called quiesced, false otherwise.
54
*/
55
-bool bdrv_parent_drained_poll_single(BdrvChild *c);
56
+bool GRAPH_RDLOCK bdrv_parent_drained_poll_single(BdrvChild *c);
57
58
/**
59
* bdrv_parent_drained_end_single:
60
*
61
* End a quiesced section for the parent of @c.
62
*/
63
-void bdrv_parent_drained_end_single(BdrvChild *c);
64
+void GRAPH_RDLOCK bdrv_parent_drained_end_single(BdrvChild *c);
65
66
/**
67
* bdrv_drain_poll:
68
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c);
69
*
70
* This is part of bdrv_drained_begin.
71
*/
72
-bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
73
- bool ignore_bds_parents);
74
+bool GRAPH_RDLOCK
75
+bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
76
+ bool ignore_bds_parents);
77
78
/**
79
* bdrv_drained_begin:
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
81
* Begin a quiesced section for exclusive access to the BDS, by disabling
82
* external request sources including NBD server, block jobs, and device model.
83
*
84
+ * This function can only be invoked by the main loop or a coroutine
85
+ * (regardless of the AioContext where it is running).
86
+ * If the coroutine is running in an Iothread AioContext, this function will
87
+ * just schedule a BH to run in the main loop.
88
+ * However, it cannot be directly called by an Iothread.
89
+ *
90
* This function can be recursive.
91
*/
92
void bdrv_drained_begin(BlockDriverState *bs);
93
@@ -XXX,XX +XXX,XX @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, BdrvChild *parent);
94
* bdrv_drained_end:
95
*
96
* End a quiescent section started by bdrv_drained_begin().
97
+ *
98
+ * This function can only be invoked by the main loop or a coroutine
99
+ * (regardless of the AioContext where it is running).
100
+ * If the coroutine is running in an Iothread AioContext, this function will
101
+ * just schedule a BH to run in the main loop.
102
+ * However, it cannot be directly called by an Iothread.
103
*/
104
void bdrv_drained_end(BlockDriverState *bs);
105
106
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
107
index XXXXXXX..XXXXXXX 100644
108
--- a/include/block/block_int-common.h
109
+++ b/include/block/block_int-common.h
110
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
111
* Note that this can be nested. If drained_begin() was called twice, new
112
* I/O is allowed only after drained_end() was called twice, too.
113
*/
114
- void (*drained_begin)(BdrvChild *child);
115
- void (*drained_end)(BdrvChild *child);
116
+ void GRAPH_RDLOCK_PTR (*drained_begin)(BdrvChild *child);
117
+ void GRAPH_RDLOCK_PTR (*drained_end)(BdrvChild *child);
118
119
/*
120
* Returns whether the parent has pending requests for the child. This
121
* callback is polled after .drained_begin() has been called until all
122
* activity on the child has stopped.
123
*/
124
- bool (*drained_poll)(BdrvChild *child);
125
+ bool GRAPH_RDLOCK_PTR (*drained_poll)(BdrvChild *child);
126
127
/*
128
* Notifies the parent that the filename of its child has changed (e.g.
129
diff --git a/block.c b/block.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block.c
132
+++ b/block.c
133
@@ -XXX,XX +XXX,XX @@ static char *bdrv_child_get_parent_desc(BdrvChild *c)
134
return g_strdup_printf("node '%s'", bdrv_get_node_name(parent));
135
}
136
137
-static void bdrv_child_cb_drained_begin(BdrvChild *child)
138
+static void GRAPH_RDLOCK bdrv_child_cb_drained_begin(BdrvChild *child)
139
{
140
BlockDriverState *bs = child->opaque;
141
bdrv_do_drained_begin_quiesce(bs, NULL);
142
}
143
144
-static bool bdrv_child_cb_drained_poll(BdrvChild *child)
145
+static bool GRAPH_RDLOCK bdrv_child_cb_drained_poll(BdrvChild *child)
146
{
147
BlockDriverState *bs = child->opaque;
148
return bdrv_drain_poll(bs, NULL, false);
149
}
150
151
-static void bdrv_child_cb_drained_end(BdrvChild *child)
152
+static void GRAPH_RDLOCK bdrv_child_cb_drained_end(BdrvChild *child)
153
{
154
BlockDriverState *bs = child->opaque;
155
bdrv_drained_end(bs);
156
diff --git a/block/io.c b/block/io.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/io.c
159
+++ b/block/io.c
160
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs);
161
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
162
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
163
164
-static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
165
+static void GRAPH_RDLOCK
166
+bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
167
{
168
BdrvChild *c, *next;
169
+ IO_OR_GS_CODE();
170
+ assert_bdrv_graph_readable();
171
172
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
173
if (c == ignore) {
174
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c)
175
}
176
}
177
178
-static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
179
+static void GRAPH_RDLOCK
180
+bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
181
{
182
BdrvChild *c;
183
+ IO_OR_GS_CODE();
184
+ assert_bdrv_graph_readable();
185
186
QLIST_FOREACH(c, &bs->parents, next_parent) {
187
if (c == ignore) {
188
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
189
190
bool bdrv_parent_drained_poll_single(BdrvChild *c)
191
{
192
+ IO_OR_GS_CODE();
193
+
194
if (c->klass->drained_poll) {
195
return c->klass->drained_poll(c);
196
}
197
return false;
198
}
199
200
-static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
201
- bool ignore_bds_parents)
202
+static bool GRAPH_RDLOCK
203
+bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
204
+ bool ignore_bds_parents)
205
{
206
BdrvChild *c, *next;
207
bool busy = false;
208
+ IO_OR_GS_CODE();
209
+ assert_bdrv_graph_readable();
210
211
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
212
if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
213
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c)
214
c->quiesced_parent = true;
215
216
if (c->klass->drained_begin) {
217
+ /* called with rdlock taken, but it doesn't really need it. */
218
c->klass->drained_begin(c);
219
}
220
}
221
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent,
222
static bool bdrv_drain_poll_top_level(BlockDriverState *bs,
223
BdrvChild *ignore_parent)
224
{
225
+ GLOBAL_STATE_CODE();
226
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
227
+
228
return bdrv_drain_poll(bs, ignore_parent, false);
229
}
230
231
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent,
232
233
/* Stop things in parent-to-child order */
234
if (qatomic_fetch_inc(&bs->quiesce_counter) == 0) {
235
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
236
bdrv_parent_drained_begin(bs, parent);
237
if (bs->drv && bs->drv->bdrv_drain_begin) {
238
bs->drv->bdrv_drain_begin(bs);
239
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
240
bdrv_co_yield_to_drain(bs, false, parent, false);
241
return;
242
}
243
+
244
+ /* At this point, we should be always running in the main loop. */
245
+ GLOBAL_STATE_CODE();
246
assert(bs->quiesce_counter > 0);
247
GLOBAL_STATE_CODE();
248
249
/* Re-enable things in child-to-parent order */
250
old_quiesce_counter = qatomic_fetch_dec(&bs->quiesce_counter);
251
if (old_quiesce_counter == 1) {
252
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
253
if (bs->drv && bs->drv->bdrv_drain_end) {
254
bs->drv->bdrv_drain_end(bs);
255
}
256
@@ -XXX,XX +XXX,XX @@ void bdrv_drain(BlockDriverState *bs)
257
static void bdrv_drain_assert_idle(BlockDriverState *bs)
258
{
259
BdrvChild *child, *next;
260
+ GLOBAL_STATE_CODE();
261
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
262
263
assert(qatomic_read(&bs->in_flight) == 0);
264
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
265
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_all_poll(void)
266
{
267
BlockDriverState *bs = NULL;
268
bool result = false;
269
+
270
GLOBAL_STATE_CODE();
271
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
272
273
/* bdrv_drain_poll() can't make changes to the graph and we are holding the
274
* main AioContext lock, so iterating bdrv_next_all_states() is safe. */
275
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/tests/unit/test-bdrv-drain.c
278
+++ b/tests/unit/test-bdrv-drain.c
279
@@ -XXX,XX +XXX,XX @@ static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
280
}
281
}
282
283
-static void detach_by_driver_cb_drained_begin(BdrvChild *child)
284
+static void GRAPH_RDLOCK detach_by_driver_cb_drained_begin(BdrvChild *child)
285
{
286
struct detach_by_parent_data *data = &detach_by_parent_data;
287
288
@@ -XXX,XX +XXX,XX @@ static BdrvChildClass detach_by_driver_cb_class;
289
* state is messed up, but if it is only polled in the single
290
* BDRV_POLL_WHILE() at the end of the drain, this should work fine.
291
*/
292
-static void test_detach_indirect(bool by_parent_cb)
293
+static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb)
294
{
295
BlockBackend *blk;
296
BlockDriverState *parent_a, *parent_b, *a, *b, *c;
297
--
298
2.41.0
diff view generated by jsdifflib
1
After processing the option string with the keyval parser, we get a
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
QDict that contains only strings. This QDict must be fed to a keyval
2
bdrv_parent_cb_resize() need to hold a reader lock for the graph.
3
visitor which converts the strings into the right data types.
4
3
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
expects a QDict where all properties already have the QType that matches
5
Message-ID: <20230929145157.45443-7-kwolf@redhat.com>
7
the data type required by the QOM object type.
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
9
Change the --object implementation in qemu-storage-daemon so that it
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
8
---
17
include/qom/object_interfaces.h | 6 +++++-
9
block/io.c | 12 +++++++++---
18
qemu-storage-daemon.c | 4 +---
10
1 file changed, 9 insertions(+), 3 deletions(-)
19
qom/object_interfaces.c | 8 ++++++--
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
22
11
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
12
diff --git a/block/io.c b/block/io.c
24
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
25
--- a/include/qom/object_interfaces.h
14
--- a/block/io.c
26
+++ b/include/qom/object_interfaces.h
15
+++ b/block/io.c
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
16
@@ -XXX,XX +XXX,XX @@
28
/**
17
/* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */
29
* user_creatable_add_dict:
18
#define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
30
* @qdict: the object definition
19
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
20
-static void bdrv_parent_cb_resize(BlockDriverState *bs);
32
+ * assume that all @qdict values are strings); otherwise, use
21
+static void coroutine_fn GRAPH_RDLOCK
33
+ * the normal QObject visitor (i.e. assume all @qdict values
22
+bdrv_parent_cb_resize(BlockDriverState *bs);
34
+ * have the QType expected by the QOM object type)
23
+
35
* @errp: if an error occurs, a pointer to an area to store the error
24
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
36
*
25
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
37
* Create an instance of the user creatable object that is defined by
26
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
27
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
28
}
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
76
}
29
}
77
30
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
31
-static inline void coroutine_fn
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
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)
80
{
35
{
81
Visitor *v;
36
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
82
Object *obj;
37
bytes, read_flags, write_flags);
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
84
}
85
qdict_del(qdict, "id");
86
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
88
+ if (keyval) {
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
90
+ } else {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
106
}
38
}
107
39
108
void qmp_object_del(const char *id, Error **errp)
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);
109
--
51
--
110
2.25.3
52
2.41.0
111
112
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_snapshot_fallback() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-8-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int-common.h | 18 ++++++++--------
11
include/block/snapshot.h | 24 +++++++++++++---------
12
block/snapshot.c | 35 ++++++++++++++++++++++++++------
13
blockdev.c | 9 ++++++++
14
qemu-img.c | 5 +++++
15
5 files changed, 67 insertions(+), 24 deletions(-)
16
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int-common.h
20
+++ b/include/block/block_int-common.h
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
23
int GRAPH_RDLOCK_PTR (*bdrv_inactivate)(BlockDriverState *bs);
24
25
- int (*bdrv_snapshot_create)(BlockDriverState *bs,
26
- QEMUSnapshotInfo *sn_info);
27
- int (*bdrv_snapshot_goto)(BlockDriverState *bs,
28
- const char *snapshot_id);
29
- int (*bdrv_snapshot_delete)(BlockDriverState *bs,
30
- const char *snapshot_id,
31
- const char *name,
32
- Error **errp);
33
+ int GRAPH_RDLOCK_PTR (*bdrv_snapshot_create)(
34
+ BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
35
+
36
+ int GRAPH_UNLOCKED_PTR (*bdrv_snapshot_goto)(
37
+ BlockDriverState *bs, const char *snapshot_id);
38
+
39
+ int GRAPH_RDLOCK_PTR (*bdrv_snapshot_delete)(
40
+ BlockDriverState *bs, const char *snapshot_id, const char *name,
41
+ Error **errp);
42
+
43
int (*bdrv_snapshot_list)(BlockDriverState *bs,
44
QEMUSnapshotInfo **psn_info);
45
int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
46
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/block/snapshot.h
49
+++ b/include/block/snapshot.h
50
@@ -XXX,XX +XXX,XX @@
51
#ifndef SNAPSHOT_H
52
#define SNAPSHOT_H
53
54
+#include "block/graph-lock.h"
55
#include "qapi/qapi-builtin-types.h"
56
57
#define SNAPSHOT_OPT_BASE "snapshot."
58
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
59
const char *name,
60
QEMUSnapshotInfo *sn_info,
61
Error **errp);
62
-int bdrv_can_snapshot(BlockDriverState *bs);
63
-int bdrv_snapshot_create(BlockDriverState *bs,
64
- QEMUSnapshotInfo *sn_info);
65
-int bdrv_snapshot_goto(BlockDriverState *bs,
66
- const char *snapshot_id,
67
- Error **errp);
68
-int bdrv_snapshot_delete(BlockDriverState *bs,
69
- const char *snapshot_id,
70
- const char *name,
71
- Error **errp);
72
+
73
+int GRAPH_RDLOCK bdrv_can_snapshot(BlockDriverState *bs);
74
+
75
+int GRAPH_RDLOCK
76
+bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
77
+
78
+int GRAPH_UNLOCKED
79
+bdrv_snapshot_goto(BlockDriverState *bs, const char *snapshot_id, Error **errp);
80
+
81
+int GRAPH_RDLOCK
82
+bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
83
+ const char *name, Error **errp);
84
+
85
int bdrv_snapshot_list(BlockDriverState *bs,
86
QEMUSnapshotInfo **psn_info);
87
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
88
diff --git a/block/snapshot.c b/block/snapshot.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/snapshot.c
91
+++ b/block/snapshot.c
92
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
93
* back if the given BDS does not support snapshots.
94
* Return NULL if there is no BDS to (safely) fall back to.
95
*/
96
-static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
97
+static BdrvChild * GRAPH_RDLOCK
98
+bdrv_snapshot_fallback_child(BlockDriverState *bs)
99
{
100
BdrvChild *fallback = bdrv_primary_child(bs);
101
BdrvChild *child;
102
103
+ GLOBAL_STATE_CODE();
104
+ assert_bdrv_graph_readable();
105
+
106
/* We allow fallback only to primary child */
107
if (!fallback) {
108
return NULL;
109
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
110
return fallback;
111
}
112
113
-static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
114
+static BlockDriverState * GRAPH_RDLOCK
115
+bdrv_snapshot_fallback(BlockDriverState *bs)
116
{
117
+ GLOBAL_STATE_CODE();
118
return child_bs(bdrv_snapshot_fallback_child(bs));
119
}
120
121
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
122
return ret;
123
}
124
125
+ bdrv_graph_rdlock_main_loop();
126
fallback = bdrv_snapshot_fallback_child(bs);
127
+ bdrv_graph_rdunlock_main_loop();
128
+
129
if (fallback) {
130
QDict *options;
131
QDict *file_options;
132
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
133
int bdrv_snapshot_list(BlockDriverState *bs,
134
QEMUSnapshotInfo **psn_info)
135
{
136
+ GLOBAL_STATE_CODE();
137
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
138
+
139
BlockDriver *drv = bs->drv;
140
BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
141
142
- GLOBAL_STATE_CODE();
143
if (!drv) {
144
return -ENOMEDIUM;
145
}
146
@@ -XXX,XX +XXX,XX @@ bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
147
148
static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
149
{
150
+ GLOBAL_STATE_CODE();
151
+ assert_bdrv_graph_readable();
152
+
153
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
154
return false;
155
}
156
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
157
{
158
g_autoptr(GList) bdrvs = NULL;
159
GList *iterbdrvs;
160
+ int ret;
161
162
GLOBAL_STATE_CODE();
163
- GRAPH_RDLOCK_GUARD_MAINLOOP();
164
165
- if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
166
+ bdrv_graph_rdlock_main_loop();
167
+ ret = bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp);
168
+ bdrv_graph_rdunlock_main_loop();
169
+
170
+ if (ret < 0) {
171
return -1;
172
}
173
174
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
175
BlockDriverState *bs = iterbdrvs->data;
176
AioContext *ctx = bdrv_get_aio_context(bs);
177
int ret = 0;
178
+ bool all_snapshots_includes_bs;
179
180
aio_context_acquire(ctx);
181
- if (devices || bdrv_all_snapshots_includes_bs(bs)) {
182
+ bdrv_graph_rdlock_main_loop();
183
+ all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
184
+ bdrv_graph_rdunlock_main_loop();
185
+
186
+ if (devices || all_snapshots_includes_bs) {
187
ret = bdrv_snapshot_goto(bs, name, errp);
188
}
189
aio_context_release(ctx);
190
diff --git a/blockdev.c b/blockdev.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/blockdev.c
193
+++ b/blockdev.c
194
@@ -XXX,XX +XXX,XX @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
195
SnapshotInfo *info = NULL;
196
int ret;
197
198
+ GLOBAL_STATE_CODE();
199
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
200
+
201
bs = qmp_get_root_bs(device, errp);
202
if (!bs) {
203
return NULL;
204
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_action(BlockdevSnapshotInternal *internal,
205
AioContext *aio_context;
206
int ret1;
207
208
+ GLOBAL_STATE_CODE();
209
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
210
+
211
tran_add(tran, &internal_snapshot_drv, state);
212
213
device = internal->device;
214
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(void *opaque)
215
AioContext *aio_context;
216
Error *local_error = NULL;
217
218
+ GLOBAL_STATE_CODE();
219
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
220
+
221
if (!state->created) {
222
return;
223
}
224
diff --git a/qemu-img.c b/qemu-img.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/qemu-img.c
227
+++ b/qemu-img.c
228
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
229
sn.date_sec = rt / G_USEC_PER_SEC;
230
sn.date_nsec = (rt % G_USEC_PER_SEC) * 1000;
231
232
+ bdrv_graph_rdlock_main_loop();
233
ret = bdrv_snapshot_create(bs, &sn);
234
+ bdrv_graph_rdunlock_main_loop();
235
+
236
if (ret) {
237
error_report("Could not create snapshot '%s': %s",
238
snapshot_name, strerror(-ret));
239
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
240
break;
241
242
case SNAPSHOT_DELETE:
243
+ bdrv_graph_rdlock_main_loop();
244
ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
245
if (ret < 0) {
246
error_report("Could not delete snapshot '%s': snapshot not "
247
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
248
ret = 1;
249
}
250
}
251
+ bdrv_graph_rdunlock_main_loop();
252
break;
253
}
254
255
--
256
2.41.0
diff view generated by jsdifflib
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
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.
2
4
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
5
Therefore just documents most of the functions to be unlocked, and take
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
6
locks internally before accessing the graph.
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
8
7
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
9
Message-ID: <20230929145157.45443-9-kwolf@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
12
---
16
hw/block/nvme.h | 2 +
13
include/block/block_int-common.h | 13 +++++---
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
14
block.c | 57 ++++++++++++++++++++------------
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
15
2 files changed, 43 insertions(+), 27 deletions(-)
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
22
16
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/block/nvme.h
19
--- a/include/block/block_int-common.h
26
+++ b/hw/block/nvme.h
20
+++ b/include/block/block_int-common.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
22
Error **errp);
29
23
30
char *serial;
24
/* For handling image reopen for split or non-split files. */
31
+ HostMemoryBackend *pmrdev;
25
- int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
32
+
26
- BlockReopenQueue *queue, Error **errp);
33
NvmeNamespace *namespaces;
27
- void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
34
NvmeSQueue **sq;
28
- void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state);
35
NvmeCQueue **cq;
29
- void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
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
37
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
43
--- a/block.c
39
+++ b/include/block/nvme.h
44
+++ b/block.c
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
45
@@ -XXX,XX +XXX,XX @@ static int bdrv_reset_options_allowed(BlockDriverState *bs,
41
uint64_t acq;
46
/*
42
uint32_t cmbloc;
47
* Returns true if @child can be reached recursively from @bs
43
uint32_t cmbsz;
48
*/
44
+ uint8_t padding[3520]; /* not used by QEMU */
49
-static bool bdrv_recurse_has_child(BlockDriverState *bs,
45
+ uint32_t pmrcap;
50
- BlockDriverState *child)
46
+ uint32_t pmrctl;
51
+static bool GRAPH_RDLOCK
47
+ uint32_t pmrsts;
52
+bdrv_recurse_has_child(BlockDriverState *bs, BlockDriverState *child)
48
+ uint32_t pmrebs;
53
{
49
+ uint32_t pmrswtp;
54
BdrvChild *c;
50
+ uint32_t pmrmsc;
55
51
} NvmeBar;
56
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
57
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
58
* To be called with bs->aio_context locked.
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
59
*/
269
60
-static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
270
#include "qemu/osdep.h"
61
- BlockDriverState *bs,
271
@@ -XXX,XX +XXX,XX @@
62
- QDict *options,
272
#include "sysemu/sysemu.h"
63
- const BdrvChildClass *klass,
273
#include "qapi/error.h"
64
- BdrvChildRole role,
274
#include "qapi/visitor.h"
65
- bool parent_is_format,
275
+#include "sysemu/hostmem.h"
66
- QDict *parent_options,
276
#include "sysemu/block-backend.h"
67
- int parent_flags,
277
+#include "exec/ram_addr.h"
68
- bool keep_old_opts)
278
69
+static BlockReopenQueue * GRAPH_RDLOCK
279
#include "qemu/log.h"
70
+bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, BlockDriverState *bs,
280
#include "qemu/module.h"
71
+ QDict *options, const BdrvChildClass *klass,
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
72
+ BdrvChildRole role, bool parent_is_format,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
73
+ QDict *parent_options, int parent_flags,
283
"invalid write to read only CMBSZ, ignored");
74
+ bool keep_old_opts)
284
return;
75
{
285
+ case 0xE00: /* PMRCAP */
76
assert(bs != NULL);
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
77
287
+ "invalid write to PMRCAP register, ignored");
78
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
288
+ return;
79
289
+ case 0xE04: /* TODO PMRCTL */
80
GLOBAL_STATE_CODE();
290
+ break;
81
291
+ case 0xE08: /* PMRSTS */
82
+ /*
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
83
+ * Strictly speaking, draining is illegal under GRAPH_RDLOCK. We know that
293
+ "invalid write to PMRSTS register, ignored");
84
+ * we've been called with bdrv_graph_rdlock_main_loop(), though, so it's ok
294
+ return;
85
+ * in practice.
295
+ case 0xE0C: /* PMREBS */
86
+ */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
87
bdrv_drained_begin(bs);
297
+ "invalid write to PMREBS register, ignored");
88
298
+ return;
89
if (bs_queue == NULL) {
299
+ case 0xE10: /* PMRSWTP */
90
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
91
QDict *options, bool keep_old_opts)
301
+ "invalid write to PMRSWTP register, ignored");
92
{
302
+ return;
93
GLOBAL_STATE_CODE();
303
+ case 0xE14: /* TODO PMRMSC */
94
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
304
+ break;
95
305
default:
96
return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
97
NULL, 0, keep_old_opts);
307
"invalid MMIO write,"
98
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
99
* Callers must make sure that their AioContext locking is still correct after
309
}
100
* this.
310
101
*/
311
if (addr < sizeof(n->bar)) {
102
-static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
312
+ /*
103
- bool is_backing, Transaction *tran,
313
+ * When PMRWBM bit 1 is set then read from
104
- Error **errp)
314
+ * from PMRSTS should ensure prior writes
105
+static int GRAPH_UNLOCKED
315
+ * made it to persistent media
106
+bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
316
+ */
107
+ bool is_backing, Transaction *tran,
317
+ if (addr == 0xE08 &&
108
+ Error **errp)
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
109
{
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
110
BlockDriverState *bs = reopen_state->bs;
320
+ 0, n->pmrdev->size);
111
BlockDriverState *new_child_bs;
321
+ }
112
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
322
memcpy(&val, ptr + addr, size);
113
QObject *value;
323
} else {
114
const char *str;
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
115
AioContext *ctx, *old_ctx;
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
116
+ bool has_child;
326
error_setg(errp, "serial property not set");
117
int ret;
327
return;
118
328
}
119
GLOBAL_STATE_CODE();
329
+
120
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
330
+ if (!n->cmb_size_mb && n->pmrdev) {
121
new_child_bs = bdrv_lookup_bs(NULL, str, errp);
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
122
if (new_child_bs == NULL) {
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
123
return -EINVAL;
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
124
- } else if (bdrv_recurse_has_child(new_child_bs, bs)) {
334
+ g_free(path);
335
+ return;
336
+ }
125
+ }
337
+
126
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
127
+ bdrv_graph_rdlock_main_loop();
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
128
+ has_child = bdrv_recurse_has_child(new_child_bs, bs);
340
+ return;
129
+ bdrv_graph_rdunlock_main_loop();
341
+ }
342
+
130
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
131
+ if (has_child) {
344
+ }
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();
345
+
153
+
346
blkconf_blocksizes(&n->conf);
154
do {
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
155
QObject *new = entry->value;
348
false, errp)) {
156
QObject *old = qdict_get(reopen_state->bs->options, entry->key);
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
157
@@ -XXX,XX +XXX,XX @@ error:
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
158
* makes them final by swapping the staging BlockDriverState contents into
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
159
* the active BlockDriverState contents.
352
160
*/
353
+ } else if (n->pmrdev) {
161
-static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
354
+ /* Controller Capabilities register */
162
+static void GRAPH_UNLOCKED bdrv_reopen_commit(BDRVReopenState *reopen_state)
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
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();
356
+
171
+
357
+ /* PMR Capabities register */
172
/* set BDS specific flags now */
358
+ n->bar.pmrcap = 0;
173
qobject_unref(bs->explicit_options);
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
174
qobject_unref(bs->options);
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
175
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
176
qdict_del(bs->explicit_options, "backing");
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
177
qdict_del(bs->options, "backing");
363
+ /* Turn on bit 1 support */
178
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
179
- bdrv_graph_rdlock_main_loop();
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
180
bdrv_refresh_limits(bs, NULL, NULL);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
181
- bdrv_graph_rdunlock_main_loop();
367
+
182
bdrv_refresh_total_sectors(bs, bs->total_sectors);
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
398
}
399
400
for (i = 0; i < n->num_namespaces; i++) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
402
if (n->cmb_size_mb) {
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
410
}
183
}
411
184
412
static Property nvme_props[] = {
185
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
186
* Abort the reopen, and delete and free the staged changes in
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
187
* reopen_state
415
+ HostMemoryBackend *),
188
*/
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
189
-static void bdrv_reopen_abort(BDRVReopenState *reopen_state)
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
190
+static void GRAPH_UNLOCKED bdrv_reopen_abort(BDRVReopenState *reopen_state)
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
191
{
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
192
BlockDriver *drv;
420
index XXXXXXX..XXXXXXX 100644
193
421
--- a/hw/block/Makefile.objs
422
+++ b/hw/block/Makefile.objs
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
424
common-obj-$(CONFIG_XEN) += xen-block.o
425
common-obj-$(CONFIG_ECC) += ecc.o
426
common-obj-$(CONFIG_ONENAND) += onenand.o
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
428
common-obj-$(CONFIG_SWIM) += swim.o
429
430
common-obj-$(CONFIG_SH4) += tc58128.o
431
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
435
436
obj-y += dataplane/
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/block/trace-events
440
+++ b/hw/block/trace-events
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
452
--
194
--
453
2.25.3
195
2.41.0
454
455
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
The raw format driver can simply forward the flag and let its bs->file
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
child take care of actually providing the zeros.
2
bdrv_refresh_filename() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
3
4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-ID: <20230929145157.45443-11-kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
block/raw-format.c | 4 +++-
10
block/vhdx.h | 5 +--
12
1 file changed, 3 insertions(+), 1 deletion(-)
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(-)
13
23
24
diff --git a/block/vhdx.h b/block/vhdx.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/vhdx.h
27
+++ b/block/vhdx.h
28
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
29
30
bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
31
32
-int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
33
- Error **errp);
34
+int GRAPH_RDLOCK
35
+vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
36
+ Error **errp);
37
38
int coroutine_fn GRAPH_RDLOCK
39
vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
40
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block-global-state.h
43
+++ b/include/block/block-global-state.h
44
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
45
Error **errp);
46
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
47
const char *backing_file);
48
-void bdrv_refresh_filename(BlockDriverState *bs);
49
+void GRAPH_RDLOCK bdrv_refresh_filename(BlockDriverState *bs);
50
51
void GRAPH_RDLOCK
52
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
53
@@ -XXX,XX +XXX,XX @@ void bdrv_next_cleanup(BdrvNextIterator *it);
54
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
55
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
56
void *opaque, bool read_only);
57
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
58
-char *bdrv_dirname(BlockDriverState *bs, Error **errp);
59
+
60
+char * GRAPH_RDLOCK
61
+bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
62
+
63
+char * GRAPH_RDLOCK bdrv_dirname(BlockDriverState *bs, Error **errp);
64
65
void bdrv_img_create(const char *filename, const char *fmt,
66
const char *base_filename, const char *base_fmt,
67
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/include/block/block_int-common.h
70
+++ b/include/block/block_int-common.h
71
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
72
* Refreshes the bs->exact_filename field. If that is impossible,
73
* bs->exact_filename has to be left empty.
74
*/
75
- void (*bdrv_refresh_filename)(BlockDriverState *bs);
76
+ void GRAPH_RDLOCK_PTR (*bdrv_refresh_filename)(BlockDriverState *bs);
77
78
/*
79
* Gathers the open options for all children into @target.
80
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
81
* block driver which implements it is probably doing something
82
* shady regarding its runtime option structure.
83
*/
84
- void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
85
- bool backing_overridden);
86
+ void GRAPH_RDLOCK_PTR (*bdrv_gather_child_options)(
87
+ BlockDriverState *bs, QDict *target, bool backing_overridden);
88
89
/*
90
* Returns an allocated string which is the directory name of this BDS: It
91
* will be used to make relative filenames absolute by prepending this
92
* function's return value to them.
93
*/
94
- char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
95
+ char * GRAPH_RDLOCK_PTR (*bdrv_dirname)(BlockDriverState *bs, Error **errp);
96
97
/*
98
* This informs the driver that we are no longer interested in the result
99
diff --git a/include/block/qapi.h b/include/block/qapi.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/block/qapi.h
102
+++ b/include/block/qapi.h
103
@@ -XXX,XX +XXX,XX @@
104
#include "block/snapshot.h"
105
#include "qapi/qapi-types-block-core.h"
106
107
-BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
108
- BlockDriverState *bs,
109
- bool flat,
110
- Error **errp);
111
+BlockDeviceInfo * GRAPH_RDLOCK
112
+bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
113
+ bool flat, Error **errp);
114
+
115
int bdrv_query_snapshot_info_list(BlockDriverState *bs,
116
SnapshotInfoList **p_list,
117
Error **errp);
118
-void bdrv_query_image_info(BlockDriverState *bs,
119
- ImageInfo **p_info,
120
- bool flat,
121
- bool skip_implicit_filters,
122
- Error **errp);
123
+void GRAPH_RDLOCK
124
+bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
125
+ bool skip_implicit_filters, Error **errp);
126
void GRAPH_RDLOCK
127
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
128
Error **errp);
129
diff --git a/block.c b/block.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block.c
132
+++ b/block.c
133
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
134
* setting @errp. In all other cases, NULL will only be returned with
135
* @errp set.
136
*/
137
-static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
138
- const char *filename, Error **errp)
139
+static char * GRAPH_RDLOCK
140
+bdrv_make_absolute_filename(BlockDriverState *relative_to,
141
+ const char *filename, Error **errp)
142
{
143
char *dir, *full_name;
144
145
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
146
*child_flags &= ~BDRV_O_NATIVE_AIO;
147
}
148
149
-static void bdrv_backing_attach(BdrvChild *c)
150
+static void GRAPH_WRLOCK bdrv_backing_attach(BdrvChild *c)
151
{
152
BlockDriverState *parent = c->opaque;
153
BlockDriverState *backing_hd = c->bs;
154
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
155
}
156
157
if (file != NULL) {
158
+ bdrv_graph_rdlock_main_loop();
159
bdrv_refresh_filename(blk_bs(file));
160
+ bdrv_graph_rdunlock_main_loop();
161
+
162
filename = blk_bs(file)->filename;
163
} else {
164
/*
165
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
166
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
167
}
168
169
+ bdrv_graph_rdlock_main_loop();
170
backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
171
+ bdrv_graph_rdunlock_main_loop();
172
+
173
if (local_err) {
174
ret = -EINVAL;
175
error_propagate(errp, local_err);
176
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
177
}
178
179
if (implicit_backing) {
180
+ bdrv_graph_rdlock_main_loop();
181
bdrv_refresh_filename(backing_hd);
182
+ bdrv_graph_rdunlock_main_loop();
183
pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
184
backing_hd->filename);
185
}
186
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
187
if (local_err != NULL) {
188
error_propagate(errp, local_err);
189
} else {
190
+ bdrv_graph_rdlock_main_loop();
191
bdrv_refresh_filename(reopen_state->bs);
192
+ bdrv_graph_rdunlock_main_loop();
193
error_setg(errp, "failed while preparing to reopen image '%s'",
194
reopen_state->bs->filename);
195
}
196
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
197
198
bdrv_ref(top);
199
bdrv_drained_begin(base);
200
+ bdrv_graph_rdlock_main_loop();
201
202
if (!top->drv || !base->drv) {
203
goto exit;
204
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
205
backing_file_str = base->filename;
206
}
207
208
- bdrv_graph_rdlock_main_loop();
209
QLIST_FOREACH(c, &top->parents, next_parent) {
210
updated_children = g_slist_prepend(updated_children, c);
211
}
212
- bdrv_graph_rdunlock_main_loop();
213
214
/*
215
* It seems correct to pass detach_subchain=true here, but it triggers
216
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
217
218
ret = 0;
219
exit:
220
+ bdrv_graph_rdunlock_main_loop();
221
bdrv_drained_end(base);
222
bdrv_unref(top);
223
return ret;
224
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfoList *bdrv_named_nodes_list(bool flat,
225
BlockDriverState *bs;
226
227
GLOBAL_STATE_CODE();
228
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
229
230
list = NULL;
231
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
232
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
233
BlockDriverState *bs_below;
234
235
GLOBAL_STATE_CODE();
236
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
237
238
if (!bs || !bs->drv || !backing_file) {
239
return NULL;
240
diff --git a/block/nfs.c b/block/nfs.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/nfs.c
243
+++ b/block/nfs.c
244
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs)
245
}
246
}
247
248
-static char *nfs_dirname(BlockDriverState *bs, Error **errp)
249
+static char * GRAPH_RDLOCK nfs_dirname(BlockDriverState *bs, Error **errp)
250
{
251
NFSClient *client = bs->opaque;
252
253
diff --git a/block/qapi.c b/block/qapi.c
254
index XXXXXXX..XXXXXXX 100644
255
--- a/block/qapi.c
256
+++ b/block/qapi.c
257
@@ -XXX,XX +XXX,XX @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
258
* Helper function for other query info functions. Store information about @bs
259
* in @info, setting @errp on error.
260
*/
261
-static void bdrv_do_query_node_info(BlockDriverState *bs,
262
- BlockNodeInfo *info,
263
- Error **errp)
264
+static void GRAPH_RDLOCK
265
+bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
266
{
267
int64_t size;
268
const char *backing_filename;
269
@@ -XXX,XX +XXX,XX @@ fail:
270
}
271
272
/* @p_info will be set only on success. */
273
-static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
274
- Error **errp)
275
+static void GRAPH_RDLOCK
276
+bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, Error **errp)
277
{
278
BlockInfo *info = g_malloc0(sizeof(*info));
279
BlockDriverState *bs = blk_bs(blk);
280
@@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp)
281
BlockBackend *blk;
282
Error *local_err = NULL;
283
284
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
285
+
286
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
287
BlockInfoList *info;
288
14
diff --git a/block/raw-format.c b/block/raw-format.c
289
diff --git a/block/raw-format.c b/block/raw-format.c
15
index XXXXXXX..XXXXXXX 100644
290
index XXXXXXX..XXXXXXX 100644
16
--- a/block/raw-format.c
291
--- a/block/raw-format.c
17
+++ b/block/raw-format.c
292
+++ b/block/raw-format.c
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
19
20
s->size = offset;
21
offset += s->offset;
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
24
}
25
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
293
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
294
BDRV_REQ_ZERO_WRITE;
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
30
bs->file->bs->supported_zero_flags);
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
32
+ BDRV_REQ_ZERO_WRITE;
33
295
34
if (bs->probed && !bdrv_is_read_only(bs)) {
296
if (bs->probed && !bdrv_is_read_only(bs)) {
297
+ bdrv_graph_rdlock_main_loop();
35
bdrv_refresh_filename(bs->file->bs);
298
bdrv_refresh_filename(bs->file->bs);
299
+ bdrv_graph_rdunlock_main_loop();
300
fprintf(stderr,
301
"WARNING: Image format was not specified for '%s' and probing "
302
"guessed raw.\n"
303
diff --git a/block/vhdx.c b/block/vhdx.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/block/vhdx.c
306
+++ b/block/vhdx.c
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
308
uint64_t signature;
309
Error *local_err = NULL;
310
311
+ GLOBAL_STATE_CODE();
312
+
313
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
314
if (ret < 0) {
315
return ret;
316
}
317
318
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
319
+
320
s->bat = NULL;
321
s->first_visible_write = true;
322
323
diff --git a/block/vmdk.c b/block/vmdk.c
324
index XXXXXXX..XXXXXXX 100644
325
--- a/block/vmdk.c
326
+++ b/block/vmdk.c
327
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
328
return 0;
329
}
330
331
-static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
332
- Error **errp)
333
+static int GRAPH_RDLOCK
334
+vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, Error **errp)
335
{
336
int ret;
337
size_t l1_size;
338
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
339
return ret;
340
}
341
342
-static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
343
- BdrvChild *file,
344
- int flags, Error **errp)
345
+static int GRAPH_RDLOCK
346
+vmdk_open_vmfs_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
347
+ Error **errp)
348
{
349
int ret;
350
uint32_t magic;
351
@@ -XXX,XX +XXX,XX @@ static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
352
return 0;
353
}
354
355
-static int vmdk_open_se_sparse(BlockDriverState *bs,
356
- BdrvChild *file,
357
- int flags, Error **errp)
358
+static int GRAPH_RDLOCK
359
+vmdk_open_se_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
360
+ Error **errp)
361
{
362
int ret;
363
VMDKSESparseConstHeader const_header;
364
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
365
return buf;
366
}
367
368
-static int vmdk_open_vmdk4(BlockDriverState *bs,
369
- BdrvChild *file,
370
- int flags, QDict *options, Error **errp)
371
+static int GRAPH_RDLOCK
372
+vmdk_open_vmdk4(BlockDriverState *bs, BdrvChild *file, int flags,
373
+ QDict *options, Error **errp)
374
{
375
int ret;
376
uint32_t magic;
377
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
378
}
379
380
/* Open an extent file and append to bs array */
381
-static int vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
382
- char *buf, QDict *options, Error **errp)
383
+static int GRAPH_RDLOCK
384
+vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
385
+ char *buf, QDict *options, Error **errp)
386
{
387
uint32_t magic;
388
389
@@ -XXX,XX +XXX,XX @@ static const char *next_line(const char *s)
390
return s;
391
}
392
393
-static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
394
- QDict *options, Error **errp)
395
+static int GRAPH_RDLOCK
396
+vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
397
+ Error **errp)
398
{
399
int ret;
400
int matches;
401
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
402
char extent_opt_prefix[32];
403
Error *local_err = NULL;
404
405
+ GLOBAL_STATE_CODE();
406
+
407
for (p = desc; *p; p = next_line(p)) {
408
/* parse extent line in one of below formats:
409
*
410
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
411
ret = vmdk_add_extent(bs, extent_file, true, sectors,
412
0, 0, 0, 0, 0, &extent, errp);
413
if (ret < 0) {
414
+ bdrv_graph_rdunlock_main_loop();
415
bdrv_graph_wrlock(NULL);
416
bdrv_unref_child(bs, extent_file);
417
bdrv_graph_wrunlock();
418
+ bdrv_graph_rdlock_main_loop();
419
goto out;
420
}
421
extent->flat_start_offset = flat_offset << 9;
422
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
423
}
424
g_free(buf);
425
if (ret) {
426
+ bdrv_graph_rdunlock_main_loop();
427
bdrv_graph_wrlock(NULL);
428
bdrv_unref_child(bs, extent_file);
429
bdrv_graph_wrunlock();
430
+ bdrv_graph_rdlock_main_loop();
431
goto out;
432
}
433
extent = &s->extents[s->num_extents - 1];
434
} else if (!strcmp(type, "SESPARSE")) {
435
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
436
if (ret) {
437
+ bdrv_graph_rdunlock_main_loop();
438
bdrv_graph_wrlock(NULL);
439
bdrv_unref_child(bs, extent_file);
440
bdrv_graph_wrunlock();
441
+ bdrv_graph_rdlock_main_loop();
442
goto out;
443
}
444
extent = &s->extents[s->num_extents - 1];
445
} else {
446
error_setg(errp, "Unsupported extent type '%s'", type);
447
+ bdrv_graph_rdunlock_main_loop();
448
bdrv_graph_wrlock(NULL);
449
bdrv_unref_child(bs, extent_file);
450
bdrv_graph_wrunlock();
451
+ bdrv_graph_rdlock_main_loop();
452
ret = -ENOTSUP;
453
goto out;
454
}
455
@@ -XXX,XX +XXX,XX @@ out:
456
return ret;
457
}
458
459
-static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
460
- QDict *options, Error **errp)
461
+static int GRAPH_RDLOCK
462
+vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf, QDict *options,
463
+ Error **errp)
464
{
465
int ret;
466
char ct[128];
467
@@ -XXX,XX +XXX,XX @@ static int vmdk_has_zero_init(BlockDriverState *bs)
468
return 1;
469
}
470
471
-static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
472
+static VmdkExtentInfo * GRAPH_RDLOCK vmdk_get_extent_info(VmdkExtent *extent)
473
{
474
VmdkExtentInfo *info = g_new0(VmdkExtentInfo, 1);
475
476
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
477
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
478
VmdkExtentInfoList **tail;
479
480
+ assume_graph_lock(); /* FIXME */
481
+
482
*spec_info = (ImageInfoSpecific){
483
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
484
.u = {
485
diff --git a/blockdev.c b/blockdev.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/blockdev.c
488
+++ b/blockdev.c
489
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
490
bool set_backing_hd = false;
491
int ret;
492
493
+ GLOBAL_STATE_CODE();
494
+
495
tran_add(tran, &drive_backup_drv, state);
496
497
if (!backup->has_mode) {
498
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
499
BlockDriverState *explicit_backing =
500
bdrv_skip_implicit_filters(source);
501
502
+ bdrv_graph_rdlock_main_loop();
503
bdrv_refresh_filename(explicit_backing);
504
+ bdrv_graph_rdunlock_main_loop();
505
+
506
bdrv_img_create(backup->target, format,
507
explicit_backing->filename,
508
explicit_backing->drv->format_name, NULL,
509
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
510
Error *local_err = NULL;
511
int job_flags = JOB_DEFAULT;
512
513
+ GLOBAL_STATE_CODE();
514
+
515
if (base && base_node) {
516
error_setg(errp, "'base' and 'base-node' cannot be specified "
517
"at the same time");
518
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
519
goto out;
520
}
521
assert(bdrv_get_aio_context(base_bs) == aio_context);
522
+
523
+ bdrv_graph_rdlock_main_loop();
524
bdrv_refresh_filename(base_bs);
525
+ bdrv_graph_rdunlock_main_loop();
526
}
527
528
if (bottom) {
529
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
530
break;
531
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
532
/* create new image with backing file */
533
+ bdrv_graph_rdlock_main_loop();
534
bdrv_refresh_filename(explicit_backing);
535
+ bdrv_graph_rdunlock_main_loop();
536
+
537
bdrv_img_create(arg->target, format,
538
explicit_backing->filename,
539
explicit_backing->drv->format_name,
540
diff --git a/qemu-img.c b/qemu-img.c
541
index XXXXXXX..XXXXXXX 100644
542
--- a/qemu-img.c
543
+++ b/qemu-img.c
544
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
545
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
546
547
if (file && has_offset) {
548
+ bdrv_graph_rdlock_main_loop();
549
bdrv_refresh_filename(file);
550
+ bdrv_graph_rdunlock_main_loop();
551
filename = file->filename;
552
}
553
554
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
555
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
556
}
557
558
+ bdrv_graph_rdlock_main_loop();
559
bdrv_refresh_filename(bs);
560
+ bdrv_graph_rdunlock_main_loop();
561
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
562
: bs->filename;
563
out_real_path =
36
--
564
--
37
2.25.3
565
2.41.0
38
39
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
Now that block drivers can support flags for .bdrv_co_truncate, expose
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
the parameter in the node level interfaces bdrv_co_truncate() and
2
bdrv_get_parent_name() need to hold a reader lock for the graph
3
bdrv_truncate().
3
because it accesses the parents list of a node.
4
5
For some places, we know that they will hold the lock, but we don't have
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
7
with a FIXME comment. These places will be removed once everything is
8
properly annotated.
4
9
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-ID: <20230929145157.45443-13-kwolf@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
14
---
12
include/block/block.h | 5 +++--
15
block/qcow2.h | 7 +++----
13
block/block-backend.c | 2 +-
16
include/block/block-io.h | 8 ++++++--
14
block/crypto.c | 2 +-
17
include/block/block_int-io.h | 2 +-
15
block/io.c | 12 +++++++-----
18
include/block/qapi.h | 7 ++++---
16
block/parallels.c | 6 +++---
19
block.c | 14 ++++++++++++--
17
block/qcow.c | 4 ++--
20
block/backup.c | 1 +
18
block/qcow2-refcount.c | 2 +-
21
block/parallels.c | 3 +++
19
block/qcow2.c | 15 +++++++++------
22
block/qcow.c | 3 +++
20
block/raw-format.c | 2 +-
23
block/qcow2-bitmap.c | 2 ++
21
block/vhdx-log.c | 2 +-
24
block/qcow2.c | 4 ++++
22
block/vhdx.c | 2 +-
25
block/quorum.c | 4 ++--
23
block/vmdk.c | 2 +-
26
block/rbd.c | 2 ++
24
tests/test-block-iothread.c | 6 +++---
27
block/snapshot.c | 3 +++
25
13 files changed, 34 insertions(+), 28 deletions(-)
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(-)
26
33
27
diff --git a/include/block/block.h b/include/block/block.h
34
diff --git a/block/qcow2.h b/block/qcow2.h
28
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block.h
36
--- a/block/qcow2.h
30
+++ b/include/block/block.h
37
+++ b/block/qcow2.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp
32
void bdrv_refresh_filename(BlockDriverState *bs);
39
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
33
40
bool release_stored, Error **errp);
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
41
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
35
- PreallocMode prealloc, Error **errp);
42
-bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
43
- const char *name,
37
+ Error **errp);
44
- uint32_t granularity,
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
45
- Error **errp);
39
- PreallocMode prealloc, Error **errp);
46
+bool coroutine_fn GRAPH_RDLOCK
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
47
+qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
41
48
+ uint32_t granularity, Error **errp);
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
49
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
43
int64_t bdrv_getlength(BlockDriverState *bs);
50
const char *name,
44
diff --git a/block/block-backend.c b/block/block-backend.c
51
Error **errp);
45
index XXXXXXX..XXXXXXX 100644
52
diff --git a/include/block/block-io.h b/include/block/block-io.h
46
--- a/block/block-backend.c
53
index XXXXXXX..XXXXXXX 100644
47
+++ b/block/block-backend.c
54
--- a/include/block/block-io.h
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
55
+++ b/include/block/block-io.h
49
return -ENOMEDIUM;
56
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_format_name(BlockDriverState *bs);
50
}
57
51
58
bool bdrv_supports_compressed_writes(BlockDriverState *bs);
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
59
const char *bdrv_get_node_name(const BlockDriverState *bs);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
60
-const char *bdrv_get_device_name(const BlockDriverState *bs);
61
-const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
62
+
63
+const char * GRAPH_RDLOCK
64
+bdrv_get_device_name(const BlockDriverState *bs);
65
+
66
+const char * GRAPH_RDLOCK
67
+bdrv_get_device_or_node_name(const BlockDriverState *bs);
68
69
int coroutine_fn GRAPH_RDLOCK
70
bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
71
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-io.h
74
+++ b/include/block/block_int-io.h
75
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
76
*/
77
void bdrv_wakeup(BlockDriverState *bs);
78
79
-const char *bdrv_get_parent_name(const BlockDriverState *bs);
80
+const char * GRAPH_RDLOCK bdrv_get_parent_name(const BlockDriverState *bs);
81
bool blk_dev_has_tray(BlockBackend *blk);
82
bool blk_dev_is_tray_open(BlockBackend *blk);
83
84
diff --git a/include/block/qapi.h b/include/block/qapi.h
85
index XXXXXXX..XXXXXXX 100644
86
--- a/include/block/qapi.h
87
+++ b/include/block/qapi.h
88
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo * GRAPH_RDLOCK
89
bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
90
bool flat, Error **errp);
91
92
-int bdrv_query_snapshot_info_list(BlockDriverState *bs,
93
- SnapshotInfoList **p_list,
94
- Error **errp);
95
+int GRAPH_RDLOCK
96
+bdrv_query_snapshot_info_list(BlockDriverState *bs,
97
+ SnapshotInfoList **p_list,
98
+ Error **errp);
99
void GRAPH_RDLOCK
100
bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
101
bool skip_implicit_filters, Error **errp);
102
diff --git a/block.c b/block.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block.c
105
+++ b/block.c
106
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
107
return !(bs->open_flags & BDRV_O_RDWR);
54
}
108
}
55
109
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
110
-static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
57
diff --git a/block/crypto.c b/block/crypto.c
111
- bool ignore_allow_rdw, Error **errp)
58
index XXXXXXX..XXXXXXX 100644
112
+static int GRAPH_RDLOCK
59
--- a/block/crypto.c
113
+bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
60
+++ b/block/crypto.c
114
+ bool ignore_allow_rdw, Error **errp)
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
81
{
115
{
82
BlockDriverState *bs = child->bs;
116
IO_CODE();
83
BlockDriver *drv = bs->drv;
117
84
BdrvTrackedRequest req;
118
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
85
- BdrvRequestFlags flags = 0;
119
int ret = 0;
86
int64_t old_size, new_bytes;
120
IO_CODE();
87
int ret;
121
88
122
+ assume_graph_lock(); /* FIXME */
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
123
+
90
}
124
if (!(bs->open_flags & BDRV_O_RDWR)) {
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
125
return 0;
92
} else if (bs->file && drv->is_filter) {
126
}
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
127
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
128
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
129
* not set, or if the BDS still has copy_on_read enabled */
130
read_only = !(reopen_state->flags & BDRV_O_RDWR);
131
+
132
+ bdrv_graph_rdlock_main_loop();
133
ret = bdrv_can_set_read_only(reopen_state->bs, read_only, true, &local_err);
134
+ bdrv_graph_rdunlock_main_loop();
135
if (local_err) {
136
error_propagate(errp, local_err);
137
goto error;
138
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
95
} else {
139
} else {
96
error_setg(errp, "Image format driver does not support resize");
140
/* It is currently mandatory to have a bdrv_reopen_prepare()
97
ret = -ENOTSUP;
141
* handler for each supported drv. */
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
142
+ bdrv_graph_rdlock_main_loop();
99
int64_t offset;
143
error_setg(errp, "Block format '%s' used by node '%s' "
100
bool exact;
144
"does not support reopening files", drv->format_name,
101
PreallocMode prealloc;
145
bdrv_get_device_or_node_name(reopen_state->bs));
102
+ BdrvRequestFlags flags;
146
+ bdrv_graph_rdunlock_main_loop();
103
Error **errp;
147
ret = -1;
104
int ret;
148
goto error;
105
} TruncateCo;
149
}
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
150
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
107
{
151
{
108
TruncateCo *tco = opaque;
152
BdrvOpBlocker *blocker;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
153
GLOBAL_STATE_CODE();
110
- tco->prealloc, tco->errp);
154
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
111
+ tco->prealloc, tco->flags, tco->errp);
155
+
112
aio_wait_kick();
156
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
113
}
157
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
114
158
blocker = QLIST_FIRST(&bs->op_blockers[op]);
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
159
diff --git a/block/backup.c b/block/backup.c
116
- PreallocMode prealloc, Error **errp)
160
index XXXXXXX..XXXXXXX 100644
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
161
--- a/block/backup.c
118
{
162
+++ b/block/backup.c
119
Coroutine *co;
163
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
120
TruncateCo tco = {
164
assert(bs);
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
165
assert(target);
122
.offset = offset,
166
GLOBAL_STATE_CODE();
123
.exact = exact,
167
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
124
.prealloc = prealloc,
168
125
+ .flags = flags,
169
/* QMP interface protects us from these cases */
126
.errp = errp,
170
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
171
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
172
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
173
--- a/block/parallels.c
132
+++ b/block/parallels.c
174
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
175
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
134
} else {
176
bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
135
ret = bdrv_truncate(bs->file,
177
136
(s->data_end + space) << BDRV_SECTOR_BITS,
178
/* Disable migration until bdrv_activate method is added */
137
- false, PREALLOC_MODE_OFF, NULL);
179
+ bdrv_graph_rdlock_main_loop();
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
180
error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
139
}
181
"does not support live migration",
140
if (ret < 0) {
182
bdrv_get_device_or_node_name(bs));
141
return ret;
183
+ bdrv_graph_rdunlock_main_loop();
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
184
+
143
* That means we have to pass exact=true.
185
ret = migrate_add_blocker(s->migration_blocker, errp);
144
*/
186
if (ret < 0) {
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
187
error_setg(errp, "Migration blocker error");
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
188
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
189
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
190
--- a/block/qcow.c
163
+++ b/block/qcow.c
191
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
192
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
165
return -E2BIG;
193
}
166
}
194
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
195
/* Disable migration when qcow images are used */
168
- false, PREALLOC_MODE_OFF, NULL);
196
+ bdrv_graph_rdlock_main_loop();
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
197
error_setg(&s->migration_blocker, "The qcow format used by node '%s' "
170
if (ret < 0) {
198
"does not support live migration",
171
return ret;
199
bdrv_get_device_or_node_name(bs));
172
}
200
+ bdrv_graph_rdunlock_main_loop();
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
201
+
174
l1_length) < 0)
202
ret = migrate_add_blocker(s->migration_blocker, errp);
175
return -1;
203
if (ret < 0) {
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
204
error_free(s->migration_blocker);
177
- PREALLOC_MODE_OFF, NULL);
205
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
178
+ PREALLOC_MODE_OFF, 0, NULL);
206
index XXXXXXX..XXXXXXX 100644
179
if (ret < 0)
207
--- a/block/qcow2-bitmap.c
180
return ret;
208
+++ b/block/qcow2-bitmap.c
181
209
@@ -XXX,XX +XXX,XX @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
210
int64_t len = bdrv_getlength(bs);
183
index XXXXXXX..XXXXXXX 100644
211
int64_t bitmap_bytes;
184
--- a/block/qcow2-refcount.c
212
185
+++ b/block/qcow2-refcount.c
213
+ assume_graph_lock(); /* FIXME */
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
214
+
187
}
215
assert(granularity > 0);
188
216
assert((granularity & (granularity - 1)) == 0);
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
217
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
218
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
219
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
220
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
221
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
222
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
200
mode = PREALLOC_MODE_OFF;
223
int ret, result = 0;
224
Error *local_err = NULL;
225
226
+ assume_graph_lock(); /* FIXME */
227
+
228
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
229
if (local_err != NULL) {
230
result = -EINVAL;
231
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
232
char *message;
233
va_list ap;
234
235
+ assume_graph_lock(); /* FIXME */
236
+
237
fatal = fatal && bdrv_is_writable(bs);
238
239
if (s->signaled_corruption &&
240
diff --git a/block/quorum.c b/block/quorum.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/quorum.c
243
+++ b/block/quorum.c
244
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad(QuorumOpType type, uint64_t offset,
245
end_sector - start_sector);
246
}
247
248
-static void quorum_report_failure(QuorumAIOCB *acb)
249
+static void GRAPH_RDLOCK quorum_report_failure(QuorumAIOCB *acb)
250
{
251
const char *reference = bdrv_get_device_or_node_name(acb->bs);
252
int64_t start_sector = acb->offset / BDRV_SECTOR_SIZE;
253
@@ -XXX,XX +XXX,XX @@ static void quorum_report_failure(QuorumAIOCB *acb)
254
255
static int quorum_vote_error(QuorumAIOCB *acb);
256
257
-static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
258
+static bool GRAPH_RDLOCK quorum_has_too_much_io_failed(QuorumAIOCB *acb)
259
{
260
BDRVQuorumState *s = acb->bs->opaque;
261
262
diff --git a/block/rbd.c b/block/rbd.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/block/rbd.c
265
+++ b/block/rbd.c
266
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
267
BDRVRBDState *s = state->bs->opaque;
268
int ret = 0;
269
270
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
271
+
272
if (s->snap && state->flags & BDRV_O_RDWR) {
273
error_setg(errp,
274
"Cannot change node '%s' to r/w when using RBD snapshot",
275
diff --git a/block/snapshot.c b/block/snapshot.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/block/snapshot.c
278
+++ b/block/snapshot.c
279
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
280
BlockDriver *drv = bs->drv;
281
282
GLOBAL_STATE_CODE();
283
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
284
285
if (!drv) {
286
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
287
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
201
}
288
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
289
aio_context_release(ctx);
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
290
if (ret < 0) {
206
return ret;
291
+ bdrv_graph_rdlock_main_loop();
292
error_prepend(errp, "Could not load snapshot '%s' on '%s': ",
293
name, bdrv_get_device_or_node_name(bs));
294
+ bdrv_graph_rdunlock_main_loop();
295
return -1;
207
}
296
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
297
209
* always fulfilled, so there is no need to pass it on.)
298
diff --git a/block/vdi.c b/block/vdi.c
210
*/
299
index XXXXXXX..XXXXXXX 100644
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
300
--- a/block/vdi.c
212
- false, PREALLOC_MODE_OFF, &local_err);
301
+++ b/block/vdi.c
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
302
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
214
if (local_err) {
303
}
215
warn_reportf_err(local_err,
304
216
"Failed to truncate the tail of the image: ");
305
/* Disable migration when vdi images are used */
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
306
+ bdrv_graph_rdlock_main_loop();
218
* file should be resized to the exact target size, too,
307
error_setg(&s->migration_blocker, "The vdi format used by node '%s' "
219
* so we pass @exact here.
308
"does not support live migration",
220
*/
309
bdrv_get_device_or_node_name(bs));
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
310
+ bdrv_graph_rdunlock_main_loop();
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
311
+
223
+ errp);
312
ret = migrate_add_blocker(s->migration_blocker, errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
313
if (ret < 0) {
254
error_report_err(local_err);
314
error_free(s->migration_blocker);
255
goto fail;
315
diff --git a/block/vpc.c b/block/vpc.c
256
diff --git a/block/raw-format.c b/block/raw-format.c
316
index XXXXXXX..XXXXXXX 100644
257
index XXXXXXX..XXXXXXX 100644
317
--- a/block/vpc.c
258
--- a/block/raw-format.c
318
+++ b/block/vpc.c
259
+++ b/block/raw-format.c
319
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
320
}
261
321
262
s->size = offset;
322
/* Disable migration when VHD images are used */
263
offset += s->offset;
323
+ bdrv_graph_rdlock_main_loop();
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
324
error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
325
"does not support live migration",
266
}
326
bdrv_get_device_or_node_name(bs));
267
327
+ bdrv_graph_rdunlock_main_loop();
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
328
+
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
329
ret = migrate_add_blocker(s->migration_blocker, errp);
270
index XXXXXXX..XXXXXXX 100644
330
if (ret < 0) {
271
--- a/block/vhdx-log.c
331
error_free(s->migration_blocker);
272
+++ b/block/vhdx-log.c
332
diff --git a/block/vvfat.c b/block/vvfat.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
333
index XXXXXXX..XXXXXXX 100644
274
goto exit;
334
--- a/block/vvfat.c
275
}
335
+++ b/block/vvfat.c
276
ret = bdrv_truncate(bs->file, new_file_size, false,
336
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
277
- PREALLOC_MODE_OFF, NULL);
337
QemuOpts *opts;
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
307
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/tests/test-block-iothread.c
311
+++ b/tests/test-block-iothread.c
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
338
int ret;
314
339
315
/* Normal success path */
340
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
341
+
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
342
#ifdef DEBUG
318
g_assert_cmpint(ret, ==, 0);
343
vvv = s;
319
344
#endif
320
/* Early error: Negative offset */
345
diff --git a/blockjob.c b/blockjob.c
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
346
index XXXXXXX..XXXXXXX 100644
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
347
--- a/blockjob.c
323
g_assert_cmpint(ret, ==, -EINVAL);
348
+++ b/blockjob.c
324
349
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
325
/* Error: Read-only image */
350
BlockJob *job;
326
c->bs->read_only = true;
351
int ret;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
352
GLOBAL_STATE_CODE();
328
353
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
354
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
355
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
331
g_assert_cmpint(ret, ==, -EACCES);
356
job_id = bdrv_get_device_name(bs);
332
333
c->bs->read_only = false;
334
--
357
--
335
2.25.3
358
2.41.0
336
337
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_amend_options() need to hold a reader lock for the graph. This
3
removes an assume_graph_lock() call in crypto's implementation.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-14-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-global-state.h | 8 ++++----
11
include/block/block_int-common.h | 10 ++++------
12
block/crypto.c | 4 +---
13
qemu-img.c | 7 +++++++
14
4 files changed, 16 insertions(+), 13 deletions(-)
15
16
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-global-state.h
19
+++ b/include/block/block-global-state.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
21
*/
22
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
23
int64_t total_work_size, void *opaque);
24
-int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
25
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
26
- bool force,
27
- Error **errp);
28
+int GRAPH_RDLOCK
29
+bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
30
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
31
+ bool force, Error **errp);
32
33
/* check if a named node can be replaced when doing drive-mirror */
34
BlockDriverState * GRAPH_RDLOCK
35
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int-common.h
38
+++ b/include/block/block_int-common.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
int coroutine_fn GRAPH_UNLOCKED_PTR (*bdrv_co_create_opts)(
41
BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
42
43
- int (*bdrv_amend_options)(BlockDriverState *bs,
44
- QemuOpts *opts,
45
- BlockDriverAmendStatusCB *status_cb,
46
- void *cb_opaque,
47
- bool force,
48
- Error **errp);
49
+ int GRAPH_RDLOCK_PTR (*bdrv_amend_options)(
50
+ BlockDriverState *bs, QemuOpts *opts,
51
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
52
+ bool force, Error **errp);
53
54
int (*bdrv_make_empty)(BlockDriverState *bs);
55
56
diff --git a/block/crypto.c b/block/crypto.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/crypto.c
59
+++ b/block/crypto.c
60
@@ -XXX,XX +XXX,XX @@ block_crypto_amend_options_generic_luks(BlockDriverState *bs,
61
errp);
62
}
63
64
-static int
65
+static int GRAPH_RDLOCK
66
block_crypto_amend_options_luks(BlockDriverState *bs,
67
QemuOpts *opts,
68
BlockDriverAmendStatusCB *status_cb,
69
@@ -XXX,XX +XXX,XX @@ block_crypto_amend_options_luks(BlockDriverState *bs,
70
QCryptoBlockAmendOptions *amend_options = NULL;
71
int ret = -EINVAL;
72
73
- assume_graph_lock(); /* FIXME */
74
-
75
assert(crypto);
76
assert(crypto->block);
77
78
diff --git a/qemu-img.c b/qemu-img.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/qemu-img.c
81
+++ b/qemu-img.c
82
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
83
{
84
BlockDriver *drv;
85
86
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
87
+
88
/* Find driver and parse its options */
89
drv = bdrv_find_format(format);
90
if (!drv) {
91
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
92
goto out;
93
}
94
95
+ bdrv_graph_rdlock_main_loop();
96
if (!bs->drv->bdrv_amend_options) {
97
error_report("Format driver '%s' does not support option amendment",
98
fmt);
99
+ bdrv_graph_rdunlock_main_loop();
100
ret = -1;
101
goto out;
102
}
103
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
104
"This option is only supported for image creation\n");
105
}
106
107
+ bdrv_graph_rdunlock_main_loop();
108
error_report_err(err);
109
ret = -1;
110
goto out;
111
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
112
qemu_progress_print(0.f, 0);
113
ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL, force, &err);
114
qemu_progress_print(100.f, 0);
115
+ bdrv_graph_rdunlock_main_loop();
116
+
117
if (ret < 0) {
118
error_report_err(err);
119
goto out;
120
--
121
2.41.0
diff view generated by jsdifflib
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
2
qcow2_signal_corruption() need to hold a reader lock for the graph
3
undo any previous preallocation, but just adds the zero flag to all
3
because it calls bdrv_get_node_name(), which accesses the parents list
4
relevant L2 entries. If an external data file is in use, a write_zeroes
4
of a node.
5
request to the data file is made instead.
5
6
For some places, we know that they will hold the lock, but we don't have
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
6
10
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
12
Message-ID: <20230929145157.45443-15-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
15
---
13
block/qcow2-cluster.c | 2 +-
16
block/qcow2.h | 180 +++++++++++++++++------------
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
17
include/block/block-global-state.h | 2 +-
15
2 files changed, 35 insertions(+), 1 deletion(-)
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(-)
16
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;
17
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
18
index XXXXXXX..XXXXXXX 100644
479
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
480
--- a/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
481
+++ b/block/qcow2-cluster.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
482
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
22
/* Caller must pass aligned values, except at image end */
483
* the cache is used; otherwise the L2 slice is loaded from the image
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
484
* file.
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
485
*/
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
486
-static int l2_load(BlockDriverState *bs, uint64_t offset,
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
487
- uint64_t l2_offset, uint64_t **l2_slice)
27
488
+static int GRAPH_RDLOCK
28
/* The zero flag is only supported by version 3 and newer */
489
+l2_load(BlockDriverState *bs, uint64_t offset,
29
if (s->qcow_version < 3) {
490
+ uint64_t l2_offset, uint64_t **l2_slice)
491
{
492
BDRVQcow2State *s = bs->opaque;
493
int start_of_slice = l2_entry_size(s) *
494
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
495
*
496
*/
497
498
-static int l2_allocate(BlockDriverState *bs, int l1_index)
499
+static int GRAPH_RDLOCK l2_allocate(BlockDriverState *bs, int l1_index)
500
{
501
BDRVQcow2State *s = bs->opaque;
502
uint64_t old_l2_offset;
503
@@ -XXX,XX +XXX,XX @@ fail:
504
*
505
* Returns 0 on success, -errno in failure case
506
*/
507
-static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
508
- uint64_t **new_l2_slice,
509
- int *new_l2_index)
510
+static int GRAPH_RDLOCK
511
+get_cluster_table(BlockDriverState *bs, uint64_t offset,
512
+ uint64_t **new_l2_slice, int *new_l2_index)
513
{
514
BDRVQcow2State *s = bs->opaque;
515
unsigned int l2_index;
516
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
517
*
518
* Returns 0 on success, -errno on failure.
519
*/
520
-static int coroutine_fn calculate_l2_meta(BlockDriverState *bs,
521
- uint64_t host_cluster_offset,
522
- uint64_t guest_offset, unsigned bytes,
523
- uint64_t *l2_slice, QCowL2Meta **m,
524
- bool keep_old)
525
+static int coroutine_fn GRAPH_RDLOCK
526
+calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
527
+ uint64_t guest_offset, unsigned bytes, uint64_t *l2_slice,
528
+ QCowL2Meta **m, bool keep_old)
529
{
530
BDRVQcow2State *s = bs->opaque;
531
int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
532
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
533
*
534
* -errno: in error cases
535
*/
536
-static int coroutine_fn handle_copied(BlockDriverState *bs,
537
- uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
538
- QCowL2Meta **m)
539
+static int coroutine_fn GRAPH_RDLOCK
540
+handle_copied(BlockDriverState *bs, uint64_t guest_offset,
541
+ uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
542
{
543
BDRVQcow2State *s = bs->opaque;
544
int l2_index;
545
@@ -XXX,XX +XXX,XX @@ out:
546
* function has been waiting for another request and the allocation must be
547
* restarted, but the whole request should not be failed.
548
*/
549
-static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
550
- uint64_t guest_offset,
551
- uint64_t *host_offset,
552
- uint64_t *nb_clusters)
553
+static int coroutine_fn GRAPH_RDLOCK
554
+do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
555
+ uint64_t *host_offset, uint64_t *nb_clusters)
556
{
557
BDRVQcow2State *s = bs->opaque;
558
559
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
560
*
561
* -errno: in error cases
562
*/
563
-static int coroutine_fn handle_alloc(BlockDriverState *bs,
564
- uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
565
- QCowL2Meta **m)
566
+static int coroutine_fn GRAPH_RDLOCK
567
+handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
568
+ uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
569
{
570
BDRVQcow2State *s = bs->opaque;
571
int l2_index;
572
@@ -XXX,XX +XXX,XX @@ again:
573
* all clusters in the same L2 slice) and returns the number of discarded
574
* clusters.
575
*/
576
-static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
577
- uint64_t nb_clusters,
578
- enum qcow2_discard_type type, bool full_discard)
579
+static int GRAPH_RDLOCK
580
+discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters,
581
+ enum qcow2_discard_type type, bool full_discard)
582
{
583
BDRVQcow2State *s = bs->opaque;
584
uint64_t *l2_slice;
585
@@ -XXX,XX +XXX,XX @@ fail:
586
* all clusters in the same L2 slice) and returns the number of zeroed
587
* clusters.
588
*/
589
-static int coroutine_fn
590
+static int coroutine_fn GRAPH_RDLOCK
591
zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
592
uint64_t nb_clusters, int flags)
593
{
594
@@ -XXX,XX +XXX,XX @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
595
return nb_clusters;
596
}
597
598
-static int coroutine_fn
599
+static int coroutine_fn GRAPH_RDLOCK
600
zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
601
unsigned nb_subclusters)
602
{
603
@@ -XXX,XX +XXX,XX @@ fail:
604
* status_cb(). l1_entries contains the total number of L1 entries and
605
* *visited_l1_entries counts all visited L1 entries.
606
*/
607
-static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
608
- int l1_size, int64_t *visited_l1_entries,
609
- int64_t l1_entries,
610
- BlockDriverAmendStatusCB *status_cb,
611
- void *cb_opaque)
612
+static int GRAPH_RDLOCK
613
+expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
614
+ int l1_size, int64_t *visited_l1_entries,
615
+ int64_t l1_entries,
616
+ BlockDriverAmendStatusCB *status_cb,
617
+ void *cb_opaque)
618
{
619
BDRVQcow2State *s = bs->opaque;
620
bool is_active_l1 = (l1_table == s->l1_table);
621
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
622
index XXXXXXX..XXXXXXX 100644
623
--- a/block/qcow2-refcount.c
624
+++ b/block/qcow2-refcount.c
625
@@ -XXX,XX +XXX,XX @@ static void set_refcount_ro6(void *refcount_array, uint64_t index,
626
}
627
628
629
-static int load_refcount_block(BlockDriverState *bs,
630
- int64_t refcount_block_offset,
631
- void **refcount_block)
632
+static int GRAPH_RDLOCK
633
+load_refcount_block(BlockDriverState *bs, int64_t refcount_block_offset,
634
+ void **refcount_block)
635
{
636
BDRVQcow2State *s = bs->opaque;
637
638
@@ -XXX,XX +XXX,XX @@ static int in_same_refcount_block(BDRVQcow2State *s, uint64_t offset_a,
639
*
640
* Returns 0 on success or -errno in error case
641
*/
642
-static int alloc_refcount_block(BlockDriverState *bs,
643
- int64_t cluster_index, void **refcount_block)
644
+static int GRAPH_RDLOCK
645
+alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index,
646
+ void **refcount_block)
647
{
648
BDRVQcow2State *s = bs->opaque;
649
unsigned int refcount_table_index;
650
@@ -XXX,XX +XXX,XX @@ found:
651
/* XXX: cache several refcount block clusters ? */
652
/* @addend is the absolute value of the addend; if @decrease is set, @addend
653
* will be subtracted from the current refcount, otherwise it will be added */
654
-static int update_refcount(BlockDriverState *bs,
655
- int64_t offset,
656
- int64_t length,
657
- uint64_t addend,
658
- bool decrease,
659
- enum qcow2_discard_type type)
660
+static int GRAPH_RDLOCK
661
+update_refcount(BlockDriverState *bs, int64_t offset, int64_t length,
662
+ uint64_t addend, bool decrease, enum qcow2_discard_type type)
663
{
664
BDRVQcow2State *s = bs->opaque;
665
int64_t start, last, cluster_offset;
666
@@ -XXX,XX +XXX,XX @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
667
668
669
/* return < 0 if error */
670
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
671
- uint64_t max)
672
+static int64_t GRAPH_RDLOCK
673
+alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max)
674
{
675
BDRVQcow2State *s = bs->opaque;
676
uint64_t i, nb_clusters, refcount;
677
@@ -XXX,XX +XXX,XX @@ calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
678
* Compares the actual reference count for each cluster in the image against the
679
* refcount as reported by the refcount structures on-disk.
680
*/
681
-static void coroutine_fn
682
+static void coroutine_fn GRAPH_RDLOCK
683
compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
684
BdrvCheckMode fix, bool *rebuild,
685
int64_t *highest_cluster,
686
@@ -XXX,XX +XXX,XX @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
687
*
688
* @allocated should be set to true if a new cluster has been allocated.
689
*/
690
-typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
691
- uint64_t reftable_index, uint64_t *reftable_size,
692
- void *refblock, bool refblock_empty,
693
- bool *allocated, Error **errp);
694
+typedef int /* GRAPH_RDLOCK_PTR */
695
+ (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
696
+ uint64_t reftable_index, uint64_t *reftable_size,
697
+ void *refblock, bool refblock_empty,
698
+ bool *allocated, Error **errp);
699
700
/**
701
* This "operation" for walk_over_reftable() allocates the refblock on disk (if
702
* it is not empty) and inserts its offset into the new reftable. The size of
703
* this new reftable is increased as required.
704
*/
705
-static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
706
- uint64_t reftable_index, uint64_t *reftable_size,
707
- void *refblock, bool refblock_empty, bool *allocated,
708
- Error **errp)
709
+static int GRAPH_RDLOCK
710
+alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
711
+ uint64_t reftable_index, uint64_t *reftable_size,
712
+ void *refblock, bool refblock_empty, bool *allocated,
713
+ Error **errp)
714
{
715
BDRVQcow2State *s = bs->opaque;
716
int64_t offset;
717
@@ -XXX,XX +XXX,XX @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
718
* offset specified by the new reftable's entry. It does not modify the new
719
* reftable or change any refcounts.
720
*/
721
-static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
722
- uint64_t reftable_index, uint64_t *reftable_size,
723
- void *refblock, bool refblock_empty, bool *allocated,
724
- Error **errp)
725
+static int GRAPH_RDLOCK
726
+flush_refblock(BlockDriverState *bs, uint64_t **reftable,
727
+ uint64_t reftable_index, uint64_t *reftable_size,
728
+ void *refblock, bool refblock_empty, bool *allocated,
729
+ Error **errp)
730
{
731
BDRVQcow2State *s = bs->opaque;
732
int64_t offset;
733
@@ -XXX,XX +XXX,XX @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
734
*
735
* @allocated is set to true if a new cluster has been allocated.
736
*/
737
-static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
738
- uint64_t *new_reftable_index,
739
- uint64_t *new_reftable_size,
740
- void *new_refblock, int new_refblock_size,
741
- int new_refcount_bits,
742
- RefblockFinishOp *operation, bool *allocated,
743
- Qcow2SetRefcountFunc *new_set_refcount,
744
- BlockDriverAmendStatusCB *status_cb,
745
- void *cb_opaque, int index, int total,
746
- Error **errp)
747
+static int GRAPH_RDLOCK
748
+walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
749
+ uint64_t *new_reftable_index,
750
+ uint64_t *new_reftable_size,
751
+ void *new_refblock, int new_refblock_size,
752
+ int new_refcount_bits,
753
+ RefblockFinishOp *operation, bool *allocated,
754
+ Qcow2SetRefcountFunc *new_set_refcount,
755
+ BlockDriverAmendStatusCB *status_cb,
756
+ void *cb_opaque, int index, int total,
757
+ Error **errp)
758
{
759
BDRVQcow2State *s = bs->opaque;
760
uint64_t reftable_index;
761
@@ -XXX,XX +XXX,XX @@ done:
762
return ret;
763
}
764
765
-static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
766
- uint64_t offset)
767
+static int64_t coroutine_fn GRAPH_RDLOCK
768
+get_refblock_offset(BlockDriverState *bs, uint64_t offset)
769
{
770
BDRVQcow2State *s = bs->opaque;
771
uint32_t index = offset_to_reftable_index(s, offset);
772
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
773
return covering_refblock_offset;
774
}
775
776
-static int coroutine_fn
777
+static int coroutine_fn GRAPH_RDLOCK
778
qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
779
{
780
BDRVQcow2State *s = bs->opaque;
30
diff --git a/block/qcow2.c b/block/qcow2.c
781
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
782
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
783
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
784
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
785
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
35
786
* function when there are no pending requests, it does not guard against
36
bs->supported_zero_flags = header.version >= 3 ?
787
* concurrent requests dirtying the image.
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
788
*/
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
789
-static int qcow2_mark_clean(BlockDriverState *bs)
39
790
+static int GRAPH_RDLOCK qcow2_mark_clean(BlockDriverState *bs)
40
/* Repair image if dirty */
791
{
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
792
BDRVQcow2State *s = bs->opaque;
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
793
43
g_assert_not_reached();
794
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_corrupt(BlockDriverState *bs)
44
}
795
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
45
796
* before if necessary.
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
797
*/
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
798
-static int coroutine_fn qcow2_mark_consistent(BlockDriverState *bs)
48
+
799
+static int coroutine_fn GRAPH_RDLOCK
49
+ /*
800
+qcow2_mark_consistent(BlockDriverState *bs)
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
801
{
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
802
BDRVQcow2State *s = bs->opaque;
52
+ * at the end of the image (which it is here).
803
53
+ */
804
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2ReopenState {
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
805
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
55
+ if (ret < 0) {
806
} Qcow2ReopenState;
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
807
57
+ goto fail;
808
-static int qcow2_update_options_prepare(BlockDriverState *bs,
58
+ }
809
- Qcow2ReopenState *r,
59
+
810
- QDict *options, int flags,
60
+ /* Write explicit zeros for the unaligned head */
811
- Error **errp)
61
+ if (zero_start > old_length) {
812
+static int GRAPH_RDLOCK
62
+ uint64_t len = zero_start - old_length;
813
+qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r,
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
814
+ QDict *options, int flags, Error **errp)
64
+ QEMUIOVector qiov;
815
{
65
+ qemu_iovec_init_buf(&qiov, buf, len);
816
BDRVQcow2State *s = bs->opaque;
66
+
817
QemuOpts *opts = NULL;
67
+ qemu_co_mutex_unlock(&s->lock);
818
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
819
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
69
+ qemu_co_mutex_lock(&s->lock);
820
}
70
+
821
71
+ qemu_vfree(buf);
822
-static int coroutine_fn
72
+ if (ret < 0) {
823
+static int coroutine_fn GRAPH_RDLOCK
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
824
qcow2_update_options(BlockDriverState *bs, QDict *options, int flags,
74
+ goto fail;
825
Error **errp)
75
+ }
826
{
76
+ }
827
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
77
+ }
828
bs->bl.pdiscard_alignment = s->cluster_size;
78
+
829
}
79
if (prealloc != PREALLOC_MODE_OFF) {
830
80
/* Flush metadata before actually changing the image size */
831
-static int qcow2_reopen_prepare(BDRVReopenState *state,
81
ret = qcow2_write_caches(bs);
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);
82
--
995
--
83
2.25.3
996
2.41.0
84
85
diff view generated by jsdifflib
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
image is possibly preallocated and then the zero flag is added to all
2
qcow2_inactivate() need to hold a reader lock for the graph because it
3
clusters. This means that a copy-on-write operation may be needed when
3
calls bdrv_get_device_or_node_name(), which accesses the parents list of
4
writing to these clusters, despite having used preallocation, negating
4
a node.
5
one of the major benefits of preallocation.
6
5
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
6
qcow2_do_close() is a bit strange because it is called from different
8
and if the protocol driver can ensure that the new area reads as zeros,
7
contexts. If close_data_file = true, we know that we were called from
9
we can skip setting the zero flag in the qcow2 layer.
8
non-coroutine main loop context (more specifically, we're coming from
10
9
qcow2_close()) and can safely drop the reader lock temporarily with
11
Unfortunately, the same approach doesn't work for metadata
10
bdrv_graph_rdunlock_main_loop() and acquire the writer lock.
12
preallocation, so we'll still set the zero flag there.
13
11
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-ID: <20230929145157.45443-16-kwolf@redhat.com>
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
16
---
20
block/qcow2.c | 22 +++++++++++++++++++---
17
block/qcow2.c | 15 ++++++++++-----
21
tests/qemu-iotests/274.out | 4 ++--
18
1 file changed, 10 insertions(+), 5 deletions(-)
22
2 files changed, 21 insertions(+), 5 deletions(-)
23
19
24
diff --git a/block/qcow2.c b/block/qcow2.c
20
diff --git a/block/qcow2.c b/block/qcow2.c
25
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.c
22
--- a/block/qcow2.c
27
+++ b/block/qcow2.c
23
+++ b/block/qcow2.c
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
24
@@ -XXX,XX +XXX,XX @@ fail_nometa:
29
/* Allocate the data area */
25
return ret;
30
new_file_size = allocation_start +
26
}
31
nb_new_data_clusters * s->cluster_size;
27
32
- /* Image file grows, so @exact does not matter */
28
-static int qcow2_inactivate(BlockDriverState *bs)
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
29
+static int GRAPH_RDLOCK qcow2_inactivate(BlockDriverState *bs)
34
- errp);
30
{
35
+ /*
31
BDRVQcow2State *s = bs->opaque;
36
+ * Image file grows, so @exact does not matter.
32
int ret, result = 0;
37
+ *
33
Error *local_err = NULL;
38
+ * If we need to zero out the new area, try first whether the protocol
34
39
+ * driver can already take care of this.
35
- assume_graph_lock(); /* FIXME */
40
+ */
36
-
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
37
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
38
if (local_err != NULL) {
43
+ BDRV_REQ_ZERO_WRITE, NULL);
39
result = -EINVAL;
44
+ if (ret >= 0) {
40
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
41
return result;
46
+ }
42
}
47
+ } else {
43
48
+ ret = -1;
44
-static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
49
+ }
45
+static void coroutine_mixed_fn GRAPH_RDLOCK
50
+ if (ret < 0) {
46
+qcow2_do_close(BlockDriverState *bs, bool close_data_file)
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
47
{
52
+ errp);
48
BDRVQcow2State *s = bs->opaque;
53
+ }
49
qemu_vfree(s->l1_table);
54
if (ret < 0) {
50
@@ -XXX,XX +XXX,XX @@ static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
55
error_prepend(errp, "Failed to resize underlying file: ");
51
g_free(s->image_backing_format);
56
qcow2_free_clusters(bs, allocation_start,
52
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
53
if (close_data_file && has_data_file(bs)) {
58
index XXXXXXX..XXXXXXX 100644
54
+ GLOBAL_STATE_CODE();
59
--- a/tests/qemu-iotests/274.out
55
+ bdrv_graph_rdunlock_main_loop();
60
+++ b/tests/qemu-iotests/274.out
56
bdrv_graph_wrlock(NULL);
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
57
bdrv_unref_child(bs, s->data_file);
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
58
bdrv_graph_wrunlock();
63
59
s->data_file = NULL;
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
60
+ bdrv_graph_rdlock_main_loop();
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
61
}
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
62
67
63
qcow2_refcount_close(bs);
68
=== preallocation=full ===
64
qcow2_free_snapshots(bs);
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
65
}
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
66
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
67
-static void qcow2_close(BlockDriverState *bs)
72
68
+static void GRAPH_UNLOCKED qcow2_close(BlockDriverState *bs)
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
69
{
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
70
+ GLOBAL_STATE_CODE();
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
71
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
76
72
+
77
=== preallocation=off ===
73
qcow2_do_close(bs, true);
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
74
}
75
79
--
76
--
80
2.25.3
77
2.41.0
81
82
diff view generated by jsdifflib
1
It still has an assume_graph_lock() call, but all of its callers are now
2
properly annotated to hold the graph lock. Update the function to be
3
GRAPH_RDLOCK as well and remove the assume_graph_lock().
4
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-17-kwolf@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
9
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
10
block/qcow2-bitmap.c | 9 +++------
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
11
1 file changed, 3 insertions(+), 6 deletions(-)
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
13
12
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
13
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
21
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+#
24
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
28
+#
29
+# This program is distributed in the hope that it will be useful,
30
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+# GNU General Public License for more details.
33
+#
34
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
41
+import iotests
42
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
176
new file mode 100644
177
index XXXXXXX..XXXXXXX
178
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
180
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
183
+
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
185
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
450
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
451
--- a/tests/qemu-iotests/group
15
--- a/block/qcow2-bitmap.c
452
+++ b/tests/qemu-iotests/group
16
+++ b/block/qcow2-bitmap.c
453
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity)
454
270 rw backing quick
18
return DIV_ROUND_UP(num_bits, 8);
455
272 rw
19
}
456
273 backing quick
20
457
+274 rw backing
21
-static int check_constraints_on_bitmap(BlockDriverState *bs,
458
277 rw quick
22
- const char *name,
459
279 rw backing quick
23
- uint32_t granularity,
460
280 rw migration quick
24
- Error **errp)
25
+static int GRAPH_RDLOCK
26
+check_constraints_on_bitmap(BlockDriverState *bs, const char *name,
27
+ uint32_t granularity, Error **errp)
28
{
29
BDRVQcow2State *s = bs->opaque;
30
int granularity_bits = ctz32(granularity);
31
int64_t len = bdrv_getlength(bs);
32
int64_t bitmap_bytes;
33
34
- assume_graph_lock(); /* FIXME */
35
-
36
assert(granularity > 0);
37
assert((granularity & (granularity - 1)) == 0);
38
461
--
39
--
462
2.25.3
40
2.41.0
463
464
diff view generated by jsdifflib
1
Now that node level interface bdrv_truncate() supports passing request
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
flags to the block driver, expose this on the BlockBackend level, too.
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.
3
5
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-ID: <20230929145157.45443-18-kwolf@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
10
---
11
include/sysemu/block-backend.h | 2 +-
11
include/block/block-global-state.h | 4 +++-
12
block.c | 3 ++-
12
block.c | 2 --
13
block/block-backend.c | 4 ++--
13
block/block-backend.c | 1 +
14
block/commit.c | 4 ++--
14
block/commit.c | 1 +
15
block/crypto.c | 2 +-
15
block/monitor/block-hmp-cmds.c | 3 +++
16
block/mirror.c | 2 +-
16
block/qapi-sysemu.c | 9 +++++++--
17
block/qcow2.c | 4 ++--
17
blockdev.c | 15 +++++++++++++++
18
block/qed.c | 2 +-
18
7 files changed, 30 insertions(+), 5 deletions(-)
19
block/vdi.c | 2 +-
20
block/vhdx.c | 4 ++--
21
block/vmdk.c | 6 +++---
22
block/vpc.c | 2 +-
23
blockdev.c | 2 +-
24
qemu-img.c | 2 +-
25
qemu-io-cmds.c | 2 +-
26
15 files changed, 22 insertions(+), 21 deletions(-)
27
19
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
29
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend.h
22
--- a/include/block/block-global-state.h
31
+++ b/include/sysemu/block-backend.h
23
+++ b/include/block/block-global-state.h
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
24
@@ -XXX,XX +XXX,XX @@ bdrv_attach_child(BlockDriverState *parent_bs,
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
25
BdrvChildRole child_role,
34
int bytes);
26
Error **errp);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
27
36
- PreallocMode prealloc, Error **errp);
28
-bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
29
+bool GRAPH_RDLOCK
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
30
+bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
31
+
40
int64_t pos, int size);
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);
41
diff --git a/block.c b/block.c
35
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
37
--- a/block.c
44
+++ b/block.c
38
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
39
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
46
int64_t size;
40
BdrvOpBlocker *blocker;
47
int ret;
41
GLOBAL_STATE_CODE();
48
42
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
43
- assume_graph_lock(); /* FIXME */
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
44
-
51
+ &local_err);
45
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
52
if (ret < 0 && ret != -ENOTSUP) {
46
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
53
error_propagate(errp, local_err);
47
blocker = QLIST_FIRST(&bs->op_blockers[op]);
54
return ret;
55
diff --git a/block/block-backend.c b/block/block-backend.c
48
diff --git a/block/block-backend.c b/block/block-backend.c
56
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
57
--- a/block/block-backend.c
50
--- a/block/block-backend.c
58
+++ b/block/block-backend.c
51
+++ b/block/block-backend.c
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
52
@@ -XXX,XX +XXX,XX @@ bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
60
}
61
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
63
- PreallocMode prealloc, Error **errp)
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
65
{
53
{
66
if (!blk_is_available(blk)) {
54
BlockDriverState *bs = blk_bs(blk);
67
error_setg(errp, "No medium inserted");
55
GLOBAL_STATE_CODE();
68
return -ENOMEDIUM;
56
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
69
}
57
70
58
if (!bs) {
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
59
return false;
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
73
}
74
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
76
diff --git a/block/commit.c b/block/commit.c
60
diff --git a/block/commit.c b/block/commit.c
77
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
78
--- a/block/commit.c
62
--- a/block/commit.c
79
+++ b/block/commit.c
63
+++ b/block/commit.c
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
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,
81
}
91
}
82
83
if (base_len < len) {
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
86
if (ret) {
87
goto out;
88
}
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
90
* grow the backing file image if possible. If not possible,
91
* we must return an error */
92
if (length > backing_length) {
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
95
&local_err);
96
if (ret < 0) {
97
error_report_err(local_err);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
108
}
92
}
109
93
110
94
-static void blockdev_remove_medium(const char *device, const char *id,
111
diff --git a/block/mirror.c b/block/mirror.c
95
- Error **errp)
112
index XXXXXXX..XXXXXXX 100644
96
+static void GRAPH_UNLOCKED
113
--- a/block/mirror.c
97
+blockdev_remove_medium(const char *device, const char *id, Error **errp)
114
+++ b/block/mirror.c
98
{
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
99
BlockBackend *blk;
116
100
BlockDriverState *bs;
117
if (s->bdev_length > base_length) {
101
AioContext *aio_context;
118
ret = blk_truncate(s->target, s->bdev_length, false,
102
bool has_attached_device;
119
- PREALLOC_MODE_OFF, NULL);
103
120
+ PREALLOC_MODE_OFF, 0, NULL);
104
+ GLOBAL_STATE_CODE();
121
if (ret < 0) {
105
+
122
goto immediate_exit;
106
blk = qmp_get_blk(device, id, errp);
123
}
107
if (!blk) {
124
diff --git a/block/qcow2.c b/block/qcow2.c
108
return;
125
index XXXXXXX..XXXXXXX 100644
109
@@ -XXX,XX +XXX,XX @@ static void blockdev_remove_medium(const char *device, const char *id,
126
--- a/block/qcow2.c
110
aio_context = bdrv_get_aio_context(bs);
127
+++ b/block/qcow2.c
111
aio_context_acquire(aio_context);
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
112
129
113
+ bdrv_graph_rdlock_main_loop();
130
/* Okay, now that we have a valid image, let's give it the right size */
114
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
115
+ bdrv_graph_rdunlock_main_loop();
132
- errp);
133
+ 0, errp);
134
if (ret < 0) {
135
error_prepend(errp, "Could not resize image: ");
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
116
goto out;
158
}
117
}
159
diff --git a/block/vdi.c b/block/vdi.c
118
+ bdrv_graph_rdunlock_main_loop();
160
index XXXXXXX..XXXXXXX 100644
119
161
--- a/block/vdi.c
120
blk_remove_bs(blk);
162
+++ b/block/vdi.c
121
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
236
diff --git a/blockdev.c b/blockdev.c
122
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
123
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
124
--- a/blockdev.c
239
+++ b/blockdev.c
125
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
126
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
241
}
127
}
242
128
243
bdrv_drained_begin(bs);
129
/* Early check to avoid creating target */
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
130
+ bdrv_graph_rdlock_main_loop();
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
131
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
246
bdrv_drained_end(bs);
132
+ bdrv_graph_rdunlock_main_loop();
247
133
goto out;
248
out:
134
}
249
diff --git a/qemu-img.c b/qemu-img.c
135
+ bdrv_graph_rdunlock_main_loop();
250
index XXXXXXX..XXXXXXX 100644
136
251
--- a/qemu-img.c
137
flags = bs->open_flags | BDRV_O_RDWR;
252
+++ b/qemu-img.c
138
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
139
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
254
* resizing, so pass @exact=true. It is of no use to report
140
return;
255
* success when the image has not actually been resized.
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)
256
*/
155
*/
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
156
iter_end = bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
157
+ bdrv_graph_rdlock_main_loop();
259
if (!ret) {
158
for (iter = bs; iter && iter != iter_end;
260
qprintf(quiet, "Image resized.\n");
159
iter = bdrv_filter_or_cow_bs(iter))
261
} else {
160
{
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
161
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
263
index XXXXXXX..XXXXXXX 100644
162
+ bdrv_graph_rdunlock_main_loop();
264
--- a/qemu-io-cmds.c
163
goto out;
265
+++ b/qemu-io-cmds.c
164
}
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
165
}
267
* exact=true. It is better to err on the "emit more errors" side
166
+ bdrv_graph_rdunlock_main_loop();
268
* than to be overly permissive.
167
269
*/
168
/* if we are streaming the entire chain, the result will have no backing
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
169
* file, and specifying one is therefore an error */
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
170
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
272
if (ret < 0) {
171
}
273
error_report_err(local_err);
172
274
return ret;
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)) {
275
--
196
--
276
2.25.3
197
2.41.0
277
278
diff view generated by jsdifflib
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
driver callbacks, and a supported_truncate_flags field in
2
bdrv_apply_auto_read_only() need to hold a reader lock for the graph
3
BlockDriverState that allows drivers to advertise support for request
3
because it calls bdrv_can_set_read_only(), which indirectly accesses the
4
flags in the context of truncate.
4
parents list of a node.
5
6
For now, we always pass 0 and no drivers declare support for any flag.
7
5
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-ID: <20230929145157.45443-19-kwolf@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
10
---
15
include/block/block_int.h | 10 +++++++++-
11
include/block/block-io.h | 6 ++++--
16
block/crypto.c | 3 ++-
12
block.c | 4 ++--
17
block/file-posix.c | 2 +-
13
block/bochs.c | 2 ++
18
block/file-win32.c | 2 +-
14
block/cloop.c | 2 ++
19
block/gluster.c | 1 +
15
block/curl.c | 2 ++
20
block/io.c | 8 +++++++-
16
block/dmg.c | 2 ++
21
block/iscsi.c | 2 +-
17
block/gluster.c | 2 ++
22
block/nfs.c | 3 ++-
18
block/iscsi.c | 2 ++
23
block/qcow2.c | 2 +-
19
block/nbd.c | 3 ++-
24
block/qed.c | 1 +
20
block/rbd.c | 2 ++
25
block/raw-format.c | 2 +-
21
10 files changed, 22 insertions(+), 5 deletions(-)
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
31
22
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
23
diff --git a/include/block/block-io.h b/include/block/block-io.h
33
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
25
--- a/include/block/block-io.h
35
+++ b/include/block/block_int.h
26
+++ b/include/block/block-io.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
27
@@ -XXX,XX +XXX,XX @@ bdrv_is_allocated_above(BlockDriverState *bs, BlockDriverState *base,
37
*/
28
int coroutine_fn GRAPH_RDLOCK
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
29
bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
39
bool exact, PreallocMode prealloc,
30
40
- Error **errp);
31
-int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
41
+ BdrvRequestFlags flags, Error **errp);
32
- Error **errp);
42
33
+int GRAPH_RDLOCK
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
34
+bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
44
bool has_variable_length;
35
+ Error **errp);
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
36
+
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
37
bool bdrv_is_read_only(BlockDriverState *bs);
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
38
bool bdrv_is_writable(BlockDriverState *bs);
48
unsigned int supported_zero_flags;
39
bool bdrv_is_sg(BlockDriverState *bs);
49
+ /*
40
diff --git a/block.c b/block.c
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
42
--- a/block.c
63
+++ b/block/crypto.c
43
+++ b/block.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
44
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
65
45
int ret = 0;
66
static int coroutine_fn
46
IO_CODE();
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
47
68
- PreallocMode prealloc, Error **errp)
48
- assume_graph_lock(); /* FIXME */
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
49
-
70
+ Error **errp)
50
if (!(bs->open_flags & BDRV_O_RDWR)) {
71
{
51
return 0;
72
BlockCrypto *crypto = bs->opaque;
52
}
73
uint64_t payload_offset =
53
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
74
diff --git a/block/file-posix.c b/block/file-posix.c
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
75
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
65
--- a/block/bochs.c
77
+++ b/block/file-posix.c
66
+++ b/block/bochs.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
67
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
79
68
int ret;
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
69
81
bool exact, PreallocMode prealloc,
70
/* No write support yet */
82
- Error **errp)
71
+ bdrv_graph_rdlock_main_loop();
83
+ BdrvRequestFlags flags, Error **errp)
72
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
84
{
73
+ bdrv_graph_rdunlock_main_loop();
85
BDRVRawState *s = bs->opaque;
74
if (ret < 0) {
86
struct stat st;
75
return ret;
87
diff --git a/block/file-win32.c b/block/file-win32.c
76
}
77
diff --git a/block/cloop.c b/block/cloop.c
88
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
79
--- a/block/cloop.c
90
+++ b/block/file-win32.c
80
+++ b/block/cloop.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
81
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
92
82
uint32_t offsets_size, max_compressed_block_size = 1, i;
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
83
int ret;
94
bool exact, PreallocMode prealloc,
84
95
- Error **errp)
85
+ bdrv_graph_rdlock_main_loop();
96
+ BdrvRequestFlags flags, Error **errp)
86
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
97
{
87
+ bdrv_graph_rdunlock_main_loop();
98
BDRVRawState *s = bs->opaque;
88
if (ret < 0) {
99
LONG low, high;
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
}
100
diff --git a/block/gluster.c b/block/gluster.c
120
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
122
--- a/block/gluster.c
103
+++ b/block/gluster.c
123
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
124
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
105
int64_t offset,
125
if (ret == -EACCES || ret == -EROFS) {
106
bool exact,
126
/* Try to degrade to read-only, but if it doesn't work, still use the
107
PreallocMode prealloc,
127
* normal error message. */
108
+ BdrvRequestFlags flags,
128
+ bdrv_graph_rdlock_main_loop();
109
Error **errp)
129
if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
110
{
130
open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
111
BDRVGlusterState *s = bs->opaque;
131
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
112
diff --git a/block/io.c b/block/io.c
132
ret = s->fd ? 0 : -errno;
113
index XXXXXXX..XXXXXXX 100644
133
}
114
--- a/block/io.c
134
+ bdrv_graph_rdunlock_main_loop();
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
135
}
126
136
127
if (drv->bdrv_co_truncate) {
137
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
133
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
135
} else if (bs->file && drv->is_filter) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
142
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
143
143
/* Check the write protect flag of the LUN if we want to write */
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
144
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
145
bool exact, PreallocMode prealloc,
145
iscsilun->write_protected) {
146
- Error **errp)
146
+ bdrv_graph_rdlock_main_loop();
147
+ BdrvRequestFlags flags, Error **errp)
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)
148
{
163
{
149
IscsiLun *iscsilun = bs->opaque;
164
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
166
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
167
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
168
--- a/block/rbd.c
206
+++ b/block/rbd.c
169
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
170
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
208
int64_t offset,
171
/* If we are using an rbd snapshot, we must be r/o, otherwise
209
bool exact,
172
* leave as-is */
210
PreallocMode prealloc,
173
if (s->snap != NULL) {
211
+ BdrvRequestFlags flags,
174
+ bdrv_graph_rdlock_main_loop();
212
Error **errp)
175
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
213
{
176
+ bdrv_graph_rdunlock_main_loop();
214
int r;
177
if (r < 0) {
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
178
goto failed_post_open;
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
179
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
264
--
180
--
265
2.25.3
181
2.41.0
266
267
diff view generated by jsdifflib
1
We want to keep TEST_IMG for the full path of the main test image, but
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
filter_testfiles() must be called for other test images before replacing
2
bdrv_get_specific_info() need to hold a reader lock for the graph.
3
other things like the image format because the test directory path could
3
This removes an assume_graph_lock() call in vmdk's implementation.
4
contain the format as a substring.
5
6
Insert a filter_testfiles() call between both.
7
4
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-ID: <20230929145157.45443-20-kwolf@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
9
---
14
tests/qemu-iotests/iotests.py | 5 +++--
10
include/block/block-io.h | 5 +++--
15
1 file changed, 3 insertions(+), 2 deletions(-)
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(-)
16
15
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
18
--- a/include/block/block-io.h
20
+++ b/tests/qemu-iotests/iotests.py
19
+++ b/include/block/block-io.h
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
20
@@ -XXX,XX +XXX,XX @@ bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
22
for line in output.split('\n'):
21
int co_wrapper_mixed_bdrv_rdlock
23
if 'disk size' in line or 'actual-size' in line:
22
bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
24
continue
23
25
- line = line.replace(filename, 'TEST_IMG') \
24
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
26
- .replace(imgfmt, 'IMGFMT')
25
- Error **errp);
27
+ line = line.replace(filename, 'TEST_IMG')
26
+ImageInfoSpecific * GRAPH_RDLOCK
28
+ line = filter_testfiles(line)
27
+bdrv_get_specific_info(BlockDriverState *bs, Error **errp);
29
+ line = line.replace(imgfmt, 'IMGFMT')
28
+
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
29
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
30
void bdrv_round_to_subclusters(BlockDriverState *bs,
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
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
}
33
--
84
--
34
2.25.3
85
2.41.0
35
36
diff view generated by jsdifflib
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
1
Almost all functions that access the parent link already take the graph
2
OS, so we can advertise the flag and just ignore it.
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.
3
4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-ID: <20230929145157.45443-21-kwolf@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
block/file-posix.c | 4 ++++
10
include/block/block_int-common.h | 4 ++--
12
1 file changed, 4 insertions(+)
11
tests/unit/test-block-iothread.c | 5 +++++
12
2 files changed, 7 insertions(+), 2 deletions(-)
13
13
14
diff --git a/block/file-posix.c b/block/file-posix.c
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/file-posix.c
16
--- a/include/block/block_int-common.h
17
+++ b/block/file-posix.c
17
+++ b/include/block/block_int-common.h
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
18
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
19
#endif
19
bool quiesced_parent;
20
20
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
21
QLIST_ENTRY(BdrvChild) next;
22
+ if (S_ISREG(st.st_mode)) {
22
- QLIST_ENTRY(BdrvChild) next_parent;
23
+ /* When extending regular files, we get zeros from the OS */
23
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
24
};
25
+ }
25
26
ret = 0;
26
/*
27
fail:
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
28
BdrvChild *backing;
29
BdrvChild *file;
30
31
- QLIST_HEAD(, BdrvChild) parents;
32
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) parents;
33
34
QDict *options;
35
QDict *explicit_options;
36
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/unit/test-block-iothread.c
39
+++ b/tests/unit/test-block-iothread.c
40
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
41
BlockDriverState *bs;
42
BdrvChild *c;
43
44
+ GLOBAL_STATE_CODE();
45
+
46
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
47
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
48
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
49
blk_insert_bs(blk, bs, &error_abort);
50
+
51
+ bdrv_graph_rdlock_main_loop();
52
c = QLIST_FIRST(&bs->parents);
53
+ bdrv_graph_rdunlock_main_loop();
54
55
blk_set_aio_context(blk, ctx, &error_abort);
56
aio_context_acquire(ctx);
29
--
57
--
30
2.25.3
58
2.41.0
31
32
diff view generated by jsdifflib
1
The QMP handler qmp_object_add() and the implementation of --object in
1
Almost all functions that access the child links already take the graph
2
qemu-storage-daemon can share most of the code. Currently,
2
lock now. Add locking to the remaining users and finally annotate the
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
3
struct field itself as protected by the graph lock.
4
because different visitors need to be used.
5
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
7
new function user_creatable_add_dict() that can get an additional
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
11
4
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-ID: <20230929145157.45443-22-kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
9
---
14
include/qom/object_interfaces.h | 12 ++++++++++++
10
include/block/block_int-common.h | 4 ++--
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
11
block.c | 2 ++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
12
block/replication.c | 3 ++-
17
3 files changed, 40 insertions(+), 23 deletions(-)
13
tests/unit/test-bdrv-drain.c | 4 ++++
14
4 files changed, 10 insertions(+), 3 deletions(-)
18
15
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
16
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qom/object_interfaces.h
18
--- a/include/block/block_int-common.h
22
+++ b/include/qom/object_interfaces.h
19
+++ b/include/block/block_int-common.h
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
20
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
24
const QDict *qdict,
21
*/
25
Visitor *v, Error **errp);
22
bool quiesced_parent;
26
23
27
+/**
24
- QLIST_ENTRY(BdrvChild) next;
28
+ * user_creatable_add_dict:
25
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next;
29
+ * @qdict: the object definition
26
QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
30
+ * @errp: if an error occurs, a pointer to an area to store the error
27
};
31
+ *
28
32
+ * Create an instance of the user creatable object that is defined by
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
30
* See also comment in include/block/block.h, to learn how backing and file
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
31
* are connected with BdrvChildRole.
35
+ * initialize the object properties.
32
*/
36
+ */
33
- QLIST_HEAD(, BdrvChild) children;
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
34
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) children;
35
BdrvChild *backing;
36
BdrvChild *file;
37
38
diff --git a/block.c b/block.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block.c
41
+++ b/block.c
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
43
{
44
assert(!child->bs);
45
GLOBAL_STATE_CODE();
46
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
38
+
47
+
39
/**
48
assert(!child->next.le_prev); /* not in children list */
40
* user_creatable_add_opts:
49
41
* @opts: the object definition
50
g_free(child->name);
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
51
diff --git a/block/replication.c b/block/replication.c
43
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
53
--- a/block/replication.c
45
+++ b/qom/object_interfaces.c
54
+++ b/block/replication.c
46
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@ static void backup_job_completed(void *opaque, int ret)
47
#include "qapi/qmp/qerror.h"
56
backup_job_cleanup(bs);
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
56
}
57
}
57
58
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
59
-static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
59
+{
60
+static bool GRAPH_RDLOCK
60
+ Visitor *v;
61
+check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
61
+ Object *obj;
62
+ g_autofree char *type = NULL;
63
+ g_autofree char *id = NULL;
64
+
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
86
{
62
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
63
BdrvChild *child;
64
65
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
88
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
67
--- a/tests/unit/test-bdrv-drain.c
90
+++ b/qom/qom-qmp-cmds.c
68
+++ b/tests/unit/test-bdrv-drain.c
91
@@ -XXX,XX +XXX,XX @@
69
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
92
#include "qapi/qapi-commands-qom.h"
70
blk_co_unref(blk);
93
#include "qapi/qmp/qdict.h"
71
} else {
94
#include "qapi/qmp/qerror.h"
72
BdrvChild *c, *next_c;
95
-#include "qapi/qobject-input-visitor.h"
73
+ bdrv_graph_co_rdlock();
96
#include "qemu/cutils.h"
74
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
97
#include "qom/object_interfaces.h"
75
+ bdrv_graph_co_rdunlock();
98
#include "qom/qom-qobject.h"
76
bdrv_co_unref_child(bs, c);
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
77
+ bdrv_graph_co_rdlock();
100
{
78
}
101
QObject *props;
79
+ bdrv_graph_co_rdunlock();
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
126
}
80
}
127
81
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
82
dbdd->done = true;
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
133
}
134
135
void qmp_object_del(const char *id, Error **errp)
136
--
83
--
137
2.25.3
84
2.41.0
138
139
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
bdrv_graph_wrlock() can't run in a coroutine (because it polls) and
2
requires holding the BQL. We already have GLOBAL_STATE_CODE() to assert
3
the latter. Assert the former as well and add a no_coroutine_fn marker.
2
4
3
Backing files and raw external data files are mutually exclusive.
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
The documentation of the raw external data bit (in autoclear_features)
6
Message-ID: <20230929145157.45443-23-kwolf@redhat.com>
5
already indicates that, but we should also mention it on the other
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
side.
7
8
Suggested-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
9
---
14
docs/interop/qcow2.txt | 3 +++
10
include/block/graph-lock.h | 3 ++-
15
1 file changed, 3 insertions(+)
11
block/graph-lock.c | 3 ++-
12
2 files changed, 4 insertions(+), 2 deletions(-)
16
13
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
14
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
16
--- a/include/block/graph-lock.h
20
+++ b/docs/interop/qcow2.txt
17
+++ b/include/block/graph-lock.h
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
18
@@ -XXX,XX +XXX,XX @@ void unregister_aiocontext(AioContext *ctx);
22
is stored (NB: The string is not null terminated). 0 if the
19
* This function polls. Callers must not hold the lock of any AioContext other
23
image doesn't have a backing file.
20
* than the current one and the one of @bs.
24
21
*/
25
+ Note: backing files are incompatible with raw external data
22
-void bdrv_graph_wrlock(BlockDriverState *bs) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
26
+ files (auto-clear feature bit 1).
23
+void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
27
+
24
+bdrv_graph_wrlock(BlockDriverState *bs);
28
16 - 19: backing_file_size
25
29
Length of the backing file name in bytes. Must not be
26
/*
30
longer than 1023 bytes. Undefined if the image doesn't have
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
31
--
47
--
32
2.25.3
48
2.41.0
33
34
diff view generated by jsdifflib