1
The following changes since commit 86f4c7e05b1c44dbe1b329a51f311f10aef6ff34:
1
The following changes since commit a51e5124a655b3dad80b36b18547cb1eca2c5eb2:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180302' into staging (2018-03-02 14:37:10 +0000)
3
Merge tag 'pull-omnibus-111023-1' of https://gitlab.com/stsquad/qemu into staging (2023-10-11 09:43:10 -0400)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
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 9d9b4b640f9e583ff4b24dc762630945f3ccc16d:
9
for you to fetch changes up to e6e964b8b021446c8d3d1f91c0208f653e9ec92c:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-02' into queue-block (2018-03-02 18:45:03 +0100)
11
block: Add assertion for bdrv_graph_wrlock() (2023-10-12 16:31:33 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Clean up coroutine versions of bdrv_{is_allocated,block_status}*
17
- Graph locking part 5 (protect children/parent links)
18
16
----------------------------------------------------------------
19
----------------------------------------------------------------
17
Alberto Garcia (3):
20
Emanuele Giuseppe Esposito (1):
18
specs/qcow2: Fix documentation of the compressed cluster descriptor
21
block: Mark drain related functions GRAPH_RDLOCK
19
docs: document how to use the l2-cache-entry-size parameter
20
qcow2: Replace align_offset() with ROUND_UP()
21
22
22
Anton Nefedov (2):
23
Kevin Wolf (21):
23
block: fix write with zero flag set and iovector provided
24
test-bdrv-drain: Don't call bdrv_graph_wrlock() in coroutine context
24
iotest 033: add misaligned write-zeroes test via truncate
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()
25
45
26
Eric Blake (21):
46
Paolo Bonzini (4):
27
block: Add .bdrv_co_block_status() callback
47
block: rename the bdrv_co_block_status static function
28
nvme: Drop pointless .bdrv_co_get_block_status()
48
block: complete public block status API
29
block: Switch passthrough drivers to .bdrv_co_block_status()
49
block: switch to co_wrapper for bdrv_is_allocated_*
30
file-posix: Switch to .bdrv_co_block_status()
50
block: convert more bdrv_is_allocated* and bdrv_block_status* calls to coroutine versions
31
gluster: Switch to .bdrv_co_block_status()
32
iscsi: Switch cluster_sectors to byte-based
33
iscsi: Switch iscsi_allocmap_update() to byte-based
34
iscsi: Switch to .bdrv_co_block_status()
35
null: Switch to .bdrv_co_block_status()
36
parallels: Switch to .bdrv_co_block_status()
37
qcow: Switch to .bdrv_co_block_status()
38
qcow2: Switch to .bdrv_co_block_status()
39
qed: Switch to .bdrv_co_block_status()
40
raw: Switch to .bdrv_co_block_status()
41
sheepdog: Switch to .bdrv_co_block_status()
42
vdi: Avoid bitrot of debugging code
43
vdi: Switch to .bdrv_co_block_status()
44
vmdk: Switch to .bdrv_co_block_status()
45
vpc: Switch to .bdrv_co_block_status()
46
vvfat: Switch to .bdrv_co_block_status()
47
block: Drop unused .bdrv_co_get_block_status()
48
51
49
Kevin Wolf (2):
52
block/qcow2.h | 187 ++++++++++++++++------------
50
block: test blk_aio_flush() with blk->root == NULL
53
block/vhdx.h | 5 +-
51
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-02' into queue-block
54
include/block/block-common.h | 7 +-
52
55
include/block/block-global-state.h | 34 ++---
53
Max Reitz (4):
56
include/block/block-io.h | 71 +++++++----
54
qemu-img: Make resize error message more general
57
include/block/block_int-common.h | 69 +++++-----
55
block/ssh: Pull ssh_grow_file() from ssh_create()
58
include/block/block_int-io.h | 7 +-
56
block/ssh: Make ssh_grow_file() blocking
59
include/block/graph-lock.h | 3 +-
57
block/ssh: Add basic .bdrv_truncate()
60
include/block/qapi.h | 23 ++--
58
61
include/block/snapshot.h | 24 ++--
59
Stefan Hajnoczi (6):
62
include/sysemu/block-backend-global-state.h | 4 +-
60
aio: rename aio_context_in_iothread() to in_aio_context_home_thread()
63
block.c | 120 ++++++++++++------
61
block: extract AIO_WAIT_WHILE() from BlockDriverState
64
block/backup.c | 1 +
62
block: add BlockBackend->in_flight counter
65
block/block-backend.c | 9 +-
63
Revert "IDE: Do not flush empty CDROM drives"
66
block/bochs.c | 2 +
64
block: rename .bdrv_create() to .bdrv_co_create_opts()
67
block/cloop.c | 2 +
65
qcow2: make qcow2_co_create2() a coroutine_fn
68
block/commit.c | 1 +
66
69
block/copy-before-write.c | 2 +-
67
docs/interop/qcow2.txt | 16 ++++-
70
block/copy-on-read.c | 8 +-
68
docs/qcow2-cache.txt | 46 ++++++++++++-
71
block/crypto.c | 4 +-
69
block/qcow2.h | 6 --
72
block/curl.c | 2 +
70
include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++
73
block/dmg.c | 2 +
71
include/block/aio.h | 7 +-
74
block/export/export.c | 4 +
72
include/block/block.h | 54 ++++-----------
75
block/gluster.c | 2 +
73
include/block/block_int.h | 61 ++++++++++-------
76
block/graph-lock.c | 3 +-
74
block.c | 11 ++-
77
block/io.c | 143 ++++++++++-----------
75
block/blkdebug.c | 20 +++---
78
block/iscsi.c | 2 +
76
block/block-backend.c | 60 +++++++++++++++--
79
block/mirror.c | 10 +-
77
block/commit.c | 2 +-
80
block/monitor/block-hmp-cmds.c | 5 +
78
block/crypto.c | 8 +--
81
block/nbd.c | 3 +-
79
block/file-posix.c | 79 +++++++++++-----------
82
block/nfs.c | 2 +-
80
block/file-win32.c | 5 +-
83
block/parallels.c | 3 +
81
block/gluster.c | 83 ++++++++++++-----------
84
block/qapi-sysemu.c | 11 +-
82
block/io.c | 98 +++++++++++----------------
85
block/qapi.c | 11 +-
83
block/iscsi.c | 164 ++++++++++++++++++++++++---------------------
86
block/qcow.c | 3 +
84
block/mirror.c | 2 +-
87
block/qcow2-bitmap.c | 38 +++---
85
block/nfs.c | 5 +-
88
block/qcow2-cache.c | 11 +-
86
block/null.c | 23 ++++---
89
block/qcow2-cluster.c | 62 ++++-----
87
block/nvme.c | 14 ----
90
block/qcow2-refcount.c | 80 ++++++------
88
block/parallels.c | 28 +++++---
91
block/qcow2.c | 77 +++++++-----
89
block/qcow.c | 32 +++++----
92
block/quorum.c | 4 +-
90
block/qcow2-bitmap.c | 4 +-
93
block/raw-format.c | 2 +
91
block/qcow2-cluster.c | 4 +-
94
block/rbd.c | 4 +
92
block/qcow2-refcount.c | 4 +-
95
block/replication.c | 29 +++--
93
block/qcow2-snapshot.c | 10 +--
96
block/snapshot.c | 54 ++++++--
94
block/qcow2.c | 60 +++++++++--------
97
block/stream.c | 8 +-
95
block/qed.c | 82 ++++++++---------------
98
block/vdi.c | 3 +
96
block/raw-format.c | 21 +++---
99
block/vhdx.c | 4 +
97
block/rbd.c | 6 +-
100
block/vmdk.c | 53 +++++---
98
block/sheepdog.c | 36 +++++-----
101
block/vpc.c | 3 +
99
block/ssh.c | 66 +++++++++++++++---
102
block/vvfat.c | 20 +--
100
block/throttle.c | 2 +-
103
blockdev.c | 44 +++++++
101
block/vdi.c | 50 +++++++-------
104
blockjob.c | 1 +
102
block/vhdx.c | 5 +-
105
migration/block.c | 2 +
103
block/vmdk.c | 43 +++++-------
106
migration/migration-hmp-cmds.c | 2 +
104
block/vpc.c | 50 +++++++-------
107
qemu-img.c | 16 +++
105
block/vvfat.c | 16 ++---
108
qemu-io-cmds.c | 3 +
106
hw/ide/core.c | 10 +--
109
tests/unit/test-bdrv-drain.c | 15 ++-
107
qemu-img.c | 2 +-
110
tests/unit/test-block-iothread.c | 8 ++
108
tests/test-block-backend.c | 82 +++++++++++++++++++++++
111
scripts/block-coroutine-wrapper.py | 10 +-
109
util/aio-wait.c | 40 +++++++++++
112
60 files changed, 843 insertions(+), 499 deletions(-)
110
tests/Makefile.include | 2 +
111
tests/qemu-iotests/033 | 29 ++++++++
112
tests/qemu-iotests/033.out | 13 ++++
113
util/Makefile.objs | 2 +-
114
47 files changed, 973 insertions(+), 606 deletions(-)
115
create mode 100644 include/block/aio-wait.h
116
create mode 100644 tests/test-block-backend.c
117
create mode 100644 util/aio-wait.c
118
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The normal bdrv_co_pwritev() use is either
3
bdrv_block_status exists as a wrapper for bdrv_block_status_above, but
4
- BDRV_REQ_ZERO_WRITE clear and iovector provided
4
the name of the (hypothetical) coroutine version, bdrv_co_block_status,
5
- BDRV_REQ_ZERO_WRITE set and iovector == NULL
5
is squatted by a random static function. Rename it to
6
bdrv_co_do_block_status.
6
7
7
while
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
- the flag clear and iovector == NULL is an assertion failure
9
Message-ID: <20230904100306.156197-2-pbonzini@redhat.com>
9
in bdrv_co_do_zero_pwritev()
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
- the flag set and iovector provided is in fact allowed
11
(the flag prevails and zeroes are written)
12
13
However the alignment logic does not support the latter case so the padding
14
areas get overwritten with zeroes.
15
16
Currently, general functions like bdrv_rw_co() do provide iovector
17
regardless of flags. So, keep it supported and use bdrv_co_do_zero_pwritev()
18
alignment for it which also makes the code a bit more obvious anyway.
19
20
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
---
12
---
25
block/io.c | 2 +-
13
block/io.c | 21 +++++++++++----------
26
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 11 insertions(+), 10 deletions(-)
27
15
28
diff --git a/block/io.c b/block/io.c
16
diff --git a/block/io.c b/block/io.c
29
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
30
--- a/block/io.c
18
--- a/block/io.c
31
+++ b/block/io.c
19
+++ b/block/io.c
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
20
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
33
*/
21
* set to the host mapping and BDS corresponding to the guest offset.
34
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
22
*/
35
23
static int coroutine_fn GRAPH_RDLOCK
36
- if (!qiov) {
24
-bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
37
+ if (flags & BDRV_REQ_ZERO_WRITE) {
25
- int64_t offset, int64_t bytes,
38
ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req);
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);
39
goto out;
41
goto out;
40
}
42
}
43
44
@@ -XXX,XX +XXX,XX @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
45
int64_t file_pnum;
46
int ret2;
47
48
- ret2 = bdrv_co_block_status(local_file, want_zero, local_map,
49
- *pnum, &file_pnum, NULL, NULL);
50
+ ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map,
51
+ *pnum, &file_pnum, NULL, NULL);
52
if (ret2 >= 0) {
53
/* Ignore errors. This is just providing extra information, it
54
* is useful but not necessary.
55
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
56
return 0;
57
}
58
59
- ret = bdrv_co_block_status(bs, want_zero, offset, bytes, pnum, map, file);
60
+ ret = bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum,
61
+ map, file);
62
++*depth;
63
if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) {
64
return ret;
65
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
66
for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base;
67
p = bdrv_filter_or_cow_bs(p))
68
{
69
- ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map,
70
- file);
71
+ ret = bdrv_co_do_block_status(p, want_zero, offset, bytes, pnum,
72
+ map, file);
73
++*depth;
74
if (ret < 0) {
75
return ret;
41
--
76
--
42
2.13.6
77
2.41.0
43
44
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Include both coroutine and non-coroutine versions, the latter being
4
byte-based. Update the qed driver accordingly, taking the opportunity
4
co_wrapper_mixed_bdrv_rdlock of the former.
5
to inline qed_is_allocated_cb() into its lone caller (the callback
6
used to be important, until we switched qed to coroutines). There is
7
no intent to optimize based on the want_zero flag for this format.
8
5
9
Signed-off-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Message-ID: <20230904100306.156197-3-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
11
---
14
block/qed.c | 76 +++++++++++++++++++------------------------------------------
12
include/block/block-io.h | 17 +++++++++++------
15
1 file changed, 24 insertions(+), 52 deletions(-)
13
block/io.c | 18 +++++-------------
14
2 files changed, 16 insertions(+), 19 deletions(-)
16
15
17
diff --git a/block/qed.c b/block/qed.c
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/block/qed.c
18
--- a/include/block/block-io.h
20
+++ b/block/qed.c
19
+++ b/include/block/block-io.h
21
@@ -XXX,XX +XXX,XX @@ finish:
20
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_append(BlockDriverState *bs,
22
return ret;
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);
23
}
55
}
24
56
25
-typedef struct {
57
-int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
26
- BlockDriverState *bs;
58
- int64_t offset, int64_t bytes, int64_t *pnum,
27
- Coroutine *co;
59
- int64_t *map, BlockDriverState **file)
28
- uint64_t pos;
60
+int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, int64_t offset,
29
- int64_t status;
61
+ int64_t bytes, int64_t *pnum,
30
- int *pnum;
62
+ int64_t *map, BlockDriverState **file)
31
- BlockDriverState **file;
32
-} QEDIsAllocatedCB;
33
-
34
-/* Called with table_lock held. */
35
-static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len)
36
+static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
37
+ bool want_zero,
38
+ int64_t pos, int64_t bytes,
39
+ int64_t *pnum, int64_t *map,
40
+ BlockDriverState **file)
41
{
63
{
42
- QEDIsAllocatedCB *cb = opaque;
64
IO_CODE();
43
- BDRVQEDState *s = cb->bs->opaque;
65
- return bdrv_common_block_status_above(bs, base, false, true, offset, bytes,
44
- *cb->pnum = len / BDRV_SECTOR_SIZE;
66
- pnum, map, file, NULL);
45
+ BDRVQEDState *s = bs->opaque;
46
+ size_t len = MIN(bytes, SIZE_MAX);
47
+ int status;
48
+ QEDRequest request = { .l2_table = NULL };
49
+ uint64_t offset;
50
+ int ret;
51
+
52
+ qemu_co_mutex_lock(&s->table_lock);
53
+ ret = qed_find_cluster(s, &request, pos, &len, &offset);
54
+
55
+ *pnum = len;
56
switch (ret) {
57
case QED_CLUSTER_FOUND:
58
- offset |= qed_offset_into_cluster(s, cb->pos);
59
- cb->status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
60
- *cb->file = cb->bs->file->bs;
61
+ *map = offset | qed_offset_into_cluster(s, pos);
62
+ status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
63
+ *file = bs->file->bs;
64
break;
65
case QED_CLUSTER_ZERO:
66
- cb->status = BDRV_BLOCK_ZERO;
67
+ status = BDRV_BLOCK_ZERO;
68
break;
69
case QED_CLUSTER_L2:
70
case QED_CLUSTER_L1:
71
- cb->status = 0;
72
+ status = 0;
73
break;
74
default:
75
assert(ret < 0);
76
- cb->status = ret;
77
+ status = ret;
78
break;
79
}
80
81
- if (cb->co) {
82
- aio_co_wake(cb->co);
83
- }
84
-}
67
-}
85
-
68
-
86
-static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs,
69
-int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
87
- int64_t sector_num,
70
- int64_t *pnum, int64_t *map, BlockDriverState **file)
88
- int nb_sectors, int *pnum,
89
- BlockDriverState **file)
90
-{
71
-{
91
- BDRVQEDState *s = bs->opaque;
72
- IO_CODE();
92
- size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE;
73
- return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
93
- QEDIsAllocatedCB cb = {
74
- offset, bytes, pnum, map, file);
94
- .bs = bs,
75
+ return bdrv_co_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
95
- .pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE,
76
+ offset, bytes, pnum, map, file);
96
- .status = BDRV_BLOCK_OFFSET_MASK,
97
- .pnum = pnum,
98
- .file = file,
99
- };
100
- QEDRequest request = { .l2_table = NULL };
101
- uint64_t offset;
102
- int ret;
103
-
104
- qemu_co_mutex_lock(&s->table_lock);
105
- ret = qed_find_cluster(s, &request, cb.pos, &len, &offset);
106
- qed_is_allocated_cb(&cb, ret, offset, len);
107
-
108
- /* The callback was invoked immediately */
109
- assert(cb.status != BDRV_BLOCK_OFFSET_MASK);
110
-
111
qed_unref_l2_cache_entry(request.l2_table);
112
qemu_co_mutex_unlock(&s->table_lock);
113
114
- return cb.status;
115
+ return status;
116
}
77
}
117
78
118
static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
79
/*
119
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
120
.bdrv_child_perm = bdrv_format_default_perms,
121
.bdrv_create = bdrv_qed_create,
122
.bdrv_has_zero_init = bdrv_has_zero_init_1,
123
- .bdrv_co_get_block_status = bdrv_qed_co_get_block_status,
124
+ .bdrv_co_block_status = bdrv_qed_co_block_status,
125
.bdrv_co_readv = bdrv_qed_co_readv,
126
.bdrv_co_writev = bdrv_qed_co_writev,
127
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
128
--
80
--
129
2.13.6
81
2.41.0
130
131
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
byte-based. Update the qcow driver accordingly. There is no
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
intent to optimize based on the want_zero flag for this format.
5
Message-ID: <20230904100306.156197-4-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
block/qcow.c | 27 ++++++++++++++++-----------
9
include/block/block-io.h | 12 +++++----
13
1 file changed, 16 insertions(+), 11 deletions(-)
10
block/io.c | 53 ++++++----------------------------------
11
2 files changed, 14 insertions(+), 51 deletions(-)
14
12
15
diff --git a/block/qcow.c b/block/qcow.c
13
diff --git a/include/block/block-io.h b/include/block/block-io.h
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow.c
15
--- a/include/block/block-io.h
18
+++ b/block/qcow.c
16
+++ b/include/block/block-io.h
19
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
17
@@ -XXX,XX +XXX,XX @@ bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
20
return 1;
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);
21
}
47
}
22
48
23
-static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
49
-int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
24
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
50
- int64_t *pnum)
25
+static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
51
-{
26
+ bool want_zero,
52
- int ret;
27
+ int64_t offset, int64_t bytes,
53
- int64_t dummy;
28
+ int64_t *pnum, int64_t *map,
54
- IO_CODE();
29
+ BlockDriverState **file)
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)
30
{
103
{
31
BDRVQcowState *s = bs->opaque;
104
int depth;
32
- int index_in_cluster, n, ret;
105
int ret;
33
+ int index_in_cluster, ret;
106
IO_CODE();
34
+ int64_t n;
107
35
uint64_t cluster_offset;
108
- ret = bdrv_common_block_status_above(top, base, include_base, false,
36
109
- offset, bytes, pnum, NULL, NULL,
37
qemu_co_mutex_lock(&s->lock);
110
- &depth);
38
- ret = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0, &cluster_offset);
111
+ ret = bdrv_co_common_block_status_above(bs, base, include_base, false,
39
+ ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
112
+ offset, bytes, pnum, NULL, NULL,
40
qemu_co_mutex_unlock(&s->lock);
113
+ &depth);
41
if (ret < 0) {
114
if (ret < 0) {
42
return ret;
115
return ret;
43
}
116
}
44
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
45
- n = s->cluster_sectors - index_in_cluster;
46
- if (n > nb_sectors)
47
- n = nb_sectors;
48
+ index_in_cluster = offset & (s->cluster_size - 1);
49
+ n = s->cluster_size - index_in_cluster;
50
+ if (n > bytes) {
51
+ n = bytes;
52
+ }
53
*pnum = n;
54
if (!cluster_offset) {
55
return 0;
56
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
57
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypto) {
58
return BDRV_BLOCK_DATA;
59
}
60
- cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
61
+ *map = cluster_offset | index_in_cluster;
62
*file = bs->file->bs;
63
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset;
64
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
65
}
66
67
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
68
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
69
70
.bdrv_co_readv = qcow_co_readv,
71
.bdrv_co_writev = qcow_co_writev,
72
- .bdrv_co_get_block_status = qcow_co_get_block_status,
73
+ .bdrv_co_block_status = qcow_co_block_status,
74
75
.bdrv_make_empty = qcow_make_empty,
76
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
77
--
117
--
78
2.13.6
118
2.41.0
79
80
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
byte-based. Update the generic helpers, and all passthrough clients
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
(blkdebug, commit, mirror, throttle) accordingly.
5
Message-ID: <20230904100306.156197-5-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
include/block/block_int.h | 28 ++++++++++++++++------------
9
block/copy-before-write.c | 2 +-
13
block/blkdebug.c | 20 +++++++++++---------
10
block/copy-on-read.c | 8 ++++----
14
block/commit.c | 2 +-
11
block/io.c | 6 +++---
15
block/io.c | 36 ++++++++++++++++++++----------------
12
block/mirror.c | 10 +++++-----
16
block/mirror.c | 2 +-
13
block/qcow2.c | 5 +++--
17
block/throttle.c | 2 +-
14
block/replication.c | 8 ++++----
18
6 files changed, 50 insertions(+), 40 deletions(-)
15
block/stream.c | 8 ++++----
16
block/vvfat.c | 18 +++++++++---------
17
8 files changed, 33 insertions(+), 32 deletions(-)
19
18
20
diff --git a/include/block/block_int.h b/include/block/block_int.h
19
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block_int.h
21
--- a/block/copy-before-write.c
23
+++ b/include/block/block_int.h
22
+++ b/block/copy-before-write.c
24
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
23
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
25
uint64_t *nperm, uint64_t *nshared);
24
return -EACCES;
26
25
}
27
/*
26
28
- * Default implementation for drivers to pass bdrv_co_get_block_status() to
27
- ret = bdrv_block_status(child->bs, offset, cur_bytes, pnum, map, file);
29
+ * Default implementation for drivers to pass bdrv_co_block_status() to
28
+ ret = bdrv_co_block_status(child->bs, offset, cur_bytes, pnum, map, file);
30
* their file.
29
if (child == s->target) {
31
*/
30
/*
32
-int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
31
* We refer to s->target only for areas that we've written to it.
33
- int64_t sector_num,
32
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
34
- int nb_sectors,
33
index XXXXXXX..XXXXXXX 100644
35
- int *pnum,
34
--- a/block/copy-on-read.c
36
- BlockDriverState **file);
35
+++ b/block/copy-on-read.c
37
+int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
36
@@ -XXX,XX +XXX,XX @@ cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
38
+ bool want_zero,
37
local_flags = flags;
39
+ int64_t offset,
38
40
+ int64_t bytes,
39
/* In case of failure, try to copy-on-read anyway */
41
+ int64_t *pnum,
40
- ret = bdrv_is_allocated(bs->file->bs, offset, bytes, &n);
42
+ int64_t *map,
41
+ ret = bdrv_co_is_allocated(bs->file->bs, offset, bytes, &n);
43
+ BlockDriverState **file);
42
if (ret <= 0) {
44
/*
43
- ret = bdrv_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
45
- * Default implementation for drivers to pass bdrv_co_get_block_status() to
44
- state->bottom_bs, true, offset,
46
+ * Default implementation for drivers to pass bdrv_co_block_status() to
45
- n, &n);
47
* their backing file.
46
+ ret = bdrv_co_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
48
*/
47
+ state->bottom_bs, true, offset,
49
-int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
48
+ n, &n);
50
- int64_t sector_num,
49
if (ret > 0 || ret < 0) {
51
- int nb_sectors,
50
local_flags |= BDRV_REQ_COPY_ON_READ;
52
- int *pnum,
51
}
53
- BlockDriverState **file);
54
+int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
55
+ bool want_zero,
56
+ int64_t offset,
57
+ int64_t bytes,
58
+ int64_t *pnum,
59
+ int64_t *map,
60
+ BlockDriverState **file);
61
const char *bdrv_get_parent_name(const BlockDriverState *bs);
62
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
63
bool blk_dev_has_removable_media(BlockBackend *blk);
64
diff --git a/block/blkdebug.c b/block/blkdebug.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block/blkdebug.c
67
+++ b/block/blkdebug.c
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
69
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
70
}
71
72
-static int64_t coroutine_fn blkdebug_co_get_block_status(
73
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
74
- BlockDriverState **file)
75
+static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
76
+ bool want_zero,
77
+ int64_t offset,
78
+ int64_t bytes,
79
+ int64_t *pnum,
80
+ int64_t *map,
81
+ BlockDriverState **file)
82
{
83
- assert(QEMU_IS_ALIGNED(sector_num | nb_sectors,
84
- DIV_ROUND_UP(bs->bl.request_alignment,
85
- BDRV_SECTOR_SIZE)));
86
- return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors,
87
- pnum, file);
88
+ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
89
+ return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes,
90
+ pnum, map, file);
91
}
92
93
static void blkdebug_close(BlockDriverState *bs)
94
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
95
.bdrv_co_flush_to_disk = blkdebug_co_flush,
96
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
97
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
98
- .bdrv_co_get_block_status = blkdebug_co_get_block_status,
99
+ .bdrv_co_block_status = blkdebug_co_block_status,
100
101
.bdrv_debug_event = blkdebug_debug_event,
102
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
103
diff --git a/block/commit.c b/block/commit.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/commit.c
106
+++ b/block/commit.c
107
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
108
static BlockDriver bdrv_commit_top = {
109
.format_name = "commit_top",
110
.bdrv_co_preadv = bdrv_commit_top_preadv,
111
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
112
+ .bdrv_co_block_status = bdrv_co_block_status_from_backing,
113
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
114
.bdrv_close = bdrv_commit_top_close,
115
.bdrv_child_perm = bdrv_commit_top_child_perm,
116
diff --git a/block/io.c b/block/io.c
52
diff --git a/block/io.c b/block/io.c
117
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
118
--- a/block/io.c
54
--- a/block/io.c
119
+++ b/block/io.c
55
+++ b/block/io.c
120
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvCoBlockStatusData {
56
@@ -XXX,XX +XXX,XX @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
121
bool done;
57
ret = 1; /* "already allocated", so nothing will be copied */
122
} BdrvCoBlockStatusData;
58
pnum = MIN(align_bytes, max_transfer);
123
59
} else {
124
-int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
60
- ret = bdrv_is_allocated(bs, align_offset,
125
- int64_t sector_num,
61
- MIN(align_bytes, max_transfer), &pnum);
126
- int nb_sectors,
62
+ ret = bdrv_co_is_allocated(bs, align_offset,
127
- int *pnum,
63
+ MIN(align_bytes, max_transfer), &pnum);
128
- BlockDriverState **file)
64
if (ret < 0) {
129
+int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
65
/*
130
+ bool want_zero,
66
* Safe to treat errors in querying allocation as if
131
+ int64_t offset,
67
@@ -XXX,XX +XXX,XX @@ bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
132
+ int64_t bytes,
68
/* The flag BDRV_REQ_COPY_ON_READ has reached its addressee */
133
+ int64_t *pnum,
69
flags &= ~BDRV_REQ_COPY_ON_READ;
134
+ int64_t *map,
70
135
+ BlockDriverState **file)
71
- ret = bdrv_is_allocated(bs, offset, bytes, &pnum);
136
{
72
+ ret = bdrv_co_is_allocated(bs, offset, bytes, &pnum);
137
assert(bs->file && bs->file->bs);
73
if (ret < 0) {
138
- *pnum = nb_sectors;
74
goto out;
139
+ *pnum = bytes;
75
}
140
+ *map = offset;
141
*file = bs->file->bs;
142
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
143
- (sector_num << BDRV_SECTOR_BITS);
144
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
145
}
146
147
-int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
148
- int64_t sector_num,
149
- int nb_sectors,
150
- int *pnum,
151
- BlockDriverState **file)
152
+int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
153
+ bool want_zero,
154
+ int64_t offset,
155
+ int64_t bytes,
156
+ int64_t *pnum,
157
+ int64_t *map,
158
+ BlockDriverState **file)
159
{
160
assert(bs->backing && bs->backing->bs);
161
- *pnum = nb_sectors;
162
+ *pnum = bytes;
163
+ *map = offset;
164
*file = bs->backing->bs;
165
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
166
- (sector_num << BDRV_SECTOR_BITS);
167
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
168
}
169
170
/*
171
diff --git a/block/mirror.c b/block/mirror.c
76
diff --git a/block/mirror.c b/block/mirror.c
172
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
173
--- a/block/mirror.c
78
--- a/block/mirror.c
174
+++ b/block/mirror.c
79
+++ b/block/mirror.c
175
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
80
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
176
.bdrv_co_pwrite_zeroes = bdrv_mirror_top_pwrite_zeroes,
81
177
.bdrv_co_pdiscard = bdrv_mirror_top_pdiscard,
82
assert(!(offset % s->granularity));
178
.bdrv_co_flush = bdrv_mirror_top_flush,
83
WITH_GRAPH_RDLOCK_GUARD() {
179
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
84
- ret = bdrv_block_status_above(source, NULL, offset,
180
+ .bdrv_co_block_status = bdrv_co_block_status_from_backing,
85
- nb_chunks * s->granularity,
181
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
86
- &io_bytes, NULL, NULL);
182
.bdrv_close = bdrv_mirror_top_close,
87
+ ret = bdrv_co_block_status_above(source, NULL, offset,
183
.bdrv_child_perm = bdrv_mirror_top_child_perm,
88
+ nb_chunks * s->granularity,
184
diff --git a/block/throttle.c b/block/throttle.c
89
+ &io_bytes, NULL, NULL);
185
index XXXXXXX..XXXXXXX 100644
90
}
186
--- a/block/throttle.c
91
if (ret < 0) {
187
+++ b/block/throttle.c
92
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
188
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
189
.bdrv_reopen_prepare = throttle_reopen_prepare,
94
}
190
.bdrv_reopen_commit = throttle_reopen_commit,
95
191
.bdrv_reopen_abort = throttle_reopen_abort,
96
WITH_GRAPH_RDLOCK_GUARD() {
192
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
97
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
193
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
98
- bytes, &count);
194
99
+ ret = bdrv_co_is_allocated_above(bs, s->base_overlay, true, offset,
195
.bdrv_co_drain_begin = throttle_co_drain_begin,
100
+ bytes, &count);
196
.bdrv_co_drain_end = throttle_co_drain_end,
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
}
197
--
215
--
198
2.13.6
216
2.41.0
199
200
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
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.
2
5
3
We are gradually moving away from sector-based interfaces, towards
6
Change the test to use a BH to drop out of coroutine context, and add
4
byte-based. Update the null driver accordingly.
7
coroutine_mixed_fn and no_coroutine_fn markers to clarify the context
8
each function runs in.
5
9
6
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-ID: <20230929145157.45443-2-kwolf@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
14
---
11
block/null.c | 23 ++++++++++++-----------
15
tests/unit/test-bdrv-drain.c | 7 ++++---
12
1 file changed, 12 insertions(+), 11 deletions(-)
16
1 file changed, 4 insertions(+), 3 deletions(-)
13
17
14
diff --git a/block/null.c b/block/null.c
18
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/block/null.c
20
--- a/tests/unit/test-bdrv-drain.c
17
+++ b/block/null.c
21
+++ b/tests/unit/test-bdrv-drain.c
18
@@ -XXX,XX +XXX,XX @@ static int null_reopen_prepare(BDRVReopenState *reopen_state,
22
@@ -XXX,XX +XXX,XX @@ struct detach_by_parent_data {
19
return 0;
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();
20
}
33
}
21
34
22
-static int64_t coroutine_fn null_co_get_block_status(BlockDriverState *bs,
35
-static void detach_by_parent_aio_cb(void *opaque, int ret)
23
- int64_t sector_num,
36
+static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
24
- int nb_sectors, int *pnum,
25
- BlockDriverState **file)
26
+static int coroutine_fn null_co_block_status(BlockDriverState *bs,
27
+ bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *pnum,
29
+ int64_t *map,
30
+ BlockDriverState **file)
31
{
37
{
32
BDRVNullState *s = bs->opaque;
38
struct detach_by_parent_data *data = &detach_by_parent_data;
33
- off_t start = sector_num * BDRV_SECTOR_SIZE;
39
34
+ int ret = BDRV_BLOCK_OFFSET_VALID;
40
g_assert_cmpint(ret, ==, 0);
35
41
if (data->by_parent_cb) {
36
- *pnum = nb_sectors;
42
bdrv_inc_in_flight(data->child_b->bs);
37
+ *pnum = bytes;
43
- detach_indirect_bh(data);
38
+ *map = offset;
44
+ aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
39
*file = bs;
45
+ detach_indirect_bh, &detach_by_parent_data);
40
41
if (s->read_zeroes) {
42
- return BDRV_BLOCK_OFFSET_VALID | start | BDRV_BLOCK_ZERO;
43
- } else {
44
- return BDRV_BLOCK_OFFSET_VALID | start;
45
+ ret |= BDRV_BLOCK_ZERO;
46
}
46
}
47
+ return ret;
48
}
47
}
49
48
50
static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
51
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
52
.bdrv_co_flush_to_disk = null_co_flush,
53
.bdrv_reopen_prepare = null_reopen_prepare,
54
55
- .bdrv_co_get_block_status = null_co_get_block_status,
56
+ .bdrv_co_block_status = null_co_block_status,
57
58
.bdrv_refresh_filename = null_refresh_filename,
59
};
60
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
61
.bdrv_aio_flush = null_aio_flush,
62
.bdrv_reopen_prepare = null_reopen_prepare,
63
64
- .bdrv_co_get_block_status = null_co_get_block_status,
65
+ .bdrv_co_block_status = null_co_block_status,
66
67
.bdrv_refresh_filename = null_refresh_filename,
68
};
69
--
49
--
70
2.13.6
50
2.41.0
71
72
diff view generated by jsdifflib
1
This patch adds test cases for the scenario where blk_aio_flush() is
1
Add a new wrapper type for GRAPH_RDLOCK functions that should be called
2
called on a BlockBackend with no root. Calling drain afterwards should
2
from coroutine context.
3
complete the requests with -ENOMEDIUM.
4
3
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Message-ID: <20230929145157.45443-3-kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
8
---
10
tests/test-block-backend.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
9
include/block/block-common.h | 7 +++++--
11
tests/Makefile.include | 2 ++
10
scripts/block-coroutine-wrapper.py | 10 +++++++---
12
2 files changed, 84 insertions(+)
11
2 files changed, 12 insertions(+), 5 deletions(-)
13
create mode 100644 tests/test-block-backend.c
14
12
15
diff --git a/tests/test-block-backend.c b/tests/test-block-backend.c
13
diff --git a/include/block/block-common.h b/include/block/block-common.h
16
new file mode 100644
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX
15
--- a/include/block/block-common.h
18
--- /dev/null
16
+++ b/include/block/block-common.h
19
+++ b/tests/test-block-backend.c
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
21
+/*
18
* function. The coroutine yields after scheduling the BH and is reentered when
22
+ * BlockBackend tests
19
* the wrapped function returns.
23
+ *
20
*
24
+ * Copyright (c) 2017 Kevin Wolf <kwolf@redhat.com>
21
- * A no_co_wrapper_bdrv_wrlock function is a no_co_wrapper function that
25
+ *
22
- * automatically takes the graph wrlock when calling the wrapped function.
26
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
23
+ * A no_co_wrapper_bdrv_rdlock function is a no_co_wrapper function that
27
+ * of this software and associated documentation files (the "Software"), to deal
24
+ * automatically takes the graph rdlock when calling the wrapped function. In
28
+ * in the Software without restriction, including without limitation the rights
25
+ * the same way, no_co_wrapper_bdrv_wrlock functions automatically take the
29
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26
+ * graph wrlock.
30
+ * copies of the Software, and to permit persons to whom the Software is
27
*
31
+ * furnished to do so, subject to the following conditions:
28
* If the first parameter of the function is a BlockDriverState, BdrvChild or
32
+ *
29
* BlockBackend pointer, the AioContext lock for it is taken in the wrapper.
33
+ * The above copyright notice and this permission notice shall be included in
30
*/
34
+ * all copies or substantial portions of the Software.
31
#define no_co_wrapper
35
+ *
32
+#define no_co_wrapper_bdrv_rdlock
36
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33
#define no_co_wrapper_bdrv_wrlock
37
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34
38
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
35
#include "block/blockjob.h"
39
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
40
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42
+ * THE SOFTWARE.
43
+ */
44
+
45
+#include "qemu/osdep.h"
46
+#include "block/block.h"
47
+#include "sysemu/block-backend.h"
48
+#include "qapi/error.h"
49
+
50
+static void test_drain_aio_error_flush_cb(void *opaque, int ret)
51
+{
52
+ bool *completed = opaque;
53
+
54
+ g_assert(ret == -ENOMEDIUM);
55
+ *completed = true;
56
+}
57
+
58
+static void test_drain_aio_error(void)
59
+{
60
+ BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
61
+ BlockAIOCB *acb;
62
+ bool completed = false;
63
+
64
+ acb = blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed);
65
+ g_assert(acb != NULL);
66
+ g_assert(completed == false);
67
+
68
+ blk_drain(blk);
69
+ g_assert(completed == true);
70
+
71
+ blk_unref(blk);
72
+}
73
+
74
+static void test_drain_all_aio_error(void)
75
+{
76
+ BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
77
+ BlockAIOCB *acb;
78
+ bool completed = false;
79
+
80
+ acb = blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed);
81
+ g_assert(acb != NULL);
82
+ g_assert(completed == false);
83
+
84
+ blk_drain_all();
85
+ g_assert(completed == true);
86
+
87
+ blk_unref(blk);
88
+}
89
+
90
+int main(int argc, char **argv)
91
+{
92
+ bdrv_init();
93
+ qemu_init_main_loop(&error_abort);
94
+
95
+ g_test_init(&argc, &argv, NULL);
96
+
97
+ g_test_add_func("/block-backend/drain_aio_error", test_drain_aio_error);
98
+ g_test_add_func("/block-backend/drain_all_aio_error",
99
+ test_drain_all_aio_error);
100
+
101
+ return g_test_run();
102
+}
103
diff --git a/tests/Makefile.include b/tests/Makefile.include
104
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
105
--- a/tests/Makefile.include
38
--- a/scripts/block-coroutine-wrapper.py
106
+++ b/tests/Makefile.include
39
+++ b/scripts/block-coroutine-wrapper.py
107
@@ -XXX,XX +XXX,XX @@ gcov-files-test-hbitmap-y = blockjob.c
40
@@ -XXX,XX +XXX,XX @@ def __init__(self, wrapper_type: str, return_type: str, name: str,
108
check-unit-y += tests/test-bdrv-drain$(EXESUF)
41
raise ValueError(f"Invalid no_co function name: {self.name}")
109
check-unit-y += tests/test-blockjob$(EXESUF)
42
if not self.create_only_co:
110
check-unit-y += tests/test-blockjob-txn$(EXESUF)
43
raise ValueError(f"no_co function can't be mixed: {self.name}")
111
+check-unit-y += tests/test-block-backend$(EXESUF)
44
- if self.graph_rdlock:
112
check-unit-y += tests/test-x86-cpuid$(EXESUF)
45
- raise ValueError(f"no_co function can't be rdlock: {self.name}")
113
# all code tested by test-x86-cpuid is inside topology.h
46
+ if self.graph_rdlock and self.graph_wrlock:
114
gcov-files-test-x86-cpuid-y =
47
+ raise ValueError("function can't be both rdlock and wrlock: "
115
@@ -XXX,XX +XXX,XX @@ tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
48
+ f"{self.name}")
116
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
49
self.target_name = f'{subsystem}_{subname}'
117
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
50
118
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
51
self.ctx = self.gen_ctx()
119
+tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
52
@@ -XXX,XX +XXX,XX @@ def gen_no_co_wrapper(func: FuncDecl) -> str:
120
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
53
121
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
54
graph_lock=''
122
tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y)
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
123
--
64
--
124
2.13.6
65
2.41.0
125
126
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
The function reads the parents list, so it needs to hold the graph lock.
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
easier to reason about than sector-based. Convert all uses of
4
Message-ID: <20230929145157.45443-4-kwolf@redhat.com>
5
the allocmap (no semantic change). Callers that already had bytes
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
available are simpler, and callers that now scale to bytes will be
7
easier to switch to byte-based in the future.
8
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
7
---
14
block/iscsi.c | 90 +++++++++++++++++++++++++++++------------------------------
8
block.c | 7 ++++---
15
1 file changed, 44 insertions(+), 46 deletions(-)
9
1 file changed, 4 insertions(+), 3 deletions(-)
16
10
17
diff --git a/block/iscsi.c b/block/iscsi.c
11
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/block/iscsi.c
13
--- a/block.c
20
+++ b/block/iscsi.c
14
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
15
@@ -XXX,XX +XXX,XX @@ void bdrv_activate_all(Error **errp)
16
}
22
}
17
}
23
18
24
static void
19
-static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
25
-iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
20
+static bool GRAPH_RDLOCK
26
- int nb_sectors, bool allocated, bool valid)
21
+bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
27
+iscsi_allocmap_update(IscsiLun *iscsilun, int64_t offset,
28
+ int64_t bytes, bool allocated, bool valid)
29
{
22
{
30
int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk;
23
BdrvChild *parent;
31
- int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
24
GLOBAL_STATE_CODE();
32
25
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
33
if (iscsilun->allocmap == NULL) {
26
return false;
34
return;
35
}
36
/* expand to entirely contain all affected clusters */
37
- assert(cluster_sectors);
38
- cl_num_expanded = sector_num / cluster_sectors;
39
- nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors,
40
- cluster_sectors) - cl_num_expanded;
41
+ assert(iscsilun->cluster_size);
42
+ cl_num_expanded = offset / iscsilun->cluster_size;
43
+ nb_cls_expanded = DIV_ROUND_UP(offset + bytes,
44
+ iscsilun->cluster_size) - cl_num_expanded;
45
/* shrink to touch only completely contained clusters */
46
- cl_num_shrunk = DIV_ROUND_UP(sector_num, cluster_sectors);
47
- nb_cls_shrunk = (sector_num + nb_sectors) / cluster_sectors
48
- - cl_num_shrunk;
49
+ cl_num_shrunk = DIV_ROUND_UP(offset, iscsilun->cluster_size);
50
+ nb_cls_shrunk = (offset + bytes) / iscsilun->cluster_size - cl_num_shrunk;
51
if (allocated) {
52
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
53
} else {
54
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
55
}
27
}
56
28
57
static void
29
-static int bdrv_inactivate_recurse(BlockDriverState *bs)
58
-iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t sector_num,
30
+static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs)
59
- int nb_sectors)
60
+iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t offset,
61
+ int64_t bytes)
62
{
31
{
63
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, true, true);
32
BdrvChild *child, *parent;
64
+ iscsi_allocmap_update(iscsilun, offset, bytes, true, true);
33
int ret;
65
}
34
uint64_t cumulative_perms, cumulative_shared_perms;
66
35
67
static void
36
GLOBAL_STATE_CODE();
68
-iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t sector_num,
37
- GRAPH_RDLOCK_GUARD_MAINLOOP();
69
- int nb_sectors)
38
70
+iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t offset,
39
if (!bs->drv) {
71
+ int64_t bytes)
40
return -ENOMEDIUM;
72
{
41
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
73
/* Note: if cache.direct=on the fifth argument to iscsi_allocmap_update
42
GSList *aio_ctxs = NULL, *ctx;
74
* is ignored, so this will in effect be an iscsi_allocmap_set_invalid.
43
75
*/
44
GLOBAL_STATE_CODE();
76
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, true);
45
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
77
+ iscsi_allocmap_update(iscsilun, offset, bytes, false, true);
46
78
}
47
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
79
48
AioContext *aio_context = bdrv_get_aio_context(bs);
80
-static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t sector_num,
81
- int nb_sectors)
82
+static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t offset,
83
+ int64_t bytes)
84
{
85
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, false);
86
+ iscsi_allocmap_update(iscsilun, offset, bytes, false, false);
87
}
88
89
static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
90
@@ -XXX,XX +XXX,XX @@ static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
91
}
92
93
static inline bool
94
-iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num,
95
- int nb_sectors)
96
+iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t offset,
97
+ int64_t bytes)
98
{
99
unsigned long size;
100
if (iscsilun->allocmap == NULL) {
101
return true;
102
}
103
assert(iscsilun->cluster_size);
104
- size = DIV_ROUND_UP(sector_num + nb_sectors,
105
- iscsilun->cluster_size >> BDRV_SECTOR_BITS);
106
+ size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
107
return !(find_next_bit(iscsilun->allocmap, size,
108
- sector_num * BDRV_SECTOR_SIZE /
109
- iscsilun->cluster_size) == size);
110
+ offset / iscsilun->cluster_size) == size);
111
}
112
113
static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
114
- int64_t sector_num, int nb_sectors)
115
+ int64_t offset, int64_t bytes)
116
{
117
unsigned long size;
118
if (iscsilun->allocmap_valid == NULL) {
119
return false;
120
}
121
assert(iscsilun->cluster_size);
122
- size = DIV_ROUND_UP(sector_num + nb_sectors,
123
- iscsilun->cluster_size >> BDRV_SECTOR_BITS);
124
+ size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
125
return (find_next_zero_bit(iscsilun->allocmap_valid, size,
126
- sector_num * BDRV_SECTOR_SIZE /
127
- iscsilun->cluster_size) == size);
128
+ offset / iscsilun->cluster_size) == size);
129
}
130
131
static int coroutine_fn
132
@@ -XXX,XX +XXX,XX @@ retry:
133
}
134
135
if (iTask.status != SCSI_STATUS_GOOD) {
136
- iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors);
137
+ iscsi_allocmap_set_invalid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
138
+ nb_sectors * BDRV_SECTOR_SIZE);
139
error_report("iSCSI WRITE10/16 failed at lba %" PRIu64 ": %s", lba,
140
iTask.err_str);
141
r = iTask.err_code;
142
goto out_unlock;
143
}
144
145
- iscsi_allocmap_set_allocated(iscsilun, sector_num, nb_sectors);
146
+ iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
147
+ nb_sectors * BDRV_SECTOR_SIZE);
148
149
out_unlock:
150
qemu_mutex_unlock(&iscsilun->mutex);
151
@@ -XXX,XX +XXX,XX @@ retry:
152
}
153
154
if (ret & BDRV_BLOCK_ZERO) {
155
- iscsi_allocmap_set_unallocated(iscsilun, sector_num, *pnum);
156
+ iscsi_allocmap_set_unallocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
157
+ *pnum * BDRV_SECTOR_SIZE);
158
} else {
159
- iscsi_allocmap_set_allocated(iscsilun, sector_num, *pnum);
160
+ iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
161
+ *pnum * BDRV_SECTOR_SIZE);
162
}
163
164
if (*pnum > nb_sectors) {
165
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
166
/* if cache.direct is off and we have a valid entry in our allocation map
167
* we can skip checking the block status and directly return zeroes if
168
* the request falls within an unallocated area */
169
- if (iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
170
- !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
171
+ if (iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
172
+ nb_sectors * BDRV_SECTOR_SIZE) &&
173
+ !iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
174
+ nb_sectors * BDRV_SECTOR_SIZE)) {
175
qemu_iovec_memset(iov, 0, 0x00, iov->size);
176
return 0;
177
}
178
179
if (nb_sectors >= ISCSI_CHECKALLOC_THRES &&
180
- !iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
181
- !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
182
+ !iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
183
+ nb_sectors * BDRV_SECTOR_SIZE) &&
184
+ !iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
185
+ nb_sectors * BDRV_SECTOR_SIZE)) {
186
int pnum;
187
BlockDriverState *file;
188
/* check the block status from the beginning of the cluster
189
@@ -XXX,XX +XXX,XX @@ retry:
190
goto retry;
191
}
192
193
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
194
- bytes >> BDRV_SECTOR_BITS);
195
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
196
197
if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
198
/* the target might fail with a check condition if it
199
@@ -XXX,XX +XXX,XX @@ retry:
200
}
201
202
if (iTask.status != SCSI_STATUS_GOOD) {
203
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
204
- bytes >> BDRV_SECTOR_BITS);
205
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
206
error_report("iSCSI WRITESAME10/16 failed at lba %" PRIu64 ": %s",
207
lba, iTask.err_str);
208
r = iTask.err_code;
209
@@ -XXX,XX +XXX,XX @@ retry:
210
}
211
212
if (flags & BDRV_REQ_MAY_UNMAP) {
213
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
214
- bytes >> BDRV_SECTOR_BITS);
215
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
216
} else {
217
- iscsi_allocmap_set_allocated(iscsilun, offset >> BDRV_SECTOR_BITS,
218
- bytes >> BDRV_SECTOR_BITS);
219
+ iscsi_allocmap_set_allocated(iscsilun, offset, bytes);
220
}
221
222
out_unlock:
223
--
49
--
224
2.13.6
50
2.41.0
225
226
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
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.
2
5
3
We are gradually moving away from sector-based interfaces, towards
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Now that all drivers have been updated to provide the
7
Message-ID: <20230929145157.45443-5-kwolf@redhat.com>
5
byte-based .bdrv_co_block_status(), we can delete the sector-based
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
interface.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
10
---
13
include/block/block_int.h | 3 ---
11
include/block/block-global-state.h | 9 +++++----
14
block/io.c | 50 ++++++++++-------------------------------------
12
include/sysemu/block-backend-global-state.h | 4 ++--
15
2 files changed, 10 insertions(+), 43 deletions(-)
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(-)
16
26
17
diff --git a/include/block/block_int.h b/include/block/block_int.h
27
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int.h
29
--- a/include/block/block-global-state.h
20
+++ b/include/block/block_int.h
30
+++ b/include/block/block-global-state.h
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState * GRAPH_RDLOCK
22
* as well as non-NULL pnum, map, and file; in turn, the driver
32
check_to_replace_node(BlockDriverState *parent_bs, const char *node_name,
23
* must return an error or set pnum to an aligned non-zero value.
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.
24
*/
133
*/
25
- int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
134
+ bdrv_graph_rdlock_main_loop();
26
- int64_t sector_num, int nb_sectors, int *pnum,
135
bdrv_activate(bs, NULL);
27
- BlockDriverState **file);
136
+ bdrv_graph_rdunlock_main_loop();
28
int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
137
29
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
138
perm = BLK_PERM_CONSISTENT_READ;
30
int64_t *map, BlockDriverState **file);
139
if (export->writable) {
31
diff --git a/block/io.c b/block/io.c
140
diff --git a/block/io.c b/block/io.c
32
index XXXXXXX..XXXXXXX 100644
141
index XXXXXXX..XXXXXXX 100644
33
--- a/block/io.c
142
--- a/block/io.c
34
+++ b/block/io.c
143
+++ b/block/io.c
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
144
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
36
145
int result = 0;
37
/* Must be non-NULL or bdrv_getlength() would have failed */
146
38
assert(bs->drv);
147
GLOBAL_STATE_CODE();
39
- if (!bs->drv->bdrv_co_get_block_status && !bs->drv->bdrv_co_block_status) {
148
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
40
+ if (!bs->drv->bdrv_co_block_status) {
149
41
*pnum = bytes;
150
/*
42
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
151
* bdrv queue is managed by record/replay,
43
if (offset + bytes == total_size) {
152
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
153
index XXXXXXX..XXXXXXX 100644
45
154
--- a/block/monitor/block-hmp-cmds.c
46
/* Round out to request_alignment boundaries */
155
+++ b/block/monitor/block-hmp-cmds.c
47
align = bs->bl.request_alignment;
156
@@ -XXX,XX +XXX,XX @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
48
- if (bs->drv->bdrv_co_get_block_status && align < BDRV_SECTOR_SIZE) {
157
SnapshotEntry *snapshot_entry;
49
- align = BDRV_SECTOR_SIZE;
158
Error *err = NULL;
50
- }
159
51
aligned_offset = QEMU_ALIGN_DOWN(offset, align);
160
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
52
aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
161
+
53
162
bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, &err);
54
- if (bs->drv->bdrv_co_get_block_status) {
163
if (!bs) {
55
- int count; /* sectors */
164
error_report_err(err);
56
- int64_t longret;
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();
57
-
212
-
58
- assert(QEMU_IS_ALIGNED(aligned_offset | aligned_bytes,
213
/* start backup job now */
59
- BDRV_SECTOR_SIZE));
214
error_setg(&s->blocker,
60
- /*
215
"Block device is in use by internal backup job");
61
- * The contract allows us to return pnum smaller than bytes, even
216
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
62
- * if the next query would see the same status; we truncate the
217
if (!top_bs || !bdrv_is_root_node(top_bs) ||
63
- * request to avoid overflowing the driver's 32-bit interface.
218
!check_top_bs(top_bs, bs)) {
64
- */
219
error_setg(errp, "No top_bs or it is invalid");
65
- longret = bs->drv->bdrv_co_get_block_status(
220
+ bdrv_graph_wrunlock();
66
- bs, aligned_offset >> BDRV_SECTOR_BITS,
221
reopen_backing_file(bs, false, NULL);
67
- MIN(INT_MAX, aligned_bytes) >> BDRV_SECTOR_BITS, &count,
222
aio_context_release(aio_context);
68
- &local_file);
223
return;
69
- if (longret < 0) {
224
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
70
- assert(INT_MIN <= longret);
225
bdrv_op_block_all(top_bs, s->blocker);
71
- ret = longret;
226
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
72
- goto out;
227
73
- }
228
+ bdrv_graph_wrunlock();
74
- if (longret & BDRV_BLOCK_OFFSET_VALID) {
229
+
75
- local_map = longret & BDRV_BLOCK_OFFSET_MASK;
230
s->backup_job = backup_job_create(
76
- }
231
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
77
- ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
232
0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL,
78
- *pnum = count * BDRV_SECTOR_SIZE;
233
diff --git a/block/snapshot.c b/block/snapshot.c
79
- } else {
234
index XXXXXXX..XXXXXXX 100644
80
- ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
235
--- a/block/snapshot.c
81
- aligned_bytes, pnum, &local_map,
236
+++ b/block/snapshot.c
82
- &local_file);
237
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
83
- if (ret < 0) {
238
}
84
- *pnum = 0;
239
85
- goto out;
240
86
- }
241
-static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
87
- assert(*pnum); /* The block driver must make progress */
242
- GList **all_bdrvs,
88
+ ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
243
- Error **errp)
89
+ aligned_bytes, pnum, &local_map,
244
+static int GRAPH_RDLOCK
90
+ &local_file);
245
+bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
91
+ if (ret < 0) {
246
+ GList **all_bdrvs, Error **errp)
92
+ *pnum = 0;
247
{
93
+ goto out;
248
g_autoptr(GList) bdrvs = NULL;
94
}
249
95
250
@@ -XXX,XX +XXX,XX @@ static int bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
96
/*
251
}
97
- * The driver's result must be a multiple of request_alignment.
252
98
+ * The driver's result must be a non-zero multiple of request_alignment.
253
99
* Clamp pnum and adjust map to original request.
254
-static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
100
*/
255
+static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
101
- assert(QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset);
256
{
102
+ assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) &&
257
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
103
+ align > offset - aligned_offset);
258
return false;
104
*pnum -= offset - aligned_offset;
259
@@ -XXX,XX +XXX,XX @@ bool bdrv_all_can_snapshot(bool has_devices, strList *devices,
105
if (*pnum > bytes) {
260
GList *iterbdrvs;
106
*pnum = bytes;
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
}
107
--
379
--
108
2.13.6
380
2.41.0
109
110
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Draining recursively traverses the graph, therefore we need to make sure
4
byte-based. Now that the block layer exposes byte-based allocation,
4
that also such accesses to the graph are protected by the graph rdlock.
5
it's time to tackle the drivers. Add a new callback that operates
5
6
on as small as byte boundaries. Subsequent patches will then update
6
There are 3 different drain callers to consider:
7
individual drivers, then finally remove .bdrv_co_get_block_status().
7
1. drain in the main loop: no issue at all, rdlock is nop.
8
8
2. drain in an iothread: rdlock only works in main loop or coroutines,
9
The new code also passes through the 'want_zero' hint, which will
9
so disallow it.
10
allow subsequent patches to further optimize callers that only care
10
3. drain in a coroutine (regardless of AioContext): the drain mechanism
11
about how much of the image is allocated (want_zero is false),
11
takes care of scheduling a BH in the bs->aio_context that will
12
rather than full details about runs of zeroes and which offsets the
12
then take care of perform the actual draining. This is wrong,
13
allocation actually maps to (want_zero is true). As part of this
13
because as pointed in (2) if bs->aio_context is an iothread then
14
effort, fix another part of the documentation: the claim in commit
14
rdlock won't work. Therefore change bdrv_co_yield_to_drain to
15
4c41cb4 that BDRV_BLOCK_ALLOCATED is short for 'DATA || ZERO' is a
15
schedule the BH in the main loop.
16
lie at the block layer (see commit e88ae2264), even though it is
16
17
how the bit is computed from the driver layer. After all, there
17
Caller (2) also implies that we need to modify test-bdrv-drain.c to
18
are intentionally cases where we return ZERO but not ALLOCATED at
18
disallow draining in the iothreads.
19
the block layer, when we know that a read sees zero because the
19
20
backing file is too short. Note that the driver interface is thus
20
For some places, we know that they will hold the lock, but we don't have
21
slightly different than the public interface with regards to which
21
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
22
bits will be set, and what guarantees are provided on input.
22
with a FIXME comment. These places will be removed once everything is
23
23
properly annotated.
24
We also add an assertion that any driver using the new callback will
24
25
make progress (the only time pnum will be 0 is if the block layer
25
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
26
already handled an out-of-bounds request, or if there is an error);
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
the old driver interface did not provide this guarantee, which
27
Message-ID: <20230929145157.45443-6-kwolf@redhat.com>
28
could lead to some inf-loops in drastic corner-case failures.
28
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
29
30
Signed-off-by: Eric Blake <eblake@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Reviewed-by: Fam Zheng <famz@redhat.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
30
---
35
include/block/block.h | 14 +++++++-------
31
include/block/block-io.h | 23 ++++++++++++++++++-----
36
include/block/block_int.h | 20 +++++++++++++++-----
32
include/block/block_int-common.h | 6 +++---
37
block/io.c | 28 +++++++++++++++++++---------
33
block.c | 6 +++---
38
3 files changed, 41 insertions(+), 21 deletions(-)
34
block/io.c | 32 ++++++++++++++++++++++++++++----
39
35
tests/unit/test-bdrv-drain.c | 4 ++--
40
diff --git a/include/block/block.h b/include/block/block.h
36
5 files changed, 54 insertions(+), 17 deletions(-)
41
index XXXXXXX..XXXXXXX 100644
37
42
--- a/include/block/block.h
38
diff --git a/include/block/block-io.h b/include/block/block-io.h
43
+++ b/include/block/block.h
39
index XXXXXXX..XXXXXXX 100644
44
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
40
--- a/include/block/block-io.h
45
* BDRV_BLOCK_ZERO: offset reads as zero
41
+++ b/include/block/block-io.h
46
* BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
42
@@ -XXX,XX +XXX,XX @@ bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
47
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
43
*
48
- * layer (short for DATA || ZERO), set by block layer
44
* Begin a quiesced section for the parent of @c.
49
- * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this layer
45
*/
50
+ * layer rather than any backing, set by block layer
46
-void bdrv_parent_drained_begin_single(BdrvChild *c);
51
+ * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this
47
+void GRAPH_RDLOCK bdrv_parent_drained_begin_single(BdrvChild *c);
52
+ * layer, set by block layer
48
53
*
49
/**
54
* Internal flag:
50
* bdrv_parent_drained_poll_single:
55
* BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request
51
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c);
56
* that the block layer recompute the answer from the returned
52
* Returns true if there is any pending activity to cease before @c can be
57
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
53
* called quiesced, false otherwise.
58
*
54
*/
59
- * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) of
55
-bool bdrv_parent_drained_poll_single(BdrvChild *c);
60
- * the return value (old interface) or the entire map parameter (new
56
+bool GRAPH_RDLOCK bdrv_parent_drained_poll_single(BdrvChild *c);
61
- * interface) represent the offset in the returned BDS that is allocated for
57
62
- * the corresponding raw data. However, whether that offset actually
58
/**
63
- * contains data also depends on BDRV_BLOCK_DATA, as follows:
59
* bdrv_parent_drained_end_single:
64
+ * If BDRV_BLOCK_OFFSET_VALID is set, the map parameter represents the
60
*
65
+ * host offset within the returned BDS that is allocated for the
61
* End a quiesced section for the parent of @c.
66
+ * corresponding raw guest data. However, whether that offset
62
*/
67
+ * actually contains data also depends on BDRV_BLOCK_DATA, as follows:
63
-void bdrv_parent_drained_end_single(BdrvChild *c);
68
*
64
+void GRAPH_RDLOCK bdrv_parent_drained_end_single(BdrvChild *c);
69
* DATA ZERO OFFSET_VALID
65
70
* t t t sectors read as zero, returned file is zero at offset
66
/**
71
diff --git a/include/block/block_int.h b/include/block/block_int.h
67
* bdrv_drain_poll:
72
index XXXXXXX..XXXXXXX 100644
68
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c);
73
--- a/include/block/block_int.h
69
*
74
+++ b/include/block/block_int.h
70
* This is part of bdrv_drained_begin.
75
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
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
76
/*
119
/*
77
* Building block for bdrv_block_status[_above] and
120
* Returns whether the parent has pending requests for the child. This
78
* bdrv_is_allocated[_above]. The driver should answer only
121
* callback is polled after .drained_begin() has been called until all
79
- * according to the current layer, and should not set
122
* activity on the child has stopped.
80
- * BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
81
- * for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block
82
- * layer guarantees input aligned to request_alignment, as well as
83
- * non-NULL pnum and file.
84
+ * according to the current layer, and should only need to set
85
+ * BDRV_BLOCK_DATA, BDRV_BLOCK_ZERO, BDRV_BLOCK_OFFSET_VALID,
86
+ * and/or BDRV_BLOCK_RAW; if the current layer defers to a backing
87
+ * layer, the result should be 0 (and not BDRV_BLOCK_ZERO). See
88
+ * block.h for the overall meaning of the bits. As a hint, the
89
+ * flag want_zero is true if the caller cares more about precise
90
+ * mappings (favor accurate _OFFSET_VALID/_ZERO) or false for
91
+ * overall allocation (favor larger *pnum, perhaps by reporting
92
+ * _DATA instead of _ZERO). The block layer guarantees input
93
+ * clamped to bdrv_getlength() and aligned to request_alignment,
94
+ * as well as non-NULL pnum, map, and file; in turn, the driver
95
+ * must return an error or set pnum to an aligned non-zero value.
96
*/
123
*/
97
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
124
- bool (*drained_poll)(BdrvChild *child);
98
int64_t sector_num, int nb_sectors, int *pnum,
125
+ bool GRAPH_RDLOCK_PTR (*drained_poll)(BdrvChild *child);
99
BlockDriverState **file);
100
+ int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
101
+ bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
102
+ int64_t *map, BlockDriverState **file);
103
126
104
/*
127
/*
105
* Invalidate any cached meta-data.
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);
106
diff --git a/block/io.c b/block/io.c
156
diff --git a/block/io.c b/block/io.c
107
index XXXXXXX..XXXXXXX 100644
157
index XXXXXXX..XXXXXXX 100644
108
--- a/block/io.c
158
--- a/block/io.c
109
+++ b/block/io.c
159
+++ b/block/io.c
110
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
160
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs);
111
* Drivers not implementing the functionality are assumed to not support
161
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
112
* backing files, hence all their sectors are reported as allocated.
162
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
113
*
163
114
- * If 'want_zero' is true, the caller is querying for mapping purposes,
164
-static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
115
- * and the result should include BDRV_BLOCK_OFFSET_VALID and
165
+static void GRAPH_RDLOCK
116
- * BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those
166
+bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
117
- * bits particularly if it allows for a larger value in 'pnum'.
167
{
118
+ * If 'want_zero' is true, the caller is querying for mapping
168
BdrvChild *c, *next;
119
+ * purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and
169
+ IO_OR_GS_CODE();
120
+ * _ZERO where possible; otherwise, the result favors larger 'pnum',
170
+ assert_bdrv_graph_readable();
121
+ * with a focus on accurate BDRV_BLOCK_ALLOCATED.
171
122
*
172
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
123
* If 'offset' is beyond the end of the disk image the return value is
173
if (c == ignore) {
124
* BDRV_BLOCK_EOF and 'pnum' is set to 0.
174
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end_single(BdrvChild *c)
125
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
175
}
126
176
}
127
/* Must be non-NULL or bdrv_getlength() would have failed */
177
128
assert(bs->drv);
178
-static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
129
- if (!bs->drv->bdrv_co_get_block_status) {
179
+static void GRAPH_RDLOCK
130
+ if (!bs->drv->bdrv_co_get_block_status && !bs->drv->bdrv_co_block_status) {
180
+bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
131
*pnum = bytes;
181
{
132
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
182
BdrvChild *c;
133
if (offset + bytes == total_size) {
183
+ IO_OR_GS_CODE();
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
184
+ assert_bdrv_graph_readable();
135
bdrv_inc_in_flight(bs);
185
136
186
QLIST_FOREACH(c, &bs->parents, next_parent) {
137
/* Round out to request_alignment boundaries */
187
if (c == ignore) {
138
- /* TODO: until we have a byte-based driver callback, we also have to
188
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
139
- * round out to sectors, even if that is bigger than request_alignment */
189
140
- align = MAX(bs->bl.request_alignment, BDRV_SECTOR_SIZE);
190
bool bdrv_parent_drained_poll_single(BdrvChild *c)
141
+ align = bs->bl.request_alignment;
191
{
142
+ if (bs->drv->bdrv_co_get_block_status && align < BDRV_SECTOR_SIZE) {
192
+ IO_OR_GS_CODE();
143
+ align = BDRV_SECTOR_SIZE;
193
+
144
+ }
194
if (c->klass->drained_poll) {
145
aligned_offset = QEMU_ALIGN_DOWN(offset, align);
195
return c->klass->drained_poll(c);
146
aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
196
}
147
197
return false;
148
- {
198
}
149
+ if (bs->drv->bdrv_co_get_block_status) {
199
150
int count; /* sectors */
200
-static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
151
int64_t longret;
201
- bool ignore_bds_parents)
152
202
+static bool GRAPH_RDLOCK
153
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
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);
154
}
255
}
155
ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
256
@@ -XXX,XX +XXX,XX @@ void bdrv_drain(BlockDriverState *bs)
156
*pnum = count * BDRV_SECTOR_SIZE;
257
static void bdrv_drain_assert_idle(BlockDriverState *bs)
157
+ } else {
258
{
158
+ ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
259
BdrvChild *child, *next;
159
+ aligned_bytes, pnum, &local_map,
260
+ GLOBAL_STATE_CODE();
160
+ &local_file);
261
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
161
+ if (ret < 0) {
262
162
+ *pnum = 0;
263
assert(qatomic_read(&bs->in_flight) == 0);
163
+ goto out;
264
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
164
+ }
265
@@ -XXX,XX +XXX,XX @@ static bool bdrv_drain_all_poll(void)
165
+ assert(*pnum); /* The block driver must make progress */
266
{
166
}
267
BlockDriverState *bs = NULL;
167
268
bool result = false;
168
/*
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;
169
--
297
--
170
2.13.6
298
2.41.0
171
172
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_parent_cb_resize() need to hold a reader lock for the graph.
2
3
3
BlockDriverState has the BDRV_POLL_WHILE() macro to wait on event loop
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
activity while a condition evaluates to true. This is used to implement
5
Message-ID: <20230929145157.45443-7-kwolf@redhat.com>
5
synchronous operations where it acts as a condvar between the IOThread
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
running the operation and the main loop waiting for the operation. It
7
can also be called from the thread that owns the AioContext and in that
8
case it's just a nested event loop.
9
10
BlockBackend needs this behavior but doesn't always have a
11
BlockDriverState it can use. This patch extracts BDRV_POLL_WHILE() into
12
the AioWait abstraction, which can be used with AioContext and isn't
13
tied to BlockDriverState anymore.
14
15
This feature could be built directly into AioContext but then all users
16
would kick the event loop even if they signal different conditions.
17
Imagine an AioContext with many BlockDriverStates, each time a request
18
completes any waiter would wake up and re-check their condition. It's
19
nicer to keep a separate AioWait object for each condition instead.
20
21
Please see "block/aio-wait.h" for details on the API.
22
23
The name AIO_WAIT_WHILE() avoids the confusion between AIO_POLL_WHILE()
24
and AioContext polling.
25
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
8
---
30
include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++++++++++++++++
9
block/io.c | 12 +++++++++---
31
include/block/block.h | 40 +++-------------
10
1 file changed, 9 insertions(+), 3 deletions(-)
32
include/block/block_int.h | 7 ++-
33
block.c | 5 ++
34
block/io.c | 10 +---
35
util/aio-wait.c | 40 ++++++++++++++++
36
util/Makefile.objs | 2 +-
37
7 files changed, 174 insertions(+), 46 deletions(-)
38
create mode 100644 include/block/aio-wait.h
39
create mode 100644 util/aio-wait.c
40
11
41
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
42
new file mode 100644
43
index XXXXXXX..XXXXXXX
44
--- /dev/null
45
+++ b/include/block/aio-wait.h
46
@@ -XXX,XX +XXX,XX @@
47
+/*
48
+ * AioContext wait support
49
+ *
50
+ * Copyright (C) 2018 Red Hat, Inc.
51
+ *
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
58
+ *
59
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
61
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
+ * THE SOFTWARE.
69
+ */
70
+
71
+#ifndef QEMU_AIO_WAIT_H
72
+#define QEMU_AIO_WAIT_H
73
+
74
+#include "block/aio.h"
75
+
76
+/**
77
+ * AioWait:
78
+ *
79
+ * An object that facilitates synchronous waiting on a condition. The main
80
+ * loop can wait on an operation running in an IOThread as follows:
81
+ *
82
+ * AioWait *wait = ...;
83
+ * AioContext *ctx = ...;
84
+ * MyWork work = { .done = false };
85
+ * schedule_my_work_in_iothread(ctx, &work);
86
+ * AIO_WAIT_WHILE(wait, ctx, !work.done);
87
+ *
88
+ * The IOThread must call aio_wait_kick() to notify the main loop when
89
+ * work.done changes:
90
+ *
91
+ * static void do_work(...)
92
+ * {
93
+ * ...
94
+ * work.done = true;
95
+ * aio_wait_kick(wait);
96
+ * }
97
+ */
98
+typedef struct {
99
+ /* Is the main loop waiting for a kick? Accessed with atomic ops. */
100
+ bool need_kick;
101
+} AioWait;
102
+
103
+/**
104
+ * AIO_WAIT_WHILE:
105
+ * @wait: the aio wait object
106
+ * @ctx: the aio context
107
+ * @cond: wait while this conditional expression is true
108
+ *
109
+ * Wait while a condition is true. Use this to implement synchronous
110
+ * operations that require event loop activity.
111
+ *
112
+ * The caller must be sure that something calls aio_wait_kick() when the value
113
+ * of @cond might have changed.
114
+ *
115
+ * The caller's thread must be the IOThread that owns @ctx or the main loop
116
+ * thread (with @ctx acquired exactly once). This function cannot be used to
117
+ * wait on conditions between two IOThreads since that could lead to deadlock,
118
+ * go via the main loop instead.
119
+ */
120
+#define AIO_WAIT_WHILE(wait, ctx, cond) ({ \
121
+ bool waited_ = false; \
122
+ bool busy_ = true; \
123
+ AioWait *wait_ = (wait); \
124
+ AioContext *ctx_ = (ctx); \
125
+ if (in_aio_context_home_thread(ctx_)) { \
126
+ while ((cond) || busy_) { \
127
+ busy_ = aio_poll(ctx_, (cond)); \
128
+ waited_ |= !!(cond) | busy_; \
129
+ } \
130
+ } else { \
131
+ assert(qemu_get_current_aio_context() == \
132
+ qemu_get_aio_context()); \
133
+ assert(!wait_->need_kick); \
134
+ /* Set wait_->need_kick before evaluating cond. */ \
135
+ atomic_mb_set(&wait_->need_kick, true); \
136
+ while (busy_) { \
137
+ if ((cond)) { \
138
+ waited_ = busy_ = true; \
139
+ aio_context_release(ctx_); \
140
+ aio_poll(qemu_get_aio_context(), true); \
141
+ aio_context_acquire(ctx_); \
142
+ } else { \
143
+ busy_ = aio_poll(ctx_, false); \
144
+ waited_ |= busy_; \
145
+ } \
146
+ } \
147
+ atomic_set(&wait_->need_kick, false); \
148
+ } \
149
+ waited_; })
150
+
151
+/**
152
+ * aio_wait_kick:
153
+ * @wait: the aio wait object that should re-evaluate its condition
154
+ *
155
+ * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During
156
+ * synchronous operations performed in an IOThread, the main thread lets the
157
+ * IOThread's event loop run, waiting for the operation to complete. A
158
+ * aio_wait_kick() call will wake up the main thread.
159
+ */
160
+void aio_wait_kick(AioWait *wait);
161
+
162
+#endif /* QEMU_AIO_WAIT */
163
diff --git a/include/block/block.h b/include/block/block.h
164
index XXXXXXX..XXXXXXX 100644
165
--- a/include/block/block.h
166
+++ b/include/block/block.h
167
@@ -XXX,XX +XXX,XX @@
168
#define BLOCK_H
169
170
#include "block/aio.h"
171
+#include "block/aio-wait.h"
172
#include "qapi-types.h"
173
#include "qemu/iov.h"
174
#include "qemu/coroutine.h"
175
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void);
176
void bdrv_drain_all_end(void);
177
void bdrv_drain_all(void);
178
179
+/* Returns NULL when bs == NULL */
180
+AioWait *bdrv_get_aio_wait(BlockDriverState *bs);
181
+
182
#define BDRV_POLL_WHILE(bs, cond) ({ \
183
- bool waited_ = false; \
184
- bool busy_ = true; \
185
BlockDriverState *bs_ = (bs); \
186
- AioContext *ctx_ = bdrv_get_aio_context(bs_); \
187
- if (in_aio_context_home_thread(ctx_)) { \
188
- while ((cond) || busy_) { \
189
- busy_ = aio_poll(ctx_, (cond)); \
190
- waited_ |= !!(cond) | busy_; \
191
- } \
192
- } else { \
193
- assert(qemu_get_current_aio_context() == \
194
- qemu_get_aio_context()); \
195
- /* Ask bdrv_dec_in_flight to wake up the main \
196
- * QEMU AioContext. Extra I/O threads never take \
197
- * other I/O threads' AioContexts (see for example \
198
- * block_job_defer_to_main_loop for how to do it). \
199
- */ \
200
- assert(!bs_->wakeup); \
201
- /* Set bs->wakeup before evaluating cond. */ \
202
- atomic_mb_set(&bs_->wakeup, true); \
203
- while (busy_) { \
204
- if ((cond)) { \
205
- waited_ = busy_ = true; \
206
- aio_context_release(ctx_); \
207
- aio_poll(qemu_get_aio_context(), true); \
208
- aio_context_acquire(ctx_); \
209
- } else { \
210
- busy_ = aio_poll(ctx_, false); \
211
- waited_ |= busy_; \
212
- } \
213
- } \
214
- atomic_set(&bs_->wakeup, false); \
215
- } \
216
- waited_; })
217
+ AIO_WAIT_WHILE(bdrv_get_aio_wait(bs_), \
218
+ bdrv_get_aio_context(bs_), \
219
+ cond); })
220
221
int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
222
int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
223
diff --git a/include/block/block_int.h b/include/block/block_int.h
224
index XXXXXXX..XXXXXXX 100644
225
--- a/include/block/block_int.h
226
+++ b/include/block/block_int.h
227
@@ -XXX,XX +XXX,XX @@
228
229
#include "block/accounting.h"
230
#include "block/block.h"
231
+#include "block/aio-wait.h"
232
#include "qemu/queue.h"
233
#include "qemu/coroutine.h"
234
#include "qemu/stats64.h"
235
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
236
unsigned int in_flight;
237
unsigned int serialising_in_flight;
238
239
- /* Internal to BDRV_POLL_WHILE and bdrv_wakeup. Accessed with atomic
240
- * ops.
241
- */
242
- bool wakeup;
243
+ /* Kicked to signal main loop when a request completes. */
244
+ AioWait wait;
245
246
/* counter for nested bdrv_io_plug.
247
* Accessed with atomic ops.
248
diff --git a/block.c b/block.c
249
index XXXXXXX..XXXXXXX 100644
250
--- a/block.c
251
+++ b/block.c
252
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
253
return bs->aio_context;
254
}
255
256
+AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
257
+{
258
+ return bs ? &bs->wait : NULL;
259
+}
260
+
261
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
262
{
263
aio_co_enter(bdrv_get_aio_context(bs), co);
264
diff --git a/block/io.c b/block/io.c
12
diff --git a/block/io.c b/block/io.c
265
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
266
--- a/block/io.c
14
--- a/block/io.c
267
+++ b/block/io.c
15
+++ b/block/io.c
268
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
269
#include "qemu/osdep.h"
17
/* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */
270
#include "trace.h"
18
#define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
271
#include "sysemu/block-backend.h"
19
272
+#include "block/aio-wait.h"
20
-static void bdrv_parent_cb_resize(BlockDriverState *bs);
273
#include "block/blockjob.h"
21
+static void coroutine_fn GRAPH_RDLOCK
274
#include "block/blockjob_int.h"
22
+bdrv_parent_cb_resize(BlockDriverState *bs);
275
#include "block/block_int.h"
23
+
276
@@ -XXX,XX +XXX,XX @@ void bdrv_inc_in_flight(BlockDriverState *bs)
24
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
277
atomic_inc(&bs->in_flight);
25
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
26
27
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
28
}
278
}
29
}
279
30
280
-static void dummy_bh_cb(void *opaque)
31
-static inline void coroutine_fn
281
-{
32
+static inline void coroutine_fn GRAPH_RDLOCK
282
-}
33
bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
283
-
34
BdrvTrackedRequest *req, int ret)
284
void bdrv_wakeup(BlockDriverState *bs)
285
{
35
{
286
- /* The barrier (or an atomic op) is in the caller. */
36
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
287
- if (atomic_read(&bs->wakeup)) {
37
bytes, read_flags, write_flags);
288
- aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
289
- }
290
+ aio_wait_kick(bdrv_get_aio_wait(bs));
291
}
38
}
292
39
293
void bdrv_dec_in_flight(BlockDriverState *bs)
40
-static void bdrv_parent_cb_resize(BlockDriverState *bs)
294
diff --git a/util/aio-wait.c b/util/aio-wait.c
41
+static void coroutine_fn GRAPH_RDLOCK
295
new file mode 100644
42
+bdrv_parent_cb_resize(BlockDriverState *bs)
296
index XXXXXXX..XXXXXXX
43
{
297
--- /dev/null
44
BdrvChild *c;
298
+++ b/util/aio-wait.c
299
@@ -XXX,XX +XXX,XX @@
300
+/*
301
+ * AioContext wait support
302
+ *
303
+ * Copyright (C) 2018 Red Hat, Inc.
304
+ *
305
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
306
+ * of this software and associated documentation files (the "Software"), to deal
307
+ * in the Software without restriction, including without limitation the rights
308
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
309
+ * copies of the Software, and to permit persons to whom the Software is
310
+ * furnished to do so, subject to the following conditions:
311
+ *
312
+ * The above copyright notice and this permission notice shall be included in
313
+ * all copies or substantial portions of the Software.
314
+ *
315
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
316
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
317
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
318
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
319
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
320
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
321
+ * THE SOFTWARE.
322
+ */
323
+
45
+
324
+#include "qemu/osdep.h"
46
+ assert_bdrv_graph_readable();
325
+#include "qemu/main-loop.h"
326
+#include "block/aio-wait.h"
327
+
47
+
328
+static void dummy_bh_cb(void *opaque)
48
QLIST_FOREACH(c, &bs->parents, next_parent) {
329
+{
49
if (c->klass->resize) {
330
+ /* The point is to make AIO_WAIT_WHILE()'s aio_poll() return */
50
c->klass->resize(c);
331
+}
332
+
333
+void aio_wait_kick(AioWait *wait)
334
+{
335
+ /* The barrier (or an atomic op) is in the caller. */
336
+ if (atomic_read(&wait->need_kick)) {
337
+ aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
338
+ }
339
+}
340
diff --git a/util/Makefile.objs b/util/Makefile.objs
341
index XXXXXXX..XXXXXXX 100644
342
--- a/util/Makefile.objs
343
+++ b/util/Makefile.objs
344
@@ -XXX,XX +XXX,XX @@
345
util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
346
util-obj-y += bufferiszero.o
347
util-obj-y += lockcnt.o
348
-util-obj-y += aiocb.o async.o thread-pool.o qemu-timer.o
349
+util-obj-y += aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o
350
util-obj-y += main-loop.o iohandler.o
351
util-obj-$(CONFIG_POSIX) += aio-posix.o
352
util-obj-$(CONFIG_POSIX) += compatfd.o
353
--
51
--
354
2.13.6
52
2.41.0
355
356
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_snapshot_fallback() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the gluster driver accordingly.
6
Message-ID: <20230929145157.45443-8-kwolf@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
In want_zero mode, we continue to report fine-grained hole
7
information (the caller wants as much mapping detail as possible);
8
but when not in that mode, the caller prefers larger *pnum and
9
merely cares about what offsets are allocated at this layer, rather
10
than where the holes live. Since holes still read as zeroes at
11
this layer (rather than deferring to a backing layer), we can take
12
the shortcut of skipping find_allocation(), and merely state that
13
all bytes are allocated.
14
15
We can also drop redundant bounds checks that are already
16
guaranteed by the block layer.
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
20
Reviewed-by: Fam Zheng <famz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
9
---
23
block/gluster.c | 70 ++++++++++++++++++++++++++++-----------------------------
10
include/block/block_int-common.h | 18 ++++++++--------
24
1 file changed, 34 insertions(+), 36 deletions(-)
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(-)
25
16
26
diff --git a/block/gluster.c b/block/gluster.c
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/block/gluster.c
19
--- a/include/block/block_int-common.h
29
+++ b/block/gluster.c
20
+++ b/include/block/block_int-common.h
30
@@ -XXX,XX +XXX,XX @@ exit:
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;
31
}
111
}
32
112
33
/*
113
-static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
34
- * Returns the allocation status of the specified sectors.
114
+static BlockDriverState * GRAPH_RDLOCK
35
+ * Returns the allocation status of the specified offset.
115
+bdrv_snapshot_fallback(BlockDriverState *bs)
36
*
116
{
37
- * If 'sector_num' is beyond the end of the disk image the return value is 0
117
+ GLOBAL_STATE_CODE();
38
- * and 'pnum' is set to 0.
118
return child_bs(bdrv_snapshot_fallback_child(bs));
39
+ * The block layer guarantees 'offset' and 'bytes' are within bounds.
119
}
40
*
120
41
- * 'pnum' is set to the number of sectors (including and immediately following
121
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
42
- * the specified sector) that are known to be in the same
43
+ * 'pnum' is set to the number of bytes (including and immediately following
44
+ * the specified offset) that are known to be in the same
45
* allocated/unallocated state.
46
*
47
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
48
- * beyond the end of the disk image it will be clamped.
49
+ * 'bytes' is the max value 'pnum' should be set to.
50
*
51
- * (Based on raw_co_get_block_status() from file-posix.c.)
52
+ * (Based on raw_co_block_status() from file-posix.c.)
53
*/
54
-static int64_t coroutine_fn qemu_gluster_co_get_block_status(
55
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
56
- BlockDriverState **file)
57
+static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
58
+ bool want_zero,
59
+ int64_t offset,
60
+ int64_t bytes,
61
+ int64_t *pnum,
62
+ int64_t *map,
63
+ BlockDriverState **file)
64
{
65
BDRVGlusterState *s = bs->opaque;
66
- off_t start, data = 0, hole = 0;
67
- int64_t total_size;
68
+ off_t data = 0, hole = 0;
69
int ret = -EINVAL;
70
71
if (!s->fd) {
72
return ret;
122
return ret;
73
}
123
}
74
124
75
- start = sector_num * BDRV_SECTOR_SIZE;
125
+ bdrv_graph_rdlock_main_loop();
76
- total_size = bdrv_getlength(bs);
126
fallback = bdrv_snapshot_fallback_child(bs);
77
- if (total_size < 0) {
127
+ bdrv_graph_rdunlock_main_loop();
78
- return total_size;
128
+
79
- } else if (start >= total_size) {
129
if (fallback) {
80
- *pnum = 0;
130
QDict *options;
81
- return 0;
131
QDict *file_options;
82
- } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
132
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
83
- nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
133
int bdrv_snapshot_list(BlockDriverState *bs,
84
+ if (!want_zero) {
134
QEMUSnapshotInfo **psn_info)
85
+ *pnum = bytes;
135
{
86
+ *map = offset;
136
+ GLOBAL_STATE_CODE();
87
+ *file = bs;
137
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
88
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
138
+
89
}
139
BlockDriver *drv = bs->drv;
90
140
BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
91
- ret = find_allocation(bs, start, &data, &hole);
141
92
+ ret = find_allocation(bs, offset, &data, &hole);
142
- GLOBAL_STATE_CODE();
93
if (ret == -ENXIO) {
143
if (!drv) {
94
/* Trailing hole */
144
return -ENOMEDIUM;
95
- *pnum = nb_sectors;
145
}
96
+ *pnum = bytes;
146
@@ -XXX,XX +XXX,XX @@ bdrv_all_get_snapshot_devices(bool has_devices, strList *devices,
97
ret = BDRV_BLOCK_ZERO;
147
98
} else if (ret < 0) {
148
static bool GRAPH_RDLOCK bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
99
/* No info available, so pretend there are no holes */
149
{
100
- *pnum = nb_sectors;
150
+ GLOBAL_STATE_CODE();
101
+ *pnum = bytes;
151
+ assert_bdrv_graph_readable();
102
ret = BDRV_BLOCK_DATA;
152
+
103
- } else if (data == start) {
153
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
104
- /* On a data extent, compute sectors to the end of the extent,
154
return false;
105
+ } else if (data == offset) {
155
}
106
+ /* On a data extent, compute bytes to the end of the extent,
156
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
107
* possibly including a partial sector at EOF. */
157
{
108
- *pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
158
g_autoptr(GList) bdrvs = NULL;
109
+ *pnum = MIN(bytes, hole - offset);
159
GList *iterbdrvs;
110
ret = BDRV_BLOCK_DATA;
160
+ int ret;
111
} else {
161
112
- /* On a hole, compute sectors to the beginning of the next extent. */
162
GLOBAL_STATE_CODE();
113
- assert(hole == start);
163
- GRAPH_RDLOCK_GUARD_MAINLOOP();
114
- *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
164
115
+ /* On a hole, compute bytes to the beginning of the next extent. */
165
- if (bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp) < 0) {
116
+ assert(hole == offset);
166
+ bdrv_graph_rdlock_main_loop();
117
+ *pnum = MIN(bytes, data - offset);
167
+ ret = bdrv_all_get_snapshot_devices(has_devices, devices, &bdrvs, errp);
118
ret = BDRV_BLOCK_ZERO;
168
+ bdrv_graph_rdunlock_main_loop();
119
}
169
+
120
170
+ if (ret < 0) {
121
+ *map = offset;
171
return -1;
122
*file = bs;
172
}
123
173
124
- return ret | BDRV_BLOCK_OFFSET_VALID | start;
174
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
125
+ return ret | BDRV_BLOCK_OFFSET_VALID;
175
BlockDriverState *bs = iterbdrvs->data;
126
}
176
AioContext *ctx = bdrv_get_aio_context(bs);
127
177
int ret = 0;
128
178
+ bool all_snapshots_includes_bs;
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
179
130
#ifdef CONFIG_GLUSTERFS_ZEROFILL
180
aio_context_acquire(ctx);
131
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
181
- if (devices || bdrv_all_snapshots_includes_bs(bs)) {
132
#endif
182
+ bdrv_graph_rdlock_main_loop();
133
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
183
+ all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
134
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
184
+ bdrv_graph_rdunlock_main_loop();
135
.create_opts = &qemu_gluster_create_opts,
185
+
136
};
186
+ if (devices || all_snapshots_includes_bs) {
137
187
ret = bdrv_snapshot_goto(bs, name, errp);
138
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
188
}
139
#ifdef CONFIG_GLUSTERFS_ZEROFILL
189
aio_context_release(ctx);
140
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
190
diff --git a/blockdev.c b/blockdev.c
141
#endif
191
index XXXXXXX..XXXXXXX 100644
142
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
192
--- a/blockdev.c
143
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
193
+++ b/blockdev.c
144
.create_opts = &qemu_gluster_create_opts,
194
@@ -XXX,XX +XXX,XX @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
145
};
195
SnapshotInfo *info = NULL;
146
196
int ret;
147
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
197
148
#ifdef CONFIG_GLUSTERFS_ZEROFILL
198
+ GLOBAL_STATE_CODE();
149
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
199
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
150
#endif
200
+
151
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
201
bs = qmp_get_root_bs(device, errp);
152
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
202
if (!bs) {
153
.create_opts = &qemu_gluster_create_opts,
203
return NULL;
154
};
204
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_action(BlockdevSnapshotInternal *internal,
155
205
AioContext *aio_context;
156
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
206
int ret1;
157
#ifdef CONFIG_GLUSTERFS_ZEROFILL
207
158
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
208
+ GLOBAL_STATE_CODE();
159
#endif
209
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
160
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
210
+
161
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
211
tran_add(tran, &internal_snapshot_drv, state);
162
.create_opts = &qemu_gluster_create_opts,
212
163
};
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
}
164
254
165
--
255
--
166
2.13.6
256
2.41.0
167
168
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.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
We are gradually moving away from sector-based interfaces, towards
5
Therefore just documents most of the functions to be unlocked, and take
4
byte-based. Update the vpc driver accordingly.
6
locks internally before accessing the graph.
5
7
6
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-ID: <20230929145157.45443-9-kwolf@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
12
---
11
block/vpc.c | 45 +++++++++++++++++++++++----------------------
13
include/block/block_int-common.h | 13 +++++---
12
1 file changed, 23 insertions(+), 22 deletions(-)
14
block.c | 57 ++++++++++++++++++++------------
15
2 files changed, 43 insertions(+), 27 deletions(-)
13
16
14
diff --git a/block/vpc.c b/block/vpc.c
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vpc.c
19
--- a/include/block/block_int-common.h
17
+++ b/block/vpc.c
20
+++ b/include/block/block_int-common.h
18
@@ -XXX,XX +XXX,XX @@ fail:
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
19
return ret;
22
Error **errp);
23
24
/* For handling image reopen for split or non-split files. */
25
- int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
26
- BlockReopenQueue *queue, Error **errp);
27
- void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
28
- void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state);
29
- void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
30
+ int GRAPH_UNLOCKED_PTR (*bdrv_reopen_prepare)(
31
+ BDRVReopenState *reopen_state, BlockReopenQueue *queue, Error **errp);
32
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_commit)(
33
+ BDRVReopenState *reopen_state);
34
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_commit_post)(
35
+ BDRVReopenState *reopen_state);
36
+ void GRAPH_UNLOCKED_PTR (*bdrv_reopen_abort)(
37
+ BDRVReopenState *reopen_state);
38
void (*bdrv_join_options)(QDict *options, QDict *old_options);
39
40
int GRAPH_UNLOCKED_PTR (*bdrv_open)(
41
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
44
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int bdrv_reset_options_allowed(BlockDriverState *bs,
46
/*
47
* Returns true if @child can be reached recursively from @bs
48
*/
49
-static bool bdrv_recurse_has_child(BlockDriverState *bs,
50
- BlockDriverState *child)
51
+static bool GRAPH_RDLOCK
52
+bdrv_recurse_has_child(BlockDriverState *bs, BlockDriverState *child)
53
{
54
BdrvChild *c;
55
56
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
57
*
58
* To be called with bs->aio_context locked.
59
*/
60
-static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
61
- BlockDriverState *bs,
62
- QDict *options,
63
- const BdrvChildClass *klass,
64
- BdrvChildRole role,
65
- bool parent_is_format,
66
- QDict *parent_options,
67
- int parent_flags,
68
- bool keep_old_opts)
69
+static BlockReopenQueue * GRAPH_RDLOCK
70
+bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, BlockDriverState *bs,
71
+ QDict *options, const BdrvChildClass *klass,
72
+ BdrvChildRole role, bool parent_is_format,
73
+ QDict *parent_options, int parent_flags,
74
+ bool keep_old_opts)
75
{
76
assert(bs != NULL);
77
78
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
79
80
GLOBAL_STATE_CODE();
81
82
+ /*
83
+ * Strictly speaking, draining is illegal under GRAPH_RDLOCK. We know that
84
+ * we've been called with bdrv_graph_rdlock_main_loop(), though, so it's ok
85
+ * in practice.
86
+ */
87
bdrv_drained_begin(bs);
88
89
if (bs_queue == NULL) {
90
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
91
QDict *options, bool keep_old_opts)
92
{
93
GLOBAL_STATE_CODE();
94
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
95
96
return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
97
NULL, 0, keep_old_opts);
98
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
99
* Callers must make sure that their AioContext locking is still correct after
100
* this.
101
*/
102
-static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
103
- bool is_backing, Transaction *tran,
104
- Error **errp)
105
+static int GRAPH_UNLOCKED
106
+bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
107
+ bool is_backing, Transaction *tran,
108
+ Error **errp)
109
{
110
BlockDriverState *bs = reopen_state->bs;
111
BlockDriverState *new_child_bs;
112
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
113
QObject *value;
114
const char *str;
115
AioContext *ctx, *old_ctx;
116
+ bool has_child;
117
int ret;
118
119
GLOBAL_STATE_CODE();
120
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
121
new_child_bs = bdrv_lookup_bs(NULL, str, errp);
122
if (new_child_bs == NULL) {
123
return -EINVAL;
124
- } else if (bdrv_recurse_has_child(new_child_bs, bs)) {
125
+ }
126
+
127
+ bdrv_graph_rdlock_main_loop();
128
+ has_child = bdrv_recurse_has_child(new_child_bs, bs);
129
+ bdrv_graph_rdunlock_main_loop();
130
+
131
+ if (has_child) {
132
error_setg(errp, "Making '%s' a %s child of '%s' would create a "
133
"cycle", str, child_name, bs->node_name);
134
return -EINVAL;
135
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
136
* After calling this function, the transaction @change_child_tran may only be
137
* completed while holding a writer lock for the graph.
138
*/
139
-static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
140
- BlockReopenQueue *queue,
141
- Transaction *change_child_tran, Error **errp)
142
+static int GRAPH_UNLOCKED
143
+bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
144
+ Transaction *change_child_tran, Error **errp)
145
{
146
int ret = -1;
147
int old_flags;
148
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
149
if (qdict_size(reopen_state->options)) {
150
const QDictEntry *entry = qdict_first(reopen_state->options);
151
152
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
153
+
154
do {
155
QObject *new = entry->value;
156
QObject *old = qdict_get(reopen_state->bs->options, entry->key);
157
@@ -XXX,XX +XXX,XX @@ error:
158
* makes them final by swapping the staging BlockDriverState contents into
159
* the active BlockDriverState contents.
160
*/
161
-static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
162
+static void GRAPH_UNLOCKED bdrv_reopen_commit(BDRVReopenState *reopen_state)
163
{
164
BlockDriver *drv;
165
BlockDriverState *bs;
166
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
167
drv->bdrv_reopen_commit(reopen_state);
168
}
169
170
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
171
+
172
/* set BDS specific flags now */
173
qobject_unref(bs->explicit_options);
174
qobject_unref(bs->options);
175
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
176
qdict_del(bs->explicit_options, "backing");
177
qdict_del(bs->options, "backing");
178
179
- bdrv_graph_rdlock_main_loop();
180
bdrv_refresh_limits(bs, NULL, NULL);
181
- bdrv_graph_rdunlock_main_loop();
182
bdrv_refresh_total_sectors(bs, bs->total_sectors);
20
}
183
}
21
184
22
-static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
185
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
23
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
186
* Abort the reopen, and delete and free the staged changes in
24
+static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
187
* reopen_state
25
+ bool want_zero,
188
*/
26
+ int64_t offset, int64_t bytes,
189
-static void bdrv_reopen_abort(BDRVReopenState *reopen_state)
27
+ int64_t *pnum, int64_t *map,
190
+static void GRAPH_UNLOCKED bdrv_reopen_abort(BDRVReopenState *reopen_state)
28
+ BlockDriverState **file)
29
{
191
{
30
BDRVVPCState *s = bs->opaque;
192
BlockDriver *drv;
31
VHDFooter *footer = (VHDFooter*) s->footer_buf;
32
- int64_t start, offset;
33
+ int64_t image_offset;
34
bool allocated;
35
- int64_t ret;
36
- int n;
37
+ int ret;
38
+ int64_t n;
39
40
if (be32_to_cpu(footer->type) == VHD_FIXED) {
41
- *pnum = nb_sectors;
42
+ *pnum = bytes;
43
+ *map = offset;
44
*file = bs->file->bs;
45
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
46
- (sector_num << BDRV_SECTOR_BITS);
47
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
48
}
49
50
qemu_co_mutex_lock(&s->lock);
51
52
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false, NULL);
53
- start = offset;
54
- allocated = (offset != -1);
55
+ image_offset = get_image_offset(bs, offset, false, NULL);
56
+ allocated = (image_offset != -1);
57
*pnum = 0;
58
ret = 0;
59
60
do {
61
/* All sectors in a block are contiguous (without using the bitmap) */
62
- n = ROUND_UP(sector_num + 1, s->block_size / BDRV_SECTOR_SIZE)
63
- - sector_num;
64
- n = MIN(n, nb_sectors);
65
+ n = ROUND_UP(offset + 1, s->block_size) - offset;
66
+ n = MIN(n, bytes);
67
68
*pnum += n;
69
- sector_num += n;
70
- nb_sectors -= n;
71
+ offset += n;
72
+ bytes -= n;
73
/* *pnum can't be greater than one block for allocated
74
* sectors since there is always a bitmap in between. */
75
if (allocated) {
76
*file = bs->file->bs;
77
- ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
78
+ *map = image_offset;
79
+ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
80
break;
81
}
82
- if (nb_sectors == 0) {
83
+ if (bytes == 0) {
84
break;
85
}
86
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false,
87
- NULL);
88
- } while (offset == -1);
89
+ image_offset = get_image_offset(bs, offset, false, NULL);
90
+ } while (image_offset == -1);
91
92
qemu_co_mutex_unlock(&s->lock);
93
return ret;
94
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
95
96
.bdrv_co_preadv = vpc_co_preadv,
97
.bdrv_co_pwritev = vpc_co_pwritev,
98
- .bdrv_co_get_block_status = vpc_co_get_block_status,
99
+ .bdrv_co_block_status = vpc_co_block_status,
100
101
.bdrv_get_info = vpc_get_info,
102
193
103
--
194
--
104
2.13.6
195
2.41.0
105
106
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
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.
2
4
3
qcow2_create2() calls qemu_co_mutex_lock(). Only a coroutine_fn may
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
call another coroutine_fn. In fact, qcow2_create2 is always called from
6
Message-ID: <20230929145157.45443-10-kwolf@redhat.com>
5
coroutine context.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
7
Rename the function to add the "co" moniker and add coroutine_fn.
8
9
Reported-by: Marc-André Lureau <marcandre.lureau@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20170705102231.20711-3-stefanha@redhat.com>
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
9
---
16
block/qcow2.c | 17 +++++++++--------
10
include/block/block-global-state.h | 2 +-
17
1 file changed, 9 insertions(+), 8 deletions(-)
11
blockdev.c | 2 ++
12
2 files changed, 3 insertions(+), 1 deletion(-)
18
13
19
diff --git a/block/qcow2.c b/block/qcow2.c
14
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
16
--- a/include/block/block-global-state.h
22
+++ b/block/qcow2.c
17
+++ b/include/block/block-global-state.h
23
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
18
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init_1(BlockDriverState *bs);
24
return refcount_bits;
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);
25
}
38
}
26
39
27
-static int qcow2_create2(const char *filename, int64_t total_size,
28
- const char *backing_file, const char *backing_format,
29
- int flags, size_t cluster_size, PreallocMode prealloc,
30
- QemuOpts *opts, int version, int refcount_order,
31
- const char *encryptfmt, Error **errp)
32
+static int coroutine_fn
33
+qcow2_co_create2(const char *filename, int64_t total_size,
34
+ const char *backing_file, const char *backing_format,
35
+ int flags, size_t cluster_size, PreallocMode prealloc,
36
+ QemuOpts *opts, int version, int refcount_order,
37
+ const char *encryptfmt, Error **errp)
38
{
39
QDict *options;
40
41
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
42
43
refcount_order = ctz32(refcount_bits);
44
45
- ret = qcow2_create2(filename, size, backing_file, backing_fmt, flags,
46
- cluster_size, prealloc, opts, version, refcount_order,
47
- encryptfmt, &local_err);
48
+ ret = qcow2_co_create2(filename, size, backing_file, backing_fmt, flags,
49
+ cluster_size, prealloc, opts, version, refcount_order,
50
+ encryptfmt, &local_err);
51
error_propagate(errp, local_err);
52
53
finish:
54
--
40
--
55
2.13.6
41
2.41.0
56
57
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_refresh_filename() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the raw driver accordingly.
6
Message-ID: <20230929145157.45443-11-kwolf@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@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 | 16 ++++++++--------
10
block/vhdx.h | 5 +--
12
1 file changed, 8 insertions(+), 8 deletions(-)
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 @@ fail:
293
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
294
BDRV_REQ_ZERO_WRITE;
295
296
if (bs->probed && !bdrv_is_read_only(bs)) {
297
+ bdrv_graph_rdlock_main_loop();
298
bdrv_refresh_filename(bs->file->bs);
299
+ bdrv_graph_rdunlock_main_loop();
300
fprintf(stderr,
301
"WARNING: Image format was not specified for '%s' and probing "
302
"guessed raw.\n"
303
diff --git a/block/vhdx.c b/block/vhdx.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/block/vhdx.c
306
+++ b/block/vhdx.c
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
308
uint64_t signature;
309
Error *local_err = NULL;
310
311
+ GLOBAL_STATE_CODE();
312
+
313
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
314
if (ret < 0) {
315
return ret;
316
}
317
318
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
319
+
320
s->bat = NULL;
321
s->first_visible_write = true;
322
323
diff --git a/block/vmdk.c b/block/vmdk.c
324
index XXXXXXX..XXXXXXX 100644
325
--- a/block/vmdk.c
326
+++ b/block/vmdk.c
327
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
328
return 0;
329
}
330
331
-static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
332
- Error **errp)
333
+static int GRAPH_RDLOCK
334
+vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, Error **errp)
335
{
336
int ret;
337
size_t l1_size;
338
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
19
return ret;
339
return ret;
20
}
340
}
21
341
22
-static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
342
-static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
23
- int64_t sector_num,
343
- BdrvChild *file,
24
- int nb_sectors, int *pnum,
344
- int flags, Error **errp)
25
+static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
345
+static int GRAPH_RDLOCK
26
+ bool want_zero, int64_t offset,
346
+vmdk_open_vmfs_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
27
+ int64_t bytes, int64_t *pnum,
347
+ Error **errp)
28
+ int64_t *map,
348
{
29
BlockDriverState **file)
349
int ret;
30
{
350
uint32_t magic;
31
BDRVRawState *s = bs->opaque;
351
@@ -XXX,XX +XXX,XX @@ static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
32
- *pnum = nb_sectors;
352
return 0;
33
+ *pnum = bytes;
353
}
34
*file = bs->file->bs;
354
35
- sector_num += s->offset / BDRV_SECTOR_SIZE;
355
-static int vmdk_open_se_sparse(BlockDriverState *bs,
36
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
356
- BdrvChild *file,
37
- (sector_num << BDRV_SECTOR_BITS);
357
- int flags, Error **errp)
38
+ *map = offset + s->offset;
358
+static int GRAPH_RDLOCK
39
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
359
+vmdk_open_se_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
40
}
360
+ Error **errp)
41
361
{
42
static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
362
int ret;
43
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
363
VMDKSESparseConstHeader const_header;
44
.bdrv_co_pwritev = &raw_co_pwritev,
364
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
45
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
365
return buf;
46
.bdrv_co_pdiscard = &raw_co_pdiscard,
366
}
47
- .bdrv_co_get_block_status = &raw_co_get_block_status,
367
48
+ .bdrv_co_block_status = &raw_co_block_status,
368
-static int vmdk_open_vmdk4(BlockDriverState *bs,
49
.bdrv_truncate = &raw_truncate,
369
- BdrvChild *file,
50
.bdrv_getlength = &raw_getlength,
370
- int flags, QDict *options, Error **errp)
51
.has_variable_length = true,
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 =
52
--
564
--
53
2.13.6
565
2.41.0
54
55
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
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.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the vvfat driver accordingly. Note that we
6
Message-ID: <20230929145157.45443-12-kwolf@redhat.com>
5
can rely on the block driver having already clamped limits to our
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
block size, and simplify accordingly.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block/vvfat.c | 16 +++++++---------
10
include/block/block_int-io.h | 5 +++--
14
1 file changed, 7 insertions(+), 9 deletions(-)
11
block.c | 11 ++++++++++-
12
block/snapshot.c | 3 +++
13
3 files changed, 16 insertions(+), 3 deletions(-)
15
14
16
diff --git a/block/vvfat.c b/block/vvfat.c
15
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vvfat.c
17
--- a/include/block/block_int-io.h
19
+++ b/block/vvfat.c
18
+++ b/include/block/block_int-io.h
20
@@ -XXX,XX +XXX,XX @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
19
@@ -XXX,XX +XXX,XX @@ bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
21
return ret;
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));
22
}
30
}
23
31
24
-static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
32
-static inline BlockDriverState *bdrv_primary_bs(BlockDriverState *bs)
25
- int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
33
+static inline BlockDriverState * GRAPH_RDLOCK
26
+static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
34
+bdrv_primary_bs(BlockDriverState *bs)
27
+ bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *n,
29
+ int64_t *map,
30
+ BlockDriverState **file)
31
{
35
{
32
- *n = bs->total_sectors - sector_num;
36
IO_CODE();
33
- if (*n > nb_sectors) {
37
return child_bs(bdrv_primary_child(bs));
34
- *n = nb_sectors;
38
diff --git a/block.c b/block.c
35
- } else if (*n < 0) {
39
index XXXXXXX..XXXXXXX 100644
36
- return 0;
40
--- a/block.c
37
- }
41
+++ b/block.c
38
+ *n = bytes;
42
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
39
return BDRV_BLOCK_DATA;
43
bs->drv->bdrv_co_debug_event(bs, event);
40
}
44
}
41
45
42
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
46
-static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
43
47
+static BlockDriverState * GRAPH_RDLOCK
44
.bdrv_co_preadv = vvfat_co_preadv,
48
+bdrv_find_debug_node(BlockDriverState *bs)
45
.bdrv_co_pwritev = vvfat_co_pwritev,
49
{
46
- .bdrv_co_get_block_status = vvfat_co_get_block_status,
50
GLOBAL_STATE_CODE();
47
+ .bdrv_co_block_status = vvfat_co_block_status,
51
while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
48
};
52
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
49
53
const char *tag)
50
static void bdrv_vvfat_init(void)
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
}
51
--
103
--
52
2.13.6
104
2.41.0
53
54
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_get_parent_name() need to hold a reader lock for the graph
3
because it accesses the parents list of a node.
2
4
3
BlockDriver->bdrv_create() has been called from coroutine context since
5
For some places, we know that they will hold the lock, but we don't have
4
commit 5b7e1542cfa41a281af9629d31cef03704d976e6 ("block: make
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
bdrv_create adopt coroutine").
7
with a FIXME comment. These places will be removed once everything is
8
properly annotated.
6
9
7
Make this explicit by renaming to .bdrv_co_create_opts() and add the
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
coroutine_fn annotation. This makes it obvious to block driver authors
11
Message-ID: <20230929145157.45443-13-kwolf@redhat.com>
9
that they may yield, use CoMutex, or other coroutine_fn APIs.
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
bdrv_co_create is reserved for the QAPI-based version that Kevin is
11
working on.
12
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20170705102231.20711-2-stefanha@redhat.com>
15
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
14
---
19
include/block/block_int.h | 3 ++-
15
block/qcow2.h | 7 +++----
20
block.c | 4 ++--
16
include/block/block-io.h | 8 ++++++--
21
block/crypto.c | 8 ++++----
17
include/block/block_int-io.h | 2 +-
22
block/file-posix.c | 15 ++++++++-------
18
include/block/qapi.h | 7 ++++---
23
block/file-win32.c | 5 +++--
19
block.c | 14 ++++++++++++--
24
block/gluster.c | 13 +++++++------
20
block/backup.c | 1 +
25
block/iscsi.c | 7 ++++---
21
block/parallels.c | 3 +++
26
block/nfs.c | 5 +++--
22
block/qcow.c | 3 +++
27
block/parallels.c | 6 ++++--
23
block/qcow2-bitmap.c | 2 ++
28
block/qcow.c | 5 +++--
24
block/qcow2.c | 4 ++++
29
block/qcow2.c | 5 +++--
25
block/quorum.c | 4 ++--
30
block/qed.c | 6 ++++--
26
block/rbd.c | 2 ++
31
block/raw-format.c | 5 +++--
27
block/snapshot.c | 3 +++
32
block/rbd.c | 6 ++++--
28
block/vdi.c | 3 +++
33
block/sheepdog.c | 10 +++++-----
29
block/vpc.c | 3 +++
34
block/ssh.c | 5 +++--
30
block/vvfat.c | 2 ++
35
block/vdi.c | 5 +++--
31
blockjob.c | 1 +
36
block/vhdx.c | 5 +++--
32
17 files changed, 55 insertions(+), 14 deletions(-)
37
block/vmdk.c | 5 +++--
38
block/vpc.c | 5 +++--
39
20 files changed, 74 insertions(+), 54 deletions(-)
40
33
41
diff --git a/include/block/block_int.h b/include/block/block_int.h
34
diff --git a/block/qcow2.h b/block/qcow2.h
42
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block_int.h
36
--- a/block/qcow2.h
44
+++ b/include/block/block_int.h
37
+++ b/block/qcow2.h
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp
46
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
39
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
47
Error **errp);
40
bool release_stored, Error **errp);
48
void (*bdrv_close)(BlockDriverState *bs);
41
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
49
- int (*bdrv_create)(const char *filename, QemuOpts *opts, Error **errp);
42
-bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
50
+ int coroutine_fn (*bdrv_co_create_opts)(const char *filename, QemuOpts *opts,
43
- const char *name,
51
+ Error **errp);
44
- uint32_t granularity,
52
int (*bdrv_make_empty)(BlockDriverState *bs);
45
- Error **errp);
53
46
+bool coroutine_fn GRAPH_RDLOCK
54
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
47
+qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
48
+ uint32_t granularity, Error **errp);
49
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
50
const char *name,
51
Error **errp);
52
diff --git a/include/block/block-io.h b/include/block/block-io.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/include/block/block-io.h
55
+++ b/include/block/block-io.h
56
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_format_name(BlockDriverState *bs);
57
58
bool bdrv_supports_compressed_writes(BlockDriverState *bs);
59
const char *bdrv_get_node_name(const BlockDriverState *bs);
60
-const char *bdrv_get_device_name(const BlockDriverState *bs);
61
-const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
62
+
63
+const char * GRAPH_RDLOCK
64
+bdrv_get_device_name(const BlockDriverState *bs);
65
+
66
+const char * GRAPH_RDLOCK
67
+bdrv_get_device_or_node_name(const BlockDriverState *bs);
68
69
int coroutine_fn GRAPH_RDLOCK
70
bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
71
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-io.h
74
+++ b/include/block/block_int-io.h
75
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
76
*/
77
void bdrv_wakeup(BlockDriverState *bs);
78
79
-const char *bdrv_get_parent_name(const BlockDriverState *bs);
80
+const char * GRAPH_RDLOCK bdrv_get_parent_name(const BlockDriverState *bs);
81
bool blk_dev_has_tray(BlockBackend *blk);
82
bool blk_dev_is_tray_open(BlockBackend *blk);
83
84
diff --git a/include/block/qapi.h b/include/block/qapi.h
85
index XXXXXXX..XXXXXXX 100644
86
--- a/include/block/qapi.h
87
+++ b/include/block/qapi.h
88
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo * GRAPH_RDLOCK
89
bdrv_block_device_info(BlockBackend *blk, BlockDriverState *bs,
90
bool flat, Error **errp);
91
92
-int bdrv_query_snapshot_info_list(BlockDriverState *bs,
93
- SnapshotInfoList **p_list,
94
- Error **errp);
95
+int GRAPH_RDLOCK
96
+bdrv_query_snapshot_info_list(BlockDriverState *bs,
97
+ SnapshotInfoList **p_list,
98
+ Error **errp);
99
void GRAPH_RDLOCK
100
bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
101
bool skip_implicit_filters, Error **errp);
55
diff --git a/block.c b/block.c
102
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
104
--- a/block.c
58
+++ b/block.c
105
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
106
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
60
CreateCo *cco = opaque;
107
return !(bs->open_flags & BDRV_O_RDWR);
61
assert(cco->drv);
62
63
- ret = cco->drv->bdrv_create(cco->filename, cco->opts, &local_err);
64
+ ret = cco->drv->bdrv_co_create_opts(cco->filename, cco->opts, &local_err);
65
error_propagate(&cco->err, local_err);
66
cco->ret = ret;
67
}
108
}
68
@@ -XXX,XX +XXX,XX @@ int bdrv_create(BlockDriver *drv, const char* filename,
109
69
.err = NULL,
110
-static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
70
};
111
- bool ignore_allow_rdw, Error **errp)
71
112
+static int GRAPH_RDLOCK
72
- if (!drv->bdrv_create) {
113
+bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
73
+ if (!drv->bdrv_co_create_opts) {
114
+ bool ignore_allow_rdw, Error **errp)
74
error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
75
ret = -ENOTSUP;
76
goto out;
77
diff --git a/block/crypto.c b/block/crypto.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/crypto.c
80
+++ b/block/crypto.c
81
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_luks(BlockDriverState *bs,
82
bs, options, flags, errp);
83
}
84
85
-static int block_crypto_create_luks(const char *filename,
86
- QemuOpts *opts,
87
- Error **errp)
88
+static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
89
+ QemuOpts *opts,
90
+ Error **errp)
91
{
115
{
92
return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
116
IO_CODE();
93
filename, opts, errp);
117
94
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
118
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
95
.bdrv_open = block_crypto_open_luks,
119
int ret = 0;
96
.bdrv_close = block_crypto_close,
120
IO_CODE();
97
.bdrv_child_perm = bdrv_format_default_perms,
121
98
- .bdrv_create = block_crypto_create_luks,
122
+ assume_graph_lock(); /* FIXME */
99
+ .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
123
+
100
.bdrv_truncate = block_crypto_truncate,
124
if (!(bs->open_flags & BDRV_O_RDWR)) {
101
.create_opts = &block_crypto_create_opts_luks,
125
return 0;
102
126
}
103
diff --git a/block/file-posix.c b/block/file-posix.c
127
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
104
index XXXXXXX..XXXXXXX 100644
128
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
105
--- a/block/file-posix.c
129
* not set, or if the BDS still has copy_on_read enabled */
106
+++ b/block/file-posix.c
130
read_only = !(reopen_state->flags & BDRV_O_RDWR);
107
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
131
+
108
return (int64_t)st.st_blocks * 512;
132
+ bdrv_graph_rdlock_main_loop();
109
}
133
ret = bdrv_can_set_read_only(reopen_state->bs, read_only, true, &local_err);
110
134
+ bdrv_graph_rdunlock_main_loop();
111
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
135
if (local_err) {
112
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
136
error_propagate(errp, local_err);
113
+ Error **errp)
137
goto error;
138
@@ -XXX,XX +XXX,XX @@ bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
139
} else {
140
/* It is currently mandatory to have a bdrv_reopen_prepare()
141
* handler for each supported drv. */
142
+ bdrv_graph_rdlock_main_loop();
143
error_setg(errp, "Block format '%s' used by node '%s' "
144
"does not support reopening files", drv->format_name,
145
bdrv_get_device_or_node_name(reopen_state->bs));
146
+ bdrv_graph_rdunlock_main_loop();
147
ret = -1;
148
goto error;
149
}
150
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
114
{
151
{
115
int fd;
152
BdrvOpBlocker *blocker;
116
int result = 0;
153
GLOBAL_STATE_CODE();
117
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
154
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
118
.bdrv_reopen_commit = raw_reopen_commit,
155
+
119
.bdrv_reopen_abort = raw_reopen_abort,
156
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
120
.bdrv_close = raw_close,
157
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
121
- .bdrv_create = raw_create,
158
blocker = QLIST_FIRST(&bs->op_blockers[op]);
122
+ .bdrv_co_create_opts = raw_co_create_opts,
159
diff --git a/block/backup.c b/block/backup.c
123
.bdrv_has_zero_init = bdrv_has_zero_init_1,
160
index XXXXXXX..XXXXXXX 100644
124
.bdrv_co_block_status = raw_co_block_status,
161
--- a/block/backup.c
125
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
162
+++ b/block/backup.c
126
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
163
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
127
return -ENOTSUP;
164
assert(bs);
128
}
165
assert(target);
129
166
GLOBAL_STATE_CODE();
130
-static int hdev_create(const char *filename, QemuOpts *opts,
167
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
131
- Error **errp)
168
132
+static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
169
/* QMP interface protects us from these cases */
133
+ Error **errp)
170
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
134
{
135
int fd;
136
int ret = 0;
137
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
138
.bdrv_reopen_prepare = raw_reopen_prepare,
139
.bdrv_reopen_commit = raw_reopen_commit,
140
.bdrv_reopen_abort = raw_reopen_abort,
141
- .bdrv_create = hdev_create,
142
+ .bdrv_co_create_opts = hdev_co_create_opts,
143
.create_opts = &raw_create_opts,
144
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
145
146
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
147
.bdrv_reopen_prepare = raw_reopen_prepare,
148
.bdrv_reopen_commit = raw_reopen_commit,
149
.bdrv_reopen_abort = raw_reopen_abort,
150
- .bdrv_create = hdev_create,
151
+ .bdrv_co_create_opts = hdev_co_create_opts,
152
.create_opts = &raw_create_opts,
153
154
155
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
156
.bdrv_reopen_prepare = raw_reopen_prepare,
157
.bdrv_reopen_commit = raw_reopen_commit,
158
.bdrv_reopen_abort = raw_reopen_abort,
159
- .bdrv_create = hdev_create,
160
+ .bdrv_co_create_opts = hdev_co_create_opts,
161
.create_opts = &raw_create_opts,
162
163
.bdrv_co_preadv = raw_co_preadv,
164
diff --git a/block/file-win32.c b/block/file-win32.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/file-win32.c
167
+++ b/block/file-win32.c
168
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
169
return st.st_size;
170
}
171
172
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
173
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
174
+ Error **errp)
175
{
176
int fd;
177
int64_t total_size = 0;
178
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
179
.bdrv_file_open = raw_open,
180
.bdrv_refresh_limits = raw_probe_alignment,
181
.bdrv_close = raw_close,
182
- .bdrv_create = raw_create,
183
+ .bdrv_co_create_opts = raw_co_create_opts,
184
.bdrv_has_zero_init = bdrv_has_zero_init_1,
185
186
.bdrv_aio_readv = raw_aio_readv,
187
diff --git a/block/gluster.c b/block/gluster.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/block/gluster.c
190
+++ b/block/gluster.c
191
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
192
return 0;
193
}
194
195
-static int qemu_gluster_create(const char *filename,
196
- QemuOpts *opts, Error **errp)
197
+static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
198
+ QemuOpts *opts,
199
+ Error **errp)
200
{
201
BlockdevOptionsGluster *gconf;
202
struct glfs *glfs;
203
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
204
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
205
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
206
.bdrv_close = qemu_gluster_close,
207
- .bdrv_create = qemu_gluster_create,
208
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
209
.bdrv_getlength = qemu_gluster_getlength,
210
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
211
.bdrv_truncate = qemu_gluster_truncate,
212
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
213
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
214
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
215
.bdrv_close = qemu_gluster_close,
216
- .bdrv_create = qemu_gluster_create,
217
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
218
.bdrv_getlength = qemu_gluster_getlength,
219
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
220
.bdrv_truncate = qemu_gluster_truncate,
221
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
222
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
223
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
224
.bdrv_close = qemu_gluster_close,
225
- .bdrv_create = qemu_gluster_create,
226
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
227
.bdrv_getlength = qemu_gluster_getlength,
228
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
229
.bdrv_truncate = qemu_gluster_truncate,
230
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
231
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
232
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
233
.bdrv_close = qemu_gluster_close,
234
- .bdrv_create = qemu_gluster_create,
235
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
236
.bdrv_getlength = qemu_gluster_getlength,
237
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
238
.bdrv_truncate = qemu_gluster_truncate,
239
diff --git a/block/iscsi.c b/block/iscsi.c
240
index XXXXXXX..XXXXXXX 100644
241
--- a/block/iscsi.c
242
+++ b/block/iscsi.c
243
@@ -XXX,XX +XXX,XX @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
244
return 0;
245
}
246
247
-static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
248
+static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts,
249
+ Error **errp)
250
{
251
int ret = 0;
252
int64_t total_size = 0;
253
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
254
.bdrv_parse_filename = iscsi_parse_filename,
255
.bdrv_file_open = iscsi_open,
256
.bdrv_close = iscsi_close,
257
- .bdrv_create = iscsi_create,
258
+ .bdrv_co_create_opts = iscsi_co_create_opts,
259
.create_opts = &iscsi_create_opts,
260
.bdrv_reopen_prepare = iscsi_reopen_prepare,
261
.bdrv_reopen_commit = iscsi_reopen_commit,
262
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
263
.bdrv_parse_filename = iscsi_parse_filename,
264
.bdrv_file_open = iscsi_open,
265
.bdrv_close = iscsi_close,
266
- .bdrv_create = iscsi_create,
267
+ .bdrv_co_create_opts = iscsi_co_create_opts,
268
.create_opts = &iscsi_create_opts,
269
.bdrv_reopen_prepare = iscsi_reopen_prepare,
270
.bdrv_reopen_commit = iscsi_reopen_commit,
271
diff --git a/block/nfs.c b/block/nfs.c
272
index XXXXXXX..XXXXXXX 100644
273
--- a/block/nfs.c
274
+++ b/block/nfs.c
275
@@ -XXX,XX +XXX,XX @@ static QemuOptsList nfs_create_opts = {
276
}
277
};
278
279
-static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
280
+static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
281
+ Error **errp)
282
{
283
int64_t ret, total_size;
284
NFSClient *client = g_new0(NFSClient, 1);
285
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
286
287
.bdrv_file_open = nfs_file_open,
288
.bdrv_close = nfs_file_close,
289
- .bdrv_create = nfs_file_create,
290
+ .bdrv_co_create_opts = nfs_file_co_create_opts,
291
.bdrv_reopen_prepare = nfs_reopen_prepare,
292
293
.bdrv_co_preadv = nfs_co_preadv,
294
diff --git a/block/parallels.c b/block/parallels.c
171
diff --git a/block/parallels.c b/block/parallels.c
295
index XXXXXXX..XXXXXXX 100644
172
index XXXXXXX..XXXXXXX 100644
296
--- a/block/parallels.c
173
--- a/block/parallels.c
297
+++ b/block/parallels.c
174
+++ b/block/parallels.c
298
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
175
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
299
}
176
bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
300
177
301
178
/* Disable migration until bdrv_activate method is added */
302
-static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
179
+ bdrv_graph_rdlock_main_loop();
303
+static int coroutine_fn parallels_co_create_opts(const char *filename,
180
error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
304
+ QemuOpts *opts,
181
"does not support live migration",
305
+ Error **errp)
182
bdrv_get_device_or_node_name(bs));
306
{
183
+ bdrv_graph_rdunlock_main_loop();
307
int64_t total_size, cl_size;
184
+
308
uint8_t tmp[BDRV_SECTOR_SIZE];
185
ret = migrate_add_blocker(s->migration_blocker, errp);
309
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
186
if (ret < 0) {
310
.bdrv_co_readv = parallels_co_readv,
187
error_setg(errp, "Migration blocker error");
311
.bdrv_co_writev = parallels_co_writev,
312
.supports_backing = true,
313
- .bdrv_create = parallels_create,
314
+ .bdrv_co_create_opts = parallels_co_create_opts,
315
.bdrv_check = parallels_check,
316
.create_opts = &parallels_create_opts,
317
};
318
diff --git a/block/qcow.c b/block/qcow.c
188
diff --git a/block/qcow.c b/block/qcow.c
319
index XXXXXXX..XXXXXXX 100644
189
index XXXXXXX..XXXXXXX 100644
320
--- a/block/qcow.c
190
--- a/block/qcow.c
321
+++ b/block/qcow.c
191
+++ b/block/qcow.c
322
@@ -XXX,XX +XXX,XX @@ static void qcow_close(BlockDriverState *bs)
192
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
323
error_free(s->migration_blocker);
193
}
324
}
194
325
195
/* Disable migration when qcow images are used */
326
-static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
196
+ bdrv_graph_rdlock_main_loop();
327
+static int coroutine_fn qcow_co_create_opts(const char *filename, QemuOpts *opts,
197
error_setg(&s->migration_blocker, "The qcow format used by node '%s' "
328
+ Error **errp)
198
"does not support live migration",
329
{
199
bdrv_get_device_or_node_name(bs));
330
int header_size, backing_filename_len, l1_size, shift, i;
200
+ bdrv_graph_rdunlock_main_loop();
331
QCowHeader header;
201
+
332
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
202
ret = migrate_add_blocker(s->migration_blocker, errp);
333
.bdrv_close        = qcow_close,
203
if (ret < 0) {
334
.bdrv_child_perm = bdrv_format_default_perms,
204
error_free(s->migration_blocker);
335
.bdrv_reopen_prepare = qcow_reopen_prepare,
205
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
336
- .bdrv_create = qcow_create,
206
index XXXXXXX..XXXXXXX 100644
337
+ .bdrv_co_create_opts = qcow_co_create_opts,
207
--- a/block/qcow2-bitmap.c
338
.bdrv_has_zero_init = bdrv_has_zero_init_1,
208
+++ b/block/qcow2-bitmap.c
339
.supports_backing = true,
209
@@ -XXX,XX +XXX,XX @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
210
int64_t len = bdrv_getlength(bs);
211
int64_t bitmap_bytes;
212
213
+ assume_graph_lock(); /* FIXME */
214
+
215
assert(granularity > 0);
216
assert((granularity & (granularity - 1)) == 0);
340
217
341
diff --git a/block/qcow2.c b/block/qcow2.c
218
diff --git a/block/qcow2.c b/block/qcow2.c
342
index XXXXXXX..XXXXXXX 100644
219
index XXXXXXX..XXXXXXX 100644
343
--- a/block/qcow2.c
220
--- a/block/qcow2.c
344
+++ b/block/qcow2.c
221
+++ b/block/qcow2.c
345
@@ -XXX,XX +XXX,XX @@ out:
222
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
346
return ret;
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);
347
}
246
}
348
247
349
-static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
248
-static void quorum_report_failure(QuorumAIOCB *acb)
350
+static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opts,
249
+static void GRAPH_RDLOCK quorum_report_failure(QuorumAIOCB *acb)
351
+ Error **errp)
352
{
250
{
353
char *backing_file = NULL;
251
const char *reference = bdrv_get_device_or_node_name(acb->bs);
354
char *backing_fmt = NULL;
252
int64_t start_sector = acb->offset / BDRV_SECTOR_SIZE;
355
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
253
@@ -XXX,XX +XXX,XX @@ static void quorum_report_failure(QuorumAIOCB *acb)
356
.bdrv_reopen_abort = qcow2_reopen_abort,
254
357
.bdrv_join_options = qcow2_join_options,
255
static int quorum_vote_error(QuorumAIOCB *acb);
358
.bdrv_child_perm = bdrv_format_default_perms,
256
359
- .bdrv_create = qcow2_create,
257
-static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
360
+ .bdrv_co_create_opts = qcow2_co_create_opts,
258
+static bool GRAPH_RDLOCK quorum_has_too_much_io_failed(QuorumAIOCB *acb)
361
.bdrv_has_zero_init = bdrv_has_zero_init_1,
362
.bdrv_co_block_status = qcow2_co_block_status,
363
364
diff --git a/block/qed.c b/block/qed.c
365
index XXXXXXX..XXXXXXX 100644
366
--- a/block/qed.c
367
+++ b/block/qed.c
368
@@ -XXX,XX +XXX,XX @@ out:
369
return ret;
370
}
371
372
-static int bdrv_qed_create(const char *filename, QemuOpts *opts, Error **errp)
373
+static int coroutine_fn bdrv_qed_co_create_opts(const char *filename,
374
+ QemuOpts *opts,
375
+ Error **errp)
376
{
259
{
377
uint64_t image_size = 0;
260
BDRVQuorumState *s = acb->bs->opaque;
378
uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE;
261
379
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
380
.bdrv_close = bdrv_qed_close,
381
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
382
.bdrv_child_perm = bdrv_format_default_perms,
383
- .bdrv_create = bdrv_qed_create,
384
+ .bdrv_co_create_opts = bdrv_qed_co_create_opts,
385
.bdrv_has_zero_init = bdrv_has_zero_init_1,
386
.bdrv_co_block_status = bdrv_qed_co_block_status,
387
.bdrv_co_readv = bdrv_qed_co_readv,
388
diff --git a/block/raw-format.c b/block/raw-format.c
389
index XXXXXXX..XXXXXXX 100644
390
--- a/block/raw-format.c
391
+++ b/block/raw-format.c
392
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
393
return bdrv_has_zero_init(bs->file->bs);
394
}
395
396
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
397
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
398
+ Error **errp)
399
{
400
return bdrv_create_file(filename, opts, errp);
401
}
402
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
403
.bdrv_open = &raw_open,
404
.bdrv_close = &raw_close,
405
.bdrv_child_perm = bdrv_filter_default_perms,
406
- .bdrv_create = &raw_create,
407
+ .bdrv_co_create_opts = &raw_co_create_opts,
408
.bdrv_co_preadv = &raw_co_preadv,
409
.bdrv_co_pwritev = &raw_co_pwritev,
410
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
411
diff --git a/block/rbd.c b/block/rbd.c
262
diff --git a/block/rbd.c b/block/rbd.c
412
index XXXXXXX..XXXXXXX 100644
263
index XXXXXXX..XXXXXXX 100644
413
--- a/block/rbd.c
264
--- a/block/rbd.c
414
+++ b/block/rbd.c
265
+++ b/block/rbd.c
415
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
266
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
416
},
267
BDRVRBDState *s = state->bs->opaque;
417
};
418
419
-static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
420
+static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
421
+ QemuOpts *opts,
422
+ Error **errp)
423
{
424
Error *local_err = NULL;
425
int64_t bytes = 0;
426
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
427
.bdrv_file_open = qemu_rbd_open,
428
.bdrv_close = qemu_rbd_close,
429
.bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
430
- .bdrv_create = qemu_rbd_create,
431
+ .bdrv_co_create_opts = qemu_rbd_co_create_opts,
432
.bdrv_has_zero_init = bdrv_has_zero_init_1,
433
.bdrv_get_info = qemu_rbd_getinfo,
434
.create_opts = &qemu_rbd_create_opts,
435
diff --git a/block/sheepdog.c b/block/sheepdog.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/block/sheepdog.c
438
+++ b/block/sheepdog.c
439
@@ -XXX,XX +XXX,XX @@ static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
440
return 0;
441
}
442
443
-static int sd_create(const char *filename, QemuOpts *opts,
444
- Error **errp)
445
+static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
446
+ Error **errp)
447
{
448
Error *err = NULL;
449
int ret = 0;
268
int ret = 0;
450
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
269
451
.bdrv_reopen_commit = sd_reopen_commit,
270
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
452
.bdrv_reopen_abort = sd_reopen_abort,
271
+
453
.bdrv_close = sd_close,
272
if (s->snap && state->flags & BDRV_O_RDWR) {
454
- .bdrv_create = sd_create,
273
error_setg(errp,
455
+ .bdrv_co_create_opts = sd_co_create_opts,
274
"Cannot change node '%s' to r/w when using RBD snapshot",
456
.bdrv_has_zero_init = bdrv_has_zero_init_1,
275
diff --git a/block/snapshot.c b/block/snapshot.c
457
.bdrv_getlength = sd_getlength,
276
index XXXXXXX..XXXXXXX 100644
458
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
277
--- a/block/snapshot.c
459
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
278
+++ b/block/snapshot.c
460
.bdrv_reopen_commit = sd_reopen_commit,
279
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
461
.bdrv_reopen_abort = sd_reopen_abort,
280
BlockDriver *drv = bs->drv;
462
.bdrv_close = sd_close,
281
463
- .bdrv_create = sd_create,
282
GLOBAL_STATE_CODE();
464
+ .bdrv_co_create_opts = sd_co_create_opts,
283
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
465
.bdrv_has_zero_init = bdrv_has_zero_init_1,
284
466
.bdrv_getlength = sd_getlength,
285
if (!drv) {
467
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
286
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
468
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
287
@@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name,
469
.bdrv_reopen_commit = sd_reopen_commit,
288
}
470
.bdrv_reopen_abort = sd_reopen_abort,
289
aio_context_release(ctx);
471
.bdrv_close = sd_close,
290
if (ret < 0) {
472
- .bdrv_create = sd_create,
291
+ bdrv_graph_rdlock_main_loop();
473
+ .bdrv_co_create_opts = sd_co_create_opts,
292
error_prepend(errp, "Could not load snapshot '%s' on '%s': ",
474
.bdrv_has_zero_init = bdrv_has_zero_init_1,
293
name, bdrv_get_device_or_node_name(bs));
475
.bdrv_getlength = sd_getlength,
294
+ bdrv_graph_rdunlock_main_loop();
476
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
295
return -1;
477
diff --git a/block/ssh.c b/block/ssh.c
296
}
478
index XXXXXXX..XXXXXXX 100644
297
479
--- a/block/ssh.c
480
+++ b/block/ssh.c
481
@@ -XXX,XX +XXX,XX @@ static QemuOptsList ssh_create_opts = {
482
}
483
};
484
485
-static int ssh_create(const char *filename, QemuOpts *opts, Error **errp)
486
+static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
487
+ Error **errp)
488
{
489
int r, ret;
490
int64_t total_size = 0;
491
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
492
.instance_size = sizeof(BDRVSSHState),
493
.bdrv_parse_filename = ssh_parse_filename,
494
.bdrv_file_open = ssh_file_open,
495
- .bdrv_create = ssh_create,
496
+ .bdrv_co_create_opts = ssh_co_create_opts,
497
.bdrv_close = ssh_close,
498
.bdrv_has_zero_init = ssh_has_zero_init,
499
.bdrv_co_readv = ssh_co_readv,
500
diff --git a/block/vdi.c b/block/vdi.c
298
diff --git a/block/vdi.c b/block/vdi.c
501
index XXXXXXX..XXXXXXX 100644
299
index XXXXXXX..XXXXXXX 100644
502
--- a/block/vdi.c
300
--- a/block/vdi.c
503
+++ b/block/vdi.c
301
+++ b/block/vdi.c
504
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
302
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
505
return ret;
303
}
506
}
304
507
305
/* Disable migration when vdi images are used */
508
-static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
306
+ bdrv_graph_rdlock_main_loop();
509
+static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
307
error_setg(&s->migration_blocker, "The vdi format used by node '%s' "
510
+ Error **errp)
308
"does not support live migration",
511
{
309
bdrv_get_device_or_node_name(bs));
512
int ret = 0;
310
+ bdrv_graph_rdunlock_main_loop();
513
uint64_t bytes = 0;
311
+
514
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
312
ret = migrate_add_blocker(s->migration_blocker, errp);
515
.bdrv_close = vdi_close,
313
if (ret < 0) {
516
.bdrv_reopen_prepare = vdi_reopen_prepare,
314
error_free(s->migration_blocker);
517
.bdrv_child_perm = bdrv_format_default_perms,
518
- .bdrv_create = vdi_create,
519
+ .bdrv_co_create_opts = vdi_co_create_opts,
520
.bdrv_has_zero_init = bdrv_has_zero_init_1,
521
.bdrv_co_block_status = vdi_co_block_status,
522
.bdrv_make_empty = vdi_make_empty,
523
diff --git a/block/vhdx.c b/block/vhdx.c
524
index XXXXXXX..XXXXXXX 100644
525
--- a/block/vhdx.c
526
+++ b/block/vhdx.c
527
@@ -XXX,XX +XXX,XX @@ exit:
528
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
529
* 1MB
530
*/
531
-static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
532
+static int coroutine_fn vhdx_co_create_opts(const char *filename, QemuOpts *opts,
533
+ Error **errp)
534
{
535
int ret = 0;
536
uint64_t image_size = (uint64_t) 2 * GiB;
537
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
538
.bdrv_child_perm = bdrv_format_default_perms,
539
.bdrv_co_readv = vhdx_co_readv,
540
.bdrv_co_writev = vhdx_co_writev,
541
- .bdrv_create = vhdx_create,
542
+ .bdrv_co_create_opts = vhdx_co_create_opts,
543
.bdrv_get_info = vhdx_get_info,
544
.bdrv_check = vhdx_check,
545
.bdrv_has_zero_init = bdrv_has_zero_init_1,
546
diff --git a/block/vmdk.c b/block/vmdk.c
547
index XXXXXXX..XXXXXXX 100644
548
--- a/block/vmdk.c
549
+++ b/block/vmdk.c
550
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
551
return VMDK_OK;
552
}
553
554
-static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
555
+static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts,
556
+ Error **errp)
557
{
558
int idx = 0;
559
BlockBackend *new_blk = NULL;
560
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
561
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
562
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
563
.bdrv_close = vmdk_close,
564
- .bdrv_create = vmdk_create,
565
+ .bdrv_co_create_opts = vmdk_co_create_opts,
566
.bdrv_co_flush_to_disk = vmdk_co_flush,
567
.bdrv_co_block_status = vmdk_co_block_status,
568
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
569
diff --git a/block/vpc.c b/block/vpc.c
315
diff --git a/block/vpc.c b/block/vpc.c
570
index XXXXXXX..XXXXXXX 100644
316
index XXXXXXX..XXXXXXX 100644
571
--- a/block/vpc.c
317
--- a/block/vpc.c
572
+++ b/block/vpc.c
318
+++ b/block/vpc.c
573
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
319
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
574
return ret;
320
}
575
}
321
576
322
/* Disable migration when VHD images are used */
577
-static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
323
+ bdrv_graph_rdlock_main_loop();
578
+static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts,
324
error_setg(&s->migration_blocker, "The vpc format used by node '%s' "
579
+ Error **errp)
325
"does not support live migration",
580
{
326
bdrv_get_device_or_node_name(bs));
581
uint8_t buf[1024];
327
+ bdrv_graph_rdunlock_main_loop();
582
VHDFooter *footer = (VHDFooter *) buf;
328
+
583
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
329
ret = migrate_add_blocker(s->migration_blocker, errp);
584
.bdrv_close = vpc_close,
330
if (ret < 0) {
585
.bdrv_reopen_prepare = vpc_reopen_prepare,
331
error_free(s->migration_blocker);
586
.bdrv_child_perm = bdrv_format_default_perms,
332
diff --git a/block/vvfat.c b/block/vvfat.c
587
- .bdrv_create = vpc_create,
333
index XXXXXXX..XXXXXXX 100644
588
+ .bdrv_co_create_opts = vpc_co_create_opts,
334
--- a/block/vvfat.c
589
335
+++ b/block/vvfat.c
590
.bdrv_co_preadv = vpc_co_preadv,
336
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
591
.bdrv_co_pwritev = vpc_co_pwritev,
337
QemuOpts *opts;
338
int ret;
339
340
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
341
+
342
#ifdef DEBUG
343
vvv = s;
344
#endif
345
diff --git a/blockjob.c b/blockjob.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/blockjob.c
348
+++ b/blockjob.c
349
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
350
BlockJob *job;
351
int ret;
352
GLOBAL_STATE_CODE();
353
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
354
355
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
356
job_id = bdrv_get_device_name(bs);
592
--
357
--
593
2.13.6
358
2.41.0
594
595
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_amend_options() need to hold a reader lock for the graph. This
3
removes an assume_graph_lock() call in crypto's implementation.
2
4
3
The issue:
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(-)
4
15
5
$ qemu-img resize -f qcow2 foo.qcow2
16
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
6
qemu-img: Expecting one image file name
17
index XXXXXXX..XXXXXXX 100644
7
Try 'qemu-img --help' for more information
18
--- a/include/block/block-global-state.h
8
19
+++ b/include/block/block-global-state.h
9
So we gave an image file name, but we omitted the length. qemu-img
20
@@ -XXX,XX +XXX,XX @@ void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
10
thinks the last argument is always the size and removes it immediately
21
*/
11
from argv (by decrementing argc), and tries to verify that it is a valid
22
typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset,
12
size only at a later point.
23
int64_t total_work_size, void *opaque);
13
24
-int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
14
So we do not actually know whether that last argument we called "size"
25
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
15
is indeed a size or whether the user instead forgot to specify that size
26
- bool force,
16
but did give a file name.
27
- Error **errp);
17
28
+int GRAPH_RDLOCK
18
Therefore, the error message should be more general.
29
+bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
19
30
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
20
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1523458
31
+ bool force, Error **errp);
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
32
22
Message-id: 20180205162745.23650-1-mreitz@redhat.com
33
/* check if a named node can be replaced when doing drive-mirror */
23
Reviewed-by: John Snow <jsnow@redhat.com>
34
BlockDriverState * GRAPH_RDLOCK
24
Reviewed-by: Eric Blake <eblake@redhat.com>
35
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
36
index XXXXXXX..XXXXXXX 100644
26
---
37
--- a/include/block/block_int-common.h
27
qemu-img.c | 2 +-
38
+++ b/include/block/block_int-common.h
28
1 file changed, 1 insertion(+), 1 deletion(-)
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
29
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
30
diff --git a/qemu-img.c b/qemu-img.c
78
diff --git a/qemu-img.c b/qemu-img.c
31
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
32
--- a/qemu-img.c
80
--- a/qemu-img.c
33
+++ b/qemu-img.c
81
+++ b/qemu-img.c
34
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
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");
35
}
105
}
36
}
106
37
if (optind != argc - 1) {
107
+ bdrv_graph_rdunlock_main_loop();
38
- error_exit("Expecting one image file name");
108
error_report_err(err);
39
+ error_exit("Expecting image file name and size");
109
ret = -1;
40
}
110
goto out;
41
filename = argv[optind++];
111
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
42
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;
43
--
120
--
44
2.13.6
121
2.41.0
45
46
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
qcow2_signal_corruption() need to hold a reader lock for the graph
3
because it calls bdrv_get_node_name(), which accesses the parents list
4
of a node.
2
5
3
The align_offset() function is equivalent to the ROUND_UP() macro so
6
For some places, we know that they will hold the lock, but we don't have
4
there's no need to use the former. The ROUND_UP() name is also a bit
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
more explicit.
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
6
10
7
This patch uses ROUND_UP() instead of the slower QEMU_ALIGN_UP()
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
because align_offset() already requires that the second parameter is a
12
Message-ID: <20230929145157.45443-15-kwolf@redhat.com>
9
power of two.
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20180215131008.5153-1-berto@igalia.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
15
---
17
block/qcow2.h | 6 ------
16
block/qcow2.h | 180 +++++++++++++++++------------
18
block/qcow2-bitmap.c | 4 ++--
17
include/block/block-global-state.h | 2 +-
19
block/qcow2-cluster.c | 4 ++--
18
include/block/block_int-common.h | 2 +-
20
block/qcow2-refcount.c | 4 ++--
19
block.c | 3 +-
21
block/qcow2-snapshot.c | 10 +++++-----
20
block/block-backend.c | 2 +
22
block/qcow2.c | 14 +++++++-------
21
block/qcow2-bitmap.c | 31 ++---
23
6 files changed, 18 insertions(+), 24 deletions(-)
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(-)
24
28
25
diff --git a/block/qcow2.h b/block/qcow2.h
29
diff --git a/block/qcow2.h b/block/qcow2.h
26
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2.h
31
--- a/block/qcow2.h
28
+++ b/block/qcow2.h
32
+++ b/block/qcow2.h
29
@@ -XXX,XX +XXX,XX @@ static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset)
33
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs);
30
return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
34
int qcow2_mark_corrupt(BlockDriverState *bs);
31
}
35
int qcow2_update_header(BlockDriverState *bs);
32
36
33
-static inline int64_t align_offset(int64_t offset, int n)
37
-void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
34
-{
38
- int64_t size, const char *message_format, ...)
35
- offset = (offset + n - 1) & ~(n - 1);
39
- G_GNUC_PRINTF(5, 6);
36
- return offset;
40
+void GRAPH_RDLOCK
37
-}
41
+qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
38
-
42
+ int64_t size, const char *message_format, ...)
39
static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
43
+ G_GNUC_PRINTF(5, 6);
40
{
44
41
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
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;
42
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
358
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
43
index XXXXXXX..XXXXXXX 100644
359
index XXXXXXX..XXXXXXX 100644
44
--- a/block/qcow2-bitmap.c
360
--- a/block/qcow2-bitmap.c
45
+++ b/block/qcow2-bitmap.c
361
+++ b/block/qcow2-bitmap.c
46
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
362
@@ -XXX,XX +XXX,XX @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
47
363
return 0;
48
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
364
}
49
{
365
50
- return align_offset(sizeof(Qcow2BitmapDirEntry) +
366
-static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
51
- name_size + extra_data_size, 8);
367
- uint32_t bitmap_table_size)
52
+ int size = sizeof(Qcow2BitmapDirEntry) + name_size + extra_data_size;
368
+static void GRAPH_RDLOCK
53
+ return ROUND_UP(size, 8);
369
+clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
54
}
370
+ uint32_t bitmap_table_size)
55
371
{
56
static inline int dir_entry_size(Qcow2BitmapDirEntry *entry)
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;
57
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
58
index XXXXXXX..XXXXXXX 100644
479
index XXXXXXX..XXXXXXX 100644
59
--- a/block/qcow2-cluster.c
480
--- a/block/qcow2-cluster.c
60
+++ b/block/qcow2-cluster.c
481
+++ b/block/qcow2-cluster.c
61
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
482
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
62
483
* the cache is used; otherwise the L2 slice is loaded from the image
63
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
484
* file.
64
new_l1_table = qemu_try_blockalign(bs->file->bs,
485
*/
65
- align_offset(new_l1_size2, 512));
486
-static int l2_load(BlockDriverState *bs, uint64_t offset,
66
+ ROUND_UP(new_l1_size2, 512));
487
- uint64_t l2_offset, uint64_t **l2_slice)
67
if (new_l1_table == NULL) {
488
+static int GRAPH_RDLOCK
68
return -ENOMEM;
489
+l2_load(BlockDriverState *bs, uint64_t offset,
69
}
490
+ uint64_t l2_offset, uint64_t **l2_slice)
70
- memset(new_l1_table, 0, align_offset(new_l1_size2, 512));
491
{
71
+ memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512));
492
BDRVQcow2State *s = bs->opaque;
72
493
int start_of_slice = l2_entry_size(s) *
73
if (s->l1_size) {
494
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
74
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
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);
75
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
621
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
76
index XXXXXXX..XXXXXXX 100644
622
index XXXXXXX..XXXXXXX 100644
77
--- a/block/qcow2-refcount.c
623
--- a/block/qcow2-refcount.c
78
+++ b/block/qcow2-refcount.c
624
+++ b/block/qcow2-refcount.c
79
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
625
@@ -XXX,XX +XXX,XX @@ static void set_refcount_ro6(void *refcount_array, uint64_t index,
80
* l1_table_offset when it is the current s->l1_table_offset! Be careful
626
}
81
* when changing this! */
627
82
if (l1_table_offset != s->l1_table_offset) {
628
83
- l1_table = g_try_malloc0(align_offset(l1_size2, 512));
629
-static int load_refcount_block(BlockDriverState *bs,
84
+ l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512));
630
- int64_t refcount_block_offset,
85
if (l1_size2 && l1_table == NULL) {
631
- void **refcount_block)
86
ret = -ENOMEM;
632
+static int GRAPH_RDLOCK
87
goto fail;
633
+load_refcount_block(BlockDriverState *bs, int64_t refcount_block_offset,
88
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
634
+ void **refcount_block)
89
}
635
{
90
636
BDRVQcow2State *s = bs->opaque;
91
/* align range to test to cluster boundaries */
637
92
- size = align_offset(offset_into_cluster(s, offset) + size, s->cluster_size);
638
@@ -XXX,XX +XXX,XX @@ static int in_same_refcount_block(BDRVQcow2State *s, uint64_t offset_a,
93
+ size = ROUND_UP(offset_into_cluster(s, offset) + size, s->cluster_size);
639
*
94
offset = start_of_cluster(s, offset);
640
* Returns 0 on success or -errno in error case
95
641
*/
96
if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) {
642
-static int alloc_refcount_block(BlockDriverState *bs,
97
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
643
- int64_t cluster_index, void **refcount_block)
98
index XXXXXXX..XXXXXXX 100644
644
+static int GRAPH_RDLOCK
99
--- a/block/qcow2-snapshot.c
645
+alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index,
100
+++ b/block/qcow2-snapshot.c
646
+ void **refcount_block)
101
@@ -XXX,XX +XXX,XX @@ int qcow2_read_snapshots(BlockDriverState *bs)
647
{
102
648
BDRVQcow2State *s = bs->opaque;
103
for(i = 0; i < s->nb_snapshots; i++) {
649
unsigned int refcount_table_index;
104
/* Read statically sized part of the snapshot header */
650
@@ -XXX,XX +XXX,XX @@ found:
105
- offset = align_offset(offset, 8);
651
/* XXX: cache several refcount block clusters ? */
106
+ offset = ROUND_UP(offset, 8);
652
/* @addend is the absolute value of the addend; if @decrease is set, @addend
107
ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
653
* will be subtracted from the current refcount, otherwise it will be added */
108
if (ret < 0) {
654
-static int update_refcount(BlockDriverState *bs,
109
goto fail;
655
- int64_t offset,
110
@@ -XXX,XX +XXX,XX @@ static int qcow2_write_snapshots(BlockDriverState *bs)
656
- int64_t length,
111
offset = 0;
657
- uint64_t addend,
112
for(i = 0; i < s->nb_snapshots; i++) {
658
- bool decrease,
113
sn = s->snapshots + i;
659
- enum qcow2_discard_type type)
114
- offset = align_offset(offset, 8);
660
+static int GRAPH_RDLOCK
115
+ offset = ROUND_UP(offset, 8);
661
+update_refcount(BlockDriverState *bs, int64_t offset, int64_t length,
116
offset += sizeof(h);
662
+ uint64_t addend, bool decrease, enum qcow2_discard_type type)
117
offset += sizeof(extra);
663
{
118
offset += strlen(sn->id_str);
664
BDRVQcow2State *s = bs->opaque;
119
@@ -XXX,XX +XXX,XX @@ static int qcow2_write_snapshots(BlockDriverState *bs)
665
int64_t start, last, cluster_offset;
120
assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
666
@@ -XXX,XX +XXX,XX @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
121
h.id_str_size = cpu_to_be16(id_str_size);
667
122
h.name_size = cpu_to_be16(name_size);
668
123
- offset = align_offset(offset, 8);
669
/* return < 0 if error */
124
+ offset = ROUND_UP(offset, 8);
670
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
125
671
- uint64_t max)
126
ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
672
+static int64_t GRAPH_RDLOCK
127
if (ret < 0) {
673
+alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max)
128
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
674
{
129
/* The VM state isn't needed any more in the active L1 table; in fact, it
675
BDRVQcow2State *s = bs->opaque;
130
* hurts by causing expensive COW for the next snapshot. */
676
uint64_t i, nb_clusters, refcount;
131
qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
677
@@ -XXX,XX +XXX,XX @@ calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
132
- align_offset(sn->vm_state_size, s->cluster_size),
678
* Compares the actual reference count for each cluster in the image against the
133
+ ROUND_UP(sn->vm_state_size, s->cluster_size),
679
* refcount as reported by the refcount structures on-disk.
134
QCOW2_DISCARD_NEVER, false);
680
*/
135
681
-static void coroutine_fn
136
#ifdef DEBUG_ALLOC
682
+static void coroutine_fn GRAPH_RDLOCK
137
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
683
compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
138
}
684
BdrvCheckMode fix, bool *rebuild,
139
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
685
int64_t *highest_cluster,
140
new_l1_table = qemu_try_blockalign(bs->file->bs,
686
@@ -XXX,XX +XXX,XX @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
141
- align_offset(new_l1_bytes, 512));
687
*
142
+ ROUND_UP(new_l1_bytes, 512));
688
* @allocated should be set to true if a new cluster has been allocated.
143
if (new_l1_table == NULL) {
689
*/
144
return -ENOMEM;
690
-typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
145
}
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;
146
diff --git a/block/qcow2.c b/block/qcow2.c
781
diff --git a/block/qcow2.c b/block/qcow2.c
147
index XXXXXXX..XXXXXXX 100644
782
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qcow2.c
783
--- a/block/qcow2.c
149
+++ b/block/qcow2.c
784
+++ b/block/qcow2.c
150
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
785
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
151
786
* function when there are no pending requests, it does not guard against
152
if (s->l1_size > 0) {
787
* concurrent requests dirtying the image.
153
s->l1_table = qemu_try_blockalign(bs->file->bs,
788
*/
154
- align_offset(s->l1_size * sizeof(uint64_t), 512));
789
-static int qcow2_mark_clean(BlockDriverState *bs)
155
+ ROUND_UP(s->l1_size * sizeof(uint64_t), 512));
790
+static int GRAPH_RDLOCK qcow2_mark_clean(BlockDriverState *bs)
156
if (s->l1_table == NULL) {
791
{
157
error_setg(errp, "Could not allocate L1 table");
792
BDRVQcow2State *s = bs->opaque;
158
ret = -ENOMEM;
793
159
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
794
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_corrupt(BlockDriverState *bs)
160
{
795
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
161
int64_t meta_size = 0;
796
* before if necessary.
162
uint64_t nl1e, nl2e;
797
*/
163
- int64_t aligned_total_size = align_offset(total_size, cluster_size);
798
-static int coroutine_fn qcow2_mark_consistent(BlockDriverState *bs)
164
+ int64_t aligned_total_size = ROUND_UP(total_size, cluster_size);
799
+static int coroutine_fn GRAPH_RDLOCK
165
800
+qcow2_mark_consistent(BlockDriverState *bs)
166
/* header: 1 cluster */
801
{
167
meta_size += cluster_size;
802
BDRVQcow2State *s = bs->opaque;
168
803
169
/* total size of L2 tables */
804
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2ReopenState {
170
nl2e = aligned_total_size / cluster_size;
805
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
171
- nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t));
806
} Qcow2ReopenState;
172
+ nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t));
807
173
meta_size += nl2e * sizeof(uint64_t);
808
-static int qcow2_update_options_prepare(BlockDriverState *bs,
174
809
- Qcow2ReopenState *r,
175
/* total size of L1 tables */
810
- QDict *options, int flags,
176
nl1e = nl2e * sizeof(uint64_t) / cluster_size;
811
- Error **errp)
177
- nl1e = align_offset(nl1e, cluster_size / sizeof(uint64_t));
812
+static int GRAPH_RDLOCK
178
+ nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t));
813
+qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r,
179
meta_size += nl1e * sizeof(uint64_t);
814
+ QDict *options, int flags, Error **errp)
180
815
{
181
/* total size of refcount table and blocks */
816
BDRVQcow2State *s = bs->opaque;
182
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
817
QemuOpts *opts = NULL;
183
has_backing_file = !!optstr;
818
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
184
g_free(optstr);
819
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
185
820
}
186
- virtual_size = align_offset(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
821
187
- cluster_size);
822
-static int coroutine_fn
188
+ virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
823
+static int coroutine_fn GRAPH_RDLOCK
189
+ virtual_size = ROUND_UP(virtual_size, cluster_size);
824
qcow2_update_options(BlockDriverState *bs, QDict *options, int flags,
190
825
Error **errp)
191
/* Check that virtual disk size is valid */
826
{
192
l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,
827
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
193
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
828
bs->bl.pdiscard_alignment = s->cluster_size;
194
goto err;
829
}
830
831
-static int qcow2_reopen_prepare(BDRVReopenState *state,
832
- BlockReopenQueue *queue, Error **errp)
833
+static int GRAPH_UNLOCKED
834
+qcow2_reopen_prepare(BDRVReopenState *state,BlockReopenQueue *queue,
835
+ Error **errp)
836
{
837
BDRVQcow2State *s = state->bs->opaque;
838
Qcow2ReopenState *r;
839
int ret;
840
841
+ GLOBAL_STATE_CODE();
842
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
843
+
844
r = g_new0(Qcow2ReopenState, 1);
845
state->opaque = r;
846
847
@@ -XXX,XX +XXX,XX @@ static void qcow2_reopen_commit(BDRVReopenState *state)
848
849
static void qcow2_reopen_commit_post(BDRVReopenState *state)
850
{
851
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
852
+
853
if (state->flags & BDRV_O_RDWR) {
854
Error *local_err = NULL;
855
856
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
857
return ret;
858
}
859
860
-static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
861
- int64_t offset, int64_t bytes)
862
+static int coroutine_fn GRAPH_RDLOCK
863
+qcow2_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
864
{
865
int ret;
866
BDRVQcow2State *s = bs->opaque;
867
@@ -XXX,XX +XXX,XX @@ fail:
868
return ret;
869
}
870
871
-static int make_completely_empty(BlockDriverState *bs)
872
+static int GRAPH_RDLOCK make_completely_empty(BlockDriverState *bs)
873
{
874
BDRVQcow2State *s = bs->opaque;
875
Error *local_err = NULL;
876
@@ -XXX,XX +XXX,XX @@ fail:
877
return ret;
878
}
879
880
-static int qcow2_make_empty(BlockDriverState *bs)
881
+static int GRAPH_RDLOCK qcow2_make_empty(BlockDriverState *bs)
882
{
883
BDRVQcow2State *s = bs->opaque;
884
uint64_t offset, end_offset;
885
@@ -XXX,XX +XXX,XX @@ static int qcow2_make_empty(BlockDriverState *bs)
886
return ret;
887
}
888
889
-static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
890
+static coroutine_fn GRAPH_RDLOCK int qcow2_co_flush_to_os(BlockDriverState *bs)
891
{
892
BDRVQcow2State *s = bs->opaque;
893
int ret;
894
@@ -XXX,XX +XXX,XX @@ qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
895
return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0);
896
}
897
898
-static int qcow2_has_compressed_clusters(BlockDriverState *bs)
899
+static int GRAPH_RDLOCK qcow2_has_compressed_clusters(BlockDriverState *bs)
900
{
901
int64_t offset = 0;
902
int64_t bytes = bdrv_getlength(bs);
903
@@ -XXX,XX +XXX,XX @@ static int qcow2_has_compressed_clusters(BlockDriverState *bs)
904
* Downgrades an image's version. To achieve this, any incompatible features
905
* have to be removed.
906
*/
907
-static int qcow2_downgrade(BlockDriverState *bs, int target_version,
908
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
909
- Error **errp)
910
+static int GRAPH_RDLOCK
911
+qcow2_downgrade(BlockDriverState *bs, int target_version,
912
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
913
+ Error **errp)
914
{
915
BDRVQcow2State *s = bs->opaque;
916
int current_version = s->qcow_version;
917
@@ -XXX,XX +XXX,XX @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
918
* features of older versions, some things may have to be presented
919
* differently.
920
*/
921
-static int qcow2_upgrade(BlockDriverState *bs, int target_version,
922
- BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
923
- Error **errp)
924
+static int GRAPH_RDLOCK
925
+qcow2_upgrade(BlockDriverState *bs, int target_version,
926
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
927
+ Error **errp)
928
{
929
BDRVQcow2State *s = bs->opaque;
930
bool need_snapshot_update;
931
@@ -XXX,XX +XXX,XX @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
932
info->original_cb_opaque);
933
}
934
935
-static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
936
- BlockDriverAmendStatusCB *status_cb,
937
- void *cb_opaque,
938
- bool force,
939
- Error **errp)
940
+static int GRAPH_RDLOCK
941
+qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
942
+ BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
943
+ bool force, Error **errp)
944
{
945
BDRVQcow2State *s = bs->opaque;
946
int old_version = s->qcow_version, new_version = old_version;
947
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
948
char *message;
949
va_list ap;
950
951
- assume_graph_lock(); /* FIXME */
952
-
953
fatal = fatal && bdrv_is_writable(bs);
954
955
if (s->signaled_corruption &&
956
diff --git a/block/replication.c b/block/replication.c
957
index XXXXXXX..XXXXXXX 100644
958
--- a/block/replication.c
959
+++ b/block/replication.c
960
@@ -XXX,XX +XXX,XX @@ out:
961
return ret;
962
}
963
964
-static void secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
965
+static void GRAPH_UNLOCKED
966
+secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
967
{
968
BDRVReplicationState *s = bs->opaque;
969
BdrvChild *active_disk = bs->file;
970
Error *local_err = NULL;
971
int ret;
972
973
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
974
+
975
if (!s->backup_job) {
976
error_setg(errp, "Backup job was cancelled unexpectedly");
977
return;
978
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
979
/* Must be true, or the bdrv_getlength() calls would have failed */
980
assert(active_disk->bs->drv && hidden_disk->bs->drv);
981
982
+ bdrv_graph_rdlock_main_loop();
983
if (!active_disk->bs->drv->bdrv_make_empty ||
984
!hidden_disk->bs->drv->bdrv_make_empty) {
985
error_setg(errp,
986
"Active disk or hidden disk doesn't support make_empty");
987
aio_context_release(aio_context);
988
+ bdrv_graph_rdunlock_main_loop();
989
return;
195
}
990
}
196
991
+ bdrv_graph_rdunlock_main_loop();
197
- virtual_size = align_offset(ssize, cluster_size);
992
198
+ virtual_size = ROUND_UP(ssize, cluster_size);
993
/* reopen the backing file in r/w mode */
199
994
reopen_backing_file(bs, true, &local_err);
200
if (has_backing_file) {
201
/* We don't how much of the backing chain is shared by the input
202
--
995
--
203
2.13.6
996
2.41.0
204
205
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
qcow2_inactivate() need to hold a reader lock for the graph because it
3
calls bdrv_get_device_or_node_name(), which accesses the parents list of
4
a node.
2
5
3
We are gradually moving away from sector-based interfaces, towards
6
qcow2_do_close() is a bit strange because it is called from different
4
byte-based. Update the qcow2 driver accordingly.
7
contexts. If close_data_file = true, we know that we were called from
8
non-coroutine main loop context (more specifically, we're coming from
9
qcow2_close()) and can safely drop the reader lock temporarily with
10
bdrv_graph_rdunlock_main_loop() and acquire the writer lock.
5
11
6
For now, we are ignoring the 'want_zero' hint. However, it should
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
be relatively straightforward to honor the hint as a way to return
13
Message-ID: <20230929145157.45443-16-kwolf@redhat.com>
8
larger *pnum values when we have consecutive clusters with the same
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
data/zero status but which differ only in having non-consecutive
10
mappings.
11
12
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
16
---
17
block/qcow2.c | 24 +++++++++++++-----------
17
block/qcow2.c | 15 ++++++++++-----
18
1 file changed, 13 insertions(+), 11 deletions(-)
18
1 file changed, 10 insertions(+), 5 deletions(-)
19
19
20
diff --git a/block/qcow2.c b/block/qcow2.c
20
diff --git a/block/qcow2.c b/block/qcow2.c
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2.c
22
--- a/block/qcow2.c
23
+++ b/block/qcow2.c
23
+++ b/block/qcow2.c
24
@@ -XXX,XX +XXX,XX @@ static void qcow2_join_options(QDict *options, QDict *old_options)
24
@@ -XXX,XX +XXX,XX @@ fail_nometa:
25
}
25
return ret;
26
}
26
}
27
27
28
-static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
28
-static int qcow2_inactivate(BlockDriverState *bs)
29
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
29
+static int GRAPH_RDLOCK qcow2_inactivate(BlockDriverState *bs)
30
+static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
31
+ bool want_zero,
32
+ int64_t offset, int64_t count,
33
+ int64_t *pnum, int64_t *map,
34
+ BlockDriverState **file)
35
{
30
{
36
BDRVQcow2State *s = bs->opaque;
31
BDRVQcow2State *s = bs->opaque;
37
uint64_t cluster_offset;
32
int ret, result = 0;
38
int index_in_cluster, ret;
33
Error *local_err = NULL;
39
unsigned int bytes;
34
40
- int64_t status = 0;
35
- assume_graph_lock(); /* FIXME */
41
+ int status = 0;
36
-
42
37
qcow2_store_persistent_dirty_bitmaps(bs, true, &local_err);
43
- bytes = MIN(INT_MAX, nb_sectors * BDRV_SECTOR_SIZE);
38
if (local_err != NULL) {
44
+ bytes = MIN(INT_MAX, count);
39
result = -EINVAL;
45
qemu_co_mutex_lock(&s->lock);
40
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
46
- ret = qcow2_get_cluster_offset(bs, sector_num << BDRV_SECTOR_BITS, &bytes,
41
return result;
47
- &cluster_offset);
42
}
48
+ ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
43
49
qemu_co_mutex_unlock(&s->lock);
44
-static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
50
if (ret < 0) {
45
+static void coroutine_mixed_fn GRAPH_RDLOCK
51
return ret;
46
+qcow2_do_close(BlockDriverState *bs, bool close_data_file)
47
{
48
BDRVQcow2State *s = bs->opaque;
49
qemu_vfree(s->l1_table);
50
@@ -XXX,XX +XXX,XX @@ static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
51
g_free(s->image_backing_format);
52
53
if (close_data_file && has_data_file(bs)) {
54
+ GLOBAL_STATE_CODE();
55
+ bdrv_graph_rdunlock_main_loop();
56
bdrv_graph_wrlock(NULL);
57
bdrv_unref_child(bs, s->data_file);
58
bdrv_graph_wrunlock();
59
s->data_file = NULL;
60
+ bdrv_graph_rdlock_main_loop();
52
}
61
}
53
62
54
- *pnum = bytes >> BDRV_SECTOR_BITS;
63
qcow2_refcount_close(bs);
55
+ *pnum = bytes;
64
qcow2_free_snapshots(bs);
56
65
}
57
if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
66
58
!s->crypto) {
67
-static void qcow2_close(BlockDriverState *bs)
59
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
68
+static void GRAPH_UNLOCKED qcow2_close(BlockDriverState *bs)
60
- cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
69
{
61
+ index_in_cluster = offset & (s->cluster_size - 1);
70
+ GLOBAL_STATE_CODE();
62
+ *map = cluster_offset | index_in_cluster;
71
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
63
*file = bs->file->bs;
72
+
64
- status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
73
qcow2_do_close(bs, true);
65
+ status |= BDRV_BLOCK_OFFSET_VALID;
74
}
66
}
75
67
if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
68
status |= BDRV_BLOCK_ZERO;
69
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
70
.bdrv_child_perm = bdrv_format_default_perms,
71
.bdrv_create = qcow2_create,
72
.bdrv_has_zero_init = bdrv_has_zero_init_1,
73
- .bdrv_co_get_block_status = qcow2_co_get_block_status,
74
+ .bdrv_co_block_status = qcow2_co_block_status,
75
76
.bdrv_co_preadv = qcow2_co_preadv,
77
.bdrv_co_pwritev = qcow2_co_pwritev,
78
--
76
--
79
2.13.6
77
2.41.0
80
81
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
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().
2
4
3
Commit bdd6a90 has a bug: drivers should never directly set
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
BDRV_BLOCK_ALLOCATED, but only io.c should do that (as needed).
6
Message-ID: <20230929145157.45443-17-kwolf@redhat.com>
5
Instead, drivers should report BDRV_BLOCK_DATA if it knows that
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
data comes from this BDS.
7
8
But let's look at the bigger picture: semantically, the nvme
9
driver is similar to the nbd, null, and raw drivers (no backing
10
file, all data comes from this BDS). But while two of those
11
other drivers have to supply the callback (null because it can
12
special-case BDRV_BLOCK_ZERO, raw because it can special-case
13
a different offset), in this case the block layer defaults are
14
good enough without the callback at all (similar to nbd).
15
16
So, fix the bug by deletion ;)
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
9
---
21
block/nvme.c | 14 --------------
10
block/qcow2-bitmap.c | 9 +++------
22
1 file changed, 14 deletions(-)
11
1 file changed, 3 insertions(+), 6 deletions(-)
23
12
24
diff --git a/block/nvme.c b/block/nvme.c
13
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/block/nvme.c
15
--- a/block/qcow2-bitmap.c
27
+++ b/block/nvme.c
16
+++ b/block/qcow2-bitmap.c
28
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
17
@@ -XXX,XX +XXX,XX @@ static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity)
29
return 0;
18
return DIV_ROUND_UP(num_bits, 8);
30
}
19
}
31
20
32
-static int64_t coroutine_fn nvme_co_get_block_status(BlockDriverState *bs,
21
-static int check_constraints_on_bitmap(BlockDriverState *bs,
33
- int64_t sector_num,
22
- const char *name,
34
- int nb_sectors, int *pnum,
23
- uint32_t granularity,
35
- BlockDriverState **file)
24
- Error **errp)
36
-{
25
+static int GRAPH_RDLOCK
37
- *pnum = nb_sectors;
26
+check_constraints_on_bitmap(BlockDriverState *bs, const char *name,
38
- *file = bs;
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 */
39
-
35
-
40
- return BDRV_BLOCK_ALLOCATED | BDRV_BLOCK_OFFSET_VALID |
36
assert(granularity > 0);
41
- (sector_num << BDRV_SECTOR_BITS);
37
assert((granularity & (granularity - 1)) == 0);
42
-}
43
-
44
static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
45
{
46
QINCREF(opts);
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
48
.bdrv_co_flush_to_disk = nvme_co_flush,
49
.bdrv_reopen_prepare = nvme_reopen_prepare,
50
51
- .bdrv_co_get_block_status = nvme_co_get_block_status,
52
-
53
.bdrv_refresh_filename = nvme_refresh_filename,
54
.bdrv_refresh_limits = nvme_refresh_limits,
55
38
56
--
39
--
57
2.13.6
40
2.41.0
58
59
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
2
bdrv_op_is_blocked() need to hold a reader lock for the graph
3
BlockBackend currently relies on BlockDriverState->in_flight to track
3
because it calls bdrv_get_device_or_node_name(), which accesses the
4
requests for blk_drain(). There is a corner case where
4
parents list of a node.
5
BlockDriverState->in_flight cannot be used though: blk->root can be NULL
6
when there is no medium. This results in a segfault when the NULL
7
pointer is dereferenced.
8
9
Introduce a BlockBackend->in_flight counter for aio requests so it works
10
even when blk->root == NULL.
11
12
Based on a patch by Kevin Wolf <kwolf@redhat.com>.
13
5
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-ID: <20230929145157.45443-18-kwolf@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
10
---
18
block.c | 2 +-
11
include/block/block-global-state.h | 4 +++-
19
block/block-backend.c | 60 +++++++++++++++++++++++++++++++++++++++++++++------
12
block.c | 2 --
20
2 files changed, 54 insertions(+), 8 deletions(-)
13
block/block-backend.c | 1 +
14
block/commit.c | 1 +
15
block/monitor/block-hmp-cmds.c | 3 +++
16
block/qapi-sysemu.c | 9 +++++++--
17
blockdev.c | 15 +++++++++++++++
18
7 files changed, 30 insertions(+), 5 deletions(-)
21
19
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block-global-state.h
23
+++ b/include/block/block-global-state.h
24
@@ -XXX,XX +XXX,XX @@ bdrv_attach_child(BlockDriverState *parent_bs,
25
BdrvChildRole child_role,
26
Error **errp);
27
28
-bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
29
+bool GRAPH_RDLOCK
30
+bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
31
+
32
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason);
33
void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason);
34
void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
22
diff --git a/block.c b/block.c
35
diff --git a/block.c b/block.c
23
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
24
--- a/block.c
37
--- a/block.c
25
+++ b/block.c
38
+++ b/block.c
26
@@ -XXX,XX +XXX,XX @@ out:
39
@@ -XXX,XX +XXX,XX @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
27
40
BdrvOpBlocker *blocker;
28
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
41
GLOBAL_STATE_CODE();
29
{
42
30
- return bs->aio_context;
43
- assume_graph_lock(); /* FIXME */
31
+ return bs ? bs->aio_context : qemu_get_aio_context();
44
-
32
}
45
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
33
46
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
34
AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
47
blocker = QLIST_FIRST(&bs->op_blockers[op]);
35
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
36
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
37
--- a/block/block-backend.c
50
--- a/block/block-backend.c
38
+++ b/block/block-backend.c
51
+++ b/block/block-backend.c
39
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
52
@@ -XXX,XX +XXX,XX @@ bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
40
int quiesce_counter;
53
{
41
VMChangeStateEntry *vmsh;
54
BlockDriverState *bs = blk_bs(blk);
42
bool force_allow_inactivate;
55
GLOBAL_STATE_CODE();
56
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
57
58
if (!bs) {
59
return false;
60
diff --git a/block/commit.c b/block/commit.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/commit.c
63
+++ b/block/commit.c
64
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
65
Error *local_err = NULL;
66
67
GLOBAL_STATE_CODE();
68
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
69
70
if (!drv)
71
return -ENOMEDIUM;
72
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/monitor/block-hmp-cmds.c
75
+++ b/block/monitor/block-hmp-cmds.c
76
@@ -XXX,XX +XXX,XX @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
77
AioContext *aio_context;
78
Error *local_err = NULL;
79
80
+ GLOBAL_STATE_CODE();
81
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
43
+
82
+
44
+ /* Number of in-flight aio requests. BlockDriverState also counts
83
bs = bdrv_find_node(id);
45
+ * in-flight requests but aio requests can exist even when blk->root is
84
if (bs) {
46
+ * NULL, so we cannot rely on its counter for that case.
85
qmp_blockdev_del(id, &local_err);
47
+ * Accessed with atomic ops.
86
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
48
+ */
87
index XXXXXXX..XXXXXXX 100644
49
+ unsigned int in_flight;
88
--- a/block/qapi-sysemu.c
50
+ AioWait wait;
89
+++ b/block/qapi-sysemu.c
51
};
90
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_close_tray(const char *device,
52
53
typedef struct BlockBackendAIOCB {
54
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
55
return bdrv_make_zero(blk->root, flags);
56
}
57
58
+static void blk_inc_in_flight(BlockBackend *blk)
59
+{
60
+ atomic_inc(&blk->in_flight);
61
+}
62
+
63
+static void blk_dec_in_flight(BlockBackend *blk)
64
+{
65
+ atomic_dec(&blk->in_flight);
66
+ aio_wait_kick(&blk->wait);
67
+}
68
+
69
static void error_callback_bh(void *opaque)
70
{
71
struct BlockBackendAIOCB *acb = opaque;
72
73
- bdrv_dec_in_flight(acb->common.bs);
74
+ blk_dec_in_flight(acb->blk);
75
acb->common.cb(acb->common.opaque, acb->ret);
76
qemu_aio_unref(acb);
77
}
78
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
79
{
80
struct BlockBackendAIOCB *acb;
81
82
- bdrv_inc_in_flight(blk_bs(blk));
83
+ blk_inc_in_flight(blk);
84
acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
85
acb->blk = blk;
86
acb->ret = ret;
87
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
88
static void blk_aio_complete(BlkAioEmAIOCB *acb)
89
{
90
if (acb->has_returned) {
91
- bdrv_dec_in_flight(acb->common.bs);
92
+ blk_dec_in_flight(acb->rwco.blk);
93
acb->common.cb(acb->common.opaque, acb->rwco.ret);
94
qemu_aio_unref(acb);
95
}
96
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
97
BlkAioEmAIOCB *acb;
98
Coroutine *co;
99
100
- bdrv_inc_in_flight(blk_bs(blk));
101
+ blk_inc_in_flight(blk);
102
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
103
acb->rwco = (BlkRwCo) {
104
.blk = blk,
105
@@ -XXX,XX +XXX,XX @@ int blk_flush(BlockBackend *blk)
106
107
void blk_drain(BlockBackend *blk)
108
{
109
- if (blk_bs(blk)) {
110
- bdrv_drain(blk_bs(blk));
111
+ BlockDriverState *bs = blk_bs(blk);
112
+
113
+ if (bs) {
114
+ bdrv_drained_begin(bs);
115
+ }
116
+
117
+ /* We may have -ENOMEDIUM completions in flight */
118
+ AIO_WAIT_WHILE(&blk->wait,
119
+ blk_get_aio_context(blk),
120
+ atomic_mb_read(&blk->in_flight) > 0);
121
+
122
+ if (bs) {
123
+ bdrv_drained_end(bs);
124
}
91
}
125
}
92
}
126
93
127
void blk_drain_all(void)
94
-static void blockdev_remove_medium(const char *device, const char *id,
95
- Error **errp)
96
+static void GRAPH_UNLOCKED
97
+blockdev_remove_medium(const char *device, const char *id, Error **errp)
128
{
98
{
129
- bdrv_drain_all();
99
BlockBackend *blk;
130
+ BlockBackend *blk = NULL;
100
BlockDriverState *bs;
101
AioContext *aio_context;
102
bool has_attached_device;
103
104
+ GLOBAL_STATE_CODE();
131
+
105
+
132
+ bdrv_drain_all_begin();
106
blk = qmp_get_blk(device, id, errp);
133
+
107
if (!blk) {
134
+ while ((blk = blk_all_next(blk)) != NULL) {
108
return;
135
+ AioContext *ctx = blk_get_aio_context(blk);
109
@@ -XXX,XX +XXX,XX @@ static void blockdev_remove_medium(const char *device, const char *id,
136
+
110
aio_context = bdrv_get_aio_context(bs);
137
+ aio_context_acquire(ctx);
111
aio_context_acquire(aio_context);
138
+
112
139
+ /* We may have -ENOMEDIUM completions in flight */
113
+ bdrv_graph_rdlock_main_loop();
140
+ AIO_WAIT_WHILE(&blk->wait, ctx,
114
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
141
+ atomic_mb_read(&blk->in_flight) > 0);
115
+ bdrv_graph_rdunlock_main_loop();
142
+
116
goto out;
143
+ aio_context_release(ctx);
117
}
144
+ }
118
+ bdrv_graph_rdunlock_main_loop();
145
+
119
146
+ bdrv_drain_all_end();
120
blk_remove_bs(blk);
147
}
121
148
122
diff --git a/blockdev.c b/blockdev.c
149
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
123
index XXXXXXX..XXXXXXX 100644
124
--- a/blockdev.c
125
+++ b/blockdev.c
126
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(DriveBackup *backup,
127
}
128
129
/* Early check to avoid creating target */
130
+ bdrv_graph_rdlock_main_loop();
131
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
132
+ bdrv_graph_rdunlock_main_loop();
133
goto out;
134
}
135
+ bdrv_graph_rdunlock_main_loop();
136
137
flags = bs->open_flags | BDRV_O_RDWR;
138
139
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
140
return;
141
}
142
143
+ bdrv_graph_co_rdlock();
144
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
145
error_setg(errp, QERR_DEVICE_IN_USE, device);
146
+ bdrv_graph_co_rdunlock();
147
return;
148
}
149
+ bdrv_graph_co_rdunlock();
150
151
blk = blk_co_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
152
if (!blk) {
153
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(const char *job_id, const char *device,
154
* Check for op blockers in the whole chain between bs and base (or bottom)
155
*/
156
iter_end = bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
157
+ bdrv_graph_rdlock_main_loop();
158
for (iter = bs; iter && iter != iter_end;
159
iter = bdrv_filter_or_cow_bs(iter))
160
{
161
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
162
+ bdrv_graph_rdunlock_main_loop();
163
goto out;
164
}
165
}
166
+ bdrv_graph_rdunlock_main_loop();
167
168
/* if we are streaming the entire chain, the result will have no backing
169
* file, and specifying one is therefore an error */
170
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
171
}
172
173
/* Early check to avoid creating target */
174
+ bdrv_graph_rdlock_main_loop();
175
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
176
+ bdrv_graph_rdunlock_main_loop();
177
return;
178
}
179
+ bdrv_graph_rdunlock_main_loop();
180
181
aio_context = bdrv_get_aio_context(bs);
182
aio_context_acquire(aio_context);
183
@@ -XXX,XX +XXX,XX @@ void qmp_change_backing_file(const char *device,
184
185
/* even though we are not necessarily operating on bs, we need it to
186
* determine if block ops are currently prohibited on the chain */
187
+ bdrv_graph_rdlock_main_loop();
188
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
189
+ bdrv_graph_rdunlock_main_loop();
190
goto out;
191
}
192
+ bdrv_graph_rdunlock_main_loop();
193
194
/* final sanity check */
195
if (!bdrv_chain_contains(bs, image_bs)) {
150
--
196
--
151
2.13.6
197
2.41.0
152
153
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_apply_auto_read_only() need to hold a reader lock for the graph
3
because it calls bdrv_can_set_read_only(), which indirectly accesses the
4
parents list of a node.
2
5
3
We are gradually moving away from sector-based interfaces, towards
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the iscsi driver accordingly. In this case,
7
Message-ID: <20230929145157.45443-19-kwolf@redhat.com>
5
it is handy to teach iscsi_co_block_status() to handle a NULL map
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
and file parameter, even though the block layer passes non-NULL
7
values, because we also call the function directly. For now, there
8
are no optimizations done based on the want_zero flag.
9
10
We can also make the simplification of asserting that the block
11
layer passed in aligned values.
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
10
---
17
block/iscsi.c | 69 ++++++++++++++++++++++++++++-------------------------------
11
include/block/block-io.h | 6 ++++--
18
1 file changed, 33 insertions(+), 36 deletions(-)
12
block.c | 4 ++--
13
block/bochs.c | 2 ++
14
block/cloop.c | 2 ++
15
block/curl.c | 2 ++
16
block/dmg.c | 2 ++
17
block/gluster.c | 2 ++
18
block/iscsi.c | 2 ++
19
block/nbd.c | 3 ++-
20
block/rbd.c | 2 ++
21
10 files changed, 22 insertions(+), 5 deletions(-)
19
22
23
diff --git a/include/block/block-io.h b/include/block/block-io.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block-io.h
26
+++ b/include/block/block-io.h
27
@@ -XXX,XX +XXX,XX @@ bdrv_is_allocated_above(BlockDriverState *bs, BlockDriverState *base,
28
int coroutine_fn GRAPH_RDLOCK
29
bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
30
31
-int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
32
- Error **errp);
33
+int GRAPH_RDLOCK
34
+bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
35
+ Error **errp);
36
+
37
bool bdrv_is_read_only(BlockDriverState *bs);
38
bool bdrv_is_writable(BlockDriverState *bs);
39
bool bdrv_is_sg(BlockDriverState *bs);
40
diff --git a/block.c b/block.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block.c
43
+++ b/block.c
44
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
45
int ret = 0;
46
IO_CODE();
47
48
- assume_graph_lock(); /* FIXME */
49
-
50
if (!(bs->open_flags & BDRV_O_RDWR)) {
51
return 0;
52
}
53
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
54
55
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, ro)) {
56
if (!ro && bdrv_is_whitelisted(drv, true)) {
57
+ bdrv_graph_rdlock_main_loop();
58
ret = bdrv_apply_auto_read_only(bs, NULL, NULL);
59
+ bdrv_graph_rdunlock_main_loop();
60
} else {
61
ret = -ENOTSUP;
62
}
63
diff --git a/block/bochs.c b/block/bochs.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/bochs.c
66
+++ b/block/bochs.c
67
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
68
int ret;
69
70
/* No write support yet */
71
+ bdrv_graph_rdlock_main_loop();
72
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
73
+ bdrv_graph_rdunlock_main_loop();
74
if (ret < 0) {
75
return ret;
76
}
77
diff --git a/block/cloop.c b/block/cloop.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/cloop.c
80
+++ b/block/cloop.c
81
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
82
uint32_t offsets_size, max_compressed_block_size = 1, i;
83
int ret;
84
85
+ bdrv_graph_rdlock_main_loop();
86
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
87
+ bdrv_graph_rdunlock_main_loop();
88
if (ret < 0) {
89
return ret;
90
}
91
diff --git a/block/curl.c b/block/curl.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/block/curl.c
94
+++ b/block/curl.c
95
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
96
const char *protocol_delimiter;
97
int ret;
98
99
+ bdrv_graph_rdlock_main_loop();
100
ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
101
errp);
102
+ bdrv_graph_rdunlock_main_loop();
103
if (ret < 0) {
104
return ret;
105
}
106
diff --git a/block/dmg.c b/block/dmg.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/dmg.c
109
+++ b/block/dmg.c
110
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
111
int64_t offset;
112
int ret;
113
114
+ bdrv_graph_rdlock_main_loop();
115
ret = bdrv_apply_auto_read_only(bs, NULL, errp);
116
+ bdrv_graph_rdunlock_main_loop();
117
if (ret < 0) {
118
return ret;
119
}
120
diff --git a/block/gluster.c b/block/gluster.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/gluster.c
123
+++ b/block/gluster.c
124
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
125
if (ret == -EACCES || ret == -EROFS) {
126
/* Try to degrade to read-only, but if it doesn't work, still use the
127
* normal error message. */
128
+ bdrv_graph_rdlock_main_loop();
129
if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
130
open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
131
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
132
ret = s->fd ? 0 : -errno;
133
}
134
+ bdrv_graph_rdunlock_main_loop();
135
}
136
137
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
20
diff --git a/block/iscsi.c b/block/iscsi.c
138
diff --git a/block/iscsi.c b/block/iscsi.c
21
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
22
--- a/block/iscsi.c
140
--- a/block/iscsi.c
23
+++ b/block/iscsi.c
141
+++ b/block/iscsi.c
24
@@ -XXX,XX +XXX,XX @@ out_unlock:
142
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
25
143
/* Check the write protect flag of the LUN if we want to write */
26
144
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
27
145
iscsilun->write_protected) {
28
-static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
146
+ bdrv_graph_rdlock_main_loop();
29
- int64_t sector_num,
147
ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
30
- int nb_sectors, int *pnum,
148
+ bdrv_graph_rdunlock_main_loop();
31
- BlockDriverState **file)
149
if (ret < 0) {
32
+static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
150
goto out;
33
+ bool want_zero, int64_t offset,
151
}
34
+ int64_t bytes, int64_t *pnum,
152
diff --git a/block/nbd.c b/block/nbd.c
35
+ int64_t *map,
153
index XXXXXXX..XXXXXXX 100644
36
+ BlockDriverState **file)
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)
37
{
163
{
38
IscsiLun *iscsilun = bs->opaque;
164
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
39
struct scsi_get_lba_status *lbas = NULL;
165
int ret;
40
struct scsi_lba_status_descriptor *lbasd = NULL;
166
diff --git a/block/rbd.c b/block/rbd.c
41
struct IscsiTask iTask;
167
index XXXXXXX..XXXXXXX 100644
42
uint64_t lba;
168
--- a/block/rbd.c
43
- int64_t ret;
169
+++ b/block/rbd.c
44
+ int ret;
170
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
45
171
/* If we are using an rbd snapshot, we must be r/o, otherwise
46
iscsi_co_init_iscsitask(iscsilun, &iTask);
172
* leave as-is */
47
173
if (s->snap != NULL) {
48
- if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
174
+ bdrv_graph_rdlock_main_loop();
49
- ret = -EINVAL;
175
r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
50
- goto out;
176
+ bdrv_graph_rdunlock_main_loop();
51
- }
177
if (r < 0) {
52
+ assert(QEMU_IS_ALIGNED(offset | bytes, iscsilun->block_size));
178
goto failed_post_open;
53
54
/* default to all sectors allocated */
55
- ret = BDRV_BLOCK_DATA;
56
- ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
57
- *pnum = nb_sectors;
58
+ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
59
+ if (map) {
60
+ *map = offset;
61
+ }
62
+ *pnum = bytes;
63
64
/* LUN does not support logical block provisioning */
65
if (!iscsilun->lbpme) {
66
goto out;
67
}
68
69
- lba = sector_qemu2lun(sector_num, iscsilun);
70
+ lba = offset / iscsilun->block_size;
71
72
qemu_mutex_lock(&iscsilun->mutex);
73
retry:
74
@@ -XXX,XX +XXX,XX @@ retry:
75
76
lbasd = &lbas->descriptors[0];
77
78
- if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
79
+ if (lba != lbasd->lba) {
80
ret = -EIO;
81
goto out_unlock;
82
}
83
84
- *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
85
+ *pnum = lbasd->num_blocks * iscsilun->block_size;
86
87
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
88
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
89
@@ -XXX,XX +XXX,XX @@ retry:
90
}
91
92
if (ret & BDRV_BLOCK_ZERO) {
93
- iscsi_allocmap_set_unallocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
94
- *pnum * BDRV_SECTOR_SIZE);
95
+ iscsi_allocmap_set_unallocated(iscsilun, offset, *pnum);
96
} else {
97
- iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
98
- *pnum * BDRV_SECTOR_SIZE);
99
+ iscsi_allocmap_set_allocated(iscsilun, offset, *pnum);
100
}
101
102
- if (*pnum > nb_sectors) {
103
- *pnum = nb_sectors;
104
+ if (*pnum > bytes) {
105
+ *pnum = bytes;
106
}
107
out_unlock:
108
qemu_mutex_unlock(&iscsilun->mutex);
109
@@ -XXX,XX +XXX,XX @@ out:
110
if (iTask.task != NULL) {
111
scsi_free_scsi_task(iTask.task);
112
}
113
- if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) {
114
+ if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID && file) {
115
*file = bs;
116
}
117
return ret;
118
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
119
nb_sectors * BDRV_SECTOR_SIZE) &&
120
!iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
121
nb_sectors * BDRV_SECTOR_SIZE)) {
122
- int pnum;
123
- BlockDriverState *file;
124
+ int64_t pnum;
125
/* check the block status from the beginning of the cluster
126
* containing the start sector */
127
- int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
128
- int head;
129
- int64_t ret;
130
-
131
- assert(cluster_sectors);
132
- head = sector_num % cluster_sectors;
133
- ret = iscsi_co_get_block_status(bs, sector_num - head,
134
- BDRV_REQUEST_MAX_SECTORS, &pnum,
135
- &file);
136
+ int64_t head;
137
+ int ret;
138
+
139
+ assert(iscsilun->cluster_size);
140
+ head = (sector_num * BDRV_SECTOR_SIZE) % iscsilun->cluster_size;
141
+ ret = iscsi_co_block_status(bs, true,
142
+ sector_num * BDRV_SECTOR_SIZE - head,
143
+ BDRV_REQUEST_MAX_BYTES, &pnum, NULL, NULL);
144
if (ret < 0) {
145
return ret;
146
}
179
}
147
/* if the whole request falls into an unallocated area we can avoid
148
* reading and directly return zeroes instead */
149
- if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors + head) {
150
+ if (ret & BDRV_BLOCK_ZERO &&
151
+ pnum >= nb_sectors * BDRV_SECTOR_SIZE + head) {
152
qemu_iovec_memset(iov, 0, 0x00, iov->size);
153
return 0;
154
}
155
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
156
.bdrv_truncate = iscsi_truncate,
157
.bdrv_refresh_limits = iscsi_refresh_limits,
158
159
- .bdrv_co_get_block_status = iscsi_co_get_block_status,
160
+ .bdrv_co_block_status = iscsi_co_block_status,
161
.bdrv_co_pdiscard = iscsi_co_pdiscard,
162
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
163
.bdrv_co_readv = iscsi_co_readv,
164
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
165
.bdrv_truncate = iscsi_truncate,
166
.bdrv_refresh_limits = iscsi_refresh_limits,
167
168
- .bdrv_co_get_block_status = iscsi_co_get_block_status,
169
+ .bdrv_co_block_status = iscsi_co_block_status,
170
.bdrv_co_pdiscard = iscsi_co_pdiscard,
171
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
172
.bdrv_co_readv = iscsi_co_readv,
173
--
180
--
174
2.13.6
181
2.41.0
175
176
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_get_specific_info() need to hold a reader lock for the graph.
3
This removes an assume_graph_lock() call in vmdk's implementation.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the vmdk driver accordingly. Drop the
6
Message-ID: <20230929145157.45443-20-kwolf@redhat.com>
5
now-unused vmdk_find_index_in_cluster().
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
7
Also, fix a pre-existing bug: if find_extent() fails (unlikely,
8
since the block layer did a bounds check), then we must return a
9
failure, rather than 0.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
9
---
16
block/vmdk.c | 38 ++++++++++++++------------------------
10
include/block/block-io.h | 5 +++--
17
1 file changed, 14 insertions(+), 24 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(-)
18
15
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
21
int co_wrapper_mixed_bdrv_rdlock
22
bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
23
24
-ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
25
- Error **errp);
26
+ImageInfoSpecific * GRAPH_RDLOCK
27
+bdrv_get_specific_info(BlockDriverState *bs, Error **errp);
28
+
29
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
30
void bdrv_round_to_subclusters(BlockDriverState *bs,
31
int64_t offset, int64_t bytes,
32
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int-common.h
35
+++ b/include/block/block_int-common.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_get_info)(
38
BlockDriverState *bs, BlockDriverInfo *bdi);
39
40
- ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
41
- Error **errp);
42
+ ImageInfoSpecific * GRAPH_RDLOCK_PTR (*bdrv_get_specific_info)(
43
+ BlockDriverState *bs, Error **errp);
44
BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
45
46
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_save_vmstate)(
19
diff --git a/block/vmdk.c b/block/vmdk.c
47
diff --git a/block/vmdk.c b/block/vmdk.c
20
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
21
--- a/block/vmdk.c
49
--- a/block/vmdk.c
22
+++ b/block/vmdk.c
50
+++ b/block/vmdk.c
23
@@ -XXX,XX +XXX,XX @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
51
@@ -XXX,XX +XXX,XX @@ vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
24
return extent_relative_offset % cluster_size;
25
}
26
27
-static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent,
28
- int64_t sector_num)
29
-{
30
- uint64_t offset;
31
- offset = vmdk_find_offset_in_cluster(extent, sector_num * BDRV_SECTOR_SIZE);
32
- return offset / BDRV_SECTOR_SIZE;
33
-}
34
-
35
-static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
36
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
37
+static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
38
+ bool want_zero,
39
+ int64_t offset, int64_t bytes,
40
+ int64_t *pnum, int64_t *map,
41
+ BlockDriverState **file)
42
{
43
BDRVVmdkState *s = bs->opaque;
44
int64_t index_in_cluster, n, ret;
45
- uint64_t offset;
46
+ uint64_t cluster_offset;
47
VmdkExtent *extent;
48
49
- extent = find_extent(s, sector_num, NULL);
50
+ extent = find_extent(s, offset >> BDRV_SECTOR_BITS, NULL);
51
if (!extent) {
52
- return 0;
53
+ return -EIO;
54
}
55
qemu_co_mutex_lock(&s->lock);
56
- ret = get_cluster_offset(bs, extent, NULL,
57
- sector_num * 512, false, &offset,
58
+ ret = get_cluster_offset(bs, extent, NULL, offset, false, &cluster_offset,
59
0, 0);
60
qemu_co_mutex_unlock(&s->lock);
61
62
- index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
63
+ index_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
64
switch (ret) {
65
case VMDK_ERROR:
66
ret = -EIO;
67
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
68
ret = BDRV_BLOCK_DATA;
69
if (!extent->compressed) {
70
ret |= BDRV_BLOCK_OFFSET_VALID;
71
- ret |= (offset + (index_in_cluster << BDRV_SECTOR_BITS))
72
- & BDRV_BLOCK_OFFSET_MASK;
73
+ *map = cluster_offset + index_in_cluster;
74
}
75
*file = extent->file->bs;
76
break;
77
}
78
79
- n = extent->cluster_sectors - index_in_cluster;
80
- if (n > nb_sectors) {
81
- n = nb_sectors;
82
- }
83
- *pnum = n;
84
+ n = extent->cluster_sectors * BDRV_SECTOR_SIZE - index_in_cluster;
85
+ *pnum = MIN(n, bytes);
86
return ret;
52
return ret;
87
}
53
}
88
54
89
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
55
-static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs,
90
.bdrv_close = vmdk_close,
56
- Error **errp)
91
.bdrv_create = vmdk_create,
57
+static ImageInfoSpecific * GRAPH_RDLOCK
92
.bdrv_co_flush_to_disk = vmdk_co_flush,
58
+vmdk_get_specific_info(BlockDriverState *bs, Error **errp)
93
- .bdrv_co_get_block_status = vmdk_co_get_block_status,
59
{
94
+ .bdrv_co_block_status = vmdk_co_block_status,
60
int i;
95
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
61
BDRVVmdkState *s = bs->opaque;
96
.bdrv_has_zero_init = vmdk_has_zero_init,
62
ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
97
.bdrv_get_specific_info = vmdk_get_specific_info,
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
}
98
--
84
--
99
2.13.6
85
2.41.0
100
101
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
Almost all functions that access the parent link already take the graph
2
lock now. Add locking to the remaining user in a test case and finally
3
annotate the struct field itself as protected by the graph lock.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the file protocol driver accordingly.
6
Message-ID: <20230929145157.45443-21-kwolf@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
In want_zero mode, we continue to report fine-grained hole
7
information (the caller wants as much mapping detail as possible);
8
but when not in that mode, the caller prefers larger *pnum and
9
merely cares about what offsets are allocated at this layer, rather
10
than where the holes live. Since holes still read as zeroes at
11
this layer (rather than deferring to a backing layer), we can take
12
the shortcut of skipping lseek(), and merely state that all bytes
13
are allocated.
14
15
We can also drop redundant bounds checks that are already
16
guaranteed by the block layer.
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
20
Reviewed-by: Fam Zheng <famz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
9
---
23
block/file-posix.c | 64 +++++++++++++++++++++++++-----------------------------
10
include/block/block_int-common.h | 4 ++--
24
1 file changed, 30 insertions(+), 34 deletions(-)
11
tests/unit/test-block-iothread.c | 5 +++++
12
2 files changed, 7 insertions(+), 2 deletions(-)
25
13
26
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
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/block/file-posix.c
16
--- a/include/block/block_int-common.h
29
+++ b/block/file-posix.c
17
+++ b/include/block/block_int-common.h
30
@@ -XXX,XX +XXX,XX @@ static int find_allocation(BlockDriverState *bs, off_t start,
18
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
31
}
19
bool quiesced_parent;
20
21
QLIST_ENTRY(BdrvChild) next;
22
- QLIST_ENTRY(BdrvChild) next_parent;
23
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
24
};
32
25
33
/*
26
/*
34
- * Returns the allocation status of the specified sectors.
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
35
+ * Returns the allocation status of the specified offset.
28
BdrvChild *backing;
36
*
29
BdrvChild *file;
37
- * If 'sector_num' is beyond the end of the disk image the return value is 0
30
38
- * and 'pnum' is set to 0.
31
- QLIST_HEAD(, BdrvChild) parents;
39
+ * The block layer guarantees 'offset' and 'bytes' are within bounds.
32
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) parents;
40
*
33
41
- * 'pnum' is set to the number of sectors (including and immediately following
34
QDict *options;
42
- * the specified sector) that are known to be in the same
35
QDict *explicit_options;
43
+ * 'pnum' is set to the number of bytes (including and immediately following
36
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
44
+ * the specified offset) that are known to be in the same
37
index XXXXXXX..XXXXXXX 100644
45
* allocated/unallocated state.
38
--- a/tests/unit/test-block-iothread.c
46
*
39
+++ b/tests/unit/test-block-iothread.c
47
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
40
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
48
- * beyond the end of the disk image it will be clamped.
41
BlockDriverState *bs;
49
+ * 'bytes' is the max value 'pnum' should be set to.
42
BdrvChild *c;
50
*/
43
51
-static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
44
+ GLOBAL_STATE_CODE();
52
- int64_t sector_num,
45
+
53
- int nb_sectors, int *pnum,
46
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
54
- BlockDriverState **file)
47
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
55
-{
48
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
56
- off_t start, data = 0, hole = 0;
49
blk_insert_bs(blk, bs, &error_abort);
57
- int64_t total_size;
50
+
58
+static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
51
+ bdrv_graph_rdlock_main_loop();
59
+ bool want_zero,
52
c = QLIST_FIRST(&bs->parents);
60
+ int64_t offset,
53
+ bdrv_graph_rdunlock_main_loop();
61
+ int64_t bytes, int64_t *pnum,
54
62
+ int64_t *map,
55
blk_set_aio_context(blk, ctx, &error_abort);
63
+ BlockDriverState **file)
56
aio_context_acquire(ctx);
64
+{
65
+ off_t data = 0, hole = 0;
66
int ret;
67
68
ret = fd_open(bs);
69
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
70
return ret;
71
}
72
73
- start = sector_num * BDRV_SECTOR_SIZE;
74
- total_size = bdrv_getlength(bs);
75
- if (total_size < 0) {
76
- return total_size;
77
- } else if (start >= total_size) {
78
- *pnum = 0;
79
- return 0;
80
- } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
81
- nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
82
+ if (!want_zero) {
83
+ *pnum = bytes;
84
+ *map = offset;
85
+ *file = bs;
86
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
87
}
88
89
- ret = find_allocation(bs, start, &data, &hole);
90
+ ret = find_allocation(bs, offset, &data, &hole);
91
if (ret == -ENXIO) {
92
/* Trailing hole */
93
- *pnum = nb_sectors;
94
+ *pnum = bytes;
95
ret = BDRV_BLOCK_ZERO;
96
} else if (ret < 0) {
97
/* No info available, so pretend there are no holes */
98
- *pnum = nb_sectors;
99
+ *pnum = bytes;
100
ret = BDRV_BLOCK_DATA;
101
- } else if (data == start) {
102
- /* On a data extent, compute sectors to the end of the extent,
103
+ } else if (data == offset) {
104
+ /* On a data extent, compute bytes to the end of the extent,
105
* possibly including a partial sector at EOF. */
106
- *pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
107
+ *pnum = MIN(bytes, hole - offset);
108
ret = BDRV_BLOCK_DATA;
109
} else {
110
- /* On a hole, compute sectors to the beginning of the next extent. */
111
- assert(hole == start);
112
- *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
113
+ /* On a hole, compute bytes to the beginning of the next extent. */
114
+ assert(hole == offset);
115
+ *pnum = MIN(bytes, data - offset);
116
ret = BDRV_BLOCK_ZERO;
117
}
118
+ *map = offset;
119
*file = bs;
120
- return ret | BDRV_BLOCK_OFFSET_VALID | start;
121
+ return ret | BDRV_BLOCK_OFFSET_VALID;
122
}
123
124
static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
125
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
126
.bdrv_close = raw_close,
127
.bdrv_create = raw_create,
128
.bdrv_has_zero_init = bdrv_has_zero_init_1,
129
- .bdrv_co_get_block_status = raw_co_get_block_status,
130
+ .bdrv_co_block_status = raw_co_block_status,
131
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
132
133
.bdrv_co_preadv = raw_co_preadv,
134
--
57
--
135
2.13.6
58
2.41.0
136
137
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually converting to byte-based interfaces, as they are
4
easier to reason about than sector-based. Convert all uses of
5
the cluster size in sectors, along with adding assertions that we
6
are not dividing by zero.
7
8
Improve some comment grammar while in the area.
9
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/iscsi.c | 56 +++++++++++++++++++++++++++++++++++---------------------
16
1 file changed, 35 insertions(+), 21 deletions(-)
17
18
diff --git a/block/iscsi.c b/block/iscsi.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/iscsi.c
21
+++ b/block/iscsi.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct IscsiLun {
23
unsigned long *allocmap;
24
unsigned long *allocmap_valid;
25
long allocmap_size;
26
- int cluster_sectors;
27
+ int cluster_size;
28
bool use_16_for_rw;
29
bool write_protected;
30
bool lbpme;
31
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
32
{
33
iscsi_allocmap_free(iscsilun);
34
35
+ assert(iscsilun->cluster_size);
36
iscsilun->allocmap_size =
37
- DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks, iscsilun),
38
- iscsilun->cluster_sectors);
39
+ DIV_ROUND_UP(iscsilun->num_blocks * iscsilun->block_size,
40
+ iscsilun->cluster_size);
41
42
iscsilun->allocmap = bitmap_try_new(iscsilun->allocmap_size);
43
if (!iscsilun->allocmap) {
44
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
45
}
46
47
if (open_flags & BDRV_O_NOCACHE) {
48
- /* in case that cache.direct = on all allocmap entries are
49
+ /* when cache.direct = on all allocmap entries are
50
* treated as invalid to force a relookup of the block
51
* status on every read request */
52
return 0;
53
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
54
int nb_sectors, bool allocated, bool valid)
55
{
56
int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk;
57
+ int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
58
59
if (iscsilun->allocmap == NULL) {
60
return;
61
}
62
/* expand to entirely contain all affected clusters */
63
- cl_num_expanded = sector_num / iscsilun->cluster_sectors;
64
+ assert(cluster_sectors);
65
+ cl_num_expanded = sector_num / cluster_sectors;
66
nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors,
67
- iscsilun->cluster_sectors) - cl_num_expanded;
68
+ cluster_sectors) - cl_num_expanded;
69
/* shrink to touch only completely contained clusters */
70
- cl_num_shrunk = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors);
71
- nb_cls_shrunk = (sector_num + nb_sectors) / iscsilun->cluster_sectors
72
+ cl_num_shrunk = DIV_ROUND_UP(sector_num, cluster_sectors);
73
+ nb_cls_shrunk = (sector_num + nb_sectors) / cluster_sectors
74
- cl_num_shrunk;
75
if (allocated) {
76
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
77
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num,
78
if (iscsilun->allocmap == NULL) {
79
return true;
80
}
81
- size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
82
+ assert(iscsilun->cluster_size);
83
+ size = DIV_ROUND_UP(sector_num + nb_sectors,
84
+ iscsilun->cluster_size >> BDRV_SECTOR_BITS);
85
return !(find_next_bit(iscsilun->allocmap, size,
86
- sector_num / iscsilun->cluster_sectors) == size);
87
+ sector_num * BDRV_SECTOR_SIZE /
88
+ iscsilun->cluster_size) == size);
89
}
90
91
static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
92
@@ -XXX,XX +XXX,XX @@ static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
93
if (iscsilun->allocmap_valid == NULL) {
94
return false;
95
}
96
- size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
97
+ assert(iscsilun->cluster_size);
98
+ size = DIV_ROUND_UP(sector_num + nb_sectors,
99
+ iscsilun->cluster_size >> BDRV_SECTOR_BITS);
100
return (find_next_zero_bit(iscsilun->allocmap_valid, size,
101
- sector_num / iscsilun->cluster_sectors) == size);
102
+ sector_num * BDRV_SECTOR_SIZE /
103
+ iscsilun->cluster_size) == size);
104
}
105
106
static int coroutine_fn
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
108
BlockDriverState *file;
109
/* check the block status from the beginning of the cluster
110
* containing the start sector */
111
- int64_t ret = iscsi_co_get_block_status(bs,
112
- sector_num - sector_num % iscsilun->cluster_sectors,
113
- BDRV_REQUEST_MAX_SECTORS, &pnum, &file);
114
+ int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
115
+ int head;
116
+ int64_t ret;
117
+
118
+ assert(cluster_sectors);
119
+ head = sector_num % cluster_sectors;
120
+ ret = iscsi_co_get_block_status(bs, sector_num - head,
121
+ BDRV_REQUEST_MAX_SECTORS, &pnum,
122
+ &file);
123
if (ret < 0) {
124
return ret;
125
}
126
/* if the whole request falls into an unallocated area we can avoid
127
- * to read and directly return zeroes instead */
128
- if (ret & BDRV_BLOCK_ZERO &&
129
- pnum >= nb_sectors + sector_num % iscsilun->cluster_sectors) {
130
+ * reading and directly return zeroes instead */
131
+ if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors + head) {
132
qemu_iovec_memset(iov, 0, 0x00, iov->size);
133
return 0;
134
}
135
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
136
* reasonable size */
137
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
138
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
139
- iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
140
- iscsilun->block_size) >> BDRV_SECTOR_BITS;
141
+ iscsilun->cluster_size = iscsilun->bl.opt_unmap_gran *
142
+ iscsilun->block_size;
143
if (iscsilun->lbprz) {
144
ret = iscsi_allocmap_init(iscsilun, bs->open_flags);
145
}
146
@@ -XXX,XX +XXX,XX @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
147
{
148
IscsiLun *iscsilun = bs->opaque;
149
bdi->unallocated_blocks_are_zero = iscsilun->lbprz;
150
- bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE;
151
+ bdi->cluster_size = iscsilun->cluster_size;
152
return 0;
153
}
154
155
--
156
2.13.6
157
158
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Update the parallels driver accordingly. Note that
5
the internal function block_status() is still sector-based, because
6
it is still in use by other sector-based functions; but that's okay
7
because request_alignment is 512 as a result of those functions.
8
For now, no optimizations are added based on the mapping hint.
9
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/parallels.c | 22 +++++++++++++++-------
16
1 file changed, 15 insertions(+), 7 deletions(-)
17
18
diff --git a/block/parallels.c b/block/parallels.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/parallels.c
21
+++ b/block/parallels.c
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
23
}
24
25
26
-static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
27
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
28
+static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
29
+ bool want_zero,
30
+ int64_t offset,
31
+ int64_t bytes,
32
+ int64_t *pnum,
33
+ int64_t *map,
34
+ BlockDriverState **file)
35
{
36
BDRVParallelsState *s = bs->opaque;
37
- int64_t offset;
38
+ int count;
39
40
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
41
qemu_co_mutex_lock(&s->lock);
42
- offset = block_status(s, sector_num, nb_sectors, pnum);
43
+ offset = block_status(s, offset >> BDRV_SECTOR_BITS,
44
+ bytes >> BDRV_SECTOR_BITS, &count);
45
qemu_co_mutex_unlock(&s->lock);
46
47
+ *pnum = count * BDRV_SECTOR_SIZE;
48
if (offset < 0) {
49
return 0;
50
}
51
52
+ *map = offset * BDRV_SECTOR_SIZE;
53
*file = bs->file->bs;
54
- return (offset << BDRV_SECTOR_BITS) |
55
- BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
56
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
57
}
58
59
static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
60
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
61
.bdrv_open        = parallels_open,
62
.bdrv_close        = parallels_close,
63
.bdrv_child_perm = bdrv_format_default_perms,
64
- .bdrv_co_get_block_status = parallels_co_get_block_status,
65
+ .bdrv_co_block_status = parallels_co_block_status,
66
.bdrv_has_zero_init = bdrv_has_zero_init_1,
67
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
68
.bdrv_co_readv = parallels_co_readv,
69
--
70
2.13.6
71
72
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Update the sheepdog driver accordingly.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/sheepdog.c | 26 +++++++++++++-------------
13
1 file changed, 13 insertions(+), 13 deletions(-)
14
15
diff --git a/block/sheepdog.c b/block/sheepdog.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/sheepdog.c
18
+++ b/block/sheepdog.c
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
20
return acb.ret;
21
}
22
23
-static coroutine_fn int64_t
24
-sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
25
- int *pnum, BlockDriverState **file)
26
+static coroutine_fn int
27
+sd_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *pnum, int64_t *map,
29
+ BlockDriverState **file)
30
{
31
BDRVSheepdogState *s = bs->opaque;
32
SheepdogInode *inode = &s->inode;
33
uint32_t object_size = (UINT32_C(1) << inode->block_size_shift);
34
- uint64_t offset = sector_num * BDRV_SECTOR_SIZE;
35
unsigned long start = offset / object_size,
36
- end = DIV_ROUND_UP((sector_num + nb_sectors) *
37
- BDRV_SECTOR_SIZE, object_size);
38
+ end = DIV_ROUND_UP(offset + bytes, object_size);
39
unsigned long idx;
40
- int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
41
+ *map = offset;
42
+ int ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
43
44
for (idx = start; idx < end; idx++) {
45
if (inode->data_vdi_id[idx] == 0) {
46
@@ -XXX,XX +XXX,XX @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
47
}
48
}
49
50
- *pnum = (idx - start) * object_size / BDRV_SECTOR_SIZE;
51
- if (*pnum > nb_sectors) {
52
- *pnum = nb_sectors;
53
+ *pnum = (idx - start) * object_size;
54
+ if (*pnum > bytes) {
55
+ *pnum = bytes;
56
}
57
if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) {
58
*file = bs;
59
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
60
.bdrv_co_writev = sd_co_writev,
61
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
62
.bdrv_co_pdiscard = sd_co_pdiscard,
63
- .bdrv_co_get_block_status = sd_co_get_block_status,
64
+ .bdrv_co_block_status = sd_co_block_status,
65
66
.bdrv_snapshot_create = sd_snapshot_create,
67
.bdrv_snapshot_goto = sd_snapshot_goto,
68
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
69
.bdrv_co_writev = sd_co_writev,
70
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
71
.bdrv_co_pdiscard = sd_co_pdiscard,
72
- .bdrv_co_get_block_status = sd_co_get_block_status,
73
+ .bdrv_co_block_status = sd_co_block_status,
74
75
.bdrv_snapshot_create = sd_snapshot_create,
76
.bdrv_snapshot_goto = sd_snapshot_goto,
77
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
78
.bdrv_co_writev = sd_co_writev,
79
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
80
.bdrv_co_pdiscard = sd_co_pdiscard,
81
- .bdrv_co_get_block_status = sd_co_get_block_status,
82
+ .bdrv_co_block_status = sd_co_block_status,
83
84
.bdrv_snapshot_create = sd_snapshot_create,
85
.bdrv_snapshot_goto = sd_snapshot_goto,
86
--
87
2.13.6
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Rework the debug define so that we always get -Wformat checking,
4
even when debugging is disabled.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefan Weil <sw@weilnetz.de>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/vdi.c | 12 +++++++++---
14
1 file changed, 9 insertions(+), 3 deletions(-)
15
16
diff --git a/block/vdi.c b/block/vdi.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vdi.c
19
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@
21
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
22
23
#if defined(CONFIG_VDI_DEBUG)
24
-#define logout(fmt, ...) \
25
- fprintf(stderr, "vdi\t%-24s" fmt, __func__, ##__VA_ARGS__)
26
+#define VDI_DEBUG 1
27
#else
28
-#define logout(fmt, ...) ((void)0)
29
+#define VDI_DEBUG 0
30
#endif
31
32
+#define logout(fmt, ...) \
33
+ do { \
34
+ if (VDI_DEBUG) { \
35
+ fprintf(stderr, "vdi\t%-24s" fmt, __func__, ##__VA_ARGS__); \
36
+ } \
37
+ } while (0)
38
+
39
/* Image signature. */
40
#define VDI_SIGNATURE 0xbeda107f
41
42
--
43
2.13.6
44
45
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
Almost all functions that access the child links already take the graph
2
lock now. Add locking to the remaining users and finally annotate the
3
struct field itself as protected by the graph lock.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the vdi driver accordingly. Note that the
6
Message-ID: <20230929145157.45443-22-kwolf@redhat.com>
5
TODO is already covered (the block layer guarantees bounds of its
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
requests), and that we can remove the now-unused s->block_sectors.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block/vdi.c | 33 +++++++++++++--------------------
10
include/block/block_int-common.h | 4 ++--
14
1 file changed, 13 insertions(+), 20 deletions(-)
11
block.c | 2 ++
12
block/replication.c | 3 ++-
13
tests/unit/test-bdrv-drain.c | 4 ++++
14
4 files changed, 10 insertions(+), 3 deletions(-)
15
15
16
diff --git a/block/vdi.c b/block/vdi.c
16
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vdi.c
18
--- a/include/block/block_int-common.h
19
+++ b/block/vdi.c
19
+++ b/include/block/block_int-common.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
21
uint32_t *bmap;
21
*/
22
/* Size of block (bytes). */
22
bool quiesced_parent;
23
uint32_t block_size;
23
24
- /* Size of block (sectors). */
24
- QLIST_ENTRY(BdrvChild) next;
25
- uint32_t block_sectors;
25
+ QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next;
26
/* First sector of block map. */
26
QLIST_ENTRY(BdrvChild GRAPH_RDLOCK_PTR) next_parent;
27
uint32_t bmap_sector;
27
};
28
/* VDI header (converted to host endianness). */
28
29
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
30
bs->total_sectors = header.disk_size / SECTOR_SIZE;
30
* See also comment in include/block/block.h, to learn how backing and file
31
31
* are connected with BdrvChildRole.
32
s->block_size = header.block_size;
32
*/
33
- s->block_sectors = header.block_size / SECTOR_SIZE;
33
- QLIST_HEAD(, BdrvChild) children;
34
s->bmap_sector = header.offset_bmap / SECTOR_SIZE;
34
+ QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) children;
35
s->header = header;
35
BdrvChild *backing;
36
36
BdrvChild *file;
37
@@ -XXX,XX +XXX,XX @@ static int vdi_reopen_prepare(BDRVReopenState *state,
37
38
return 0;
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();
47
+
48
assert(!child->next.le_prev); /* not in children list */
49
50
g_free(child->name);
51
diff --git a/block/replication.c b/block/replication.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/replication.c
54
+++ b/block/replication.c
55
@@ -XXX,XX +XXX,XX @@ static void backup_job_completed(void *opaque, int ret)
56
backup_job_cleanup(bs);
39
}
57
}
40
58
41
-static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs,
59
-static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
42
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
60
+static bool GRAPH_RDLOCK
43
+static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
61
+check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
44
+ bool want_zero,
45
+ int64_t offset, int64_t bytes,
46
+ int64_t *pnum, int64_t *map,
47
+ BlockDriverState **file)
48
{
62
{
49
- /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
63
BdrvChild *child;
50
BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
64
51
- size_t bmap_index = sector_num / s->block_sectors;
65
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
52
- size_t sector_in_block = sector_num % s->block_sectors;
66
index XXXXXXX..XXXXXXX 100644
53
- int n_sectors = s->block_sectors - sector_in_block;
67
--- a/tests/unit/test-bdrv-drain.c
54
+ size_t bmap_index = offset / s->block_size;
68
+++ b/tests/unit/test-bdrv-drain.c
55
+ size_t index_in_block = offset % s->block_size;
69
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
56
uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
70
blk_co_unref(blk);
57
- uint64_t offset;
71
} else {
58
int result;
72
BdrvChild *c, *next_c;
59
73
+ bdrv_graph_co_rdlock();
60
- logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
74
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
61
- if (n_sectors > nb_sectors) {
75
+ bdrv_graph_co_rdunlock();
62
- n_sectors = nb_sectors;
76
bdrv_co_unref_child(bs, c);
63
- }
77
+ bdrv_graph_co_rdlock();
64
- *pnum = n_sectors;
78
}
65
+ logout("%p, %" PRId64 ", %" PRId64 ", %p\n", bs, offset, bytes, pnum);
79
+ bdrv_graph_co_rdunlock();
66
+ *pnum = MIN(s->block_size - index_in_block, bytes);
67
result = VDI_IS_ALLOCATED(bmap_entry);
68
if (!result) {
69
return 0;
70
}
80
}
71
81
72
- offset = s->header.offset_data +
82
dbdd->done = true;
73
- (uint64_t)bmap_entry * s->block_size +
74
- sector_in_block * SECTOR_SIZE;
75
+ *map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
76
+ index_in_block;
77
*file = bs->file->bs;
78
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
79
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
80
}
81
82
static int coroutine_fn
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
84
.bdrv_child_perm = bdrv_format_default_perms,
85
.bdrv_create = vdi_create,
86
.bdrv_has_zero_init = bdrv_has_zero_init_1,
87
- .bdrv_co_get_block_status = vdi_co_get_block_status,
88
+ .bdrv_co_block_status = vdi_co_block_status,
89
.bdrv_make_empty = vdi_make_empty,
90
91
.bdrv_co_preadv = vdi_co_preadv,
92
--
83
--
93
2.13.6
84
2.41.0
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
2
1
3
This new test case only makes sense for qcow2 while iotest 033 is generic;
4
however it matches the test purpose perfectly and also 033 contains those
5
do_test() tricks to pass the alignment, which won't look nice being
6
duplicated in other tests or moved to the common code.
7
8
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/qemu-iotests/033 | 29 +++++++++++++++++++++++++++++
12
tests/qemu-iotests/033.out | 13 +++++++++++++
13
2 files changed, 42 insertions(+)
14
15
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/033
18
+++ b/tests/qemu-iotests/033
19
@@ -XXX,XX +XXX,XX @@ do_test()
20
    } | $QEMU_IO $IO_EXTRA_ARGS
21
}
22
23
+echo
24
+echo "=== Test aligned and misaligned write zeroes operations ==="
25
+
26
for write_zero_cmd in "write -z" "aio_write -z"; do
27
for align in 512 4k; do
28
    echo
29
@@ -XXX,XX +XXX,XX @@ for align in 512 4k; do
30
done
31
done
32
33
+
34
+# Trigger truncate that would shrink qcow2 L1 table, which is done by
35
+# clearing one entry (8 bytes) with bdrv_co_pwrite_zeroes()
36
+
37
+echo
38
+echo "=== Test misaligned write zeroes via truncate ==="
39
+echo
40
+
41
+# any size will do, but the smaller the size the smaller the required image
42
+CLUSTER_SIZE=$((4 * 1024))
43
+L2_COVERAGE=$(($CLUSTER_SIZE * $CLUSTER_SIZE / 8))
44
+_make_test_img $(($L2_COVERAGE * 2))
45
+
46
+do_test 512 "write -P 1 0 0x200" "$TEST_IMG" | _filter_qemu_io
47
+# next L2 table
48
+do_test 512 "write -P 1 $L2_COVERAGE 0x200" "$TEST_IMG" | _filter_qemu_io
49
+
50
+# only interested in qcow2 here; also other formats might respond with
51
+# "not supported" error message
52
+if [ $IMGFMT = "qcow2" ]; then
53
+ do_test 512 "truncate $L2_COVERAGE" "$TEST_IMG" | _filter_qemu_io
54
+fi
55
+
56
+do_test 512 "read -P 1 0 0x200" "$TEST_IMG" | _filter_qemu_io
57
+
58
# success, all done
59
+echo
60
echo "*** done"
61
rm -f $seq.full
62
status=0
63
diff --git a/tests/qemu-iotests/033.out b/tests/qemu-iotests/033.out
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tests/qemu-iotests/033.out
66
+++ b/tests/qemu-iotests/033.out
67
@@ -XXX,XX +XXX,XX @@
68
QA output created by 033
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
70
71
+=== Test aligned and misaligned write zeroes operations ===
72
+
73
== preparing image ==
74
wrote 1024/1024 bytes at offset 512
75
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
76
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 512
77
read 3072/3072 bytes at offset 1024
78
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
79
80
+
81
+=== Test misaligned write zeroes via truncate ===
82
+
83
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
84
+wrote 512/512 bytes at offset 0
85
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
+wrote 512/512 bytes at offset 2097152
87
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
88
+read 512/512 bytes at offset 0
89
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
+
91
*** done
92
--
93
2.13.6
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This patch fixes several mistakes in the documentation of the
4
compressed cluster descriptor:
5
6
1) the documentation claims that the cluster descriptor contains the
7
number of sectors used to store the compressed data, but what it
8
actually contains is the number of sectors *minus one* or, in other
9
words, the number of additional sectors after the first one.
10
11
2) the width of the fields is incorrectly specified. The number of bits
12
used by each field is
13
14
x = 62 - (cluster_bits - 8) for the offset field
15
y = (cluster_bits - 8) for the size field
16
17
So the offset field's location is [0, x-1], not [0, x] as stated.
18
19
3) the size field does not contain the size of the compressed data,
20
but rather the number of sectors where that data is stored. The
21
compressed data starts at the exact point specified in the offset
22
field and ends when there's enough data to produce a cluster of
23
decompressed data. Both points can be in the middle of a sector,
24
allowing several compressed clusters to be stored next to one
25
another, sharing sectors if necessary.
26
27
Cc: qemu-stable@nongnu.org
28
Signed-off-by: Alberto Garcia <berto@igalia.com>
29
Reviewed-by: Eric Blake <eblake@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
---
32
docs/interop/qcow2.txt | 16 +++++++++++++---
33
1 file changed, 13 insertions(+), 3 deletions(-)
34
35
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
36
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/interop/qcow2.txt
38
+++ b/docs/interop/qcow2.txt
39
@@ -XXX,XX +XXX,XX @@ Standard Cluster Descriptor:
40
41
Compressed Clusters Descriptor (x = 62 - (cluster_bits - 8)):
42
43
- Bit 0 - x: Host cluster offset. This is usually _not_ aligned to a
44
- cluster boundary!
45
+ Bit 0 - x-1: Host cluster offset. This is usually _not_ aligned to a
46
+ cluster or sector boundary!
47
48
- x+1 - 61: Compressed size of the images in sectors of 512 bytes
49
+ x - 61: Number of additional 512-byte sectors used for the
50
+ compressed data, beyond the sector containing the offset
51
+ in the previous field. Some of these sectors may reside
52
+ in the next contiguous host cluster.
53
+
54
+ Note that the compressed data does not necessarily occupy
55
+ all of the bytes in the final sector; rather, decompression
56
+ stops when it has produced a cluster of data.
57
+
58
+ Another compressed cluster may map to the tail of the final
59
+ sector used by this compressed cluster.
60
61
If a cluster is unallocated, read requests shall read the data from the backing
62
file (except if bit 0 in the Standard Cluster Descriptor is set). If there is
63
--
64
2.13.6
65
66
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This patch updates docs/qcow2-cache.txt explaining how to use the new
4
l2-cache-entry-size parameter.
5
6
Here's a more detailed technical description of this feature:
7
8
https://lists.gnu.org/archive/html/qemu-block/2017-09/msg00635.html
9
10
And here are some performance numbers:
11
12
https://lists.gnu.org/archive/html/qemu-block/2017-12/msg00507.html
13
14
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
docs/qcow2-cache.txt | 46 +++++++++++++++++++++++++++++++++++++++++++---
19
1 file changed, 43 insertions(+), 3 deletions(-)
20
21
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/qcow2-cache.txt
24
+++ b/docs/qcow2-cache.txt
25
@@ -XXX,XX +XXX,XX @@
26
qcow2 L2/refcount cache configuration
27
=====================================
28
-Copyright (C) 2015 Igalia, S.L.
29
+Copyright (C) 2015, 2018 Igalia, S.L.
30
Author: Alberto Garcia <berto@igalia.com>
31
32
This work is licensed under the terms of the GNU GPL, version 2 or
33
@@ -XXX,XX +XXX,XX @@ There are three options available, and all of them take bytes:
34
35
There are two things that need to be taken into account:
36
37
- - Both caches must have a size that is a multiple of the cluster
38
- size.
39
+ - Both caches must have a size that is a multiple of the cluster size
40
+ (or the cache entry size: see "Using smaller cache sizes" below).
41
42
- If you only set one of the options above, QEMU will automatically
43
adjust the others so that the L2 cache is 4 times bigger than the
44
@@ -XXX,XX +XXX,XX @@ much less often than the L2 cache, so it's perfectly reasonable to
45
keep it small.
46
47
48
+Using smaller cache entries
49
+---------------------------
50
+The qcow2 L2 cache stores complete tables by default. This means that
51
+if QEMU needs an entry from an L2 table then the whole table is read
52
+from disk and is kept in the cache. If the cache is full then a
53
+complete table needs to be evicted first.
54
+
55
+This can be inefficient with large cluster sizes since it results in
56
+more disk I/O and wastes more cache memory.
57
+
58
+Since QEMU 2.12 you can change the size of the L2 cache entry and make
59
+it smaller than the cluster size. This can be configured using the
60
+"l2-cache-entry-size" parameter:
61
+
62
+ -drive file=hd.qcow2,l2-cache-size=2097152,l2-cache-entry-size=4096
63
+
64
+Some things to take into account:
65
+
66
+ - The L2 cache entry size has the same restrictions as the cluster
67
+ size (power of two, at least 512 bytes).
68
+
69
+ - Smaller entry sizes generally improve the cache efficiency and make
70
+ disk I/O faster. This is particularly true with solid state drives
71
+ so it's a good idea to reduce the entry size in those cases. With
72
+ rotating hard drives the situation is a bit more complicated so you
73
+ should test it first and stay with the default size if unsure.
74
+
75
+ - Try different entry sizes to see which one gives faster performance
76
+ in your case. The block size of the host filesystem is generally a
77
+ good default (usually 4096 bytes in the case of ext4).
78
+
79
+ - Only the L2 cache can be configured this way. The refcount cache
80
+ always uses the cluster size as the entry size.
81
+
82
+ - If the L2 cache is big enough to hold all of the image's L2 tables
83
+ (as explained in the "Choosing the right cache sizes" section
84
+ earlier in this document) then none of this is necessary and you
85
+ can omit the "l2-cache-entry-size" parameter altogether.
86
+
87
+
88
Reducing the memory usage
89
-------------------------
90
It is possible to clean unused cache entries in order to reduce the
91
--
92
2.13.6
93
94
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
The name aio_context_in_iothread() is misleading because it also returns
4
true when called on the main AioContext from the main loop thread, which
5
is not an IOThread.
6
7
This patch renames it to in_aio_context_home_thread() and expands the
8
doc comment to make the semantics clearer.
9
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
include/block/aio.h | 7 +++++--
15
include/block/block.h | 2 +-
16
2 files changed, 6 insertions(+), 3 deletions(-)
17
18
diff --git a/include/block/aio.h b/include/block/aio.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/aio.h
21
+++ b/include/block/aio.h
22
@@ -XXX,XX +XXX,XX @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co);
23
AioContext *qemu_get_current_aio_context(void);
24
25
/**
26
+ * in_aio_context_home_thread:
27
* @ctx: the aio context
28
*
29
- * Return whether we are running in the I/O thread that manages @ctx.
30
+ * Return whether we are running in the thread that normally runs @ctx. Note
31
+ * that acquiring/releasing ctx does not affect the outcome, each AioContext
32
+ * still only has one home thread that is responsible for running it.
33
*/
34
-static inline bool aio_context_in_iothread(AioContext *ctx)
35
+static inline bool in_aio_context_home_thread(AioContext *ctx)
36
{
37
return ctx == qemu_get_current_aio_context();
38
}
39
diff --git a/include/block/block.h b/include/block/block.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/block/block.h
42
+++ b/include/block/block.h
43
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all(void);
44
bool busy_ = true; \
45
BlockDriverState *bs_ = (bs); \
46
AioContext *ctx_ = bdrv_get_aio_context(bs_); \
47
- if (aio_context_in_iothread(ctx_)) { \
48
+ if (in_aio_context_home_thread(ctx_)) { \
49
while ((cond) || busy_) { \
50
busy_ = aio_poll(ctx_, (cond)); \
51
waited_ |= !!(cond) | busy_; \
52
--
53
2.13.6
54
55
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.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
This reverts commit 4da97120d51a4383aa96d741a2b837f8c4bbcd0b.
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
6
Message-ID: <20230929145157.45443-23-kwolf@redhat.com>
5
blk_aio_flush() now handles the blk->root == NULL case, so we no longer
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
need this workaround.
7
8
Cc: John Snow <jsnow@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
hw/ide/core.c | 10 +---------
10
include/block/graph-lock.h | 3 ++-
14
1 file changed, 1 insertion(+), 9 deletions(-)
11
block/graph-lock.c | 3 ++-
12
2 files changed, 4 insertions(+), 2 deletions(-)
15
13
16
diff --git a/hw/ide/core.c b/hw/ide/core.c
14
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ide/core.c
16
--- a/include/block/graph-lock.h
19
+++ b/hw/ide/core.c
17
+++ b/include/block/graph-lock.h
20
@@ -XXX,XX +XXX,XX @@ static void ide_flush_cache(IDEState *s)
18
@@ -XXX,XX +XXX,XX @@ void unregister_aiocontext(AioContext *ctx);
21
s->status |= BUSY_STAT;
19
* This function polls. Callers must not hold the lock of any AioContext other
22
ide_set_retry(s);
20
* than the current one and the one of @bs.
23
block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
21
*/
24
-
22
-void bdrv_graph_wrlock(BlockDriverState *bs) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
25
- if (blk_bs(s->blk)) {
23
+void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA
26
- s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
24
+bdrv_graph_wrlock(BlockDriverState *bs);
27
- } else {
25
28
- /* XXX blk_aio_flush() crashes when blk_bs(blk) is NULL, remove this
26
/*
29
- * temporary workaround when blk_aio_*() functions handle NULL blk_bs.
27
* bdrv_graph_wrunlock:
30
- */
28
diff --git a/block/graph-lock.c b/block/graph-lock.c
31
- ide_flush_cb(s, 0);
29
index XXXXXXX..XXXXXXX 100644
32
- }
30
--- a/block/graph-lock.c
33
+ s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
31
+++ b/block/graph-lock.c
32
@@ -XXX,XX +XXX,XX @@ static uint32_t reader_count(void)
33
return rd;
34
}
34
}
35
35
36
static void ide_cfata_metadata_inquiry(IDEState *s)
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
37
--
47
--
38
2.13.6
48
2.41.0
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
If we ever want to offer even rudimentary truncation functionality for
4
ssh, we should put the respective code into a reusable function.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180214204915.7980-2-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/ssh.c | 30 ++++++++++++++++++++++--------
13
1 file changed, 22 insertions(+), 8 deletions(-)
14
15
diff --git a/block/ssh.c b/block/ssh.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/ssh.c
18
+++ b/block/ssh.c
19
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
20
return ret;
21
}
22
23
+static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp)
24
+{
25
+ ssize_t ret;
26
+ char c[1] = { '\0' };
27
+
28
+ /* offset must be strictly greater than the current size so we do
29
+ * not overwrite anything */
30
+ assert(offset > 0 && offset > s->attrs.filesize);
31
+
32
+ libssh2_sftp_seek64(s->sftp_handle, offset - 1);
33
+ ret = libssh2_sftp_write(s->sftp_handle, c, 1);
34
+ if (ret < 0) {
35
+ sftp_error_setg(errp, s, "Failed to grow file");
36
+ return -EIO;
37
+ }
38
+
39
+ s->attrs.filesize = offset;
40
+ return 0;
41
+}
42
+
43
static QemuOptsList ssh_create_opts = {
44
.name = "ssh-create-opts",
45
.head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head),
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
47
int64_t total_size = 0;
48
QDict *uri_options = NULL;
49
BDRVSSHState s;
50
- ssize_t r2;
51
- char c[1] = { '\0' };
52
53
ssh_state_init(&s);
54
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
56
}
57
58
if (total_size > 0) {
59
- libssh2_sftp_seek64(s.sftp_handle, total_size-1);
60
- r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
61
- if (r2 < 0) {
62
- sftp_error_setg(errp, &s, "truncate failed");
63
- ret = -EINVAL;
64
+ ret = ssh_grow_file(&s, total_size, errp);
65
+ if (ret < 0) {
66
goto out;
67
}
68
- s.attrs.filesize = total_size;
69
}
70
71
ret = 0;
72
--
73
2.13.6
74
75
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
At runtime (that is, during a future ssh_truncate()), the SSH session is
4
non-blocking. However, ssh_truncate() (or rather, bdrv_truncate() in
5
general) is not a coroutine, so this resize operation needs to block.
6
7
For ssh_create(), that is fine, too; the session is never set to
8
non-blocking anyway.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20180214204915.7980-3-mreitz@redhat.com
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/ssh.c | 7 +++++++
17
1 file changed, 7 insertions(+)
18
19
diff --git a/block/ssh.c b/block/ssh.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/ssh.c
22
+++ b/block/ssh.c
23
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
24
return ret;
25
}
26
27
+/* Note: This is a blocking operation */
28
static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp)
29
{
30
ssize_t ret;
31
char c[1] = { '\0' };
32
+ int was_blocking = libssh2_session_get_blocking(s->session);
33
34
/* offset must be strictly greater than the current size so we do
35
* not overwrite anything */
36
assert(offset > 0 && offset > s->attrs.filesize);
37
38
+ libssh2_session_set_blocking(s->session, 1);
39
+
40
libssh2_sftp_seek64(s->sftp_handle, offset - 1);
41
ret = libssh2_sftp_write(s->sftp_handle, c, 1);
42
+
43
+ libssh2_session_set_blocking(s->session, was_blocking);
44
+
45
if (ret < 0) {
46
sftp_error_setg(errp, s, "Failed to grow file");
47
return -EIO;
48
--
49
2.13.6
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
libssh2 does not seem to offer real truncation support, so we can only
4
grow files -- but that is better than nothing.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180214204915.7980-4-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/ssh.c | 24 ++++++++++++++++++++++++
13
1 file changed, 24 insertions(+)
14
15
diff --git a/block/ssh.c b/block/ssh.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/ssh.c
18
+++ b/block/ssh.c
19
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
20
return length;
21
}
22
23
+static int ssh_truncate(BlockDriverState *bs, int64_t offset,
24
+ PreallocMode prealloc, Error **errp)
25
+{
26
+ BDRVSSHState *s = bs->opaque;
27
+
28
+ if (prealloc != PREALLOC_MODE_OFF) {
29
+ error_setg(errp, "Unsupported preallocation mode '%s'",
30
+ PreallocMode_str(prealloc));
31
+ return -ENOTSUP;
32
+ }
33
+
34
+ if (offset < s->attrs.filesize) {
35
+ error_setg(errp, "ssh driver does not support shrinking files");
36
+ return -ENOTSUP;
37
+ }
38
+
39
+ if (offset == s->attrs.filesize) {
40
+ return 0;
41
+ }
42
+
43
+ return ssh_grow_file(s, offset, errp);
44
+}
45
+
46
static BlockDriver bdrv_ssh = {
47
.format_name = "ssh",
48
.protocol_name = "ssh",
49
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
50
.bdrv_co_readv = ssh_co_readv,
51
.bdrv_co_writev = ssh_co_writev,
52
.bdrv_getlength = ssh_getlength,
53
+ .bdrv_truncate = ssh_truncate,
54
.bdrv_co_flush_to_disk = ssh_co_flush,
55
.create_opts = &ssh_create_opts,
56
};
57
--
58
2.13.6
59
60
diff view generated by jsdifflib