1
The following changes since commit 1e3ee834083227f552179f6e43902cba5a866e6b:
1
The following changes since commit 79b677d658d3d35e1e776826ac4abb28cdce69b8:
2
2
3
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging (2017-09-25 20:31:24 +0100)
3
Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging (2023-02-21 11:28:31 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to b156d51b62e6970753e1f9f36f7c4d5fdbf4c619:
9
for you to fetch changes up to 0f385a2420d2c3f8ae7ed65fbe2712027664059e:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-09-26' into queue-block (2017-09-26 15:03:02 +0200)
11
block/rbd: Add support for layered encryption (2023-02-23 19:49:35 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Lock the graph, part 2 (BlockDriver callbacks)
17
- virtio-scsi: fix SCSIDevice hot unplug with IOThread
18
- rbd: Add support for layered encryption
19
16
----------------------------------------------------------------
20
----------------------------------------------------------------
17
Alberto Garcia (1):
21
Emanuele Giuseppe Esposito (5):
18
throttle: Assert that bkt->max is valid in throttle_compute_wait()
22
block/qed: add missing graph rdlock in qed_need_check_timer_entry
23
block: Mark bdrv_co_flush() and callers GRAPH_RDLOCK
24
block: Mark bdrv_co_pdiscard() and callers GRAPH_RDLOCK
25
block: Mark bdrv_co_copy_range() GRAPH_RDLOCK
26
block: Mark bdrv_co_is_inserted() and callers GRAPH_RDLOCK
19
27
20
Cornelia Huck (3):
28
Kevin Wolf (18):
21
iotests: use -ccw on s390x for 040, 139, and 182
29
block: Make bdrv_can_set_read_only() static
22
iotests: use -ccw on s390x for 051
30
mirror: Fix access of uninitialised fields during start
23
iotests: use virtio aliases for 067
31
block: Mark bdrv_co_truncate() and callers GRAPH_RDLOCK
32
block: Mark bdrv_co_block_status() and callers GRAPH_RDLOCK
33
block: Mark bdrv_co_ioctl() and callers GRAPH_RDLOCK
34
block: Mark bdrv_co_pwrite_zeroes() and callers GRAPH_RDLOCK
35
block: Mark read/write in block/io.c GRAPH_RDLOCK
36
block: Mark public read/write functions GRAPH_RDLOCK
37
block: Mark bdrv_co_pwrite_sync() and callers GRAPH_RDLOCK
38
block: Mark bdrv_co_do_pwrite_zeroes() GRAPH_RDLOCK
39
block: Mark preadv_snapshot/snapshot_block_status GRAPH_RDLOCK
40
block: Mark bdrv_co_create() and callers GRAPH_RDLOCK
41
block: Mark bdrv_co_io_(un)plug() and callers GRAPH_RDLOCK
42
block: Mark bdrv_co_eject/lock_medium() and callers GRAPH_RDLOCK
43
block: Mark bdrv_(un)register_buf() GRAPH_RDLOCK
44
block: Mark bdrv_co_delete_file() and callers GRAPH_RDLOCK
45
block: Mark bdrv_*_dirty_bitmap() and callers GRAPH_RDLOCK
46
block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK
24
47
25
Fam Zheng (3):
48
Or Ozeri (3):
26
qemu-img: Clarify about relative backing file options
49
block/rbd: Remove redundant stack variable passphrase_len
27
file-posix: Clear out first sector in hdev_create
50
block/rbd: Add luks-any encryption opening option
28
iotests: Print full path of bad output if mismatch
51
block/rbd: Add support for layered encryption
29
52
30
Kevin Wolf (9):
53
Stefan Hajnoczi (3):
31
qemu-iotests: Add missing -machine accel=qtest
54
scsi: protect req->aiocb with AioContext lock
32
qemu-io: Drop write permissions before read-only reopen
55
dma-helpers: prevent dma_blk_cb() vs dma_aio_cancel() race
33
block: Add reopen_queue to bdrv_child_perm()
56
virtio-scsi: reset SCSI devices from main loop thread
34
block: Add reopen queue to bdrv_check_perm()
35
block: Base permissions on rw state after reopen
36
block: reopen: Queue children after their parents
37
block: Fix permissions after bdrv_reopen()
38
qemu-iotests: Test change-backing-file command
39
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-09-26' into queue-block
40
57
41
Manos Pitsidianakis (1):
58
qapi/block-core.json | 27 +++++-
42
block/throttle-groups.c: allocate RestartData on the heap
59
block/coroutines.h | 2 +-
43
60
block/qcow2.h | 27 ++++--
44
Pavel Butsykin (4):
61
block/qed.h | 45 +++++----
45
qemu-img: add --shrink flag for resize
62
include/block/block-copy.h | 6 +-
46
qcow2: add qcow2_cache_discard
63
include/block/block-global-state.h | 14 +--
47
qcow2: add shrink image support
64
include/block/block-io.h | 110 ++++++++++++----------
48
qemu-iotests: add shrinking image test
65
include/block/block_int-common.h | 173 ++++++++++++++++++----------------
49
66
include/block/block_int-io.h | 53 ++++++-----
50
Stefan Hajnoczi (1):
67
include/block/dirty-bitmap.h | 12 +--
51
docs: add qemu-block-drivers(7) man page
68
include/hw/virtio/virtio-scsi.h | 11 ++-
52
69
include/sysemu/block-backend-io.h | 7 +-
53
Thomas Huth (1):
70
block.c | 12 ++-
54
block: Clean up some bad code in the vvfat driver
71
block/backup.c | 3 +
55
72
block/blkdebug.c | 19 ++--
56
Vladimir Sementsov-Ogievskiy (2):
73
block/blklogwrites.c | 35 ++++---
57
iotests: fix 181: enable postcopy-ram capability on target
74
block/blkreplay.c | 24 +++--
58
block/qcow2-bitmap: fix use of uninitialized pointer
75
block/blkverify.c | 5 +-
59
76
block/block-backend.c | 39 +++++---
60
qapi/block-core.json | 8 +-
77
block/block-copy.c | 32 ++++---
61
block/qcow2.h | 17 +
78
block/bochs.c | 2 +-
62
include/block/block.h | 2 +-
79
block/commit.c | 5 +-
63
include/block/block_int.h | 7 +
80
block/copy-before-write.c | 33 ++++---
64
block.c | 191 +++++++---
81
block/copy-on-read.c | 44 +++++----
65
block/commit.c | 1 +
82
block/create.c | 9 +-
66
block/file-posix.c | 10 +
83
block/crypto.c | 16 ++--
67
block/mirror.c | 1 +
84
block/dirty-bitmap.c | 2 +
68
block/qcow2-bitmap.c | 2 +-
85
block/file-posix.c | 27 +++---
69
block/qcow2-cache.c | 26 ++
86
block/file-win32.c | 7 +-
70
block/qcow2-cluster.c | 50 +++
87
block/filter-compress.c | 36 ++++---
71
block/qcow2-refcount.c | 140 +++++++-
88
block/io.c | 108 +++++++++++++--------
72
block/qcow2.c | 43 ++-
89
block/iscsi.c | 28 +++---
73
block/replication.c | 1 +
90
block/mirror.c | 59 ++++++++----
74
block/throttle-groups.c | 12 +-
91
block/parallels.c | 33 +++----
75
block/vvfat.c | 27 +-
92
block/preallocate.c | 38 ++++----
76
qemu-img.c | 23 ++
93
block/qcow.c | 46 +++++----
77
qemu-io-cmds.c | 12 +
94
block/qcow2-cluster.c | 17 ++--
78
util/throttle.c | 1 +
95
block/qcow2.c | 136 +++++++++++++++------------
79
Makefile | 6 +-
96
block/qed-check.c | 3 +-
80
docs/qemu-block-drivers.texi | 804 ++++++++++++++++++++++++++++++++++++++++++
97
block/qed-table.c | 10 +-
81
qemu-doc.texi | 781 +---------------------------------------
98
block/qed.c | 101 ++++++++++----------
82
qemu-img-cmds.hx | 4 +-
99
block/quorum.c | 62 +++++++-----
83
qemu-img.texi | 15 +-
100
block/raw-format.c | 76 ++++++++-------
84
tests/qemu-iotests/040 | 6 +-
101
block/rbd.c | 188 ++++++++++++++++++++++++++++++++++---
85
tests/qemu-iotests/051 | 12 +-
102
block/replication.c | 18 ++--
86
tests/qemu-iotests/051.out | 2 +-
103
block/snapshot-access.c | 8 +-
87
tests/qemu-iotests/051.pc.out | 2 +-
104
block/stream.c | 40 ++++----
88
tests/qemu-iotests/067 | 2 +-
105
block/throttle.c | 36 ++++---
89
tests/qemu-iotests/067.out | 2 +-
106
block/vdi.c | 11 +--
90
tests/qemu-iotests/102 | 4 +-
107
block/vhdx.c | 18 ++--
91
tests/qemu-iotests/106 | 2 +-
108
block/vmdk.c | 132 ++++++++++++--------------
92
tests/qemu-iotests/139 | 12 +-
109
block/vpc.c | 11 +--
93
tests/qemu-iotests/163 | 170 +++++++++
110
hw/scsi/scsi-disk.c | 23 +++--
94
tests/qemu-iotests/163.out | 5 +
111
hw/scsi/scsi-generic.c | 11 ++-
95
tests/qemu-iotests/172 | 2 +-
112
hw/scsi/virtio-scsi.c | 169 ++++++++++++++++++++++++++-------
96
tests/qemu-iotests/181 | 2 +
113
qemu-img.c | 8 +-
97
tests/qemu-iotests/181.out | 1 -
114
softmmu/dma-helpers.c | 12 ++-
98
tests/qemu-iotests/182 | 13 +-
115
tests/unit/test-bdrv-drain.c | 20 ++--
99
tests/qemu-iotests/186 | 6 +-
116
tests/unit/test-block-iothread.c | 3 +-
100
tests/qemu-iotests/187.out | 2 +-
117
59 files changed, 1355 insertions(+), 907 deletions(-)
101
tests/qemu-iotests/195 | 92 +++++
102
tests/qemu-iotests/195.out | 78 ++++
103
tests/qemu-iotests/check | 2 +-
104
tests/qemu-iotests/group | 2 +
105
45 files changed, 1708 insertions(+), 895 deletions(-)
106
create mode 100644 docs/qemu-block-drivers.texi
107
create mode 100644 tests/qemu-iotests/163
108
create mode 100644 tests/qemu-iotests/163.out
109
create mode 100755 tests/qemu-iotests/195
110
create mode 100644 tests/qemu-iotests/195.out
111
diff view generated by jsdifflib
1
When new permissions are calculated during bdrv_reopen(), they need to
1
It is never called outside of block.c.
2
be based on the state of the graph as it will be after the reopen has
3
completed, not on the current state of the involved nodes.
4
5
This patch makes bdrv_is_writable() optionally accept a BlockReopenQueue
6
from which the new flags are taken. This is then used for determining
7
the new bs->file permissions of format drivers as soon as we add the
8
code to actually pass a non-NULL reopen queue to the .bdrv_child_perm
9
callbacks.
10
11
While moving bdrv_is_writable(), make it static. It isn't used outside
12
block.c.
13
2
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-Id: <20230203152202.49054-2-kwolf@redhat.com>
5
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
8
---
17
include/block/block.h | 1 -
9
include/block/block-io.h | 2 --
18
block.c | 52 ++++++++++++++++++++++++++++++++++++---------------
10
block.c | 4 ++--
19
2 files changed, 37 insertions(+), 16 deletions(-)
11
2 files changed, 2 insertions(+), 4 deletions(-)
20
12
21
diff --git a/include/block/block.h b/include/block/block.h
13
diff --git a/include/block/block-io.h b/include/block/block-io.h
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block.h
15
--- a/include/block/block-io.h
24
+++ b/include/block/block.h
16
+++ b/include/block/block-io.h
25
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
17
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
26
int64_t offset, int64_t bytes, int64_t *pnum);
18
int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
27
19
int64_t bytes);
20
21
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
22
- bool ignore_allow_rdw, Error **errp);
23
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
24
Error **errp);
28
bool bdrv_is_read_only(BlockDriverState *bs);
25
bool bdrv_is_read_only(BlockDriverState *bs);
29
-bool bdrv_is_writable(BlockDriverState *bs);
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
31
bool ignore_allow_rdw, Error **errp);
32
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
33
diff --git a/block.c b/block.c
26
diff --git a/block.c b/block.c
34
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
35
--- a/block.c
28
--- a/block.c
36
+++ b/block.c
29
+++ b/block.c
37
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
30
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
38
return bs->read_only;
31
return !(bs->open_flags & BDRV_O_RDWR);
39
}
32
}
40
33
41
-/* Returns whether the image file can be written to right now */
34
-int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
42
-bool bdrv_is_writable(BlockDriverState *bs)
35
- bool ignore_allow_rdw, Error **errp)
43
-{
36
+static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
44
- return !bdrv_is_read_only(bs) && !(bs->open_flags & BDRV_O_INACTIVE);
37
+ bool ignore_allow_rdw, Error **errp)
45
-}
46
-
47
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
48
bool ignore_allow_rdw, Error **errp)
49
{
38
{
50
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
39
IO_CODE();
51
static void bdrv_child_abort_perm_update(BdrvChild *c);
40
52
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
53
54
+typedef struct BlockReopenQueueEntry {
55
+ bool prepared;
56
+ BDRVReopenState state;
57
+ QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
58
+} BlockReopenQueueEntry;
59
+
60
+/*
61
+ * Return the flags that @bs will have after the reopens in @q have
62
+ * successfully completed. If @q is NULL (or @bs is not contained in @q),
63
+ * return the current flags.
64
+ */
65
+static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs)
66
+{
67
+ BlockReopenQueueEntry *entry;
68
+
69
+ if (q != NULL) {
70
+ QSIMPLEQ_FOREACH(entry, q, entry) {
71
+ if (entry->state.bs == bs) {
72
+ return entry->state.flags;
73
+ }
74
+ }
75
+ }
76
+
77
+ return bs->open_flags;
78
+}
79
+
80
+/* Returns whether the image file can be written to after the reopen queue @q
81
+ * has been successfully applied, or right now if @q is NULL. */
82
+static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q)
83
+{
84
+ int flags = bdrv_reopen_get_flags(q, bs);
85
+
86
+ return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR;
87
+}
88
+
89
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
90
BdrvChild *c, const BdrvChildRole *role,
91
BlockReopenQueue *reopen_queue,
92
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
93
94
/* Write permissions never work with read-only images */
95
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
96
- !bdrv_is_writable(bs))
97
+ !bdrv_is_writable(bs, q))
98
{
99
error_setg(errp, "Block node is read-only");
100
return -EPERM;
101
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
102
&perm, &shared);
103
104
/* Format drivers may touch metadata even if the guest doesn't write */
105
- /* TODO Take flags from reopen_queue */
106
- if (bdrv_is_writable(bs)) {
107
+ if (bdrv_is_writable(bs, reopen_queue)) {
108
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
109
}
110
111
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
112
NULL, errp);
113
}
114
115
-typedef struct BlockReopenQueueEntry {
116
- bool prepared;
117
- BDRVReopenState state;
118
- QSIMPLEQ_ENTRY(BlockReopenQueueEntry) entry;
119
-} BlockReopenQueueEntry;
120
-
121
/*
122
* Adds a BlockDriverState to a simple queue for an atomic, transactional
123
* reopen of multiple devices.
124
--
41
--
125
2.13.5
42
2.39.2
126
127
diff view generated by jsdifflib
1
qemu-io provides a 'reopen' command that allows switching from writable
1
bdrv_mirror_top_pwritev() accesses the job object when active mirroring
2
to read-only access. We need to make sure that we don't try to keep
2
is enabled. It disables this code during early initialisation while
3
write permissions to a BlockBackend that becomes read-only, otherwise
3
s->job isn't set yet.
4
things are going to fail.
5
4
6
This requires a bdrv_drain() call because otherwise in-flight AIO
5
However, s->job is still set way too early when the job object isn't
7
write requests could issue new internal requests while the permission
6
fully initialised. For example, &s->ops_in_flight isn't initialised yet
8
has already gone away, which would cause assertion failures. Draining
7
and the in_flight bitmap doesn't exist yet. This causes crashes when a
9
the queue doesn't break AIO requests in any new way, bdrv_reopen() would
8
write request comes in too early.
10
drain it anyway only a few lines later.
9
10
Move the assignment of s->job to when the mirror job is actually fully
11
initialised to make sure that the mirror_top driver doesn't access it
12
too early.
11
13
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Message-Id: <20230203152202.49054-3-kwolf@redhat.com>
16
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
19
---
15
qemu-io-cmds.c | 12 ++++++++++++
20
block/mirror.c | 8 +++++++-
16
tests/qemu-iotests/187.out | 2 +-
21
1 file changed, 7 insertions(+), 1 deletion(-)
17
2 files changed, 13 insertions(+), 1 deletion(-)
18
22
19
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
23
diff --git a/block/mirror.c b/block/mirror.c
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/qemu-io-cmds.c
25
--- a/block/mirror.c
22
+++ b/qemu-io-cmds.c
26
+++ b/block/mirror.c
23
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
24
return 0;
28
{
29
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
30
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
31
+ MirrorBDSOpaque *mirror_top_opaque = s->mirror_top_bs->opaque;
32
BlockDriverState *target_bs = blk_bs(s->target);
33
bool need_drain = true;
34
BlockDeviceIoStatus iostatus;
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
36
}
25
}
37
}
26
38
27
+ if (!(flags & BDRV_O_RDWR)) {
39
+ /*
28
+ uint64_t orig_perm, orig_shared_perm;
40
+ * Only now the job is fully initialised and mirror_top_bs should start
41
+ * accessing it.
42
+ */
43
+ mirror_top_opaque->job = s;
29
+
44
+
30
+ bdrv_drain(bs);
45
assert(!s->dbi);
31
+
46
s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap);
32
+ blk_get_perm(blk, &orig_perm, &orig_shared_perm);
47
for (;;) {
33
+ blk_set_perm(blk,
48
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
34
+ orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
49
if (!s) {
35
+ orig_shared_perm,
50
goto fail;
36
+ &error_abort);
51
}
37
+ }
52
- bs_opaque->job = s;
38
+
53
39
qopts = qemu_opts_find(&reopen_opts, NULL);
54
/* The block job now has a reference to this node */
40
opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
55
bdrv_unref(mirror_top_bs);
41
qemu_opts_reset(&reopen_opts);
42
diff --git a/tests/qemu-iotests/187.out b/tests/qemu-iotests/187.out
43
index XXXXXXX..XXXXXXX 100644
44
--- a/tests/qemu-iotests/187.out
45
+++ b/tests/qemu-iotests/187.out
46
@@ -XXX,XX +XXX,XX @@ Start from read-write
47
48
wrote 65536/65536 bytes at offset 0
49
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
50
-write failed: Operation not permitted
51
+Block node is read-only
52
wrote 65536/65536 bytes at offset 0
53
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
54
*** done
55
--
56
--
56
2.13.5
57
2.39.2
57
58
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_truncate() need to hold a reader lock for the graph.
1
3
4
For some places, we know that they will hold the lock, but we don't have
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-4-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
include/block/block-io.h | 6 +++---
15
include/block/block_int-common.h | 7 ++++---
16
block/block-backend.c | 1 +
17
block/crypto.c | 2 +-
18
block/io.c | 1 +
19
block/parallels.c | 14 ++++++++------
20
block/preallocate.c | 2 +-
21
block/qcow.c | 17 ++++++++++++-----
22
block/qcow2.c | 14 ++++++++------
23
block/raw-format.c | 6 +++---
24
block/vmdk.c | 2 ++
25
11 files changed, 44 insertions(+), 28 deletions(-)
26
27
diff --git a/include/block/block-io.h b/include/block/block-io.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block-io.h
30
+++ b/include/block/block-io.h
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
32
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
33
int64_t bytes, BdrvRequestFlags flags);
34
35
-int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
36
- PreallocMode prealloc, BdrvRequestFlags flags,
37
- Error **errp);
38
+int coroutine_fn GRAPH_RDLOCK
39
+bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
43
int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
* If @exact is true and this function fails but would succeed
50
* with @exact = false, it should return -ENOTSUP.
51
*/
52
- int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
53
- bool exact, PreallocMode prealloc,
54
- BdrvRequestFlags flags, Error **errp);
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_truncate)(
56
+ BlockDriverState *bs, int64_t offset, bool exact,
57
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
58
+
59
int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
60
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
61
BlockDriverState *bs);
62
diff --git a/block/block-backend.c b/block/block-backend.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/block-backend.c
65
+++ b/block/block-backend.c
66
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
67
Error **errp)
68
{
69
IO_OR_GS_CODE();
70
+ GRAPH_RDLOCK_GUARD();
71
if (!blk_is_available(blk)) {
72
error_setg(errp, "No medium inserted");
73
return -ENOMEDIUM;
74
diff --git a/block/crypto.c b/block/crypto.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/crypto.c
77
+++ b/block/crypto.c
78
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
79
return ret;
80
}
81
82
-static int coroutine_fn
83
+static int coroutine_fn GRAPH_RDLOCK
84
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
85
PreallocMode prealloc, BdrvRequestFlags flags,
86
Error **errp)
87
diff --git a/block/io.c b/block/io.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/io.c
90
+++ b/block/io.c
91
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
92
int64_t old_size, new_bytes;
93
int ret;
94
IO_CODE();
95
+ assert_bdrv_graph_readable();
96
97
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
98
if (!drv) {
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
104
return start_off;
105
}
106
107
-static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
108
- int64_t sector_num,
109
- int nb_sectors, int *pnum)
110
+static int64_t coroutine_fn GRAPH_RDLOCK
111
+allocate_clusters(BlockDriverState *bs, int64_t sector_num,
112
+ int nb_sectors, int *pnum)
113
{
114
int ret = 0;
115
BDRVParallelsState *s = bs->opaque;
116
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
117
QEMUIOVector hd_qiov;
118
int ret = 0;
119
120
+ assume_graph_lock(); /* FIXME */
121
+
122
qemu_iovec_init(&hd_qiov, qiov->niov);
123
124
while (nb_sectors > 0) {
125
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
126
}
127
128
129
-static int coroutine_fn parallels_co_check(BlockDriverState *bs,
130
- BdrvCheckResult *res,
131
- BdrvCheckMode fix)
132
+static int coroutine_fn GRAPH_RDLOCK
133
+parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
134
+ BdrvCheckMode fix)
135
{
136
BDRVParallelsState *s = bs->opaque;
137
int64_t size, prev_off, high_off;
138
diff --git a/block/preallocate.c b/block/preallocate.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/preallocate.c
141
+++ b/block/preallocate.c
142
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
143
flags);
144
}
145
146
-static int coroutine_fn
147
+static int coroutine_fn GRAPH_RDLOCK
148
preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
149
bool exact, PreallocMode prealloc,
150
BdrvRequestFlags flags, Error **errp)
151
diff --git a/block/qcow.c b/block/qcow.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/qcow.c
154
+++ b/block/qcow.c
155
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
156
* return 0 if not allocated, 1 if *result is assigned, and negative
157
* errno on failure.
158
*/
159
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
160
- uint64_t offset, int allocate,
161
- int compressed_size,
162
- int n_start, int n_end,
163
- uint64_t *result)
164
+static int coroutine_fn GRAPH_RDLOCK
165
+get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
166
+ int compressed_size, int n_start, int n_end,
167
+ uint64_t *result)
168
{
169
BDRVQcowState *s = bs->opaque;
170
int min_index, i, j, l1_index, l2_index, ret;
171
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
172
int64_t n;
173
uint64_t cluster_offset;
174
175
+ assume_graph_lock(); /* FIXME */
176
+
177
qemu_co_mutex_lock(&s->lock);
178
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
179
qemu_co_mutex_unlock(&s->lock);
180
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
181
uint8_t *buf;
182
void *orig_buf;
183
184
+ assume_graph_lock(); /* FIXME */
185
+
186
if (qiov->niov > 1) {
187
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
188
if (buf == NULL) {
189
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
190
uint8_t *buf;
191
void *orig_buf;
192
193
+ assume_graph_lock(); /* FIXME */
194
+
195
s->cluster_cache_offset = -1; /* disable compressed cache */
196
197
/* We must always copy the iov when encrypting, so we
198
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
199
uint8_t *buf, *out_buf;
200
uint64_t cluster_offset;
201
202
+ assume_graph_lock(); /* FIXME */
203
+
204
buf = qemu_blockalign(bs, s->cluster_size);
205
if (bytes != s->cluster_size) {
206
if (bytes > s->cluster_size ||
207
diff --git a/block/qcow2.c b/block/qcow2.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/block/qcow2.c
210
+++ b/block/qcow2.c
211
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
212
*
213
* Returns: 0 on success, -errno on failure.
214
*/
215
-static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
216
- uint64_t new_length, PreallocMode mode,
217
- Error **errp)
218
+static int coroutine_fn GRAPH_RDLOCK
219
+preallocate_co(BlockDriverState *bs, uint64_t offset, uint64_t new_length,
220
+ PreallocMode mode, Error **errp)
221
{
222
BDRVQcow2State *s = bs->opaque;
223
uint64_t bytes;
224
@@ -XXX,XX +XXX,XX @@ fail:
225
return ret;
226
}
227
228
-static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
229
- bool exact, PreallocMode prealloc,
230
- BdrvRequestFlags flags, Error **errp)
231
+static int coroutine_fn GRAPH_RDLOCK
232
+qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
233
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
234
{
235
BDRVQcow2State *s = bs->opaque;
236
uint64_t old_length;
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
AioTaskPool *aio = NULL;
239
int ret = 0;
240
241
+ assume_graph_lock(); /* FIXME */
242
+
243
if (has_data_file(bs)) {
244
return -ENOTSUP;
245
}
246
diff --git a/block/raw-format.c b/block/raw-format.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/raw-format.c
249
+++ b/block/raw-format.c
250
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
251
}
252
}
253
254
-static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
255
- bool exact, PreallocMode prealloc,
256
- BdrvRequestFlags flags, Error **errp)
257
+static int coroutine_fn GRAPH_RDLOCK
258
+raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
259
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
260
{
261
BDRVRawState *s = bs->opaque;
262
263
diff --git a/block/vmdk.c b/block/vmdk.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/block/vmdk.c
266
+++ b/block/vmdk.c
267
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
268
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
269
QEMUIOVector *qiov)
270
{
271
+ assume_graph_lock(); /* FIXME */
272
+
273
if (bytes == 0) {
274
/* The caller will write bytes 0 to signal EOF.
275
* When receive it, we align EOF to a sector boundary. */
276
--
277
2.39.2
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_block_status() need to hold a reader lock for the graph.
2
3
3
Without initialization to zero dirty_bitmap field may be not zero
4
For some places, we know that they will hold the lock, but we don't have
4
for a bitmap which should not be stored and
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
qcow2_store_persistent_dirty_bitmaps will erroneously call
6
with a FIXME comment. These places will be removed once everything is
6
store_bitmap for it which leads to SIGSEGV on bdrv_dirty_bitmap_name.
7
properly annotated.
7
8
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Message-id: 20170922144353.4220-1-vsementsov@virtuozzo.com
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Cc: qemu-stable@nongnu.org
11
Message-Id: <20230203152202.49054-5-kwolf@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
14
---
15
block/qcow2-bitmap.c | 2 +-
15
block/coroutines.h | 2 +-
16
1 file changed, 1 insertion(+), 1 deletion(-)
16
include/block/block-copy.h | 6 +++---
17
include/block/block-io.h | 22 +++++++++++-----------
18
include/block/block_int-common.h | 3 ++-
19
block/backup.c | 3 +++
20
block/block-backend.c | 2 ++
21
block/block-copy.c | 19 +++++++++++--------
22
block/io.c | 13 ++++++++-----
23
block/mirror.c | 14 +++++++++-----
24
block/qcow.c | 11 ++++-------
25
block/quorum.c | 9 ++++-----
26
block/stream.c | 32 ++++++++++++++++++--------------
27
qemu-img.c | 4 +++-
28
tests/unit/test-block-iothread.c | 3 ++-
29
14 files changed, 81 insertions(+), 62 deletions(-)
17
30
18
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
31
diff --git a/block/coroutines.h b/block/coroutines.h
19
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2-bitmap.c
33
--- a/block/coroutines.h
21
+++ b/block/qcow2-bitmap.c
34
+++ b/block/coroutines.h
22
@@ -XXX,XX +XXX,XX @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset,
35
@@ -XXX,XX +XXX,XX @@ bdrv_co_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
23
goto fail;
36
int coroutine_fn GRAPH_RDLOCK
37
bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp);
38
39
-int coroutine_fn
40
+int coroutine_fn GRAPH_RDLOCK
41
bdrv_co_common_block_status_above(BlockDriverState *bs,
42
BlockDriverState *base,
43
bool include_base,
44
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block-copy.h
47
+++ b/include/block/block-copy.h
48
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
49
void block_copy_state_free(BlockCopyState *s);
50
51
void block_copy_reset(BlockCopyState *s, int64_t offset, int64_t bytes);
52
-int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
53
- int64_t offset,
54
- int64_t *count);
55
+
56
+int64_t coroutine_fn GRAPH_RDLOCK
57
+block_copy_reset_unallocated(BlockCopyState *s, int64_t offset, int64_t *count);
58
59
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
60
bool ignore_ratelimit, uint64_t timeout_ns,
61
diff --git a/include/block/block-io.h b/include/block/block-io.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/block/block-io.h
64
+++ b/include/block/block-io.h
65
@@ -XXX,XX +XXX,XX @@ int bdrv_block_status(BlockDriverState *bs, int64_t offset,
66
int64_t bytes, int64_t *pnum, int64_t *map,
67
BlockDriverState **file);
68
69
-int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
70
- BlockDriverState *base,
71
- int64_t offset, int64_t bytes,
72
- int64_t *pnum, int64_t *map,
73
- BlockDriverState **file);
74
+int coroutine_fn GRAPH_RDLOCK
75
+bdrv_co_block_status_above(BlockDriverState *bs, BlockDriverState *base,
76
+ int64_t offset, int64_t bytes, int64_t *pnum,
77
+ int64_t *map, BlockDriverState **file);
78
int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
79
int64_t offset, int64_t bytes, int64_t *pnum,
80
int64_t *map, BlockDriverState **file);
81
82
-int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
83
- int64_t bytes, int64_t *pnum);
84
+int coroutine_fn GRAPH_RDLOCK
85
+bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
86
+ int64_t *pnum);
87
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
88
int64_t *pnum);
89
90
-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
91
- BlockDriverState *base,
92
- bool include_base, int64_t offset,
93
- int64_t bytes, int64_t *pnum);
94
+int coroutine_fn GRAPH_RDLOCK
95
+bdrv_co_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
96
+ bool include_base, int64_t offset, int64_t bytes,
97
+ int64_t *pnum);
98
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
99
bool include_base, int64_t offset, int64_t bytes,
100
int64_t *pnum);
101
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
102
index XXXXXXX..XXXXXXX 100644
103
--- a/include/block/block_int-common.h
104
+++ b/include/block/block_int-common.h
105
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
106
* *pnum value for the block-status cache on protocol nodes, prior
107
* to clamping *pnum for return to its caller.
108
*/
109
- int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
110
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)(
111
+ BlockDriverState *bs,
112
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
113
int64_t *map, BlockDriverState **file);
114
115
diff --git a/block/backup.c b/block/backup.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/block/backup.c
118
+++ b/block/backup.c
119
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
120
return -ECANCELED;
121
}
122
123
+ /* rdlock protects the subsequent call to bdrv_is_allocated() */
124
+ bdrv_graph_co_rdlock();
125
ret = block_copy_reset_unallocated(s->bcs, offset, &count);
126
+ bdrv_graph_co_rdunlock();
127
if (ret < 0) {
128
return ret;
129
}
130
diff --git a/block/block-backend.c b/block/block-backend.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/block-backend.c
133
+++ b/block/block-backend.c
134
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
135
BlockDriverState **file)
136
{
137
IO_CODE();
138
+ GRAPH_RDLOCK_GUARD();
139
return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
140
map, file);
141
}
142
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
143
int64_t bytes, int64_t *pnum)
144
{
145
IO_CODE();
146
+ GRAPH_RDLOCK_GUARD();
147
return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
148
bytes, pnum);
149
}
150
diff --git a/block/block-copy.c b/block/block-copy.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block/block-copy.c
153
+++ b/block/block-copy.c
154
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
155
return ret;
156
}
157
158
-static coroutine_fn int block_copy_block_status(BlockCopyState *s,
159
- int64_t offset,
160
- int64_t bytes, int64_t *pnum)
161
+static coroutine_fn GRAPH_RDLOCK
162
+int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes,
163
+ int64_t *pnum)
164
{
165
int64_t num;
166
BlockDriverState *base;
167
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_block_status(BlockCopyState *s,
168
* Check if the cluster starting at offset is allocated or not.
169
* return via pnum the number of contiguous clusters sharing this allocation.
170
*/
171
-static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
172
- int64_t offset,
173
- int64_t *pnum)
174
+static int coroutine_fn GRAPH_RDLOCK
175
+block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
176
+ int64_t *pnum)
177
{
178
BlockDriverState *bs = s->source->bs;
179
int64_t count, total_count = 0;
180
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
181
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
182
183
while (true) {
184
+ /* protected in backup_run() */
185
ret = bdrv_co_is_allocated(bs, offset, bytes, &count);
186
if (ret < 0) {
187
return ret;
188
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
189
* Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
190
* clusters found and -errno on failure.
191
*/
192
-static int coroutine_fn
193
+static int coroutine_fn GRAPH_RDLOCK
194
block_copy_dirty_clusters(BlockCopyCallState *call_state)
195
{
196
BlockCopyState *s = call_state->s;
197
@@ -XXX,XX +XXX,XX @@ void block_copy_kick(BlockCopyCallState *call_state)
198
* it means that some I/O operation failed in context of _this_ block_copy call,
199
* not some parallel operation.
200
*/
201
-static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
202
+static int coroutine_fn GRAPH_RDLOCK
203
+block_copy_common(BlockCopyCallState *call_state)
204
{
205
int ret;
206
BlockCopyState *s = call_state->s;
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
208
209
static void coroutine_fn block_copy_async_co_entry(void *opaque)
210
{
211
+ GRAPH_RDLOCK_GUARD();
212
block_copy_common(opaque);
213
}
214
215
diff --git a/block/io.c b/block/io.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/io.c
218
+++ b/block/io.c
219
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
220
* BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are
221
* set to the host mapping and BDS corresponding to the guest offset.
222
*/
223
-static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
224
- bool want_zero,
225
- int64_t offset, int64_t bytes,
226
- int64_t *pnum, int64_t *map,
227
- BlockDriverState **file)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
230
+ int64_t offset, int64_t bytes,
231
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
232
{
233
int64_t total_size;
234
int64_t n; /* bytes */
235
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
236
bool has_filtered_child;
237
238
assert(pnum);
239
+ assert_bdrv_graph_readable();
240
*pnum = 0;
241
total_size = bdrv_getlength(bs);
242
if (total_size < 0) {
243
@@ -XXX,XX +XXX,XX @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
244
IO_CODE();
245
246
assert(!include_base || base); /* Can't include NULL base */
247
+ assert_bdrv_graph_readable();
248
249
if (!depth) {
250
depth = &dummy;
251
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
252
int64_t pnum = bytes;
253
IO_CODE();
254
255
+ assume_graph_lock(); /* FIXME */
256
+
257
if (!bytes) {
258
return 1;
259
}
260
diff --git a/block/mirror.c b/block/mirror.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/block/mirror.c
263
+++ b/block/mirror.c
264
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
265
MirrorMethod mirror_method = MIRROR_METHOD_COPY;
266
267
assert(!(offset % s->granularity));
268
- ret = bdrv_block_status_above(source, NULL, offset,
269
- nb_chunks * s->granularity,
270
- &io_bytes, NULL, NULL);
271
+ WITH_GRAPH_RDLOCK_GUARD() {
272
+ ret = bdrv_block_status_above(source, NULL, offset,
273
+ nb_chunks * s->granularity,
274
+ &io_bytes, NULL, NULL);
275
+ }
276
if (ret < 0) {
277
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
278
} else if (ret & BDRV_BLOCK_DATA) {
279
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
280
return 0;
24
}
281
}
25
282
26
- bm = g_new(Qcow2Bitmap, 1);
283
- ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset, bytes,
27
+ bm = g_new0(Qcow2Bitmap, 1);
284
- &count);
28
bm->table.offset = e->bitmap_table_offset;
285
+ WITH_GRAPH_RDLOCK_GUARD() {
29
bm->table.size = e->bitmap_table_size;
286
+ ret = bdrv_is_allocated_above(bs, s->base_overlay, true, offset,
30
bm->flags = e->flags;
287
+ bytes, &count);
288
+ }
289
if (ret < 0) {
290
return ret;
291
}
292
diff --git a/block/qcow.c b/block/qcow.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/block/qcow.c
295
+++ b/block/qcow.c
296
@@ -XXX,XX +XXX,XX @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
297
return 1;
298
}
299
300
-static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
301
- bool want_zero,
302
- int64_t offset, int64_t bytes,
303
- int64_t *pnum, int64_t *map,
304
- BlockDriverState **file)
305
+static int coroutine_fn GRAPH_RDLOCK
306
+qcow_co_block_status(BlockDriverState *bs, bool want_zero,
307
+ int64_t offset, int64_t bytes, int64_t *pnum,
308
+ int64_t *map, BlockDriverState **file)
309
{
310
BDRVQcowState *s = bs->opaque;
311
int index_in_cluster, ret;
312
int64_t n;
313
uint64_t cluster_offset;
314
315
- assume_graph_lock(); /* FIXME */
316
-
317
qemu_co_mutex_lock(&s->lock);
318
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
319
qemu_co_mutex_unlock(&s->lock);
320
diff --git a/block/quorum.c b/block/quorum.c
321
index XXXXXXX..XXXXXXX 100644
322
--- a/block/quorum.c
323
+++ b/block/quorum.c
324
@@ -XXX,XX +XXX,XX @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
325
* return BDRV_BLOCK_ZERO if *all* children agree that a certain
326
* region contains zeroes, and BDRV_BLOCK_DATA otherwise.
327
*/
328
-static int coroutine_fn quorum_co_block_status(BlockDriverState *bs,
329
- bool want_zero,
330
- int64_t offset, int64_t count,
331
- int64_t *pnum, int64_t *map,
332
- BlockDriverState **file)
333
+static int coroutine_fn GRAPH_RDLOCK
334
+quorum_co_block_status(BlockDriverState *bs, bool want_zero,
335
+ int64_t offset, int64_t count,
336
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
337
{
338
BDRVQuorumState *s = bs->opaque;
339
int i, ret;
340
diff --git a/block/stream.c b/block/stream.c
341
index XXXXXXX..XXXXXXX 100644
342
--- a/block/stream.c
343
+++ b/block/stream.c
344
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
345
346
copy = false;
347
348
- ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
349
- if (ret == 1) {
350
- /* Allocated in the top, no need to copy. */
351
- } else if (ret >= 0) {
352
- /* Copy if allocated in the intermediate images. Limit to the
353
- * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */
354
- ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
355
- s->base_overlay, true,
356
- offset, n, &n);
357
- /* Finish early if end of backing file has been reached */
358
- if (ret == 0 && n == 0) {
359
- n = len - offset;
360
+ WITH_GRAPH_RDLOCK_GUARD() {
361
+ ret = bdrv_is_allocated(unfiltered_bs, offset, STREAM_CHUNK, &n);
362
+ if (ret == 1) {
363
+ /* Allocated in the top, no need to copy. */
364
+ } else if (ret >= 0) {
365
+ /*
366
+ * Copy if allocated in the intermediate images. Limit to the
367
+ * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE).
368
+ */
369
+ ret = bdrv_is_allocated_above(bdrv_cow_bs(unfiltered_bs),
370
+ s->base_overlay, true,
371
+ offset, n, &n);
372
+ /* Finish early if end of backing file has been reached */
373
+ if (ret == 0 && n == 0) {
374
+ n = len - offset;
375
+ }
376
+
377
+ copy = (ret > 0);
378
}
379
-
380
- copy = (ret > 0);
381
}
382
trace_stream_one_iteration(s, offset, n, ret);
383
if (copy) {
384
diff --git a/qemu-img.c b/qemu-img.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/qemu-img.c
387
+++ b/qemu-img.c
388
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn convert_co_do_copy(void *opaque)
389
qemu_co_mutex_unlock(&s->lock);
390
break;
391
}
392
- n = convert_iteration_sectors(s, s->sector_num);
393
+ WITH_GRAPH_RDLOCK_GUARD() {
394
+ n = convert_iteration_sectors(s, s->sector_num);
395
+ }
396
if (n < 0) {
397
qemu_co_mutex_unlock(&s->lock);
398
s->ret = n;
399
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/tests/unit/test-block-iothread.c
402
+++ b/tests/unit/test-block-iothread.c
403
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_truncate(BlockBackend *blk)
404
g_assert_cmpint(ret, ==, -EINVAL);
405
}
406
407
-static void test_sync_op_block_status(BdrvChild *c)
408
+/* Disable TSA to make bdrv_test.bdrv_co_block_status writable */
409
+static void TSA_NO_TSA test_sync_op_block_status(BdrvChild *c)
410
{
411
int ret;
412
int64_t n;
31
--
413
--
32
2.13.5
414
2.39.2
33
34
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_ioctl() need to hold a reader lock for the graph.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20230203152202.49054-6-kwolf@redhat.com>
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/block/block-io.h | 3 ++-
10
include/block/block_int-common.h | 9 +++++----
11
block/block-backend.c | 1 +
12
block/io.c | 1 +
13
block/raw-format.c | 4 ++--
14
5 files changed, 11 insertions(+), 7 deletions(-)
15
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
21
void bdrv_aio_cancel_async(BlockAIOCB *acb);
22
23
/* sg packet commands */
24
-int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
25
+int coroutine_fn GRAPH_RDLOCK
26
+bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
27
28
/* Ensure contents are flushed to disk. */
29
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
30
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block_int-common.h
33
+++ b/include/block/block_int-common.h
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
35
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
36
37
/* to control generic scsi devices */
38
- BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
39
- unsigned long int req, void *buf,
40
+ BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
41
+ BlockDriverState *bs, unsigned long int req, void *buf,
42
BlockCompletionFunc *cb, void *opaque);
43
- int coroutine_fn (*bdrv_co_ioctl)(BlockDriverState *bs,
44
- unsigned long int req, void *buf);
45
+
46
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_ioctl)(
47
+ BlockDriverState *bs, unsigned long int req, void *buf);
48
49
/*
50
* Returns 0 for completed check, -errno for internal errors.
51
diff --git a/block/block-backend.c b/block/block-backend.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/block-backend.c
54
+++ b/block/block-backend.c
55
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
56
IO_CODE();
57
58
blk_wait_while_drained(blk);
59
+ GRAPH_RDLOCK_GUARD();
60
61
if (!blk_is_available(blk)) {
62
return -ENOMEDIUM;
63
diff --git a/block/io.c b/block/io.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/io.c
66
+++ b/block/io.c
67
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
68
};
69
BlockAIOCB *acb;
70
IO_CODE();
71
+ assert_bdrv_graph_readable();
72
73
bdrv_inc_in_flight(bs);
74
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
75
diff --git a/block/raw-format.c b/block/raw-format.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/raw-format.c
78
+++ b/block/raw-format.c
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
80
bdrv_co_lock_medium(bs->file->bs, locked);
81
}
82
83
-static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
84
- unsigned long int req, void *buf)
85
+static int coroutine_fn GRAPH_RDLOCK
86
+raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
87
{
88
BDRVRawState *s = bs->opaque;
89
if (s->offset || s->has_size) {
90
--
91
2.39.2
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
This function is called in two different places:
4
- timer callback, which does not take the graph rdlock.
5
- bdrv_qed_drain_begin(), which is .bdrv_drain_begin()
6
callback documented as function that does not take the lock.
7
8
Since it calls recursive functions that traverse the
9
graph, we need to protect them with the graph rdlock.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-7-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/qed.c | 4 +++-
18
1 file changed, 3 insertions(+), 1 deletion(-)
19
20
diff --git a/block/qed.c b/block/qed.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qed.c
23
+++ b/block/qed.c
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
25
qemu_co_mutex_unlock(&s->table_lock);
26
}
27
28
-static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
29
+static void coroutine_fn GRAPH_RDLOCK qed_need_check_timer(BDRVQEDState *s)
30
{
31
int ret;
32
33
trace_qed_need_check_timer_cb(s);
34
+ assert_bdrv_graph_readable();
35
36
if (!qed_plug_allocating_write_reqs(s)) {
37
return;
38
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_need_check_timer(BDRVQEDState *s)
39
static void coroutine_fn qed_need_check_timer_entry(void *opaque)
40
{
41
BDRVQEDState *s = opaque;
42
+ GRAPH_RDLOCK_GUARD();
43
44
qed_need_check_timer(opaque);
45
bdrv_dec_in_flight(s->bs);
46
--
47
2.39.2
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
People get surprised when, after "qemu-img create -f raw /dev/sdX", they
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
still see qcow2 with "qemu-img info", if previously the bdev had a qcow2
4
bdrv_co_flush() need to hold a reader lock for the graph.
5
header. While this is natural because raw doesn't need to write any
6
magic bytes during creation, hdev_create is free to clear out the first
7
sector to make sure the stale qcow2 header doesn't cause such confusion.
8
5
9
Signed-off-by: Fam Zheng <famz@redhat.com>
6
For some places, we know that they will hold the lock, but we don't have
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230203152202.49054-8-kwolf@redhat.com>
14
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
16
---
12
block/file-posix.c | 10 ++++++++++
17
block/qcow2.h | 5 +++-
13
1 file changed, 10 insertions(+)
18
block/qed.h | 29 +++++++++++++--------
19
include/block/block-io.h | 2 +-
20
include/block/block_int-common.h | 12 +++++----
21
block/blkdebug.c | 2 +-
22
block/blklogwrites.c | 21 ++++++++++-----
23
block/blkreplay.c | 2 +-
24
block/blkverify.c | 2 +-
25
block/block-backend.c | 3 ++-
26
block/copy-before-write.c | 2 +-
27
block/file-posix.c | 4 +--
28
block/io.c | 7 +++++
29
block/mirror.c | 2 +-
30
block/preallocate.c | 2 +-
31
block/qed-check.c | 3 ++-
32
block/qed-table.c | 6 ++---
33
block/qed.c | 44 +++++++++++++++++++-------------
34
block/quorum.c | 2 +-
35
block/throttle.c | 2 +-
36
block/vmdk.c | 6 +++--
37
20 files changed, 98 insertions(+), 60 deletions(-)
14
38
39
diff --git a/block/qcow2.h b/block/qcow2.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.h
42
+++ b/block/qcow2.h
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
44
/* qcow2-cluster.c functions */
45
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
46
bool exact_size);
47
-int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
48
+
49
+int coroutine_fn GRAPH_RDLOCK
50
+qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
51
+
52
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
53
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
54
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
55
diff --git a/block/qed.h b/block/qed.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qed.h
58
+++ b/block/qed.h
59
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
60
* Table I/O functions
61
*/
62
int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
63
-int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index,
64
- unsigned int n);
65
-int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
66
- unsigned int n);
67
+
68
+int coroutine_fn GRAPH_RDLOCK
69
+qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
70
+
71
+int coroutine_fn GRAPH_RDLOCK
72
+qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
73
+
74
int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
75
uint64_t offset);
76
int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
77
uint64_t offset);
78
-int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
79
- unsigned int index, unsigned int n,
80
- bool flush);
81
-int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
82
- unsigned int index, unsigned int n,
83
- bool flush);
84
+
85
+int coroutine_fn GRAPH_RDLOCK
86
+qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
87
+ unsigned int n, bool flush);
88
+
89
+int coroutine_fn GRAPH_RDLOCK
90
+qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
91
+ unsigned int index, unsigned int n, bool flush);
92
93
/**
94
* Cluster functions
95
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
96
/**
97
* Consistency check
98
*/
99
-int coroutine_fn qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
100
+int coroutine_fn GRAPH_RDLOCK
101
+qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
102
+
103
104
QEDTable *qed_alloc_table(BDRVQEDState *s);
105
106
diff --git a/include/block/block-io.h b/include/block/block-io.h
107
index XXXXXXX..XXXXXXX 100644
108
--- a/include/block/block-io.h
109
+++ b/include/block/block-io.h
110
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
111
bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
112
113
/* Ensure contents are flushed to disk. */
114
-int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
115
+int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
116
117
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
118
int64_t bytes);
119
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
120
index XXXXXXX..XXXXXXX 100644
121
--- a/include/block/block_int-common.h
122
+++ b/include/block/block_int-common.h
123
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
124
BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
125
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
126
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
127
- BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
128
- BlockCompletionFunc *cb, void *opaque);
129
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
130
+ BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
131
BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
132
int64_t offset, int bytes,
133
BlockCompletionFunc *cb, void *opaque);
134
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
135
* layers, if needed. This function is needed for deterministic
136
* synchronization of the flush finishing callback.
137
*/
138
- int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
139
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
140
141
/* Delete a created file. */
142
int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
143
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
144
* Flushes all data that was already written to the OS all the way down to
145
* the disk (for example file-posix.c calls fsync()).
146
*/
147
- int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
148
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_disk)(
149
+ BlockDriverState *bs);
150
151
/*
152
* Flushes all internal caches to the OS. The data may still sit in a
153
* writeback cache of the host OS, but it will survive a crash of the qemu
154
* process.
155
*/
156
- int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
157
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush_to_os)(
158
+ BlockDriverState *bs);
159
160
/*
161
* Truncate @bs to @offset bytes using the given @prealloc mode
162
diff --git a/block/blkdebug.c b/block/blkdebug.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/block/blkdebug.c
165
+++ b/block/blkdebug.c
166
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
167
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
168
}
169
170
-static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
171
+static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
172
{
173
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
174
175
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/block/blklogwrites.c
178
+++ b/block/blklogwrites.c
179
@@ -XXX,XX +XXX,XX @@ typedef struct BlkLogWritesFileReq {
180
uint64_t bytes;
181
int file_flags;
182
QEMUIOVector *qiov;
183
- int (*func)(struct BlkLogWritesFileReq *r);
184
+ int GRAPH_RDLOCK_PTR (*func)(struct BlkLogWritesFileReq *r);
185
int file_ret;
186
} BlkLogWritesFileReq;
187
188
@@ -XXX,XX +XXX,XX @@ typedef struct {
189
int log_ret;
190
} BlkLogWritesLogReq;
191
192
-static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
193
+static void coroutine_fn GRAPH_RDLOCK
194
+blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
195
{
196
BDRVBlkLogWritesState *s = lr->bs->opaque;
197
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
198
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
199
}
200
}
201
202
-static void coroutine_fn blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
203
+static void coroutine_fn GRAPH_RDLOCK
204
+blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
205
{
206
fr->file_ret = fr->func(fr);
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
212
QEMUIOVector *qiov, int flags,
213
- int (*file_func)(BlkLogWritesFileReq *r),
214
+ int /*GRAPH_RDLOCK*/ (*file_func)(BlkLogWritesFileReq *r),
215
uint64_t entry_flags, bool is_zero_write)
216
{
217
QEMUIOVector log_qiov;
218
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
219
fr->file_flags);
220
}
221
222
-static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
223
+static int coroutine_fn GRAPH_RDLOCK
224
+blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
225
{
226
return bdrv_co_flush(fr->bs->file->bs);
227
}
228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
229
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
QEMUIOVector *qiov, BdrvRequestFlags flags)
231
{
232
+ assume_graph_lock(); /* FIXME */
233
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
234
blk_log_writes_co_do_file_pwritev, 0, false);
235
}
236
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
237
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
238
int64_t bytes, BdrvRequestFlags flags)
239
{
240
+ assume_graph_lock(); /* FIXME */
241
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
242
blk_log_writes_co_do_file_pwrite_zeroes, 0,
243
true);
244
}
245
246
-static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
247
+static int coroutine_fn GRAPH_RDLOCK
248
+blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
249
{
250
return blk_log_writes_co_log(bs, 0, 0, NULL, 0,
251
blk_log_writes_co_do_file_flush,
252
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
253
static int coroutine_fn
254
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
255
{
256
+ assume_graph_lock(); /* FIXME */
257
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
258
blk_log_writes_co_do_file_pdiscard,
259
LOG_DISCARD_FLAG, false);
260
diff --git a/block/blkreplay.c b/block/blkreplay.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/block/blkreplay.c
263
+++ b/block/blkreplay.c
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
265
return ret;
266
}
267
268
-static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
269
+static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs)
270
{
271
uint64_t reqid = blkreplay_next_id();
272
int ret = bdrv_co_flush(bs->file->bs);
273
diff --git a/block/blkverify.c b/block/blkverify.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/block/blkverify.c
276
+++ b/block/blkverify.c
277
@@ -XXX,XX +XXX,XX @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
278
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
279
}
280
281
-static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
282
+static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs)
283
{
284
BDRVBlkverifyState *s = bs->opaque;
285
286
diff --git a/block/block-backend.c b/block/block-backend.c
287
index XXXXXXX..XXXXXXX 100644
288
--- a/block/block-backend.c
289
+++ b/block/block-backend.c
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
291
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
292
static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
293
{
294
- blk_wait_while_drained(blk);
295
IO_CODE();
296
+ blk_wait_while_drained(blk);
297
+ GRAPH_RDLOCK_GUARD();
298
299
if (!blk_is_available(blk)) {
300
return -ENOMEDIUM;
301
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
302
index XXXXXXX..XXXXXXX 100644
303
--- a/block/copy-before-write.c
304
+++ b/block/copy-before-write.c
305
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
306
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
307
}
308
309
-static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
310
+static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs)
311
{
312
if (!bs->file) {
313
return 0;
15
diff --git a/block/file-posix.c b/block/file-posix.c
314
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
316
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
317
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static int hdev_create(const char *filename, QemuOpts *opts,
318
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
20
ret = -ENOSPC;
319
}
320
#endif /* __linux__ */
321
322
-static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
323
- Error **errp)
324
+static void coroutine_fn GRAPH_RDLOCK
325
+raw_co_invalidate_cache(BlockDriverState *bs, Error **errp)
326
{
327
BDRVRawState *s = bs->opaque;
328
int ret;
329
diff --git a/block/io.c b/block/io.c
330
index XXXXXXX..XXXXXXX 100644
331
--- a/block/io.c
332
+++ b/block/io.c
333
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
334
int ret;
335
IO_CODE();
336
337
+ assume_graph_lock(); /* FIXME */
338
+
339
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
340
if (ret < 0) {
341
return ret;
342
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
343
QEMUIOVector local_qiov;
344
int ret;
345
346
+ assume_graph_lock(); /* FIXME */
347
+
348
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
349
350
if (!drv) {
351
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
352
int head = 0;
353
int tail = 0;
354
355
+ assume_graph_lock(); /* FIXME */
356
+
357
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
358
INT64_MAX);
359
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
360
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
361
int ret = 0;
362
IO_CODE();
363
364
+ assert_bdrv_graph_readable();
365
bdrv_inc_in_flight(bs);
366
367
if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
368
diff --git a/block/mirror.c b/block/mirror.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/block/mirror.c
371
+++ b/block/mirror.c
372
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
373
return ret;
374
}
375
376
-static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)
377
+static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
378
{
379
if (bs->backing == NULL) {
380
/* we can be here after failed bdrv_append in mirror_start_job */
381
diff --git a/block/preallocate.c b/block/preallocate.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/block/preallocate.c
384
+++ b/block/preallocate.c
385
@@ -XXX,XX +XXX,XX @@ preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
386
return 0;
387
}
388
389
-static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
390
+static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
391
{
392
return bdrv_co_flush(bs->file->bs);
393
}
394
diff --git a/block/qed-check.c b/block/qed-check.c
395
index XXXXXXX..XXXXXXX 100644
396
--- a/block/qed-check.c
397
+++ b/block/qed-check.c
398
@@ -XXX,XX +XXX,XX @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
399
/**
400
* Descend tables and check each cluster is referenced once only
401
*/
402
-static int coroutine_fn qed_check_l1_table(QEDCheck *check, QEDTable *table)
403
+static int coroutine_fn GRAPH_RDLOCK
404
+qed_check_l1_table(QEDCheck *check, QEDTable *table)
405
{
406
BDRVQEDState *s = check->s;
407
unsigned int i, num_invalid_l1 = 0;
408
diff --git a/block/qed-table.c b/block/qed-table.c
409
index XXXXXXX..XXXXXXX 100644
410
--- a/block/qed-table.c
411
+++ b/block/qed-table.c
412
@@ -XXX,XX +XXX,XX @@ out:
413
*
414
* Called with table_lock held.
415
*/
416
-static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
417
- QEDTable *table, unsigned int index,
418
- unsigned int n, bool flush)
419
+static int coroutine_fn GRAPH_RDLOCK
420
+qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
421
+ unsigned int index, unsigned int n, bool flush)
422
{
423
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
424
unsigned int start, end, i;
425
diff --git a/block/qed.c b/block/qed.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/block/qed.c
428
+++ b/block/qed.c
429
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_init_state(BlockDriverState *bs)
430
}
431
432
/* Called with table_lock held. */
433
-static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
434
- int flags, Error **errp)
435
+static int coroutine_fn GRAPH_RDLOCK
436
+bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
437
{
438
BDRVQEDState *s = bs->opaque;
439
QEDHeader le_header;
440
@@ -XXX,XX +XXX,XX @@ typedef struct QEDOpenCo {
441
int ret;
442
} QEDOpenCo;
443
444
-static void coroutine_fn bdrv_qed_open_entry(void *opaque)
445
+static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque)
446
{
447
QEDOpenCo *qoc = opaque;
448
BDRVQEDState *s = qoc->bs->opaque;
449
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
450
};
451
int ret;
452
453
+ assume_graph_lock(); /* FIXME */
454
+
455
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
456
if (ret < 0) {
457
return ret;
458
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb)
459
*
460
* Called with table_lock held.
461
*/
462
-static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
463
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_l1_update(QEDAIOCB *acb)
464
{
465
BDRVQEDState *s = acb_to_s(acb);
466
CachedL2Table *l2_table = acb->request.l2_table;
467
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
468
*
469
* Called with table_lock held.
470
*/
471
-static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
472
+static int coroutine_fn GRAPH_RDLOCK
473
+qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
474
{
475
BDRVQEDState *s = acb_to_s(acb);
476
bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1;
477
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
478
*
479
* Called with table_lock held.
480
*/
481
-static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb)
482
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_cow(QEDAIOCB *acb)
483
{
484
BDRVQEDState *s = acb_to_s(acb);
485
uint64_t start, len, offset;
486
@@ -XXX,XX +XXX,XX @@ static bool qed_should_set_need_check(BDRVQEDState *s)
487
*
488
* Called with table_lock held.
489
*/
490
-static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
491
+static int coroutine_fn GRAPH_RDLOCK
492
+qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
493
{
494
BDRVQEDState *s = acb_to_s(acb);
495
int ret;
496
@@ -XXX,XX +XXX,XX @@ out:
497
*
498
* Called with table_lock held.
499
*/
500
-static int coroutine_fn qed_aio_write_data(void *opaque, int ret,
501
- uint64_t offset, size_t len)
502
+static int coroutine_fn GRAPH_RDLOCK
503
+qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
504
{
505
QEDAIOCB *acb = opaque;
506
507
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
508
/**
509
* Begin next I/O or complete the request
510
*/
511
-static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
512
+static int coroutine_fn GRAPH_RDLOCK qed_aio_next_io(QEDAIOCB *acb)
513
{
514
BDRVQEDState *s = acb_to_s(acb);
515
uint64_t offset;
516
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
517
return ret;
518
}
519
520
-static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num,
521
- QEMUIOVector *qiov, int nb_sectors,
522
- int flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
525
+ int nb_sectors, int flags)
526
{
527
QEDAIOCB acb = {
528
.bs = bs,
529
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
530
int64_t sector_num, int nb_sectors,
531
QEMUIOVector *qiov)
532
{
533
+ assume_graph_lock(); /* FIXME */
534
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
535
}
536
537
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
538
int64_t sector_num, int nb_sectors,
539
QEMUIOVector *qiov, int flags)
540
{
541
+ assume_graph_lock(); /* FIXME */
542
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
543
}
544
545
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
546
{
547
BDRVQEDState *s = bs->opaque;
548
549
+ assume_graph_lock(); /* FIXME */
550
+
551
/*
552
* Zero writes start without an I/O buffer. If a buffer becomes necessary
553
* then it will be allocated during request processing.
554
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
555
return ret;
556
}
557
558
-static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
559
- Error **errp)
560
+static void coroutine_fn GRAPH_RDLOCK
561
+bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp)
562
{
563
BDRVQEDState *s = bs->opaque;
564
int ret;
565
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
21
}
566
}
22
567
}
23
+ if (!ret && total_size) {
568
24
+ uint8_t buf[BDRV_SECTOR_SIZE] = { 0 };
569
-static int coroutine_fn bdrv_qed_co_check(BlockDriverState *bs,
25
+ int64_t zero_size = MIN(BDRV_SECTOR_SIZE, total_size);
570
- BdrvCheckResult *result,
26
+ if (lseek(fd, 0, SEEK_SET) == -1) {
571
- BdrvCheckMode fix)
27
+ ret = -errno;
572
+static int coroutine_fn GRAPH_RDLOCK
28
+ } else {
573
+bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
29
+ ret = qemu_write_full(fd, buf, zero_size);
574
+ BdrvCheckMode fix)
30
+ ret = ret == zero_size ? 0 : -errno;
575
{
31
+ }
576
BDRVQEDState *s = bs->opaque;
32
+ }
577
int ret;
33
qemu_close(fd);
578
diff --git a/block/quorum.c b/block/quorum.c
579
index XXXXXXX..XXXXXXX 100644
580
--- a/block/quorum.c
581
+++ b/block/quorum.c
582
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
583
return result;
584
}
585
586
-static coroutine_fn int quorum_co_flush(BlockDriverState *bs)
587
+static coroutine_fn GRAPH_RDLOCK int quorum_co_flush(BlockDriverState *bs)
588
{
589
BDRVQuorumState *s = bs->opaque;
590
QuorumVoteVersion *winner = NULL;
591
diff --git a/block/throttle.c b/block/throttle.c
592
index XXXXXXX..XXXXXXX 100644
593
--- a/block/throttle.c
594
+++ b/block/throttle.c
595
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
596
BDRV_REQ_WRITE_COMPRESSED);
597
}
598
599
-static int coroutine_fn throttle_co_flush(BlockDriverState *bs)
600
+static int coroutine_fn GRAPH_RDLOCK throttle_co_flush(BlockDriverState *bs)
601
{
602
return bdrv_co_flush(bs->file->bs);
603
}
604
diff --git a/block/vmdk.c b/block/vmdk.c
605
index XXXXXXX..XXXXXXX 100644
606
--- a/block/vmdk.c
607
+++ b/block/vmdk.c
608
@@ -XXX,XX +XXX,XX @@ exit:
34
return ret;
609
return ret;
35
}
610
}
611
612
-static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
613
- uint32_t offset)
614
+static int coroutine_fn GRAPH_RDLOCK
615
+vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
616
{
617
offset = cpu_to_le32(offset);
618
/* update L2 table */
619
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
620
uint64_t bytes_done = 0;
621
VmdkMetaData m_data;
622
623
+ assume_graph_lock(); /* FIXME */
624
+
625
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
626
error_report("Wrong offset: offset=0x%" PRIx64
627
" total_sectors=0x%" PRIx64,
36
--
628
--
37
2.13.5
629
2.39.2
38
39
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
bdrv_co_pdiscard() need to hold a reader lock for the graph.
5
6
For some places, we know that they will hold the lock, but we don't have
7
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
8
with a FIXME comment. These places will be removed once everything is
9
properly annotated.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20230203152202.49054-9-kwolf@redhat.com>
13
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
include/block/block-io.h | 5 +++--
17
include/block/block_int-common.h | 15 +++++++++------
18
include/block/block_int-io.h | 2 +-
19
block/blkdebug.c | 4 ++--
20
block/blklogwrites.c | 5 ++---
21
block/blkreplay.c | 4 ++--
22
block/block-backend.c | 1 +
23
block/copy-before-write.c | 8 ++++----
24
block/copy-on-read.c | 4 ++--
25
block/filter-compress.c | 4 ++--
26
block/io.c | 2 ++
27
block/mirror.c | 14 +++++++++-----
28
block/preallocate.c | 4 ++--
29
block/raw-format.c | 4 ++--
30
block/snapshot-access.c | 4 ++--
31
block/throttle.c | 4 ++--
32
16 files changed, 47 insertions(+), 37 deletions(-)
33
34
diff --git a/include/block/block-io.h b/include/block/block-io.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block-io.h
37
+++ b/include/block/block-io.h
38
@@ -XXX,XX +XXX,XX @@ bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
39
/* Ensure contents are flushed to disk. */
40
int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
41
42
-int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
43
- int64_t bytes);
44
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
45
+ int64_t bytes);
46
+
47
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
48
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
49
int64_t bytes, int64_t *pnum, int64_t *map,
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
56
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
57
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
58
- BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
59
- int64_t offset, int bytes,
60
+
61
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pdiscard)(
62
+ BlockDriverState *bs, int64_t offset, int bytes,
63
BlockCompletionFunc *cb, void *opaque);
64
65
int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
66
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
67
*/
68
int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
69
int64_t offset, int64_t bytes, BdrvRequestFlags flags);
70
- int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs,
71
- int64_t offset, int64_t bytes);
72
+
73
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
74
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
75
76
/*
77
* Map [offset, offset + nbytes) range onto a child of @bs to copy from,
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
79
int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
80
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
81
int64_t *map, BlockDriverState **file);
82
- int coroutine_fn (*bdrv_co_pdiscard_snapshot)(BlockDriverState *bs,
83
- int64_t offset, int64_t bytes);
84
+
85
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
86
+ BlockDriverState *bs, int64_t offset, int64_t bytes);
87
88
/*
89
* Invalidate any cached meta-data.
90
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
91
index XXXXXXX..XXXXXXX 100644
92
--- a/include/block/block_int-io.h
93
+++ b/include/block/block_int-io.h
94
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
95
int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
96
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
97
int64_t *map, BlockDriverState **file);
98
-int coroutine_fn bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
99
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
100
int64_t offset, int64_t bytes);
101
102
103
diff --git a/block/blkdebug.c b/block/blkdebug.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/blkdebug.c
106
+++ b/block/blkdebug.c
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
108
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
109
}
110
111
-static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
112
- int64_t offset, int64_t bytes)
113
+static int coroutine_fn GRAPH_RDLOCK
114
+blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
115
{
116
uint32_t align = bs->bl.pdiscard_alignment;
117
int err;
118
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/block/blklogwrites.c
121
+++ b/block/blklogwrites.c
122
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
123
return bdrv_co_flush(fr->bs->file->bs);
124
}
125
126
-static int coroutine_fn
127
+static int coroutine_fn GRAPH_RDLOCK
128
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
129
{
130
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
131
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
132
LOG_FLUSH_FLAG, false);
133
}
134
135
-static int coroutine_fn
136
+static int coroutine_fn GRAPH_RDLOCK
137
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
138
{
139
- assume_graph_lock(); /* FIXME */
140
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,
141
blk_log_writes_co_do_file_pdiscard,
142
LOG_DISCARD_FLAG, false);
143
diff --git a/block/blkreplay.c b/block/blkreplay.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/block/blkreplay.c
146
+++ b/block/blkreplay.c
147
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
148
return ret;
149
}
150
151
-static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
152
- int64_t offset, int64_t bytes)
153
+static int coroutine_fn GRAPH_RDLOCK
154
+blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
155
{
156
uint64_t reqid = blkreplay_next_id();
157
int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
158
diff --git a/block/block-backend.c b/block/block-backend.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/block-backend.c
161
+++ b/block/block-backend.c
162
@@ -XXX,XX +XXX,XX @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
163
IO_CODE();
164
165
blk_wait_while_drained(blk);
166
+ GRAPH_RDLOCK_GUARD();
167
168
ret = blk_check_byte_request(blk, offset, bytes);
169
if (ret < 0) {
170
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/copy-before-write.c
173
+++ b/block/copy-before-write.c
174
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
175
return 0;
176
}
177
178
-static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
179
- int64_t offset, int64_t bytes)
180
+static int coroutine_fn GRAPH_RDLOCK
181
+cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
182
{
183
int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
184
if (ret < 0) {
185
@@ -XXX,XX +XXX,XX @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
186
return ret;
187
}
188
189
-static int coroutine_fn cbw_co_pdiscard_snapshot(BlockDriverState *bs,
190
- int64_t offset, int64_t bytes)
191
+static int coroutine_fn GRAPH_RDLOCK
192
+cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
193
{
194
BDRVCopyBeforeWriteState *s = bs->opaque;
195
196
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/block/copy-on-read.c
199
+++ b/block/copy-on-read.c
200
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
201
}
202
203
204
-static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
205
- int64_t offset, int64_t bytes)
206
+static int coroutine_fn GRAPH_RDLOCK
207
+cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
208
{
209
return bdrv_co_pdiscard(bs->file, offset, bytes);
210
}
211
diff --git a/block/filter-compress.c b/block/filter-compress.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/block/filter-compress.c
214
+++ b/block/filter-compress.c
215
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
216
}
217
218
219
-static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
220
- int64_t offset, int64_t bytes)
221
+static int coroutine_fn GRAPH_RDLOCK
222
+compress_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
223
{
224
return bdrv_co_pdiscard(bs->file, offset, bytes);
225
}
226
diff --git a/block/io.c b/block/io.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/block/io.c
229
+++ b/block/io.c
230
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
231
int head, tail, align;
232
BlockDriverState *bs = child->bs;
233
IO_CODE();
234
+ assert_bdrv_graph_readable();
235
236
if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
237
return -ENOMEDIUM;
238
@@ -XXX,XX +XXX,XX @@ bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
239
BlockDriver *drv = bs->drv;
240
int ret;
241
IO_CODE();
242
+ assert_bdrv_graph_readable();
243
244
if (!drv) {
245
return -ENOMEDIUM;
246
diff --git a/block/mirror.c b/block/mirror.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/mirror.c
249
+++ b/block/mirror.c
250
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
251
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
252
}
253
254
-static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs,
255
- MirrorMethod method, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
256
- int flags)
257
+static int coroutine_fn GRAPH_RDLOCK
258
+bdrv_mirror_top_do_write(BlockDriverState *bs, MirrorMethod method,
259
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
260
+ int flags)
261
{
262
MirrorOp *op = NULL;
263
MirrorBDSOpaque *s = bs->opaque;
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
265
int ret = 0;
266
bool copy_to_target = false;
267
268
+ assume_graph_lock(); /* FIXME */
269
+
270
if (s->job) {
271
copy_to_target = s->job->ret >= 0 &&
272
!job_is_cancelled(&s->job->common.job) &&
273
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
274
static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
275
int64_t offset, int64_t bytes, BdrvRequestFlags flags)
276
{
277
+ assume_graph_lock(); /* FIXME */
278
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
279
flags);
280
}
281
282
-static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
283
- int64_t offset, int64_t bytes)
284
+static int coroutine_fn GRAPH_RDLOCK
285
+bdrv_mirror_top_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
286
{
287
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_DISCARD, offset, bytes,
288
NULL, 0);
289
diff --git a/block/preallocate.c b/block/preallocate.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/preallocate.c
292
+++ b/block/preallocate.c
293
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_preadv_part(
294
flags);
295
}
296
297
-static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs,
298
- int64_t offset, int64_t bytes)
299
+static int coroutine_fn GRAPH_RDLOCK
300
+preallocate_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
301
{
302
return bdrv_co_pdiscard(bs->file, offset, bytes);
303
}
304
diff --git a/block/raw-format.c b/block/raw-format.c
305
index XXXXXXX..XXXXXXX 100644
306
--- a/block/raw-format.c
307
+++ b/block/raw-format.c
308
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
309
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
310
}
311
312
-static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
313
- int64_t offset, int64_t bytes)
314
+static int coroutine_fn GRAPH_RDLOCK
315
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
316
{
317
int ret;
318
319
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/block/snapshot-access.c
322
+++ b/block/snapshot-access.c
323
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_block_status(BlockDriverState *bs,
324
bytes, pnum, map, file);
325
}
326
327
-static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs,
328
- int64_t offset, int64_t bytes)
329
+static int coroutine_fn GRAPH_RDLOCK
330
+snapshot_access_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
331
{
332
return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes);
333
}
334
diff --git a/block/throttle.c b/block/throttle.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/block/throttle.c
337
+++ b/block/throttle.c
338
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
339
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
340
}
341
342
-static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
343
- int64_t offset, int64_t bytes)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
346
{
347
ThrottleGroupMember *tgm = bs->opaque;
348
throttle_group_co_io_limits_intercept(tgm, bytes, true);
349
--
350
2.39.2
diff view generated by jsdifflib
New patch
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_pwrite_zeroes() need to hold a reader lock for the graph.
1
3
4
For some places, we know that they will hold the lock, but we don't have
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230203152202.49054-10-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/qcow2.h | 6 ++++--
15
include/block/block-io.h | 9 +++++----
16
include/block/block_int-common.h | 5 +++--
17
block/blkdebug.c | 6 +++---
18
block/blklogwrites.c | 5 ++---
19
block/blkreplay.c | 5 +++--
20
block/block-copy.c | 13 +++++++------
21
block/copy-before-write.c | 5 +++--
22
block/copy-on-read.c | 6 +++---
23
block/filter-compress.c | 6 +++---
24
block/io.c | 12 +++++++++---
25
block/mirror.c | 6 +++---
26
block/preallocate.c | 11 +++++++----
27
block/qcow2.c | 30 ++++++++++++++++++------------
28
block/qed.c | 9 +++------
29
block/quorum.c | 15 ++++++++++-----
30
block/raw-format.c | 6 +++---
31
block/throttle.c | 6 +++---
32
18 files changed, 92 insertions(+), 69 deletions(-)
33
34
diff --git a/block/qcow2.h b/block/qcow2.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/qcow2.h
37
+++ b/block/qcow2.h
38
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
39
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
40
uint64_t bytes, enum qcow2_discard_type type,
41
bool full_discard);
42
-int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
43
- uint64_t bytes, int flags);
44
+
45
+int coroutine_fn GRAPH_RDLOCK
46
+qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
47
+ int flags);
48
49
int qcow2_expand_zero_clusters(BlockDriverState *bs,
50
BlockDriverAmendStatusCB *status_cb,
51
diff --git a/include/block/block-io.h b/include/block/block-io.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/block/block-io.h
54
+++ b/include/block/block-io.h
55
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
56
* function is not suitable for zeroing the entire image in a single request
57
* because it may allocate memory for the entire region.
58
*/
59
-int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
60
- int64_t bytes, BdrvRequestFlags flags);
61
+int coroutine_fn GRAPH_RDLOCK
62
+bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, int64_t bytes,
63
+ BdrvRequestFlags flags);
64
65
int coroutine_fn GRAPH_RDLOCK
66
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
67
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
68
bool include_base, int64_t offset, int64_t bytes,
69
int64_t *pnum);
70
71
-int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
72
- int64_t bytes);
73
+int coroutine_fn GRAPH_RDLOCK
74
+bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes);
75
76
int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
77
Error **errp);
78
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
79
index XXXXXXX..XXXXXXX 100644
80
--- a/include/block/block_int-common.h
81
+++ b/include/block/block_int-common.h
82
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
83
* function pointer may be NULL or return -ENOSUP and .bdrv_co_writev()
84
* will be called instead.
85
*/
86
- int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
87
- int64_t offset, int64_t bytes, BdrvRequestFlags flags);
88
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwrite_zeroes)(
89
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
90
+ BdrvRequestFlags flags);
91
92
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard)(
93
BlockDriverState *bs, int64_t offset, int64_t bytes);
94
diff --git a/block/blkdebug.c b/block/blkdebug.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/blkdebug.c
97
+++ b/block/blkdebug.c
98
@@ -XXX,XX +XXX,XX @@ static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
99
return bdrv_co_flush(bs->file->bs);
100
}
101
102
-static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
103
- int64_t offset, int64_t bytes,
104
- BdrvRequestFlags flags)
105
+static int coroutine_fn GRAPH_RDLOCK
106
+blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
107
+ BdrvRequestFlags flags)
108
{
109
uint32_t align = MAX(bs->bl.request_alignment,
110
bs->bl.pwrite_zeroes_alignment);
111
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/blklogwrites.c
114
+++ b/block/blklogwrites.c
115
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
116
fr->qiov, fr->file_flags);
117
}
118
119
-static int coroutine_fn
120
+static int coroutine_fn GRAPH_RDLOCK
121
blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
122
{
123
return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes,
124
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
125
blk_log_writes_co_do_file_pwritev, 0, false);
126
}
127
128
-static int coroutine_fn
129
+static int coroutine_fn GRAPH_RDLOCK
130
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
131
int64_t bytes, BdrvRequestFlags flags)
132
{
133
- assume_graph_lock(); /* FIXME */
134
return blk_log_writes_co_log(bs, offset, bytes, NULL, flags,
135
blk_log_writes_co_do_file_pwrite_zeroes, 0,
136
true);
137
diff --git a/block/blkreplay.c b/block/blkreplay.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/blkreplay.c
140
+++ b/block/blkreplay.c
141
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
142
return ret;
143
}
144
145
-static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
146
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
147
+static int coroutine_fn GRAPH_RDLOCK
148
+blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
149
+ BdrvRequestFlags flags)
150
{
151
uint64_t reqid = blkreplay_next_id();
152
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
153
diff --git a/block/block-copy.c b/block/block-copy.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/block-copy.c
156
+++ b/block/block-copy.c
157
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
158
* value of @method should be used for subsequent tasks.
159
* Returns 0 on success.
160
*/
161
-static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
162
- int64_t offset, int64_t bytes,
163
- BlockCopyMethod *method,
164
- bool *error_is_read)
165
+static int coroutine_fn GRAPH_RDLOCK
166
+block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
167
+ BlockCopyMethod *method, bool *error_is_read)
168
{
169
int ret;
170
int64_t nbytes = MIN(offset + bytes, s->len) - offset;
171
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
172
BlockCopyMethod method = t->method;
173
int ret;
174
175
- ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
176
- &error_is_read);
177
+ WITH_GRAPH_RDLOCK_GUARD() {
178
+ ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
179
+ &error_is_read);
180
+ }
181
182
WITH_QEMU_LOCK_GUARD(&s->lock) {
183
if (s->method == t->method) {
184
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/block/copy-before-write.c
187
+++ b/block/copy-before-write.c
188
@@ -XXX,XX +XXX,XX @@ cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
189
return bdrv_co_pdiscard(bs->file, offset, bytes);
190
}
191
192
-static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
193
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
194
+static int coroutine_fn GRAPH_RDLOCK
195
+cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
196
+ BdrvRequestFlags flags)
197
{
198
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
199
if (ret < 0) {
200
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
201
index XXXXXXX..XXXXXXX 100644
202
--- a/block/copy-on-read.c
203
+++ b/block/copy-on-read.c
204
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
205
}
206
207
208
-static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
209
- int64_t offset, int64_t bytes,
210
- BdrvRequestFlags flags)
211
+static int coroutine_fn GRAPH_RDLOCK
212
+cor_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
213
+ BdrvRequestFlags flags)
214
{
215
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
216
}
217
diff --git a/block/filter-compress.c b/block/filter-compress.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/filter-compress.c
220
+++ b/block/filter-compress.c
221
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
222
}
223
224
225
-static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
226
- int64_t offset, int64_t bytes,
227
- BdrvRequestFlags flags)
228
+static int coroutine_fn GRAPH_RDLOCK
229
+compress_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
230
+ BdrvRequestFlags flags)
231
{
232
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
233
}
234
diff --git a/block/io.c b/block/io.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/block/io.c
237
+++ b/block/io.c
238
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
239
int64_t progress = 0;
240
bool skip_write;
241
242
+ assume_graph_lock(); /* FIXME */
243
+
244
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
245
246
if (!drv) {
247
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
248
bs->bl.request_alignment);
249
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
250
251
+ assert_bdrv_graph_readable();
252
bdrv_check_request(offset, bytes, &error_abort);
253
254
if (!drv) {
255
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
256
int64_t bytes_remaining = bytes;
257
int max_transfer;
258
259
+ assume_graph_lock(); /* FIXME */
260
+
261
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
262
263
if (!drv) {
264
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
265
{
266
IO_CODE();
267
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
268
+ assert_bdrv_graph_readable();
269
270
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
271
flags &= ~BDRV_REQ_MAY_UNMAP;
272
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
273
int64_t pnum = bytes;
274
IO_CODE();
275
276
- assume_graph_lock(); /* FIXME */
277
-
278
if (!bytes) {
279
return 1;
280
}
281
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
282
}
283
}
284
285
-static int coroutine_fn bdrv_co_copy_range_internal(
286
+static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
287
BdrvChild *src, int64_t src_offset, BdrvChild *dst,
288
int64_t dst_offset, int64_t bytes,
289
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
290
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
291
BdrvRequestFlags write_flags)
292
{
293
IO_CODE();
294
+ assume_graph_lock(); /* FIXME */
295
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
296
read_flags, write_flags);
297
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
298
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
299
BdrvRequestFlags write_flags)
300
{
301
IO_CODE();
302
+ assume_graph_lock(); /* FIXME */
303
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
304
read_flags, write_flags);
305
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
306
diff --git a/block/mirror.c b/block/mirror.c
307
index XXXXXXX..XXXXXXX 100644
308
--- a/block/mirror.c
309
+++ b/block/mirror.c
310
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_mirror_top_flush(BlockDriverState *bs)
311
return bdrv_co_flush(bs->backing->bs);
312
}
313
314
-static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
315
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
318
+ int64_t bytes, BdrvRequestFlags flags)
319
{
320
- assume_graph_lock(); /* FIXME */
321
return bdrv_mirror_top_do_write(bs, MIRROR_METHOD_ZERO, offset, bytes, NULL,
322
flags);
323
}
324
diff --git a/block/preallocate.c b/block/preallocate.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/block/preallocate.c
327
+++ b/block/preallocate.c
328
@@ -XXX,XX +XXX,XX @@ static bool has_prealloc_perms(BlockDriverState *bs)
329
* want_merge_zero is used to merge write-zero request with preallocation in
330
* one bdrv_co_pwrite_zeroes() call.
331
*/
332
-static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
333
- int64_t bytes, bool want_merge_zero)
334
+static bool coroutine_fn GRAPH_RDLOCK
335
+handle_write(BlockDriverState *bs, int64_t offset, int64_t bytes,
336
+ bool want_merge_zero)
337
{
338
BDRVPreallocateState *s = bs->opaque;
339
int64_t end = offset + bytes;
340
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
341
return want_merge_zero;
342
}
343
344
-static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs,
345
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
346
+static int coroutine_fn GRAPH_RDLOCK
347
+preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
348
+ int64_t bytes, BdrvRequestFlags flags)
349
{
350
bool want_merge_zero =
351
!(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK));
352
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
353
size_t qiov_offset,
354
BdrvRequestFlags flags)
355
{
356
+ assume_graph_lock(); /* FIXME */
357
handle_write(bs, offset, bytes, false);
358
359
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
360
diff --git a/block/qcow2.c b/block/qcow2.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/qcow2.c
363
+++ b/block/qcow2.c
364
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
365
* Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error.
366
* Note that returning 0 does not guarantee non-zero data.
367
*/
368
-static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
369
+static int coroutine_fn GRAPH_RDLOCK
370
+is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
371
{
372
/*
373
* This check is designed for optimization shortcut so it must be
374
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
375
m->cow_end.nb_bytes);
376
}
377
378
-static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
379
- QCowL2Meta *l2meta)
380
+static int coroutine_fn GRAPH_RDLOCK
381
+handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
382
{
383
BDRVQcow2State *s = bs->opaque;
384
QCowL2Meta *m;
385
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
386
* l2meta - if not NULL, qcow2_co_pwritev_task() will consume it. Caller must
387
* not use it somehow after qcow2_co_pwritev_task() call
388
*/
389
-static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
390
- uint64_t host_offset,
391
- uint64_t offset, uint64_t bytes,
392
- QEMUIOVector *qiov,
393
- uint64_t qiov_offset,
394
- QCowL2Meta *l2meta)
395
+static coroutine_fn GRAPH_RDLOCK
396
+int qcow2_co_pwritev_task(BlockDriverState *bs, uint64_t host_offset,
397
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
398
+ uint64_t qiov_offset, QCowL2Meta *l2meta)
399
{
400
int ret;
401
BDRVQcow2State *s = bs->opaque;
402
@@ -XXX,XX +XXX,XX @@ out_locked:
403
return ret;
404
}
405
406
-static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
407
+/*
408
+ * This function can count as GRAPH_RDLOCK because qcow2_co_pwritev_part() holds
409
+ * the graph lock and keeps it until this coroutine has terminated.
410
+ */
411
+static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
412
{
413
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
414
415
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
416
QCowL2Meta *l2meta = NULL;
417
AioTaskPool *aio = NULL;
418
419
+ assume_graph_lock(); /* FIXME */
420
+
421
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
422
423
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
424
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
425
return res >= 0 && (res & BDRV_BLOCK_ZERO) && bytes == 0;
426
}
427
428
-static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
429
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
430
+static int coroutine_fn GRAPH_RDLOCK
431
+qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
432
+ BdrvRequestFlags flags)
433
{
434
int ret;
435
BDRVQcow2State *s = bs->opaque;
436
diff --git a/block/qed.c b/block/qed.c
437
index XXXXXXX..XXXXXXX 100644
438
--- a/block/qed.c
439
+++ b/block/qed.c
440
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
441
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
442
}
443
444
-static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
445
- int64_t offset,
446
- int64_t bytes,
447
- BdrvRequestFlags flags)
448
+static int coroutine_fn GRAPH_RDLOCK
449
+bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
450
+ BdrvRequestFlags flags)
451
{
452
BDRVQEDState *s = bs->opaque;
453
454
- assume_graph_lock(); /* FIXME */
455
-
456
/*
457
* Zero writes start without an I/O buffer. If a buffer becomes necessary
458
* then it will be allocated during request processing.
459
diff --git a/block/quorum.c b/block/quorum.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/block/quorum.c
462
+++ b/block/quorum.c
463
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
464
return ret;
465
}
466
467
-static void coroutine_fn write_quorum_entry(void *opaque)
468
+/*
469
+ * This function can count as GRAPH_RDLOCK because quorum_co_pwritev() holds the
470
+ * graph lock and keeps it until this coroutine has terminated.
471
+ */
472
+static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
473
{
474
QuorumCo *co = opaque;
475
QuorumAIOCB *acb = co->acb;
476
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
477
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
478
int i, ret;
479
480
+ assume_graph_lock(); /* FIXME */
481
+
482
for (i = 0; i < s->num_children; i++) {
483
Coroutine *co;
484
QuorumCo data = {
485
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
486
return ret;
487
}
488
489
-static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
490
- int64_t offset, int64_t bytes,
491
- BdrvRequestFlags flags)
492
-
493
+static int coroutine_fn GRAPH_RDLOCK
494
+quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
495
+ BdrvRequestFlags flags)
496
{
497
return quorum_co_pwritev(bs, offset, bytes, NULL,
498
flags | BDRV_REQ_ZERO_WRITE);
499
diff --git a/block/raw-format.c b/block/raw-format.c
500
index XXXXXXX..XXXXXXX 100644
501
--- a/block/raw-format.c
502
+++ b/block/raw-format.c
503
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
504
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
505
}
506
507
-static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
508
- int64_t offset, int64_t bytes,
509
- BdrvRequestFlags flags)
510
+static int coroutine_fn GRAPH_RDLOCK
511
+raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
512
+ BdrvRequestFlags flags)
513
{
514
int ret;
515
516
diff --git a/block/throttle.c b/block/throttle.c
517
index XXXXXXX..XXXXXXX 100644
518
--- a/block/throttle.c
519
+++ b/block/throttle.c
520
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
521
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
522
}
523
524
-static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
525
- int64_t offset, int64_t bytes,
526
- BdrvRequestFlags flags)
527
+static int coroutine_fn GRAPH_RDLOCK
528
+throttle_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
529
+ BdrvRequestFlags flags)
530
{
531
ThrottleGroupMember *tgm = bs->opaque;
532
throttle_group_co_io_limits_intercept(tgm, bytes, true);
533
--
534
2.39.2
diff view generated by jsdifflib
1
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_driver_*() need to hold a reader lock for the graph. It doesn't add
3
the annotation to public functions yet.
2
4
3
This patch add shrinking of the image file for qcow2. As a result, this allows
5
For some places, we know that they will hold the lock, but we don't have
4
us to reduce the virtual image size and free up space on the disk without
6
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
copying the image. Image can be fragmented and shrink is done by punching holes
7
with a FIXME comment. These places will be removed once everything is
6
in the image file.
8
properly annotated.
7
9
8
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20230203152202.49054-11-kwolf@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
12
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-id: 20170918124230.8152-4-pbutsykin@virtuozzo.com
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
---
14
qapi/block-core.json | 8 +++-
15
block/qcow2.h | 5 ++-
15
block/qcow2.h | 14 ++++++
16
include/block/block_int-common.h | 40 ++++++++++---------
16
block/qcow2-cluster.c | 50 +++++++++++++++++++++
17
block/io.c | 66 +++++++++++++++-----------------
17
block/qcow2-refcount.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++
18
block/parallels.c | 8 ++--
18
block/qcow2.c | 43 ++++++++++++++----
19
block/qcow.c | 20 ++++------
19
5 files changed, 225 insertions(+), 10 deletions(-)
20
block/qcow2-cluster.c | 10 ++---
21
block/qcow2.c | 37 ++++++++++--------
22
block/qed.c | 14 +++----
23
block/quorum.c | 8 ++--
24
block/vmdk.c | 4 +-
25
10 files changed, 101 insertions(+), 111 deletions(-)
20
26
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/block-core.json
24
+++ b/qapi/block-core.json
25
@@ -XXX,XX +XXX,XX @@
26
#
27
# Trigger events supported by blkdebug.
28
#
29
+# @l1_shrink_write_table: write zeros to the l1 table to shrink image.
30
+# (since 2.11)
31
+#
32
+# @l1_shrink_free_l2_clusters: discard the l2 tables. (since 2.11)
33
+#
34
# Since: 2.9
35
##
36
{ 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG',
37
@@ -XXX,XX +XXX,XX @@
38
'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
39
'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head',
40
'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev',
41
- 'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] }
42
+ 'pwritev_zero', 'pwritev_done', 'empty_image_prepare',
43
+ 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters' ] }
44
45
##
46
# @BlkdebugInjectErrorOptions:
47
diff --git a/block/qcow2.h b/block/qcow2.h
27
diff --git a/block/qcow2.h b/block/qcow2.h
48
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
49
--- a/block/qcow2.h
29
--- a/block/qcow2.h
50
+++ b/block/qcow2.h
30
+++ b/block/qcow2.h
51
@@ -XXX,XX +XXX,XX @@ static inline uint64_t refcount_diff(uint64_t r1, uint64_t r2)
31
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
52
return r1 > r2 ? r1 - r2 : r2 - r1;
32
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
53
}
33
uint64_t *coffset, int *csize);
54
34
55
+static inline
35
-int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
56
+uint32_t offset_to_reftable_index(BDRVQcow2State *s, uint64_t offset)
36
- QCowL2Meta *m);
57
+{
37
+int coroutine_fn GRAPH_RDLOCK
58
+ return offset >> (s->refcount_block_bits + s->cluster_bits);
38
+qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
59
+}
60
+
39
+
61
+static inline uint64_t get_refblock_offset(BDRVQcow2State *s, uint64_t offset)
40
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
62
+{
41
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
63
+ uint32_t index = offset_to_reftable_index(s, offset);
42
uint64_t bytes, enum qcow2_discard_type type,
64
+ return s->refcount_table[index] & REFT_OFFSET_MASK;
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
65
+}
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
Error **errp);
49
50
/* aio */
51
- BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
52
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs,
53
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
54
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
55
- BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
66
+
56
+
67
/* qcow2.c functions */
57
+ BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_pwritev)(BlockDriverState *bs,
68
int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
58
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
69
int64_t sector_num, int nb_sectors);
59
BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque);
70
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
60
+
71
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
61
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_flush)(
72
BlockDriverAmendStatusCB *status_cb,
62
BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque);
73
void *cb_opaque, Error **errp);
63
74
+int qcow2_shrink_reftable(BlockDriverState *bs);
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
75
65
BlockDriverState *bs, int64_t offset, int bytes,
76
/* qcow2-cluster.c functions */
66
BlockCompletionFunc *cb, void *opaque);
77
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
67
78
bool exact_size);
68
- int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
79
+int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
69
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_readv)(BlockDriverState *bs,
80
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
70
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
81
int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
71
82
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
72
/**
73
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
74
*
75
* The buffer in @qiov may point directly to guest memory.
76
*/
77
- int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
78
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv)(BlockDriverState *bs,
79
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
80
BdrvRequestFlags flags);
81
82
- int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs,
83
- int64_t offset, int64_t bytes,
84
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_part)(
85
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
86
QEMUIOVector *qiov, size_t qiov_offset,
87
BdrvRequestFlags flags);
88
89
- int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
90
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_writev)(BlockDriverState *bs,
91
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
92
int flags);
93
/**
94
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
95
*
96
* The buffer in @qiov may point directly to guest memory.
97
*/
98
- int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
99
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
100
- BdrvRequestFlags flags);
101
- int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs,
102
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset,
103
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev)(
104
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
105
BdrvRequestFlags flags);
106
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_part)(
107
+ BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
108
+ size_t qiov_offset, BdrvRequestFlags flags);
109
110
/*
111
* Efficiently zero a region of the disk image. Typically an image format
112
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
113
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
114
Error **errp);
115
116
- int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
117
- int64_t offset, int64_t bytes, QEMUIOVector *qiov);
118
- int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs,
119
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
120
- size_t qiov_offset);
121
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed)(
122
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
123
+ QEMUIOVector *qiov);
124
+
125
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pwritev_compressed_part)(
126
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
127
+ QEMUIOVector *qiov, size_t qiov_offset);
128
129
int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
130
BlockDriverInfo *bdi);
131
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
132
BlockDriverState *bs, const char *name, Error **errp);
133
};
134
135
-static inline bool block_driver_can_compress(BlockDriver *drv)
136
+static inline bool TSA_NO_TSA block_driver_can_compress(BlockDriver *drv)
137
{
138
return drv->bdrv_co_pwritev_compressed ||
139
drv->bdrv_co_pwritev_compressed_part;
140
diff --git a/block/io.c b/block/io.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/io.c
143
+++ b/block/io.c
144
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
145
bool have_limits;
146
147
GLOBAL_STATE_CODE();
148
+ assume_graph_lock(); /* FIXME */
149
150
if (tran) {
151
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
152
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
153
aio_co_wake(co->coroutine);
154
}
155
156
-static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
157
- int64_t offset, int64_t bytes,
158
- QEMUIOVector *qiov,
159
- size_t qiov_offset, int flags)
160
+static int coroutine_fn GRAPH_RDLOCK
161
+bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
162
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
163
{
164
BlockDriver *drv = bs->drv;
165
int64_t sector_num;
166
@@ -XXX,XX +XXX,XX @@ out:
167
return ret;
168
}
169
170
-static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
171
- int64_t offset, int64_t bytes,
172
- QEMUIOVector *qiov,
173
- size_t qiov_offset,
174
- BdrvRequestFlags flags)
175
+static int coroutine_fn GRAPH_RDLOCK
176
+bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
177
+ QEMUIOVector *qiov, size_t qiov_offset,
178
+ BdrvRequestFlags flags)
179
{
180
BlockDriver *drv = bs->drv;
181
bool emulate_fua = false;
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
183
QEMUIOVector local_qiov;
184
int ret;
185
186
- assume_graph_lock(); /* FIXME */
187
-
188
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
189
190
if (!drv) {
191
@@ -XXX,XX +XXX,XX @@ emulate_flags:
192
return ret;
193
}
194
195
-static int coroutine_fn
196
+static int coroutine_fn GRAPH_RDLOCK
197
bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
198
int64_t bytes, QEMUIOVector *qiov,
199
size_t qiov_offset)
200
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
201
return ret;
202
}
203
204
-static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
205
- int64_t offset, int64_t bytes, QEMUIOVector *qiov,
206
- size_t qiov_offset, int flags)
207
+static int coroutine_fn GRAPH_RDLOCK
208
+bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
209
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
210
{
211
BlockDriverState *bs = child->bs;
212
213
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
214
int64_t progress = 0;
215
bool skip_write;
216
217
- assume_graph_lock(); /* FIXME */
218
-
219
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
220
221
if (!drv) {
222
@@ -XXX,XX +XXX,XX @@ err:
223
* handles copy on read, zeroing after EOF, and fragmentation of large
224
* reads; any other features must be implemented by the caller.
225
*/
226
-static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
227
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
228
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
229
+static int coroutine_fn GRAPH_RDLOCK
230
+bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req,
231
+ int64_t offset, int64_t bytes, int64_t align,
232
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
233
{
234
BlockDriverState *bs = child->bs;
235
int64_t total_bytes, max_bytes;
236
@@ -XXX,XX +XXX,XX @@ static bool bdrv_init_padding(BlockDriverState *bs,
237
return true;
238
}
239
240
-static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
241
- BdrvTrackedRequest *req,
242
- BdrvRequestPadding *pad,
243
- bool zero_middle)
244
+static int coroutine_fn GRAPH_RDLOCK
245
+bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req,
246
+ BdrvRequestPadding *pad, bool zero_middle)
247
{
248
QEMUIOVector local_qiov;
249
BlockDriverState *bs = child->bs;
250
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
251
int ret;
252
IO_CODE();
253
254
+ assume_graph_lock(); /* FIXME */
255
+
256
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
257
258
if (!bdrv_co_is_inserted(bs)) {
259
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
260
* Forwards an already correctly aligned write request to the BlockDriver,
261
* after possibly fragmenting it.
262
*/
263
-static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
264
- BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
265
- int64_t align, QEMUIOVector *qiov, size_t qiov_offset,
266
- BdrvRequestFlags flags)
267
+static int coroutine_fn GRAPH_RDLOCK
268
+bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req,
269
+ int64_t offset, int64_t bytes, int64_t align,
270
+ QEMUIOVector *qiov, size_t qiov_offset,
271
+ BdrvRequestFlags flags)
272
{
273
BlockDriverState *bs = child->bs;
274
BlockDriver *drv = bs->drv;
275
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
276
int64_t bytes_remaining = bytes;
277
int max_transfer;
278
279
- assume_graph_lock(); /* FIXME */
280
-
281
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
282
283
if (!drv) {
284
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
285
return ret;
286
}
287
288
-static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
289
- int64_t offset,
290
- int64_t bytes,
291
- BdrvRequestFlags flags,
292
- BdrvTrackedRequest *req)
293
+static int coroutine_fn GRAPH_RDLOCK
294
+bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
295
+ BdrvRequestFlags flags, BdrvTrackedRequest *req)
296
{
297
BlockDriverState *bs = child->bs;
298
QEMUIOVector local_qiov;
299
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
300
bool padded = false;
301
IO_CODE();
302
303
+ assume_graph_lock(); /* FIXME */
304
+
305
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
306
307
if (!bdrv_co_is_inserted(bs)) {
308
diff --git a/block/parallels.c b/block/parallels.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/block/parallels.c
311
+++ b/block/parallels.c
312
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
313
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
314
}
315
316
-static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
317
- int64_t sector_num, int nb_sectors,
318
- QEMUIOVector *qiov, int flags)
319
+static int coroutine_fn GRAPH_RDLOCK
320
+parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
321
+ QEMUIOVector *qiov, int flags)
322
{
323
BDRVParallelsState *s = bs->opaque;
324
uint64_t bytes_done = 0;
325
QEMUIOVector hd_qiov;
326
int ret = 0;
327
328
- assume_graph_lock(); /* FIXME */
329
-
330
qemu_iovec_init(&hd_qiov, qiov->niov);
331
332
while (nb_sectors > 0) {
333
diff --git a/block/qcow.c b/block/qcow.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/block/qcow.c
336
+++ b/block/qcow.c
337
@@ -XXX,XX +XXX,XX @@ static void qcow_refresh_limits(BlockDriverState *bs, Error **errp)
338
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
339
}
340
341
-static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
342
- int64_t bytes, QEMUIOVector *qiov,
343
- BdrvRequestFlags flags)
344
+static int coroutine_fn GRAPH_RDLOCK
345
+qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
346
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
347
{
348
BDRVQcowState *s = bs->opaque;
349
int offset_in_cluster;
350
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
351
uint8_t *buf;
352
void *orig_buf;
353
354
- assume_graph_lock(); /* FIXME */
355
-
356
if (qiov->niov > 1) {
357
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
358
if (buf == NULL) {
359
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, int64_t offset,
360
return ret;
361
}
362
363
-static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
364
- int64_t bytes, QEMUIOVector *qiov,
365
- BdrvRequestFlags flags)
366
+static int coroutine_fn GRAPH_RDLOCK
367
+qcow_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
368
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
369
{
370
BDRVQcowState *s = bs->opaque;
371
int offset_in_cluster;
372
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, int64_t offset,
373
uint8_t *buf;
374
void *orig_buf;
375
376
- assume_graph_lock(); /* FIXME */
377
-
378
s->cluster_cache_offset = -1; /* disable compressed cache */
379
380
/* We must always copy the iov when encrypting, so we
381
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
382
383
/* XXX: put compressed sectors first, then all the cluster aligned
384
tables to avoid losing bytes in alignment */
385
-static coroutine_fn int
386
+static int coroutine_fn GRAPH_RDLOCK
387
qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
388
QEMUIOVector *qiov)
389
{
390
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
391
uint8_t *buf, *out_buf;
392
uint64_t cluster_offset;
393
394
- assume_graph_lock(); /* FIXME */
395
-
396
buf = qemu_blockalign(bs, s->cluster_size);
397
if (bytes != s->cluster_size) {
398
if (bytes > s->cluster_size ||
83
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
399
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
84
index XXXXXXX..XXXXXXX 100644
400
index XXXXXXX..XXXXXXX 100644
85
--- a/block/qcow2-cluster.c
401
--- a/block/qcow2-cluster.c
86
+++ b/block/qcow2-cluster.c
402
+++ b/block/qcow2-cluster.c
87
@@ -XXX,XX +XXX,XX @@
403
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
88
#include "qemu/bswap.h"
404
return count;
89
#include "trace.h"
405
}
90
406
91
+int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
407
-static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
92
+{
408
- uint64_t src_cluster_offset,
93
+ BDRVQcow2State *s = bs->opaque;
409
- unsigned offset_in_cluster,
94
+ int new_l1_size, i, ret;
410
- QEMUIOVector *qiov)
95
+
411
+static int coroutine_fn GRAPH_RDLOCK
96
+ if (exact_size >= s->l1_size) {
412
+do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
97
+ return 0;
413
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
98
+ }
414
{
99
+
415
int ret;
100
+ new_l1_size = exact_size;
416
101
+
417
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
102
+#ifdef DEBUG_ALLOC2
418
return 0;
103
+ fprintf(stderr, "shrink l1_table from %d to %d\n", s->l1_size, new_l1_size);
419
}
104
+#endif
420
105
+
421
-static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m)
106
+ BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
422
+static int coroutine_fn GRAPH_RDLOCK
107
+ ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
423
+perform_cow(BlockDriverState *bs, QCowL2Meta *m)
108
+ new_l1_size * sizeof(uint64_t),
424
{
109
+ (s->l1_size - new_l1_size) * sizeof(uint64_t), 0);
425
BDRVQcow2State *s = bs->opaque;
110
+ if (ret < 0) {
426
Qcow2COWRegion *start = &m->cow_start;
111
+ goto fail;
112
+ }
113
+
114
+ ret = bdrv_flush(bs->file->bs);
115
+ if (ret < 0) {
116
+ goto fail;
117
+ }
118
+
119
+ BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS);
120
+ for (i = s->l1_size - 1; i > new_l1_size - 1; i--) {
121
+ if ((s->l1_table[i] & L1E_OFFSET_MASK) == 0) {
122
+ continue;
123
+ }
124
+ qcow2_free_clusters(bs, s->l1_table[i] & L1E_OFFSET_MASK,
125
+ s->cluster_size, QCOW2_DISCARD_ALWAYS);
126
+ s->l1_table[i] = 0;
127
+ }
128
+ return 0;
129
+
130
+fail:
131
+ /*
132
+ * If the write in the l1_table failed the image may contain a partially
133
+ * overwritten l1_table. In this case it would be better to clear the
134
+ * l1_table in memory to avoid possible image corruption.
135
+ */
136
+ memset(s->l1_table + new_l1_size, 0,
137
+ (s->l1_size - new_l1_size) * sizeof(uint64_t));
138
+ return ret;
139
+}
140
+
141
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
142
bool exact_size)
143
{
144
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/block/qcow2-refcount.c
147
+++ b/block/qcow2-refcount.c
148
@@ -XXX,XX +XXX,XX @@
149
#include "block/qcow2.h"
150
#include "qemu/range.h"
151
#include "qemu/bswap.h"
152
+#include "qemu/cutils.h"
153
154
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
155
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
156
@@ -XXX,XX +XXX,XX @@ done:
157
qemu_vfree(new_refblock);
158
return ret;
159
}
160
+
161
+static int qcow2_discard_refcount_block(BlockDriverState *bs,
162
+ uint64_t discard_block_offs)
163
+{
164
+ BDRVQcow2State *s = bs->opaque;
165
+ uint64_t refblock_offs = get_refblock_offset(s, discard_block_offs);
166
+ uint64_t cluster_index = discard_block_offs >> s->cluster_bits;
167
+ uint32_t block_index = cluster_index & (s->refcount_block_size - 1);
168
+ void *refblock;
169
+ int ret;
170
+
171
+ assert(discard_block_offs != 0);
172
+
173
+ ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offs,
174
+ &refblock);
175
+ if (ret < 0) {
176
+ return ret;
177
+ }
178
+
179
+ if (s->get_refcount(refblock, block_index) != 1) {
180
+ qcow2_signal_corruption(bs, true, -1, -1, "Invalid refcount:"
181
+ " refblock offset %#" PRIx64
182
+ ", reftable index %u"
183
+ ", block offset %#" PRIx64
184
+ ", refcount %#" PRIx64,
185
+ refblock_offs,
186
+ offset_to_reftable_index(s, discard_block_offs),
187
+ discard_block_offs,
188
+ s->get_refcount(refblock, block_index));
189
+ qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
190
+ return -EINVAL;
191
+ }
192
+ s->set_refcount(refblock, block_index, 0);
193
+
194
+ qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, refblock);
195
+
196
+ qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
197
+
198
+ if (cluster_index < s->free_cluster_index) {
199
+ s->free_cluster_index = cluster_index;
200
+ }
201
+
202
+ refblock = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
203
+ discard_block_offs);
204
+ if (refblock) {
205
+ /* discard refblock from the cache if refblock is cached */
206
+ qcow2_cache_discard(bs, s->refcount_block_cache, refblock);
207
+ }
208
+ update_refcount_discard(bs, discard_block_offs, s->cluster_size);
209
+
210
+ return 0;
211
+}
212
+
213
+int qcow2_shrink_reftable(BlockDriverState *bs)
214
+{
215
+ BDRVQcow2State *s = bs->opaque;
216
+ uint64_t *reftable_tmp =
217
+ g_malloc(s->refcount_table_size * sizeof(uint64_t));
218
+ int i, ret;
219
+
220
+ for (i = 0; i < s->refcount_table_size; i++) {
221
+ int64_t refblock_offs = s->refcount_table[i] & REFT_OFFSET_MASK;
222
+ void *refblock;
223
+ bool unused_block;
224
+
225
+ if (refblock_offs == 0) {
226
+ reftable_tmp[i] = 0;
227
+ continue;
228
+ }
229
+ ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offs,
230
+ &refblock);
231
+ if (ret < 0) {
232
+ goto out;
233
+ }
234
+
235
+ /* the refblock has own reference */
236
+ if (i == offset_to_reftable_index(s, refblock_offs)) {
237
+ uint64_t block_index = (refblock_offs >> s->cluster_bits) &
238
+ (s->refcount_block_size - 1);
239
+ uint64_t refcount = s->get_refcount(refblock, block_index);
240
+
241
+ s->set_refcount(refblock, block_index, 0);
242
+
243
+ unused_block = buffer_is_zero(refblock, s->cluster_size);
244
+
245
+ s->set_refcount(refblock, block_index, refcount);
246
+ } else {
247
+ unused_block = buffer_is_zero(refblock, s->cluster_size);
248
+ }
249
+ qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
250
+
251
+ reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
252
+ }
253
+
254
+ ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp,
255
+ s->refcount_table_size * sizeof(uint64_t));
256
+ /*
257
+ * If the write in the reftable failed the image may contain a partially
258
+ * overwritten reftable. In this case it would be better to clear the
259
+ * reftable in memory to avoid possible image corruption.
260
+ */
261
+ for (i = 0; i < s->refcount_table_size; i++) {
262
+ if (s->refcount_table[i] && !reftable_tmp[i]) {
263
+ if (ret == 0) {
264
+ ret = qcow2_discard_refcount_block(bs, s->refcount_table[i] &
265
+ REFT_OFFSET_MASK);
266
+ }
267
+ s->refcount_table[i] = 0;
268
+ }
269
+ }
270
+
271
+ if (!s->cache_discards) {
272
+ qcow2_process_discards(bs, ret);
273
+ }
274
+
275
+out:
276
+ g_free(reftable_tmp);
277
+ return ret;
278
+}
279
diff --git a/block/qcow2.c b/block/qcow2.c
427
diff --git a/block/qcow2.c b/block/qcow2.c
280
index XXXXXXX..XXXXXXX 100644
428
index XXXXXXX..XXXXXXX 100644
281
--- a/block/qcow2.c
429
--- a/block/qcow2.c
282
+++ b/block/qcow2.c
430
+++ b/block/qcow2.c
283
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
431
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
432
return status;
433
}
434
435
-static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
436
- QCowL2Meta **pl2meta,
437
- bool link_l2)
438
+static int coroutine_fn GRAPH_RDLOCK
439
+qcow2_handle_l2meta(BlockDriverState *bs, QCowL2Meta **pl2meta, bool link_l2)
440
{
441
int ret = 0;
442
QCowL2Meta *l2meta = *pl2meta;
443
@@ -XXX,XX +XXX,XX @@ static coroutine_fn GRAPH_RDLOCK int qcow2_co_pwritev_task_entry(AioTask *task)
444
t->l2meta);
445
}
446
447
-static coroutine_fn int qcow2_co_pwritev_part(
448
- BlockDriverState *bs, int64_t offset, int64_t bytes,
449
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
450
+static int coroutine_fn GRAPH_RDLOCK
451
+qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
452
+ QEMUIOVector *qiov, size_t qiov_offset,
453
+ BdrvRequestFlags flags)
454
{
455
BDRVQcow2State *s = bs->opaque;
456
int offset_in_cluster;
457
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
458
QCowL2Meta *l2meta = NULL;
459
AioTaskPool *aio = NULL;
460
461
- assume_graph_lock(); /* FIXME */
462
-
463
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
464
465
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
466
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
467
uint64_t host_offset;
468
QCowL2Meta *l2meta = NULL;
469
470
+ assume_graph_lock(); /* FIXME */
471
assert(!bs->encrypted);
472
473
qemu_co_mutex_lock(&s->lock);
474
@@ -XXX,XX +XXX,XX @@ fail:
475
return ret;
476
}
477
478
-static coroutine_fn int
479
+static int coroutine_fn GRAPH_RDLOCK
480
qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
481
uint64_t offset, uint64_t bytes,
482
QEMUIOVector *qiov, size_t qiov_offset)
483
@@ -XXX,XX +XXX,XX @@ fail:
484
return ret;
485
}
486
487
-static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
488
+/*
489
+ * This function can count as GRAPH_RDLOCK because
490
+ * qcow2_co_pwritev_compressed_part() holds the graph lock and keeps it until
491
+ * this coroutine has terminated.
492
+ */
493
+static int coroutine_fn GRAPH_RDLOCK
494
+qcow2_co_pwritev_compressed_task_entry(AioTask *task)
495
{
496
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
497
498
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
499
* XXX: put compressed sectors first, then all the cluster aligned
500
* tables to avoid losing bytes in alignment
501
*/
502
-static coroutine_fn int
503
+static int coroutine_fn GRAPH_RDLOCK
504
qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
505
int64_t offset, int64_t bytes,
506
QEMUIOVector *qiov, size_t qiov_offset)
507
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
508
AioTaskPool *aio = NULL;
509
int ret = 0;
510
511
- assume_graph_lock(); /* FIXME */
512
-
513
if (has_data_file(bs)) {
514
return -ENOTSUP;
284
}
515
}
285
516
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
286
old_length = bs->total_sectors * 512;
517
return pos;
287
+ new_l1_size = size_to_l1(s, offset);
518
}
288
519
289
- /* shrinking is currently not supported */
520
-static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
290
if (offset < old_length) {
521
- QEMUIOVector *qiov, int64_t pos)
291
- error_setg(errp, "qcow2 doesn't support shrinking images yet");
522
+static int coroutine_fn GRAPH_RDLOCK
292
- return -ENOTSUP;
523
+qcow2_co_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
293
- }
524
{
294
+ if (prealloc != PREALLOC_MODE_OFF) {
525
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
295
+ error_setg(errp,
526
if (offset < 0) {
296
+ "Preallocation can't be used for shrinking an image");
527
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_save_vmstate(BlockDriverState *bs,
297
+ return -EINVAL;
528
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
298
+ }
529
}
299
530
300
- new_l1_size = size_to_l1(s, offset);
531
-static coroutine_fn int qcow2_co_load_vmstate(BlockDriverState *bs,
301
- ret = qcow2_grow_l1_table(bs, new_l1_size, true);
532
- QEMUIOVector *qiov, int64_t pos)
302
- if (ret < 0) {
533
+static int coroutine_fn GRAPH_RDLOCK
303
- error_setg_errno(errp, -ret, "Failed to grow the L1 table");
534
+qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
304
- return ret;
535
{
305
+ ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size),
536
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
306
+ old_length - ROUND_UP(offset,
537
if (offset < 0) {
307
+ s->cluster_size),
538
diff --git a/block/qed.c b/block/qed.c
308
+ QCOW2_DISCARD_ALWAYS, true);
539
index XXXXXXX..XXXXXXX 100644
309
+ if (ret < 0) {
540
--- a/block/qed.c
310
+ error_setg_errno(errp, -ret, "Failed to discard cropped clusters");
541
+++ b/block/qed.c
311
+ return ret;
542
@@ -XXX,XX +XXX,XX @@ qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
312
+ }
543
return qed_aio_next_io(&acb);
313
+
544
}
314
+ ret = qcow2_shrink_l1_table(bs, new_l1_size);
545
315
+ if (ret < 0) {
546
-static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
316
+ error_setg_errno(errp, -ret,
547
- int64_t sector_num, int nb_sectors,
317
+ "Failed to reduce the number of L2 tables");
548
- QEMUIOVector *qiov)
318
+ return ret;
549
+static int coroutine_fn GRAPH_RDLOCK
319
+ }
550
+bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
320
+
551
+ QEMUIOVector *qiov)
321
+ ret = qcow2_shrink_reftable(bs);
552
{
322
+ if (ret < 0) {
553
- assume_graph_lock(); /* FIXME */
323
+ error_setg_errno(errp, -ret,
554
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
324
+ "Failed to discard unused refblocks");
555
}
325
+ return ret;
556
326
+ }
557
-static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
327
+ } else {
558
- int64_t sector_num, int nb_sectors,
328
+ ret = qcow2_grow_l1_table(bs, new_l1_size, true);
559
- QEMUIOVector *qiov, int flags)
329
+ if (ret < 0) {
560
+static int coroutine_fn GRAPH_RDLOCK
330
+ error_setg_errno(errp, -ret, "Failed to grow the L1 table");
561
+bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
331
+ return ret;
562
+ QEMUIOVector *qiov, int flags)
332
+ }
563
{
564
- assume_graph_lock(); /* FIXME */
565
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
566
}
567
568
diff --git a/block/quorum.c b/block/quorum.c
569
index XXXXXXX..XXXXXXX 100644
570
--- a/block/quorum.c
571
+++ b/block/quorum.c
572
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn GRAPH_RDLOCK write_quorum_entry(void *opaque)
333
}
573
}
334
574
}
335
switch (prealloc) {
575
576
-static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
577
- int64_t bytes, QEMUIOVector *qiov,
578
- BdrvRequestFlags flags)
579
+static int coroutine_fn GRAPH_RDLOCK
580
+quorum_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
581
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
582
{
583
BDRVQuorumState *s = bs->opaque;
584
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
585
int i, ret;
586
587
- assume_graph_lock(); /* FIXME */
588
-
589
for (i = 0; i < s->num_children; i++) {
590
Coroutine *co;
591
QuorumCo data = {
592
diff --git a/block/vmdk.c b/block/vmdk.c
593
index XXXXXXX..XXXXXXX 100644
594
--- a/block/vmdk.c
595
+++ b/block/vmdk.c
596
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
597
return ret;
598
}
599
600
-static int coroutine_fn
601
+static int coroutine_fn GRAPH_RDLOCK
602
vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
603
QEMUIOVector *qiov)
604
{
605
- assume_graph_lock(); /* FIXME */
606
-
607
if (bytes == 0) {
608
/* The caller will write bytes 0 to signal EOF.
609
* When receive it, we align EOF to a sector boundary. */
336
--
610
--
337
2.13.5
611
2.39.2
338
339
diff view generated by jsdifflib
1
In the context of bdrv_reopen(), we'll have to look at the state of the
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
graph as it will be after the reopen. This interface addition is in
2
bdrv_co_pread*/pwrite*() need to hold a reader lock for the graph.
3
preparation for the change.
3
4
For some places, we know that they will hold the lock, but we don't have
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
6
with a FIXME comment. These places will be removed once everything is
7
properly annotated.
4
8
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20230203152202.49054-12-kwolf@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
include/block/block_int.h | 7 +++++++
14
block/qcow2.h | 9 ++---
9
block.c | 19 ++++++++++++-------
15
block/qed.h | 18 +++++-----
10
block/commit.c | 1 +
16
include/block/block_int-io.h | 14 ++++----
11
block/mirror.c | 1 +
17
block/blkdebug.c | 4 +--
12
block/replication.c | 1 +
18
block/blklogwrites.c | 7 ++--
13
block/vvfat.c | 1 +
19
block/blkreplay.c | 10 +++---
14
6 files changed, 23 insertions(+), 7 deletions(-)
20
block/block-backend.c | 2 ++
21
block/bochs.c | 2 +-
22
block/commit.c | 5 +--
23
block/copy-before-write.c | 16 ++++-----
24
block/copy-on-read.c | 26 ++++++---------
25
block/crypto.c | 4 +--
26
block/filter-compress.c | 19 +++++------
27
block/io.c | 7 ++--
28
block/mirror.c | 18 +++++-----
29
block/parallels.c | 8 +++--
30
block/preallocate.c | 18 +++++-----
31
block/qcow.c | 8 ++---
32
block/qcow2-cluster.c | 7 ++--
33
block/qcow2.c | 53 +++++++++++++++--------------
34
block/qed-table.c | 4 +--
35
block/qed.c | 31 +++++++++--------
36
block/quorum.c | 29 ++++++++++------
37
block/raw-format.c | 12 +++----
38
block/replication.c | 15 ++++-----
39
block/throttle.c | 21 +++++-------
40
block/vdi.c | 4 +--
41
block/vhdx.c | 11 +++---
42
block/vmdk.c | 65 +++++++++++++++---------------------
43
block/vpc.c | 4 +--
44
tests/unit/test-bdrv-drain.c | 20 ++++++-----
45
31 files changed, 233 insertions(+), 238 deletions(-)
15
46
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
47
diff --git a/block/qcow2.h b/block/qcow2.h
17
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block_int.h
49
--- a/block/qcow2.h
19
+++ b/include/block/block_int.h
50
+++ b/block/qcow2.h
20
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
51
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
21
*
52
Error **errp);
22
* If @c is NULL, return the permissions for attaching a new child for the
53
23
* given @role.
54
/* qcow2-refcount.c functions */
24
+ *
55
-int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
25
+ * If @reopen_queue is non-NULL, don't return the currently needed
56
+int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs);
26
+ * permissions, but those that will be needed after applying the
57
void qcow2_refcount_close(BlockDriverState *bs);
27
+ * @reopen_queue.
58
28
*/
59
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
29
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
60
@@ -XXX,XX +XXX,XX @@ void qcow2_free_snapshots(BlockDriverState *bs);
30
const BdrvChildRole *role,
61
int qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
31
+ BlockReopenQueue *reopen_queue,
62
int qcow2_write_snapshots(BlockDriverState *bs);
32
uint64_t parent_perm, uint64_t parent_shared,
63
33
uint64_t *nperm, uint64_t *nshared);
64
-int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
34
65
- BdrvCheckResult *result,
35
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
66
- BdrvCheckMode fix);
36
* all children */
67
+int coroutine_fn GRAPH_RDLOCK
37
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
68
+qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
38
const BdrvChildRole *role,
69
+ BdrvCheckMode fix);
39
+ BlockReopenQueue *reopen_queue,
70
+
40
uint64_t perm, uint64_t shared,
71
int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
41
uint64_t *nperm, uint64_t *nshared);
72
BdrvCheckResult *result,
42
73
BdrvCheckMode fix);
43
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
74
diff --git a/block/qed.h b/block/qed.h
44
* CONSISTENT_READ and doesn't share WRITE. */
75
index XXXXXXX..XXXXXXX 100644
45
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
76
--- a/block/qed.h
46
const BdrvChildRole *role,
77
+++ b/block/qed.h
47
+ BlockReopenQueue *reopen_queue,
78
@@ -XXX,XX +XXX,XX @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
48
uint64_t perm, uint64_t shared,
79
/**
49
uint64_t *nperm, uint64_t *nshared);
80
* Table I/O functions
50
81
*/
51
diff --git a/block.c b/block.c
82
-int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
52
index XXXXXXX..XXXXXXX 100644
83
+int coroutine_fn GRAPH_RDLOCK qed_read_l1_table_sync(BDRVQEDState *s);
53
--- a/block.c
84
54
+++ b/block.c
85
int coroutine_fn GRAPH_RDLOCK
55
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_abort_perm_update(BdrvChild *c);
86
qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
56
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
87
@@ -XXX,XX +XXX,XX @@ qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
57
88
int coroutine_fn GRAPH_RDLOCK
58
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
89
qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
59
- BdrvChild *c,
90
60
- const BdrvChildRole *role,
91
-int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
61
+ BdrvChild *c, const BdrvChildRole *role,
92
- uint64_t offset);
62
+ BlockReopenQueue *reopen_queue,
93
-int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
63
uint64_t parent_perm, uint64_t parent_shared,
94
- uint64_t offset);
64
uint64_t *nperm, uint64_t *nshared)
95
+int coroutine_fn GRAPH_RDLOCK
65
{
96
+qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
66
if (bs->drv && bs->drv->bdrv_child_perm) {
97
+
67
- bs->drv->bdrv_child_perm(bs, c, role,
98
+int coroutine_fn GRAPH_RDLOCK
68
+ bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
99
+qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
69
parent_perm, parent_shared,
100
70
nperm, nshared);
101
int coroutine_fn GRAPH_RDLOCK
71
}
102
qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
72
+ /* TODO Take force_share from reopen_queue */
103
@@ -XXX,XX +XXX,XX @@ qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
73
if (child_bs && child_bs->force_share) {
104
/**
74
*nshared = BLK_PERM_ALL;
105
* Cluster functions
75
}
106
*/
76
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms,
107
-int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
77
/* Check all children */
108
- uint64_t pos, size_t *len,
78
QLIST_FOREACH(c, &bs->children, next) {
109
- uint64_t *img_offset);
79
uint64_t cur_perm, cur_shared;
110
+int coroutine_fn GRAPH_RDLOCK
80
- bdrv_child_perm(bs, c->bs, c, c->role,
111
+qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
81
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
112
+ size_t *len, uint64_t *img_offset);
82
cumulative_perms, cumulative_shared_perms,
113
83
&cur_perm, &cur_shared);
114
/**
84
ret = bdrv_child_check_perm(c, cur_perm, cur_shared, ignore_children,
115
* Consistency check
85
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
86
/* Update all children */
117
int coroutine_fn GRAPH_RDLOCK
87
QLIST_FOREACH(c, &bs->children, next) {
118
qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
88
uint64_t cur_perm, cur_shared;
119
89
- bdrv_child_perm(bs, c->bs, c, c->role,
120
-
90
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
121
QEDTable *qed_alloc_table(BDRVQEDState *s);
91
cumulative_perms, cumulative_shared_perms,
122
92
&cur_perm, &cur_shared);
123
/**
93
bdrv_child_set_perm(c, cur_perm, cur_shared);
124
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
94
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
125
index XXXXXXX..XXXXXXX 100644
95
126
--- a/include/block/block_int-io.h
96
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
127
+++ b/include/block/block_int-io.h
97
const BdrvChildRole *role,
128
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
98
+ BlockReopenQueue *reopen_queue,
129
int64_t offset, int64_t bytes);
99
uint64_t perm, uint64_t shared,
130
100
uint64_t *nperm, uint64_t *nshared)
131
101
{
132
-int coroutine_fn bdrv_co_preadv(BdrvChild *child,
102
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
133
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child,
103
134
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
104
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
135
BdrvRequestFlags flags);
105
const BdrvChildRole *role,
136
-int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
106
+ BlockReopenQueue *reopen_queue,
137
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child,
107
uint64_t perm, uint64_t shared,
138
int64_t offset, int64_t bytes,
108
uint64_t *nperm, uint64_t *nshared)
139
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
109
{
140
-int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
110
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
141
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child,
111
if (!backing) {
142
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
112
/* Apart from the modifications below, the same permissions are
143
BdrvRequestFlags flags);
113
* forwarded and left alone as for filters */
144
-int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
114
- bdrv_filter_default_perms(bs, c, role, perm, shared, &perm, &shared);
145
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child,
115
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
146
int64_t offset, int64_t bytes,
116
+ &perm, &shared);
147
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
117
148
118
/* Format drivers may touch metadata even if the guest doesn't write */
149
-static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
119
+ /* TODO Take flags from reopen_queue */
150
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child,
120
if (bdrv_is_writable(bs)) {
151
int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
121
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
152
{
122
}
153
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
123
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
154
IO_CODE();
124
155
+ assert_bdrv_graph_readable();
125
assert(parent_bs->drv);
156
126
assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs));
157
return bdrv_co_preadv(child, offset, bytes, &qiov, flags);
127
- bdrv_child_perm(parent_bs, child_bs, NULL, child_role,
158
}
128
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
159
129
perm, shared_perm, &perm, &shared_perm);
160
-static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
130
161
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child,
131
child = bdrv_root_attach_child(child_bs, child_name, child_role,
162
int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
163
{
164
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
165
IO_CODE();
166
+ assert_bdrv_graph_readable();
167
168
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
169
}
170
diff --git a/block/blkdebug.c b/block/blkdebug.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/blkdebug.c
173
+++ b/block/blkdebug.c
174
@@ -XXX,XX +XXX,XX @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
175
return -error;
176
}
177
178
-static int coroutine_fn
179
+static int coroutine_fn GRAPH_RDLOCK
180
blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
181
QEMUIOVector *qiov, BdrvRequestFlags flags)
182
{
183
@@ -XXX,XX +XXX,XX @@ blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
184
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
185
}
186
187
-static int coroutine_fn
188
+static int coroutine_fn GRAPH_RDLOCK
189
blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
190
QEMUIOVector *qiov, BdrvRequestFlags flags)
191
{
192
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/blklogwrites.c
195
+++ b/block/blklogwrites.c
196
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
197
bs->bl.request_alignment = s->sectorsize;
198
}
199
200
-static int coroutine_fn
201
+static int coroutine_fn GRAPH_RDLOCK
202
blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
203
QEMUIOVector *qiov, BdrvRequestFlags flags)
204
{
205
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
206
return fr.file_ret;
207
}
208
209
-static int coroutine_fn
210
+static int coroutine_fn GRAPH_RDLOCK
211
blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
212
{
213
return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes,
214
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
215
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
216
}
217
218
-static int coroutine_fn
219
+static int coroutine_fn GRAPH_RDLOCK
220
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
221
QEMUIOVector *qiov, BdrvRequestFlags flags)
222
{
223
- assume_graph_lock(); /* FIXME */
224
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
225
blk_log_writes_co_do_file_pwritev, 0, false);
226
}
227
diff --git a/block/blkreplay.c b/block/blkreplay.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/block/blkreplay.c
230
+++ b/block/blkreplay.c
231
@@ -XXX,XX +XXX,XX @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
232
replay_block_event(req->bh, reqid);
233
}
234
235
-static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
236
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
237
+static int coroutine_fn GRAPH_RDLOCK
238
+blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
239
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
240
{
241
uint64_t reqid = blkreplay_next_id();
242
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
243
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
244
return ret;
245
}
246
247
-static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
248
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
249
+static int coroutine_fn GRAPH_RDLOCK
250
+blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
251
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
252
{
253
uint64_t reqid = blkreplay_next_id();
254
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
255
diff --git a/block/block-backend.c b/block/block-backend.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/block/block-backend.c
258
+++ b/block/block-backend.c
259
@@ -XXX,XX +XXX,XX @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
260
IO_CODE();
261
262
blk_wait_while_drained(blk);
263
+ GRAPH_RDLOCK_GUARD();
264
265
/* Call blk_bs() only after waiting, the graph may have changed */
266
bs = blk_bs(blk);
267
@@ -XXX,XX +XXX,XX @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
268
IO_CODE();
269
270
blk_wait_while_drained(blk);
271
+ GRAPH_RDLOCK_GUARD();
272
273
/* Call blk_bs() only after waiting, the graph may have changed */
274
bs = blk_bs(blk);
275
diff --git a/block/bochs.c b/block/bochs.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/block/bochs.c
278
+++ b/block/bochs.c
279
@@ -XXX,XX +XXX,XX @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
280
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
281
}
282
283
-static int coroutine_fn
284
+static int coroutine_fn GRAPH_RDLOCK
285
bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
286
QEMUIOVector *qiov, BdrvRequestFlags flags)
287
{
132
diff --git a/block/commit.c b/block/commit.c
288
diff --git a/block/commit.c b/block/commit.c
133
index XXXXXXX..XXXXXXX 100644
289
index XXXXXXX..XXXXXXX 100644
134
--- a/block/commit.c
290
--- a/block/commit.c
135
+++ b/block/commit.c
291
+++ b/block/commit.c
136
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_close(BlockDriverState *bs)
292
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver commit_job_driver = {
137
293
},
138
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
294
};
139
const BdrvChildRole *role,
295
140
+ BlockReopenQueue *reopen_queue,
296
-static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
141
uint64_t perm, uint64_t shared,
297
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
142
uint64_t *nperm, uint64_t *nshared)
298
+static int coroutine_fn GRAPH_RDLOCK
143
{
299
+bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
300
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
301
{
302
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
303
}
304
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
305
index XXXXXXX..XXXXXXX 100644
306
--- a/block/copy-before-write.c
307
+++ b/block/copy-before-write.c
308
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVCopyBeforeWriteState {
309
int snapshot_error;
310
} BDRVCopyBeforeWriteState;
311
312
-static coroutine_fn int cbw_co_preadv(
313
- BlockDriverState *bs, int64_t offset, int64_t bytes,
314
- QEMUIOVector *qiov, BdrvRequestFlags flags)
315
+static int coroutine_fn GRAPH_RDLOCK
316
+cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
317
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
318
{
319
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
320
}
321
@@ -XXX,XX +XXX,XX @@ cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
322
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
323
}
324
325
-static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
326
- int64_t offset,
327
- int64_t bytes,
328
- QEMUIOVector *qiov,
329
- BdrvRequestFlags flags)
330
+static coroutine_fn GRAPH_RDLOCK
331
+int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
333
{
334
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
335
if (ret < 0) {
336
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
337
BdrvChild *file;
338
int ret;
339
340
+ assume_graph_lock(); /* FIXME */
341
+
342
/* TODO: upgrade to async loop using AioTask */
343
while (bytes) {
344
int64_t cur_bytes;
345
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
346
index XXXXXXX..XXXXXXX 100644
347
--- a/block/copy-on-read.c
348
+++ b/block/copy-on-read.c
349
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
350
}
351
352
353
-static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
354
- int64_t offset, int64_t bytes,
355
- QEMUIOVector *qiov,
356
- size_t qiov_offset,
357
- BdrvRequestFlags flags)
358
+static int coroutine_fn GRAPH_RDLOCK
359
+cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
360
+ QEMUIOVector *qiov, size_t qiov_offset,
361
+ BdrvRequestFlags flags)
362
{
363
int64_t n;
364
int local_flags;
365
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
366
}
367
368
369
-static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
370
- int64_t offset,
371
- int64_t bytes,
372
- QEMUIOVector *qiov,
373
- size_t qiov_offset,
374
- BdrvRequestFlags flags)
375
+static int coroutine_fn GRAPH_RDLOCK
376
+cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
377
+ QEMUIOVector *qiov, size_t qiov_offset,
378
+ BdrvRequestFlags flags)
379
{
380
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
381
flags);
382
@@ -XXX,XX +XXX,XX @@ cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
383
}
384
385
386
-static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
387
- int64_t offset,
388
- int64_t bytes,
389
- QEMUIOVector *qiov)
390
+static int coroutine_fn GRAPH_RDLOCK
391
+cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
392
+ QEMUIOVector *qiov)
393
{
394
return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
395
BDRV_REQ_WRITE_COMPRESSED);
396
diff --git a/block/crypto.c b/block/crypto.c
397
index XXXXXXX..XXXXXXX 100644
398
--- a/block/crypto.c
399
+++ b/block/crypto.c
400
@@ -XXX,XX +XXX,XX @@ static int block_crypto_reopen_prepare(BDRVReopenState *state,
401
*/
402
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
403
404
-static coroutine_fn int
405
+static int coroutine_fn GRAPH_RDLOCK
406
block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
407
QEMUIOVector *qiov, BdrvRequestFlags flags)
408
{
409
@@ -XXX,XX +XXX,XX @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
410
}
411
412
413
-static coroutine_fn int
414
+static int coroutine_fn GRAPH_RDLOCK
415
block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
416
QEMUIOVector *qiov, BdrvRequestFlags flags)
417
{
418
diff --git a/block/filter-compress.c b/block/filter-compress.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/filter-compress.c
421
+++ b/block/filter-compress.c
422
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
423
}
424
425
426
-static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
427
- int64_t offset, int64_t bytes,
428
- QEMUIOVector *qiov,
429
- size_t qiov_offset,
430
- BdrvRequestFlags flags)
431
+static int coroutine_fn GRAPH_RDLOCK
432
+compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
433
+ QEMUIOVector *qiov, size_t qiov_offset,
434
+ BdrvRequestFlags flags)
435
{
436
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
437
flags);
438
}
439
440
441
-static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
442
- int64_t offset,
443
- int64_t bytes,
444
- QEMUIOVector *qiov,
445
- size_t qiov_offset,
446
- BdrvRequestFlags flags)
447
+static int coroutine_fn GRAPH_RDLOCK
448
+compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
449
+ QEMUIOVector *qiov, size_t qiov_offset,
450
+ BdrvRequestFlags flags)
451
{
452
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
453
flags | BDRV_REQ_WRITE_COMPRESSED);
454
diff --git a/block/io.c b/block/io.c
455
index XXXXXXX..XXXXXXX 100644
456
--- a/block/io.c
457
+++ b/block/io.c
458
@@ -XXX,XX +XXX,XX @@ bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
459
unsigned int nb_sectors;
460
QEMUIOVector local_qiov;
461
int ret;
462
+ assert_bdrv_graph_readable();
463
464
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
465
assert(!(flags & ~bs->supported_read_flags));
466
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
467
unsigned int nb_sectors;
468
QEMUIOVector local_qiov;
469
int ret;
470
+ assert_bdrv_graph_readable();
471
472
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
473
474
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
475
BlockDriver *drv = bs->drv;
476
QEMUIOVector local_qiov;
477
int ret;
478
+ assert_bdrv_graph_readable();
479
480
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
481
482
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
483
int ret;
484
IO_CODE();
485
486
- assume_graph_lock(); /* FIXME */
487
-
488
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
489
490
if (!bdrv_co_is_inserted(bs)) {
491
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
492
bool padded = false;
493
IO_CODE();
494
495
- assume_graph_lock(); /* FIXME */
496
-
497
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
498
499
if (!bdrv_co_is_inserted(bs)) {
144
diff --git a/block/mirror.c b/block/mirror.c
500
diff --git a/block/mirror.c b/block/mirror.c
145
index XXXXXXX..XXXXXXX 100644
501
index XXXXXXX..XXXXXXX 100644
146
--- a/block/mirror.c
502
--- a/block/mirror.c
147
+++ b/block/mirror.c
503
+++ b/block/mirror.c
148
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_close(BlockDriverState *bs)
504
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_co_read(void *opaque)
149
505
op->is_in_flight = true;
150
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
506
trace_mirror_one_iteration(s, op->offset, op->bytes);
151
const BdrvChildRole *role,
507
152
+ BlockReopenQueue *reopen_queue,
508
- ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
153
uint64_t perm, uint64_t shared,
509
- &op->qiov, 0);
154
uint64_t *nperm, uint64_t *nshared)
510
+ WITH_GRAPH_RDLOCK_GUARD() {
155
{
511
+ ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
512
+ &op->qiov, 0);
513
+ }
514
mirror_read_complete(op, ret);
515
}
516
517
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn active_write_settle(MirrorOp *op)
518
g_free(op);
519
}
520
521
-static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
522
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
523
+static int coroutine_fn GRAPH_RDLOCK
524
+bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
525
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
526
{
527
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
528
}
529
@@ -XXX,XX +XXX,XX @@ out:
530
return ret;
531
}
532
533
-static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
534
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
535
+static int coroutine_fn GRAPH_RDLOCK
536
+bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
537
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
538
{
539
MirrorBDSOpaque *s = bs->opaque;
540
QEMUIOVector bounce_qiov;
541
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
542
int ret = 0;
543
bool copy_to_target = false;
544
545
- assume_graph_lock(); /* FIXME */
546
-
547
if (s->job) {
548
copy_to_target = s->job->ret >= 0 &&
549
!job_is_cancelled(&s->job->common.job) &&
550
diff --git a/block/parallels.c b/block/parallels.c
551
index XXXXXXX..XXXXXXX 100644
552
--- a/block/parallels.c
553
+++ b/block/parallels.c
554
@@ -XXX,XX +XXX,XX @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num,
555
}
556
557
558
-static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
559
+static int coroutine_fn GRAPH_RDLOCK
560
+parallels_co_flush_to_os(BlockDriverState *bs)
561
{
562
BDRVParallelsState *s = bs->opaque;
563
unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
564
@@ -XXX,XX +XXX,XX @@ parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
565
return ret;
566
}
567
568
-static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
569
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
570
+static int coroutine_fn GRAPH_RDLOCK
571
+parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
572
+ QEMUIOVector *qiov)
573
{
574
BDRVParallelsState *s = bs->opaque;
575
uint64_t bytes_done = 0;
576
diff --git a/block/preallocate.c b/block/preallocate.c
577
index XXXXXXX..XXXXXXX 100644
578
--- a/block/preallocate.c
579
+++ b/block/preallocate.c
580
@@ -XXX,XX +XXX,XX @@ static void preallocate_reopen_abort(BDRVReopenState *state)
581
state->opaque = NULL;
582
}
583
584
-static coroutine_fn int preallocate_co_preadv_part(
585
- BlockDriverState *bs, int64_t offset, int64_t bytes,
586
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
587
+static int coroutine_fn GRAPH_RDLOCK
588
+preallocate_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
589
+ QEMUIOVector *qiov, size_t qiov_offset,
590
+ BdrvRequestFlags flags)
591
{
592
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
593
flags);
594
@@ -XXX,XX +XXX,XX @@ preallocate_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
595
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
596
}
597
598
-static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
599
- int64_t offset,
600
- int64_t bytes,
601
- QEMUIOVector *qiov,
602
- size_t qiov_offset,
603
- BdrvRequestFlags flags)
604
+static int coroutine_fn GRAPH_RDLOCK
605
+preallocate_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
606
+ QEMUIOVector *qiov, size_t qiov_offset,
607
+ BdrvRequestFlags flags)
608
{
609
- assume_graph_lock(); /* FIXME */
610
handle_write(bs, offset, bytes, false);
611
612
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
613
diff --git a/block/qcow.c b/block/qcow.c
614
index XXXXXXX..XXXXXXX 100644
615
--- a/block/qcow.c
616
+++ b/block/qcow.c
617
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
618
619
static QemuOptsList qcow_create_opts;
620
621
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
622
- uint64_t cluster_offset);
623
+static int coroutine_fn GRAPH_RDLOCK
624
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
625
626
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
627
{
628
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
629
return 0;
630
}
631
632
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
633
- uint64_t cluster_offset)
634
+static int coroutine_fn GRAPH_RDLOCK
635
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
636
{
637
BDRVQcowState *s = bs->opaque;
638
int ret, csize;
639
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
640
index XXXXXXX..XXXXXXX 100644
641
--- a/block/qcow2-cluster.c
642
+++ b/block/qcow2-cluster.c
643
@@ -XXX,XX +XXX,XX @@ do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset,
644
return 0;
645
}
646
647
-static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
648
- uint64_t cluster_offset,
649
- unsigned offset_in_cluster,
650
- QEMUIOVector *qiov)
651
+static int coroutine_fn GRAPH_RDLOCK
652
+do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset,
653
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
654
{
655
BDRVQcow2State *s = bs->opaque;
656
int ret;
657
diff --git a/block/qcow2.c b/block/qcow2.c
658
index XXXXXXX..XXXXXXX 100644
659
--- a/block/qcow2.c
660
+++ b/block/qcow2.c
661
@@ -XXX,XX +XXX,XX @@ static void qcow2_add_check_result(BdrvCheckResult *out,
662
}
663
}
664
665
-static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
666
- BdrvCheckResult *result,
667
- BdrvCheckMode fix)
668
+static int coroutine_fn GRAPH_RDLOCK
669
+qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result,
670
+ BdrvCheckMode fix)
671
{
672
BdrvCheckResult snapshot_res = {};
673
BdrvCheckResult refcount_res = {};
674
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
675
return ret;
676
}
677
678
-static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
679
- BdrvCheckResult *result,
680
- BdrvCheckMode fix)
681
+static int coroutine_fn GRAPH_RDLOCK
682
+qcow2_co_check(BlockDriverState *bs, BdrvCheckResult *result,
683
+ BdrvCheckMode fix)
684
{
685
BDRVQcow2State *s = bs->opaque;
686
int ret;
687
@@ -XXX,XX +XXX,XX @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp)
688
}
689
690
/* Called with s->lock held. */
691
-static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
692
- int flags, bool open_data_file,
693
- Error **errp)
694
+static int coroutine_fn GRAPH_RDLOCK
695
+qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
696
+ bool open_data_file, Error **errp)
697
{
698
ERRP_GUARD();
699
BDRVQcow2State *s = bs->opaque;
700
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_open_entry(void *opaque)
701
QCow2OpenCo *qoc = opaque;
702
BDRVQcow2State *s = qoc->bs->opaque;
703
704
+ assume_graph_lock(); /* FIXME */
705
+
706
qemu_co_mutex_lock(&s->lock);
707
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
708
qoc->errp);
709
@@ -XXX,XX +XXX,XX @@ out:
710
return ret;
711
}
712
713
-static coroutine_fn int
714
+static int coroutine_fn GRAPH_RDLOCK
715
qcow2_co_preadv_encrypted(BlockDriverState *bs,
716
uint64_t host_offset,
717
uint64_t offset,
718
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
719
return 0;
720
}
721
722
-static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
723
- QCow2SubclusterType subc_type,
724
- uint64_t host_offset,
725
- uint64_t offset, uint64_t bytes,
726
- QEMUIOVector *qiov,
727
- size_t qiov_offset)
728
+static int coroutine_fn GRAPH_RDLOCK
729
+qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type,
730
+ uint64_t host_offset, uint64_t offset, uint64_t bytes,
731
+ QEMUIOVector *qiov, size_t qiov_offset)
732
{
733
BDRVQcow2State *s = bs->opaque;
734
735
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
736
g_assert_not_reached();
737
}
738
739
-static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
740
+/*
741
+ * This function can count as GRAPH_RDLOCK because qcow2_co_preadv_part() holds
742
+ * the graph lock and keeps it until this coroutine has terminated.
743
+ */
744
+static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_task_entry(AioTask *task)
745
{
746
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
747
748
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
749
t->qiov, t->qiov_offset);
750
}
751
752
-static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
753
- int64_t offset, int64_t bytes,
754
- QEMUIOVector *qiov,
755
- size_t qiov_offset,
756
- BdrvRequestFlags flags)
757
+static int coroutine_fn GRAPH_RDLOCK
758
+qcow2_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
759
+ QEMUIOVector *qiov, size_t qiov_offset,
760
+ BdrvRequestFlags flags)
761
{
762
BDRVQcow2State *s = bs->opaque;
763
int ret = 0;
764
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
765
qcow2_do_close(bs, true);
766
}
767
768
-static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
769
- Error **errp)
770
+static void coroutine_fn GRAPH_RDLOCK
771
+qcow2_co_invalidate_cache(BlockDriverState *bs, Error **errp)
772
{
773
ERRP_GUARD();
774
BDRVQcow2State *s = bs->opaque;
775
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
776
return ret;
777
}
778
779
-static int coroutine_fn
780
+static int coroutine_fn GRAPH_RDLOCK
781
qcow2_co_preadv_compressed(BlockDriverState *bs,
782
uint64_t l2_entry,
783
uint64_t offset,
784
diff --git a/block/qed-table.c b/block/qed-table.c
785
index XXXXXXX..XXXXXXX 100644
786
--- a/block/qed-table.c
787
+++ b/block/qed-table.c
788
@@ -XXX,XX +XXX,XX @@
789
#include "qemu/memalign.h"
790
791
/* Called with table_lock held. */
792
-static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
793
- QEDTable *table)
794
+static int coroutine_fn GRAPH_RDLOCK
795
+qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
796
{
797
unsigned int bytes = s->header.cluster_size * s->header.table_size;
798
799
diff --git a/block/qed.c b/block/qed.c
800
index XXXXXXX..XXXXXXX 100644
801
--- a/block/qed.c
802
+++ b/block/qed.c
803
@@ -XXX,XX +XXX,XX @@ int qed_write_header_sync(BDRVQEDState *s)
804
*
805
* No new allocating reqs can start while this function runs.
806
*/
807
-static int coroutine_fn qed_write_header(BDRVQEDState *s)
808
+static int coroutine_fn GRAPH_RDLOCK qed_write_header(BDRVQEDState *s)
809
{
810
/* We must write full sectors for O_DIRECT but cannot necessarily generate
811
* the data following the header if an unrecognized compat feature is
812
@@ -XXX,XX +XXX,XX @@ fail:
813
return ret;
814
}
815
816
-static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
817
- bool want_zero,
818
- int64_t pos, int64_t bytes,
819
- int64_t *pnum, int64_t *map,
820
- BlockDriverState **file)
821
+static int coroutine_fn GRAPH_RDLOCK
822
+bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos,
823
+ int64_t bytes, int64_t *pnum, int64_t *map,
824
+ BlockDriverState **file)
825
{
826
BDRVQEDState *s = bs->opaque;
827
size_t len = MIN(bytes, SIZE_MAX);
828
@@ -XXX,XX +XXX,XX @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
829
* This function reads qiov->size bytes starting at pos from the backing file.
830
* If there is no backing file then zeroes are read.
831
*/
832
-static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
833
- QEMUIOVector *qiov)
834
+static int coroutine_fn GRAPH_RDLOCK
835
+qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov)
836
{
837
if (s->bs->backing) {
838
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
839
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
840
* @len: Number of bytes
841
* @offset: Byte offset in image file
842
*/
843
-static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
844
- uint64_t pos, uint64_t len,
845
- uint64_t offset)
846
+static int coroutine_fn GRAPH_RDLOCK
847
+qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len,
848
+ uint64_t offset)
849
{
850
QEMUIOVector qiov;
851
int ret;
852
@@ -XXX,XX +XXX,XX @@ qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
853
*
854
* Called with table_lock *not* held.
855
*/
856
-static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
857
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb)
858
{
859
BDRVQEDState *s = acb_to_s(acb);
860
uint64_t offset = acb->cur_cluster +
861
@@ -XXX,XX +XXX,XX @@ qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
862
*
863
* Called with table_lock held.
864
*/
865
-static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset,
866
- size_t len)
867
+static int coroutine_fn GRAPH_RDLOCK
868
+qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len)
869
{
870
BDRVQEDState *s = acb_to_s(acb);
871
int r;
872
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
873
*
874
* Called with table_lock held.
875
*/
876
-static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
877
- uint64_t offset, size_t len)
878
+static int coroutine_fn GRAPH_RDLOCK
879
+qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len)
880
{
881
QEDAIOCB *acb = opaque;
882
BDRVQEDState *s = acb_to_s(acb);
883
diff --git a/block/quorum.c b/block/quorum.c
884
index XXXXXXX..XXXXXXX 100644
885
--- a/block/quorum.c
886
+++ b/block/quorum.c
887
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
888
}
889
}
890
891
-static void coroutine_fn quorum_rewrite_entry(void *opaque)
892
+/*
893
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
894
+ * the graph lock and keeps it until this coroutine has terminated.
895
+ */
896
+static void coroutine_fn GRAPH_RDLOCK quorum_rewrite_entry(void *opaque)
897
{
898
QuorumCo *co = opaque;
899
QuorumAIOCB *acb = co->acb;
900
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn quorum_rewrite_entry(void *opaque)
901
}
902
}
903
904
-static bool quorum_rewrite_bad_versions(QuorumAIOCB *acb,
905
- QuorumVoteValue *value)
906
+static bool coroutine_fn GRAPH_RDLOCK
907
+quorum_rewrite_bad_versions(QuorumAIOCB *acb, QuorumVoteValue *value)
908
{
909
QuorumVoteVersion *version;
910
QuorumVoteItem *item;
911
@@ -XXX,XX +XXX,XX @@ static int quorum_vote_error(QuorumAIOCB *acb)
912
return ret;
913
}
914
915
-static void quorum_vote(QuorumAIOCB *acb)
916
+static void coroutine_fn GRAPH_RDLOCK quorum_vote(QuorumAIOCB *acb)
917
{
918
bool quorum = true;
919
int i, j, ret;
920
@@ -XXX,XX +XXX,XX @@ free_exit:
921
quorum_free_vote_list(&acb->votes);
922
}
923
924
-static void coroutine_fn read_quorum_children_entry(void *opaque)
925
+/*
926
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
927
+ * the graph lock and keeps it until this coroutine has terminated.
928
+ */
929
+static void coroutine_fn GRAPH_RDLOCK read_quorum_children_entry(void *opaque)
930
{
931
QuorumCo *co = opaque;
932
QuorumAIOCB *acb = co->acb;
933
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn read_quorum_children_entry(void *opaque)
934
}
935
}
936
937
-static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
938
+static int coroutine_fn GRAPH_RDLOCK read_quorum_children(QuorumAIOCB *acb)
939
{
940
BDRVQuorumState *s = acb->bs->opaque;
941
int i;
942
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
943
return acb->vote_ret;
944
}
945
946
-static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
947
+static int coroutine_fn GRAPH_RDLOCK read_fifo_child(QuorumAIOCB *acb)
948
{
949
BDRVQuorumState *s = acb->bs->opaque;
950
int n, ret;
951
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
952
return ret;
953
}
954
955
-static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
956
- int64_t offset, int64_t bytes,
957
- QEMUIOVector *qiov,
958
- BdrvRequestFlags flags)
959
+static int coroutine_fn GRAPH_RDLOCK
960
+quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
961
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
962
{
963
BDRVQuorumState *s = bs->opaque;
964
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
965
diff --git a/block/raw-format.c b/block/raw-format.c
966
index XXXXXXX..XXXXXXX 100644
967
--- a/block/raw-format.c
968
+++ b/block/raw-format.c
969
@@ -XXX,XX +XXX,XX @@ static inline int raw_adjust_offset(BlockDriverState *bs, int64_t *offset,
970
return 0;
971
}
972
973
-static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
974
- int64_t bytes, QEMUIOVector *qiov,
975
- BdrvRequestFlags flags)
976
+static int coroutine_fn GRAPH_RDLOCK
977
+raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
978
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
979
{
980
int ret;
981
982
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
983
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
984
}
985
986
-static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
987
- int64_t bytes, QEMUIOVector *qiov,
988
- BdrvRequestFlags flags)
989
+static int coroutine_fn GRAPH_RDLOCK
990
+raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
991
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
992
{
993
void *buf = NULL;
994
BlockDriver *drv;
156
diff --git a/block/replication.c b/block/replication.c
995
diff --git a/block/replication.c b/block/replication.c
157
index XXXXXXX..XXXXXXX 100644
996
index XXXXXXX..XXXXXXX 100644
158
--- a/block/replication.c
997
--- a/block/replication.c
159
+++ b/block/replication.c
998
+++ b/block/replication.c
160
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
999
@@ -XXX,XX +XXX,XX @@ static int replication_return_value(BDRVReplicationState *s, int ret)
161
1000
return ret;
162
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
1001
}
163
const BdrvChildRole *role,
1002
164
+ BlockReopenQueue *reopen_queue,
1003
-static coroutine_fn int replication_co_readv(BlockDriverState *bs,
165
uint64_t perm, uint64_t shared,
1004
- int64_t sector_num,
166
uint64_t *nperm, uint64_t *nshared)
1005
- int remaining_sectors,
167
{
1006
- QEMUIOVector *qiov)
168
diff --git a/block/vvfat.c b/block/vvfat.c
1007
+static int coroutine_fn GRAPH_RDLOCK
169
index XXXXXXX..XXXXXXX 100644
1008
+replication_co_readv(BlockDriverState *bs, int64_t sector_num,
170
--- a/block/vvfat.c
1009
+ int remaining_sectors, QEMUIOVector *qiov)
171
+++ b/block/vvfat.c
1010
{
172
@@ -XXX,XX +XXX,XX @@ err:
1011
BDRVReplicationState *s = bs->opaque;
173
1012
int ret;
174
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
1013
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
175
const BdrvChildRole *role,
1014
return replication_return_value(s, ret);
176
+ BlockReopenQueue *reopen_queue,
1015
}
177
uint64_t perm, uint64_t shared,
1016
178
uint64_t *nperm, uint64_t *nshared)
1017
-static coroutine_fn int replication_co_writev(BlockDriverState *bs,
179
{
1018
- int64_t sector_num,
1019
- int remaining_sectors,
1020
- QEMUIOVector *qiov,
1021
- int flags)
1022
+static int coroutine_fn GRAPH_RDLOCK
1023
+replication_co_writev(BlockDriverState *bs, int64_t sector_num,
1024
+ int remaining_sectors, QEMUIOVector *qiov, int flags)
1025
{
1026
BDRVReplicationState *s = bs->opaque;
1027
QEMUIOVector hd_qiov;
1028
diff --git a/block/throttle.c b/block/throttle.c
1029
index XXXXXXX..XXXXXXX 100644
1030
--- a/block/throttle.c
1031
+++ b/block/throttle.c
1032
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
1033
return bdrv_co_getlength(bs->file->bs);
1034
}
1035
1036
-static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1037
- int64_t offset, int64_t bytes,
1038
- QEMUIOVector *qiov,
1039
- BdrvRequestFlags flags)
1040
+static int coroutine_fn GRAPH_RDLOCK
1041
+throttle_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1042
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1043
{
1044
1045
ThrottleGroupMember *tgm = bs->opaque;
1046
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
1047
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
1048
}
1049
1050
-static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
1051
- int64_t offset, int64_t bytes,
1052
- QEMUIOVector *qiov,
1053
- BdrvRequestFlags flags)
1054
+static int coroutine_fn GRAPH_RDLOCK
1055
+throttle_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1056
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1057
{
1058
ThrottleGroupMember *tgm = bs->opaque;
1059
throttle_group_co_io_limits_intercept(tgm, bytes, true);
1060
@@ -XXX,XX +XXX,XX @@ throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
1061
return bdrv_co_pdiscard(bs->file, offset, bytes);
1062
}
1063
1064
-static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
1065
- int64_t offset,
1066
- int64_t bytes,
1067
- QEMUIOVector *qiov)
1068
+static int coroutine_fn GRAPH_RDLOCK
1069
+throttle_co_pwritev_compressed(BlockDriverState *bs, int64_t offset,
1070
+ int64_t bytes, QEMUIOVector *qiov)
1071
{
1072
return throttle_co_pwritev(bs, offset, bytes, qiov,
1073
BDRV_REQ_WRITE_COMPRESSED);
1074
diff --git a/block/vdi.c b/block/vdi.c
1075
index XXXXXXX..XXXXXXX 100644
1076
--- a/block/vdi.c
1077
+++ b/block/vdi.c
1078
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
1079
(s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
1080
}
1081
1082
-static int coroutine_fn
1083
+static int coroutine_fn GRAPH_RDLOCK
1084
vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1085
QEMUIOVector *qiov, BdrvRequestFlags flags)
1086
{
1087
@@ -XXX,XX +XXX,XX @@ vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1088
return ret;
1089
}
1090
1091
-static int coroutine_fn
1092
+static int coroutine_fn GRAPH_RDLOCK
1093
vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1094
QEMUIOVector *qiov, BdrvRequestFlags flags)
1095
{
1096
diff --git a/block/vhdx.c b/block/vhdx.c
1097
index XXXXXXX..XXXXXXX 100644
1098
--- a/block/vhdx.c
1099
+++ b/block/vhdx.c
1100
@@ -XXX,XX +XXX,XX @@ vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1101
}
1102
1103
1104
-static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
1105
- int nb_sectors, QEMUIOVector *qiov)
1106
+static int coroutine_fn GRAPH_RDLOCK
1107
+vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1108
+ QEMUIOVector *qiov)
1109
{
1110
BDRVVHDXState *s = bs->opaque;
1111
int ret = 0;
1112
@@ -XXX,XX +XXX,XX @@ int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
1113
return ret;
1114
}
1115
1116
-static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
1117
- int nb_sectors, QEMUIOVector *qiov,
1118
- int flags)
1119
+static int coroutine_fn GRAPH_RDLOCK
1120
+vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
1121
+ QEMUIOVector *qiov, int flags)
1122
{
1123
int ret = -ENOTSUP;
1124
BDRVVHDXState *s = bs->opaque;
1125
diff --git a/block/vmdk.c b/block/vmdk.c
1126
index XXXXXXX..XXXXXXX 100644
1127
--- a/block/vmdk.c
1128
+++ b/block/vmdk.c
1129
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
1130
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
1131
* it for call to write user data in the request.
1132
*/
1133
-static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
1134
- VmdkExtent *extent,
1135
- uint64_t cluster_offset,
1136
- uint64_t offset,
1137
- uint64_t skip_start_bytes,
1138
- uint64_t skip_end_bytes,
1139
- bool zeroed)
1140
+static int coroutine_fn GRAPH_RDLOCK
1141
+get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent,
1142
+ uint64_t cluster_offset, uint64_t offset,
1143
+ uint64_t skip_start_bytes, uint64_t skip_end_bytes,
1144
+ bool zeroed)
1145
{
1146
int ret = VMDK_OK;
1147
int64_t cluster_bytes;
1148
@@ -XXX,XX +XXX,XX @@ vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset)
1149
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
1150
* VMDK_ERROR if failed.
1151
*/
1152
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
1153
- VmdkExtent *extent,
1154
- VmdkMetaData *m_data,
1155
- uint64_t offset,
1156
- bool allocate,
1157
- uint64_t *cluster_offset,
1158
- uint64_t skip_start_bytes,
1159
- uint64_t skip_end_bytes)
1160
+static int coroutine_fn GRAPH_RDLOCK
1161
+get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent,
1162
+ VmdkMetaData *m_data, uint64_t offset, bool allocate,
1163
+ uint64_t *cluster_offset, uint64_t skip_start_bytes,
1164
+ uint64_t skip_end_bytes)
1165
{
1166
unsigned int l1_index, l2_offset, l2_index;
1167
int min_index, i, j;
1168
@@ -XXX,XX +XXX,XX @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
1169
return extent_relative_offset % cluster_size;
1170
}
1171
1172
-static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1173
- bool want_zero,
1174
- int64_t offset, int64_t bytes,
1175
- int64_t *pnum, int64_t *map,
1176
- BlockDriverState **file)
1177
+static int coroutine_fn GRAPH_RDLOCK
1178
+vmdk_co_block_status(BlockDriverState *bs, bool want_zero,
1179
+ int64_t offset, int64_t bytes, int64_t *pnum,
1180
+ int64_t *map, BlockDriverState **file)
1181
{
1182
BDRVVmdkState *s = bs->opaque;
1183
int64_t index_in_cluster, n, ret;
1184
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
1185
return ret;
1186
}
1187
1188
-static int coroutine_fn
1189
+static int coroutine_fn GRAPH_RDLOCK
1190
vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1191
int64_t offset_in_cluster, QEMUIOVector *qiov,
1192
uint64_t qiov_offset, uint64_t n_bytes,
1193
@@ -XXX,XX +XXX,XX @@ vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
1194
return ret;
1195
}
1196
1197
-static int coroutine_fn
1198
+static int coroutine_fn GRAPH_RDLOCK
1199
vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1200
- int64_t offset_in_cluster, QEMUIOVector *qiov,
1201
- int bytes)
1202
+ int64_t offset_in_cluster, QEMUIOVector *qiov, int bytes)
1203
{
1204
int ret;
1205
int cluster_bytes, buf_bytes;
1206
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1207
return ret;
1208
}
1209
1210
-static int coroutine_fn
1211
+static int coroutine_fn GRAPH_RDLOCK
1212
vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1213
QEMUIOVector *qiov, BdrvRequestFlags flags)
1214
{
1215
@@ -XXX,XX +XXX,XX @@ fail:
1216
*
1217
* Returns: error code with 0 for success.
1218
*/
1219
-static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1220
- uint64_t bytes, QEMUIOVector *qiov,
1221
- bool zeroed, bool zero_dry_run)
1222
+static int coroutine_fn GRAPH_RDLOCK
1223
+vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1224
+ QEMUIOVector *qiov, bool zeroed, bool zero_dry_run)
1225
{
1226
BDRVVmdkState *s = bs->opaque;
1227
VmdkExtent *extent = NULL;
1228
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1229
uint64_t bytes_done = 0;
1230
VmdkMetaData m_data;
1231
1232
- assume_graph_lock(); /* FIXME */
1233
-
1234
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
1235
error_report("Wrong offset: offset=0x%" PRIx64
1236
" total_sectors=0x%" PRIx64,
1237
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
1238
return 0;
1239
}
1240
1241
-static int coroutine_fn
1242
+static int coroutine_fn GRAPH_RDLOCK
1243
vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1244
QEMUIOVector *qiov, BdrvRequestFlags flags)
1245
{
1246
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
1247
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
1248
}
1249
1250
-static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
1251
- int64_t offset,
1252
- int64_t bytes,
1253
- BdrvRequestFlags flags)
1254
+static int coroutine_fn GRAPH_RDLOCK
1255
+vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
1256
+ BdrvRequestFlags flags)
1257
{
1258
int ret;
1259
BDRVVmdkState *s = bs->opaque;
1260
@@ -XXX,XX +XXX,XX @@ static VmdkExtentInfo *vmdk_get_extent_info(VmdkExtent *extent)
1261
return info;
1262
}
1263
1264
-static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
1265
- BdrvCheckResult *result,
1266
- BdrvCheckMode fix)
1267
+static int coroutine_fn GRAPH_RDLOCK
1268
+vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
1269
{
1270
BDRVVmdkState *s = bs->opaque;
1271
VmdkExtent *extent = NULL;
1272
diff --git a/block/vpc.c b/block/vpc.c
1273
index XXXXXXX..XXXXXXX 100644
1274
--- a/block/vpc.c
1275
+++ b/block/vpc.c
1276
@@ -XXX,XX +XXX,XX @@ vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1277
return 0;
1278
}
1279
1280
-static int coroutine_fn
1281
+static int coroutine_fn GRAPH_RDLOCK
1282
vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1283
QEMUIOVector *qiov, BdrvRequestFlags flags)
1284
{
1285
@@ -XXX,XX +XXX,XX @@ fail:
1286
return ret;
1287
}
1288
1289
-static int coroutine_fn
1290
+static int coroutine_fn GRAPH_RDLOCK
1291
vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1292
QEMUIOVector *qiov, BdrvRequestFlags flags)
1293
{
1294
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
1295
index XXXXXXX..XXXXXXX 100644
1296
--- a/tests/unit/test-bdrv-drain.c
1297
+++ b/tests/unit/test-bdrv-drain.c
1298
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_top_close(BlockDriverState *bs)
1299
}
1300
}
1301
1302
-static int coroutine_fn bdrv_test_top_co_preadv(BlockDriverState *bs,
1303
- int64_t offset, int64_t bytes,
1304
- QEMUIOVector *qiov,
1305
- BdrvRequestFlags flags)
1306
+static int coroutine_fn GRAPH_RDLOCK
1307
+bdrv_test_top_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1308
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1309
{
1310
BDRVTestTopState *tts = bs->opaque;
1311
return bdrv_co_preadv(tts->wait_child, offset, bytes, qiov, flags);
1312
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
1313
void *buffer = g_malloc(65536);
1314
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
1315
1316
+ GRAPH_RDLOCK_GUARD();
1317
+
1318
/* Pretend some internal write operation from parent to child.
1319
* Important: We have to read from the child, not from the parent!
1320
* Draining works by first propagating it all up the tree to the
1321
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_test_close(BlockDriverState *bs)
1322
* Otherwise:
1323
* Set .has_read to true and return success.
1324
*/
1325
-static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs,
1326
- int64_t offset,
1327
- int64_t bytes,
1328
- QEMUIOVector *qiov,
1329
- BdrvRequestFlags flags)
1330
+static int coroutine_fn GRAPH_RDLOCK
1331
+bdrv_replace_test_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
1332
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
1333
{
1334
BDRVReplaceTestState *s = bs->opaque;
1335
1336
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_read_entry(void *opaque)
1337
int ret;
1338
1339
/* Queue a read request post-drain */
1340
+ bdrv_graph_co_rdlock();
1341
ret = bdrv_replace_test_co_preadv(bs, 0, 1, &qiov, 0);
1342
+ bdrv_graph_co_rdunlock();
1343
+
1344
g_assert(ret >= 0);
1345
bdrv_dec_in_flight(bs);
1346
}
180
--
1347
--
181
2.13.5
1348
2.39.2
182
183
diff view generated by jsdifflib
1
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_pwrite_sync() need to hold a reader lock for the graph.
2
3
3
Whenever l2/refcount table clusters are discarded from the file we can
4
For some places, we know that they will hold the lock, but we don't have
4
automatically drop unnecessary content of the cache tables. This reduces
5
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
5
the chance of eviction useful cache data and eliminates inconsistent data
6
with a FIXME comment. These places will be removed once everything is
6
in the cache with the data in the file.
7
properly annotated.
7
8
8
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20230203152202.49054-13-kwolf@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-id: 20170918124230.8152-3-pbutsykin@virtuozzo.com
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
13
---
14
block/qcow2.h | 3 +++
14
block/qcow2.h | 2 +-
15
block/qcow2-cache.c | 26 ++++++++++++++++++++++++++
15
include/block/block-io.h | 7 ++++---
16
block/qcow2-refcount.c | 20 ++++++++++++++++++--
16
block/io.c | 3 +--
17
3 files changed, 47 insertions(+), 2 deletions(-)
17
3 files changed, 6 insertions(+), 6 deletions(-)
18
18
19
diff --git a/block/qcow2.h b/block/qcow2.h
19
diff --git a/block/qcow2.h b/block/qcow2.h
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.h
21
--- a/block/qcow2.h
22
+++ b/block/qcow2.h
22
+++ b/block/qcow2.h
23
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
23
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
24
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
24
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
25
void **table);
25
BlockDriverAmendStatusCB *status_cb,
26
void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
26
void *cb_opaque, Error **errp);
27
+void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
27
-int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
28
+ uint64_t offset);
28
+int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
29
+void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);
29
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
30
30
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
31
/* qcow2-bitmap.c functions */
31
32
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
32
diff --git a/include/block/block-io.h b/include/block/block-io.h
33
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
34
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
35
--- a/block/qcow2-cache.c
34
--- a/include/block/block-io.h
36
+++ b/block/qcow2-cache.c
35
+++ b/include/block/block-io.h
37
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
36
@@ -XXX,XX +XXX,XX @@ int co_wrapper_mixed_bdrv_rdlock
38
assert(c->entries[i].offset != 0);
37
bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
39
c->entries[i].dirty = true;
38
const void *buf, BdrvRequestFlags flags);
40
}
39
40
-int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
41
- int64_t bytes, const void *buf,
42
- BdrvRequestFlags flags);
43
+int coroutine_fn GRAPH_RDLOCK
44
+bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
45
+ const void *buf, BdrvRequestFlags flags);
41
+
46
+
42
+void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
47
/*
43
+ uint64_t offset)
48
* Efficiently zero a region of the disk image. Note that this is a regular
44
+{
49
* I/O request like read or write and should have a reasonable size. This
45
+ int i;
50
diff --git a/block/io.c b/block/io.c
46
+
47
+ for (i = 0; i < c->size; i++) {
48
+ if (c->entries[i].offset == offset) {
49
+ return qcow2_cache_get_table_addr(bs, c, i);
50
+ }
51
+ }
52
+ return NULL;
53
+}
54
+
55
+void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table)
56
+{
57
+ int i = qcow2_cache_get_table_idx(bs, c, table);
58
+
59
+ assert(c->entries[i].ref == 0);
60
+
61
+ c->entries[i].offset = 0;
62
+ c->entries[i].lru_counter = 0;
63
+ c->entries[i].dirty = false;
64
+
65
+ qcow2_cache_table_release(bs, c, i, 1);
66
+}
67
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
68
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
69
--- a/block/qcow2-refcount.c
52
--- a/block/io.c
70
+++ b/block/qcow2-refcount.c
53
+++ b/block/io.c
71
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
54
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
72
}
55
{
73
s->set_refcount(refcount_block, block_index, refcount);
56
int ret;
74
57
IO_CODE();
75
- if (refcount == 0 && s->discard_passthrough[type]) {
58
-
76
- update_refcount_discard(bs, cluster_offset, s->cluster_size);
59
- assume_graph_lock(); /* FIXME */
77
+ if (refcount == 0) {
60
+ assert_bdrv_graph_readable();
78
+ void *table;
61
79
+
62
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
80
+ table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
63
if (ret < 0) {
81
+ offset);
82
+ if (table != NULL) {
83
+ qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
84
+ qcow2_cache_discard(bs, s->refcount_block_cache, table);
85
+ }
86
+
87
+ table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset);
88
+ if (table != NULL) {
89
+ qcow2_cache_discard(bs, s->l2_table_cache, table);
90
+ }
91
+
92
+ if (s->discard_passthrough[type]) {
93
+ update_refcount_discard(bs, cluster_offset, s->cluster_size);
94
+ }
95
}
96
}
97
98
--
64
--
99
2.13.5
65
2.39.2
100
101
diff view generated by jsdifflib
1
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
1
All callers are already GRAPH_RDLOCK, so just add the annotation and
2
remove assume_graph_lock().
2
3
3
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Message-Id: <20230203152202.49054-14-kwolf@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Message-id: 20170918124230.8152-5-pbutsykin@virtuozzo.com
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
8
---
9
tests/qemu-iotests/163 | 170 +++++++++++++++++++++++++++++++++++++++++++++
9
block/io.c | 7 +++----
10
tests/qemu-iotests/163.out | 5 ++
10
1 file changed, 3 insertions(+), 4 deletions(-)
11
tests/qemu-iotests/group | 1 +
12
3 files changed, 176 insertions(+)
13
create mode 100644 tests/qemu-iotests/163
14
create mode 100644 tests/qemu-iotests/163.out
15
11
16
diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163
12
diff --git a/block/io.c b/block/io.c
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/tests/qemu-iotests/163
21
@@ -XXX,XX +XXX,XX @@
22
+#!/usr/bin/env python
23
+#
24
+# Tests for shrinking images
25
+#
26
+# Copyright (c) 2016-2017 Parallels International GmbH
27
+#
28
+# This program is free software; you can redistribute it and/or modify
29
+# it under the terms of the GNU General Public License as published by
30
+# the Free Software Foundation; either version 2 of the License, or
31
+# (at your option) any later version.
32
+#
33
+# This program is distributed in the hope that it will be useful,
34
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36
+# GNU General Public License for more details.
37
+#
38
+# You should have received a copy of the GNU General Public License
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
40
+#
41
+
42
+import os, random, iotests, struct, qcow2
43
+from iotests import qemu_img, qemu_io, image_size
44
+
45
+test_img = os.path.join(iotests.test_dir, 'test.img')
46
+check_img = os.path.join(iotests.test_dir, 'check.img')
47
+
48
+def size_to_int(str):
49
+ suff = ['B', 'K', 'M', 'G', 'T']
50
+ return int(str[:-1]) * 1024**suff.index(str[-1:])
51
+
52
+class ShrinkBaseClass(iotests.QMPTestCase):
53
+ image_len = '128M'
54
+ shrink_size = '10M'
55
+ chunk_size = '16M'
56
+ refcount_bits = '16'
57
+
58
+ def __qcow2_check(self, filename):
59
+ entry_bits = 3
60
+ entry_size = 1 << entry_bits
61
+ l1_mask = 0x00fffffffffffe00
62
+ div_roundup = lambda n, d: (n + d - 1) / d
63
+
64
+ def split_by_n(data, n):
65
+ for x in xrange(0, len(data), n):
66
+ yield struct.unpack('>Q', data[x:x + n])[0] & l1_mask
67
+
68
+ def check_l1_table(h, l1_data):
69
+ l1_list = list(split_by_n(l1_data, entry_size))
70
+ real_l1_size = div_roundup(h.size,
71
+ 1 << (h.cluster_bits*2 - entry_size))
72
+ used, unused = l1_list[:real_l1_size], l1_list[real_l1_size:]
73
+
74
+ self.assertTrue(len(used) != 0, "Verifying l1 table content")
75
+ self.assertFalse(any(unused), "Verifying l1 table content")
76
+
77
+ def check_reftable(fd, h, reftable):
78
+ for offset in split_by_n(reftable, entry_size):
79
+ if offset != 0:
80
+ fd.seek(offset)
81
+ cluster = fd.read(1 << h.cluster_bits)
82
+ self.assertTrue(any(cluster), "Verifying reftable content")
83
+
84
+ with open(filename, "rb") as fd:
85
+ h = qcow2.QcowHeader(fd)
86
+
87
+ fd.seek(h.l1_table_offset)
88
+ l1_table = fd.read(h.l1_size << entry_bits)
89
+
90
+ fd.seek(h.refcount_table_offset)
91
+ reftable = fd.read(h.refcount_table_clusters << h.cluster_bits)
92
+
93
+ check_l1_table(h, l1_table)
94
+ check_reftable(fd, h, reftable)
95
+
96
+ def __raw_check(self, filename):
97
+ pass
98
+
99
+ image_check = {
100
+ 'qcow2' : __qcow2_check,
101
+ 'raw' : __raw_check
102
+ }
103
+
104
+ def setUp(self):
105
+ if iotests.imgfmt == 'raw':
106
+ qemu_img('create', '-f', iotests.imgfmt, test_img, self.image_len)
107
+ qemu_img('create', '-f', iotests.imgfmt, check_img,
108
+ self.shrink_size)
109
+ else:
110
+ qemu_img('create', '-f', iotests.imgfmt,
111
+ '-o', 'cluster_size=' + self.cluster_size +
112
+ ',refcount_bits=' + self.refcount_bits,
113
+ test_img, self.image_len)
114
+ qemu_img('create', '-f', iotests.imgfmt,
115
+ '-o', 'cluster_size=%s'% self.cluster_size,
116
+ check_img, self.shrink_size)
117
+ qemu_io('-c', 'write -P 0xff 0 ' + self.shrink_size, check_img)
118
+
119
+ def tearDown(self):
120
+ os.remove(test_img)
121
+ os.remove(check_img)
122
+
123
+ def image_verify(self):
124
+ self.assertEqual(image_size(test_img), image_size(check_img),
125
+ "Verifying image size")
126
+ self.image_check[iotests.imgfmt](self, test_img)
127
+
128
+ if iotests.imgfmt == 'raw':
129
+ return
130
+ self.assertEqual(qemu_img('check', test_img), 0,
131
+ "Verifying image corruption")
132
+
133
+ def test_empty_image(self):
134
+ qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img,
135
+ self.shrink_size)
136
+
137
+ self.assertEqual(
138
+ qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, test_img),
139
+ qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, check_img),
140
+ "Verifying image content")
141
+
142
+ self.image_verify()
143
+
144
+ def test_sequential_write(self):
145
+ for offs in range(0, size_to_int(self.image_len),
146
+ size_to_int(self.chunk_size)):
147
+ qemu_io('-c', 'write -P 0xff %d %s' % (offs, self.chunk_size),
148
+ test_img)
149
+
150
+ qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img,
151
+ self.shrink_size)
152
+
153
+ self.assertEqual(qemu_img("compare", test_img, check_img), 0,
154
+ "Verifying image content")
155
+
156
+ self.image_verify()
157
+
158
+ def test_random_write(self):
159
+ offs_list = range(0, size_to_int(self.image_len),
160
+ size_to_int(self.chunk_size))
161
+ random.shuffle(offs_list)
162
+ for offs in offs_list:
163
+ qemu_io('-c', 'write -P 0xff %d %s' % (offs, self.chunk_size),
164
+ test_img)
165
+
166
+ qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img,
167
+ self.shrink_size)
168
+
169
+ self.assertEqual(qemu_img("compare", test_img, check_img), 0,
170
+ "Verifying image content")
171
+
172
+ self.image_verify()
173
+
174
+class TestShrink512(ShrinkBaseClass):
175
+ image_len = '3M'
176
+ shrink_size = '1M'
177
+ chunk_size = '256K'
178
+ cluster_size = '512'
179
+ refcount_bits = '64'
180
+
181
+class TestShrink64K(ShrinkBaseClass):
182
+ cluster_size = '64K'
183
+
184
+class TestShrink1M(ShrinkBaseClass):
185
+ cluster_size = '1M'
186
+ refcount_bits = '1'
187
+
188
+ShrinkBaseClass = None
189
+
190
+if __name__ == '__main__':
191
+ iotests.main(supported_fmts=['raw', 'qcow2'])
192
diff --git a/tests/qemu-iotests/163.out b/tests/qemu-iotests/163.out
193
new file mode 100644
194
index XXXXXXX..XXXXXXX
195
--- /dev/null
196
+++ b/tests/qemu-iotests/163.out
197
@@ -XXX,XX +XXX,XX @@
198
+.........
199
+----------------------------------------------------------------------
200
+Ran 9 tests
201
+
202
+OK
203
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
204
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
205
--- a/tests/qemu-iotests/group
14
--- a/block/io.c
206
+++ b/tests/qemu-iotests/group
15
+++ b/block/io.c
207
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ fail:
208
159 rw auto quick
17
return ret;
209
160 rw auto quick
18
}
210
162 auto quick
19
211
+163 rw auto quick
20
-static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
212
165 rw auto quick
21
- int64_t offset, int64_t bytes, BdrvRequestFlags flags)
213
170 rw auto quick
22
+static int coroutine_fn GRAPH_RDLOCK
214
171 rw auto quick
23
+bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
24
+ BdrvRequestFlags flags)
25
{
26
BlockDriver *drv = bs->drv;
27
QEMUIOVector qiov;
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
29
int head = 0;
30
int tail = 0;
31
32
- assume_graph_lock(); /* FIXME */
33
-
34
int64_t max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
35
INT64_MAX);
36
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
215
--
37
--
216
2.13.5
38
2.39.2
217
218
diff view generated by jsdifflib
1
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The flag is additional precaution against data loss. Perhaps in the future the
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
operation shrink without this flag will be blocked for all formats, but for now
4
bdrv_co_copy_range() need to hold a reader lock for the graph.
5
we need to maintain compatibility with raw.
6
5
7
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20230203152202.49054-15-kwolf@redhat.com>
10
Message-id: 20170918124230.8152-2-pbutsykin@virtuozzo.com
9
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
[mreitz: Added a missing space to a warning]
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
11
---
14
qemu-img.c | 23 +++++++++++++++++++++++
12
include/block/block-io.h | 9 +++++----
15
qemu-img-cmds.hx | 4 ++--
13
include/block/block_int-common.h | 24 ++++++++----------------
16
qemu-img.texi | 6 +++++-
14
include/block/block_int-io.h | 20 ++++++++++----------
17
tests/qemu-iotests/102 | 4 ++--
15
block/block-backend.c | 2 ++
18
tests/qemu-iotests/106 | 2 +-
16
block/file-posix.c | 16 +++++++---------
19
5 files changed, 33 insertions(+), 6 deletions(-)
17
block/io.c | 7 +++++--
18
block/iscsi.c | 28 ++++++++++++----------------
19
block/qcow2.c | 5 ++---
20
block/raw-format.c | 28 ++++++++++++----------------
21
qemu-img.c | 4 +++-
22
10 files changed, 66 insertions(+), 77 deletions(-)
20
23
24
diff --git a/include/block/block-io.h b/include/block/block-io.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block-io.h
27
+++ b/include/block/block-io.h
28
@@ -XXX,XX +XXX,XX @@ bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
29
*
30
* Returns: 0 if succeeded; negative error code if failed.
31
**/
32
-int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
33
- BdrvChild *dst, int64_t dst_offset,
34
- int64_t bytes, BdrvRequestFlags read_flags,
35
- BdrvRequestFlags write_flags);
36
+int coroutine_fn GRAPH_RDLOCK
37
+bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
38
+ BdrvChild *dst, int64_t dst_offset,
39
+ int64_t bytes, BdrvRequestFlags read_flags,
40
+ BdrvRequestFlags write_flags);
41
42
/*
43
* "I/O or GS" API functions. These functions can run without
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
* See the comment of bdrv_co_copy_range for the parameter and return value
50
* semantics.
51
*/
52
- int coroutine_fn (*bdrv_co_copy_range_from)(BlockDriverState *bs,
53
- BdrvChild *src,
54
- int64_t offset,
55
- BdrvChild *dst,
56
- int64_t dst_offset,
57
- int64_t bytes,
58
- BdrvRequestFlags read_flags,
59
- BdrvRequestFlags write_flags);
60
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_from)(
61
+ BlockDriverState *bs, BdrvChild *src, int64_t offset,
62
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
63
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
64
65
/*
66
* Map [offset, offset + nbytes) range onto a child of bs to copy data to,
67
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
68
* See the comment of bdrv_co_copy_range for the parameter and return value
69
* semantics.
70
*/
71
- int coroutine_fn (*bdrv_co_copy_range_to)(BlockDriverState *bs,
72
- BdrvChild *src,
73
- int64_t src_offset,
74
- BdrvChild *dst,
75
- int64_t dst_offset,
76
- int64_t bytes,
77
- BdrvRequestFlags read_flags,
78
- BdrvRequestFlags write_flags);
79
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_copy_range_to)(
80
+ BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
81
+ BdrvChild *dst, int64_t dst_offset, int64_t bytes,
82
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags);
83
84
/*
85
* Building block for bdrv_block_status[_above] and
86
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/include/block/block_int-io.h
89
+++ b/include/block/block_int-io.h
90
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
91
void bdrv_inc_in_flight(BlockDriverState *bs);
92
void bdrv_dec_in_flight(BlockDriverState *bs);
93
94
-int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
95
- BdrvChild *dst, int64_t dst_offset,
96
- int64_t bytes,
97
- BdrvRequestFlags read_flags,
98
- BdrvRequestFlags write_flags);
99
-int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
100
- BdrvChild *dst, int64_t dst_offset,
101
- int64_t bytes,
102
- BdrvRequestFlags read_flags,
103
- BdrvRequestFlags write_flags);
104
+int coroutine_fn GRAPH_RDLOCK
105
+bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
106
+ BdrvChild *dst, int64_t dst_offset,
107
+ int64_t bytes, BdrvRequestFlags read_flags,
108
+ BdrvRequestFlags write_flags);
109
+int coroutine_fn GRAPH_RDLOCK
110
+bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
111
+ BdrvChild *dst, int64_t dst_offset,
112
+ int64_t bytes, BdrvRequestFlags read_flags,
113
+ BdrvRequestFlags write_flags);
114
115
int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
116
int64_t hint);
117
diff --git a/block/block-backend.c b/block/block-backend.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/block-backend.c
120
+++ b/block/block-backend.c
121
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
122
if (r) {
123
return r;
124
}
125
+
126
+ GRAPH_RDLOCK_GUARD();
127
return bdrv_co_copy_range(blk_in->root, off_in,
128
blk_out->root, off_out,
129
bytes, read_flags, write_flags);
130
diff --git a/block/file-posix.c b/block/file-posix.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/file-posix.c
133
+++ b/block/file-posix.c
134
@@ -XXX,XX +XXX,XX @@ static void raw_abort_perm_update(BlockDriverState *bs)
135
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
136
}
137
138
-static int coroutine_fn raw_co_copy_range_from(
139
+static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from(
140
BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
141
BdrvChild *dst, int64_t dst_offset, int64_t bytes,
142
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags)
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(
144
read_flags, write_flags);
145
}
146
147
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
148
- BdrvChild *src,
149
- int64_t src_offset,
150
- BdrvChild *dst,
151
- int64_t dst_offset,
152
- int64_t bytes,
153
- BdrvRequestFlags read_flags,
154
- BdrvRequestFlags write_flags)
155
+static int coroutine_fn GRAPH_RDLOCK
156
+raw_co_copy_range_to(BlockDriverState *bs,
157
+ BdrvChild *src, int64_t src_offset,
158
+ BdrvChild *dst, int64_t dst_offset,
159
+ int64_t bytes, BdrvRequestFlags read_flags,
160
+ BdrvRequestFlags write_flags)
161
{
162
RawPosixAIOData acb;
163
BDRVRawState *s = bs->opaque;
164
diff --git a/block/io.c b/block/io.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/io.c
167
+++ b/block/io.c
168
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
169
{
170
BdrvTrackedRequest req;
171
int ret;
172
+ assert_bdrv_graph_readable();
173
174
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
175
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
176
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
177
BdrvRequestFlags write_flags)
178
{
179
IO_CODE();
180
- assume_graph_lock(); /* FIXME */
181
+ assert_bdrv_graph_readable();
182
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
183
read_flags, write_flags);
184
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
185
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
186
BdrvRequestFlags write_flags)
187
{
188
IO_CODE();
189
- assume_graph_lock(); /* FIXME */
190
+ assert_bdrv_graph_readable();
191
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
192
read_flags, write_flags);
193
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
194
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
195
BdrvRequestFlags write_flags)
196
{
197
IO_CODE();
198
+ assert_bdrv_graph_readable();
199
+
200
return bdrv_co_copy_range_from(src, src_offset,
201
dst, dst_offset,
202
bytes, read_flags, write_flags);
203
diff --git a/block/iscsi.c b/block/iscsi.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/iscsi.c
206
+++ b/block/iscsi.c
207
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn iscsi_co_invalidate_cache(BlockDriverState *bs,
208
iscsi_allocmap_invalidate(iscsilun);
209
}
210
211
-static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs,
212
- BdrvChild *src,
213
- int64_t src_offset,
214
- BdrvChild *dst,
215
- int64_t dst_offset,
216
- int64_t bytes,
217
- BdrvRequestFlags read_flags,
218
- BdrvRequestFlags write_flags)
219
+static int coroutine_fn GRAPH_RDLOCK
220
+iscsi_co_copy_range_from(BlockDriverState *bs,
221
+ BdrvChild *src, int64_t src_offset,
222
+ BdrvChild *dst, int64_t dst_offset,
223
+ int64_t bytes, BdrvRequestFlags read_flags,
224
+ BdrvRequestFlags write_flags)
225
{
226
return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
227
read_flags, write_flags);
228
@@ -XXX,XX +XXX,XX @@ static void iscsi_xcopy_data(struct iscsi_data *data,
229
src_lba, dst_lba);
230
}
231
232
-static int coroutine_fn iscsi_co_copy_range_to(BlockDriverState *bs,
233
- BdrvChild *src,
234
- int64_t src_offset,
235
- BdrvChild *dst,
236
- int64_t dst_offset,
237
- int64_t bytes,
238
- BdrvRequestFlags read_flags,
239
- BdrvRequestFlags write_flags)
240
+static int coroutine_fn GRAPH_RDLOCK
241
+iscsi_co_copy_range_to(BlockDriverState *bs,
242
+ BdrvChild *src, int64_t src_offset,
243
+ BdrvChild *dst, int64_t dst_offset,
244
+ int64_t bytes, BdrvRequestFlags read_flags,
245
+ BdrvRequestFlags write_flags)
246
{
247
IscsiLun *dst_lun = dst->bs->opaque;
248
IscsiLun *src_lun;
249
diff --git a/block/qcow2.c b/block/qcow2.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/block/qcow2.c
252
+++ b/block/qcow2.c
253
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
254
return ret;
255
}
256
257
-static int coroutine_fn
258
+static int coroutine_fn GRAPH_RDLOCK
259
qcow2_co_copy_range_from(BlockDriverState *bs,
260
BdrvChild *src, int64_t src_offset,
261
BdrvChild *dst, int64_t dst_offset,
262
@@ -XXX,XX +XXX,XX @@ out:
263
return ret;
264
}
265
266
-static int coroutine_fn
267
+static int coroutine_fn GRAPH_RDLOCK
268
qcow2_co_copy_range_to(BlockDriverState *bs,
269
BdrvChild *src, int64_t src_offset,
270
BdrvChild *dst, int64_t dst_offset,
271
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
272
uint64_t host_offset;
273
QCowL2Meta *l2meta = NULL;
274
275
- assume_graph_lock(); /* FIXME */
276
assert(!bs->encrypted);
277
278
qemu_co_mutex_lock(&s->lock);
279
diff --git a/block/raw-format.c b/block/raw-format.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/block/raw-format.c
282
+++ b/block/raw-format.c
283
@@ -XXX,XX +XXX,XX @@ static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
284
return bdrv_probe_geometry(bs->file->bs, geo);
285
}
286
287
-static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
288
- BdrvChild *src,
289
- int64_t src_offset,
290
- BdrvChild *dst,
291
- int64_t dst_offset,
292
- int64_t bytes,
293
- BdrvRequestFlags read_flags,
294
- BdrvRequestFlags write_flags)
295
+static int coroutine_fn GRAPH_RDLOCK
296
+raw_co_copy_range_from(BlockDriverState *bs,
297
+ BdrvChild *src, int64_t src_offset,
298
+ BdrvChild *dst, int64_t dst_offset,
299
+ int64_t bytes, BdrvRequestFlags read_flags,
300
+ BdrvRequestFlags write_flags)
301
{
302
int ret;
303
304
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
305
bytes, read_flags, write_flags);
306
}
307
308
-static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
309
- BdrvChild *src,
310
- int64_t src_offset,
311
- BdrvChild *dst,
312
- int64_t dst_offset,
313
- int64_t bytes,
314
- BdrvRequestFlags read_flags,
315
- BdrvRequestFlags write_flags)
316
+static int coroutine_fn GRAPH_RDLOCK
317
+raw_co_copy_range_to(BlockDriverState *bs,
318
+ BdrvChild *src, int64_t src_offset,
319
+ BdrvChild *dst, int64_t dst_offset,
320
+ int64_t bytes, BdrvRequestFlags read_flags,
321
+ BdrvRequestFlags write_flags)
322
{
323
int ret;
324
21
diff --git a/qemu-img.c b/qemu-img.c
325
diff --git a/qemu-img.c b/qemu-img.c
22
index XXXXXXX..XXXXXXX 100644
326
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-img.c
327
--- a/qemu-img.c
24
+++ b/qemu-img.c
328
+++ b/qemu-img.c
25
@@ -XXX,XX +XXX,XX @@ enum {
329
@@ -XXX,XX +XXX,XX @@ retry:
26
OPTION_TARGET_IMAGE_OPTS = 263,
330
27
OPTION_SIZE = 264,
331
if (s->ret == -EINPROGRESS) {
28
OPTION_PREALLOCATION = 265,
332
if (copy_range) {
29
+ OPTION_SHRINK = 266,
333
- ret = convert_co_copy_range(s, sector_num, n);
30
};
334
+ WITH_GRAPH_RDLOCK_GUARD() {
31
335
+ ret = convert_co_copy_range(s, sector_num, n);
32
typedef enum OutputFormat {
336
+ }
33
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
337
if (ret) {
34
},
338
s->copy_range = false;
35
};
339
goto retry;
36
bool image_opts = false;
37
+ bool shrink = false;
38
39
/* Remove size from argv manually so that negative numbers are not treated
40
* as options by getopt. */
41
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
42
{"object", required_argument, 0, OPTION_OBJECT},
43
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
44
{"preallocation", required_argument, 0, OPTION_PREALLOCATION},
45
+ {"shrink", no_argument, 0, OPTION_SHRINK},
46
{0, 0, 0, 0}
47
};
48
c = getopt_long(argc, argv, ":f:hq",
49
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
50
return 1;
51
}
52
break;
53
+ case OPTION_SHRINK:
54
+ shrink = true;
55
+ break;
56
}
57
}
58
if (optind != argc - 1) {
59
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
60
goto out;
61
}
62
63
+ if (total_size < current_size && !shrink) {
64
+ warn_report("Shrinking an image will delete all data beyond the "
65
+ "shrunken image's end. Before performing such an "
66
+ "operation, make sure there is no important data there.");
67
+
68
+ if (g_strcmp0(bdrv_get_format_name(blk_bs(blk)), "raw") != 0) {
69
+ error_report(
70
+ "Use the --shrink option to perform a shrink operation.");
71
+ ret = -1;
72
+ goto out;
73
+ } else {
74
+ warn_report("Using the --shrink option will suppress this message. "
75
+ "Note that future versions of qemu-img may refuse to "
76
+ "shrink images without this option.");
77
+ }
78
+ }
79
+
80
ret = blk_truncate(blk, total_size, prealloc, &err);
81
if (!ret) {
82
qprintf(quiet, "Image resized.\n");
83
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
84
index XXXXXXX..XXXXXXX 100644
85
--- a/qemu-img-cmds.hx
86
+++ b/qemu-img-cmds.hx
87
@@ -XXX,XX +XXX,XX @@ STEXI
88
ETEXI
89
90
DEF("resize", img_resize,
91
- "resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size")
92
+ "resize [--object objectdef] [--image-opts] [-q] [--shrink] filename [+ | -]size")
93
STEXI
94
-@item resize [--object @var{objectdef}] [--image-opts] [-q] @var{filename} [+ | -]@var{size}
95
+@item resize [--object @var{objectdef}] [--image-opts] [-q] [--shrink] @var{filename} [+ | -]@var{size}
96
ETEXI
97
98
STEXI
99
diff --git a/qemu-img.texi b/qemu-img.texi
100
index XXXXXXX..XXXXXXX 100644
101
--- a/qemu-img.texi
102
+++ b/qemu-img.texi
103
@@ -XXX,XX +XXX,XX @@ qemu-img rebase -b base.img diff.qcow2
104
At this point, @code{modified.img} can be discarded, since
105
@code{base.img + diff.qcow2} contains the same information.
106
107
-@item resize [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size}
108
+@item resize [--shrink] [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size}
109
110
Change the disk image as if it had been created with @var{size}.
111
112
@@ -XXX,XX +XXX,XX @@ Before using this command to shrink a disk image, you MUST use file system and
113
partitioning tools inside the VM to reduce allocated file systems and partition
114
sizes accordingly. Failure to do so will result in data loss!
115
116
+When shrinking images, the @code{--shrink} option must be given. This informs
117
+qemu-img that the user acknowledges all loss of data beyond the truncated
118
+image's end.
119
+
120
After using this command to grow a disk image, you must use file system and
121
partitioning tools inside the VM to actually begin using the new space on the
122
device.
123
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
124
index XXXXXXX..XXXXXXX 100755
125
--- a/tests/qemu-iotests/102
126
+++ b/tests/qemu-iotests/102
127
@@ -XXX,XX +XXX,XX @@ _make_test_img $IMG_SIZE
128
$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
129
# Remove data cluster from image (first cluster: image header, second: reftable,
130
# third: refblock, fourth: L1 table, fifth: L2 table)
131
-$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024))
132
+$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))
133
134
$QEMU_IO -c map "$TEST_IMG"
135
$QEMU_IMG map "$TEST_IMG"
136
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
137
138
qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0
139
140
-$QEMU_IMG resize -f raw "$TEST_IMG" $((5 * 64 * 1024))
141
+$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))
142
143
_send_qemu_cmd $QEMU_HANDLE 'qemu-io drv0 map' 'allocated' \
144
| sed -e 's/^(qemu).*qemu-io drv0 map...$/(qemu) qemu-io drv0 map/'
145
diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
146
index XXXXXXX..XXXXXXX 100755
147
--- a/tests/qemu-iotests/106
148
+++ b/tests/qemu-iotests/106
149
@@ -XXX,XX +XXX,XX @@ echo '=== Testing image shrinking ==='
150
for growth_mode in falloc full off; do
151
echo
152
echo "--- growth_mode=$growth_mode ---"
153
- $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K
154
+ $QEMU_IMG resize -f "$IMGFMT" --shrink --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K
155
done
156
157
# success, all done
158
--
340
--
159
2.13.5
341
2.39.2
160
161
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20230203152202.49054-16-kwolf@redhat.com>
3
RestartData is the opaque data of the throttle_group_restart_queue_entry
3
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
coroutine. By being stack allocated, it isn't available anymore if
5
aio_co_enter schedules the coroutine with a bottom half and runs after
6
throttle_group_restart_queue returns.
7
8
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
5
---
14
block/throttle-groups.c | 12 +++++++-----
6
include/block/block_int-common.h | 12 +++++++-----
15
1 file changed, 7 insertions(+), 5 deletions(-)
7
include/block/block_int-io.h | 8 ++++----
8
block/copy-before-write.c | 6 ++----
9
block/io.c | 2 ++
10
block/snapshot-access.c | 4 ++--
11
5 files changed, 17 insertions(+), 15 deletions(-)
16
12
17
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
13
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/block/throttle-groups.c
15
--- a/include/block/block_int-common.h
20
+++ b/block/throttle-groups.c
16
+++ b/include/block/block_int-common.h
21
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque)
17
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
schedule_next_request(tgm, is_write);
18
* - receive the snapshot's actual length (which may differ from bs's
23
qemu_mutex_unlock(&tg->lock);
19
* length)
24
}
20
*/
21
- int coroutine_fn (*bdrv_co_preadv_snapshot)(BlockDriverState *bs,
22
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
23
- int coroutine_fn (*bdrv_co_snapshot_block_status)(BlockDriverState *bs,
24
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
25
- int64_t *map, BlockDriverState **file);
26
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_preadv_snapshot)(
27
+ BlockDriverState *bs, int64_t offset, int64_t bytes,
28
+ QEMUIOVector *qiov, size_t qiov_offset);
25
+
29
+
26
+ g_free(data);
30
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)(
31
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
32
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
33
34
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
35
BlockDriverState *bs, int64_t offset, int64_t bytes);
36
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/block_int-io.h
39
+++ b/include/block/block_int-io.h
40
@@ -XXX,XX +XXX,XX @@
41
* the I/O API.
42
*/
43
44
-int coroutine_fn bdrv_co_preadv_snapshot(BdrvChild *child,
45
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child,
46
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
47
-int coroutine_fn bdrv_co_snapshot_block_status(BlockDriverState *bs,
48
- bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
49
- int64_t *map, BlockDriverState **file);
50
+int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status(
51
+ BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
52
+ int64_t *pnum, int64_t *map, BlockDriverState **file);
53
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
54
int64_t offset, int64_t bytes);
55
56
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/copy-before-write.c
59
+++ b/block/copy-before-write.c
60
@@ -XXX,XX +XXX,XX @@ cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
61
g_free(req);
27
}
62
}
28
63
29
static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write)
64
-static coroutine_fn int
65
+static int coroutine_fn GRAPH_RDLOCK
66
cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
67
QEMUIOVector *qiov, size_t qiov_offset)
30
{
68
{
31
Coroutine *co;
69
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
32
- RestartData rd = {
70
BdrvChild *file;
33
- .tgm = tgm,
71
int ret;
34
- .is_write = is_write
72
35
- };
73
- assume_graph_lock(); /* FIXME */
36
+ RestartData *rd = g_new0(RestartData, 1);
74
-
37
+
75
/* TODO: upgrade to async loop using AioTask */
38
+ rd->tgm = tgm;
76
while (bytes) {
39
+ rd->is_write = is_write;
77
int64_t cur_bytes;
40
78
@@ -XXX,XX +XXX,XX @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
41
- co = qemu_coroutine_create(throttle_group_restart_queue_entry, &rd);
79
return 0;
42
+ co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd);
43
aio_co_enter(tgm->aio_context, co);
44
}
80
}
45
81
82
-static int coroutine_fn
83
+static int coroutine_fn GRAPH_RDLOCK
84
cbw_co_snapshot_block_status(BlockDriverState *bs,
85
bool want_zero, int64_t offset, int64_t bytes,
86
int64_t *pnum, int64_t *map,
87
diff --git a/block/io.c b/block/io.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/io.c
90
+++ b/block/io.c
91
@@ -XXX,XX +XXX,XX @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
92
BlockDriver *drv = bs->drv;
93
int ret;
94
IO_CODE();
95
+ assert_bdrv_graph_readable();
96
97
if (!drv) {
98
return -ENOMEDIUM;
99
@@ -XXX,XX +XXX,XX @@ bdrv_co_snapshot_block_status(BlockDriverState *bs,
100
BlockDriver *drv = bs->drv;
101
int ret;
102
IO_CODE();
103
+ assert_bdrv_graph_readable();
104
105
if (!drv) {
106
return -ENOMEDIUM;
107
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/snapshot-access.c
110
+++ b/block/snapshot-access.c
111
@@ -XXX,XX +XXX,XX @@
112
#include "qemu/cutils.h"
113
#include "block/block_int.h"
114
115
-static coroutine_fn int
116
+static int coroutine_fn GRAPH_RDLOCK
117
snapshot_access_co_preadv_part(BlockDriverState *bs,
118
int64_t offset, int64_t bytes,
119
QEMUIOVector *qiov, size_t qiov_offset,
120
@@ -XXX,XX +XXX,XX @@ snapshot_access_co_preadv_part(BlockDriverState *bs,
121
return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset);
122
}
123
124
-static int coroutine_fn
125
+static int coroutine_fn GRAPH_RDLOCK
126
snapshot_access_co_block_status(BlockDriverState *bs,
127
bool want_zero, int64_t offset,
128
int64_t bytes, int64_t *pnum,
46
--
129
--
47
2.13.5
130
2.39.2
48
49
diff view generated by jsdifflib
1
In the context of bdrv_reopen(), we'll have to look at the state of the
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
graph as it will be after the reopen. This interface addition is in
2
bdrv_co_create() need to hold a reader lock for the graph.
3
preparation for the change.
4
3
4
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-Id: <20230203152202.49054-17-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
9
---
8
block.c | 34 +++++++++++++++++++---------------
10
include/block/block-global-state.h | 14 ++++---
9
1 file changed, 19 insertions(+), 15 deletions(-)
11
include/block/block_int-common.h | 11 +++---
12
block.c | 1 +
13
block/create.c | 9 ++++-
14
block/crypto.c | 7 ++--
15
block/file-posix.c | 7 ++--
16
block/file-win32.c | 7 ++--
17
block/parallels.c | 7 ++--
18
block/qcow.c | 6 +--
19
block/qcow2.c | 7 ++--
20
block/qed.c | 7 ++--
21
block/raw-format.c | 7 ++--
22
block/vdi.c | 7 ++--
23
block/vhdx.c | 7 ++--
24
block/vmdk.c | 63 ++++++++++++++----------------
25
block/vpc.c | 7 ++--
26
16 files changed, 84 insertions(+), 90 deletions(-)
10
27
28
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block-global-state.h
31
+++ b/include/block/block-global-state.h
32
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_find_protocol(const char *filename,
33
Error **errp);
34
BlockDriver *bdrv_find_format(const char *format_name);
35
36
-int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
37
- QemuOpts *opts, Error **errp);
38
-int co_wrapper bdrv_create(BlockDriver *drv, const char *filename,
39
- QemuOpts *opts, Error **errp);
40
+int coroutine_fn GRAPH_RDLOCK
41
+bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts,
42
+ Error **errp);
43
44
-int coroutine_fn bdrv_co_create_file(const char *filename, QemuOpts *opts,
45
- Error **errp);
46
+int co_wrapper_bdrv_rdlock bdrv_create(BlockDriver *drv, const char *filename,
47
+ QemuOpts *opts, Error **errp);
48
+
49
+int coroutine_fn GRAPH_RDLOCK
50
+bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp);
51
52
BlockDriverState *bdrv_new(void);
53
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
54
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/block/block_int-common.h
57
+++ b/include/block/block_int-common.h
58
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
59
Error **errp);
60
void (*bdrv_close)(BlockDriverState *bs);
61
62
- int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
63
- Error **errp);
64
- int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv,
65
- const char *filename,
66
- QemuOpts *opts,
67
- Error **errp);
68
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
69
+ BlockdevCreateOptions *opts, Error **errp);
70
+
71
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create_opts)(
72
+ BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
73
74
int (*bdrv_amend_options)(BlockDriverState *bs,
75
QemuOpts *opts,
11
diff --git a/block.c b/block.c
76
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
78
--- a/block.c
14
+++ b/block.c
79
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ static int bdrv_fill_options(QDict **options, const char *filename,
80
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
81
int ret;
82
GLOBAL_STATE_CODE();
83
ERRP_GUARD();
84
+ assert_bdrv_graph_readable();
85
86
if (!drv->bdrv_co_create_opts) {
87
error_setg(errp, "Driver '%s' does not support image creation",
88
diff --git a/block/create.c b/block/create.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/create.c
91
+++ b/block/create.c
92
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
93
int ret;
94
95
GLOBAL_STATE_CODE();
96
+ GRAPH_RDLOCK_GUARD();
97
98
job_progress_set_remaining(&s->common, 1);
99
ret = s->drv->bdrv_co_create(s->opts, errp);
100
@@ -XXX,XX +XXX,XX @@ static const JobDriver blockdev_create_job_driver = {
101
.run = blockdev_create_run,
102
};
103
104
+/* Checking whether the function is present doesn't require the graph lock */
105
+static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv)
106
+{
107
+ return drv->bdrv_co_create;
108
+}
109
+
110
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
111
Error **errp)
112
{
113
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
114
}
115
116
/* Error out if the driver doesn't support .bdrv_co_create */
117
- if (!drv->bdrv_co_create) {
118
+ if (!has_bdrv_co_create(drv)) {
119
error_setg(errp, "Driver does not support blockdev-create");
120
return;
121
}
122
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
125
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ fail:
127
return ret;
128
}
129
130
-static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv,
131
- const char *filename,
132
- QemuOpts *opts,
133
- Error **errp)
134
+static int coroutine_fn GRAPH_RDLOCK
135
+block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
136
+ QemuOpts *opts, Error **errp)
137
{
138
QCryptoBlockCreateOptions *create_opts = NULL;
139
BlockDriverState *bs = NULL;
140
diff --git a/block/file-posix.c b/block/file-posix.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/file-posix.c
143
+++ b/block/file-posix.c
144
@@ -XXX,XX +XXX,XX @@ out:
145
return result;
146
}
147
148
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
149
- const char *filename,
150
- QemuOpts *opts,
151
- Error **errp)
152
+static int coroutine_fn GRAPH_RDLOCK
153
+raw_co_create_opts(BlockDriver *drv, const char *filename,
154
+ QemuOpts *opts, Error **errp)
155
{
156
BlockdevCreateOptions options;
157
int64_t total_size = 0;
158
diff --git a/block/file-win32.c b/block/file-win32.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/file-win32.c
161
+++ b/block/file-win32.c
162
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
16
return 0;
163
return 0;
17
}
164
}
18
165
19
-static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
166
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
20
+static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
167
- const char *filename,
21
+ uint64_t perm, uint64_t shared,
168
- QemuOpts *opts,
22
GSList *ignore_children, Error **errp);
169
- Error **errp)
23
static void bdrv_child_abort_perm_update(BdrvChild *c);
170
+static int coroutine_fn GRAPH_RDLOCK
24
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
171
+raw_co_create_opts(BlockDriver *drv, const char *filename,
25
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
172
+ QemuOpts *opts, Error **errp)
26
* A call to this function must always be followed by a call to bdrv_set_perm()
173
{
27
* or bdrv_abort_perm_update().
174
BlockdevCreateOptions options;
175
int64_t total_size = 0;
176
diff --git a/block/parallels.c b/block/parallels.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/block/parallels.c
179
+++ b/block/parallels.c
180
@@ -XXX,XX +XXX,XX @@ exit:
181
goto out;
182
}
183
184
-static int coroutine_fn parallels_co_create_opts(BlockDriver *drv,
185
- const char *filename,
186
- QemuOpts *opts,
187
- Error **errp)
188
+static int coroutine_fn GRAPH_RDLOCK
189
+parallels_co_create_opts(BlockDriver *drv, const char *filename,
190
+ QemuOpts *opts, Error **errp)
191
{
192
BlockdevCreateOptions *create_options = NULL;
193
BlockDriverState *bs = NULL;
194
diff --git a/block/qcow.c b/block/qcow.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/block/qcow.c
197
+++ b/block/qcow.c
198
@@ -XXX,XX +XXX,XX @@ exit:
199
return ret;
200
}
201
202
-static int coroutine_fn qcow_co_create_opts(BlockDriver *drv,
203
- const char *filename,
204
- QemuOpts *opts, Error **errp)
205
+static int coroutine_fn GRAPH_RDLOCK
206
+qcow_co_create_opts(BlockDriver *drv, const char *filename,
207
+ QemuOpts *opts, Error **errp)
208
{
209
BlockdevCreateOptions *create_options = NULL;
210
BlockDriverState *bs = NULL;
211
diff --git a/block/qcow2.c b/block/qcow2.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/block/qcow2.c
214
+++ b/block/qcow2.c
215
@@ -XXX,XX +XXX,XX @@ out:
216
return ret;
217
}
218
219
-static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
220
- const char *filename,
221
- QemuOpts *opts,
222
- Error **errp)
223
+static int coroutine_fn GRAPH_RDLOCK
224
+qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
225
+ Error **errp)
226
{
227
BlockdevCreateOptions *create_options = NULL;
228
QDict *qdict;
229
diff --git a/block/qed.c b/block/qed.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/block/qed.c
232
+++ b/block/qed.c
233
@@ -XXX,XX +XXX,XX @@ out:
234
return ret;
235
}
236
237
-static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
238
- const char *filename,
239
- QemuOpts *opts,
240
- Error **errp)
241
+static int coroutine_fn GRAPH_RDLOCK
242
+bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
243
+ QemuOpts *opts, Error **errp)
244
{
245
BlockdevCreateOptions *create_options = NULL;
246
QDict *qdict;
247
diff --git a/block/raw-format.c b/block/raw-format.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/block/raw-format.c
250
+++ b/block/raw-format.c
251
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
252
return bdrv_has_zero_init(bs->file->bs);
253
}
254
255
-static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
256
- const char *filename,
257
- QemuOpts *opts,
258
- Error **errp)
259
+static int coroutine_fn GRAPH_RDLOCK
260
+raw_co_create_opts(BlockDriver *drv, const char *filename,
261
+ QemuOpts *opts, Error **errp)
262
{
263
return bdrv_co_create_file(filename, opts, errp);
264
}
265
diff --git a/block/vdi.c b/block/vdi.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/vdi.c
268
+++ b/block/vdi.c
269
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options,
270
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
271
}
272
273
-static int coroutine_fn vdi_co_create_opts(BlockDriver *drv,
274
- const char *filename,
275
- QemuOpts *opts,
276
- Error **errp)
277
+static int coroutine_fn GRAPH_RDLOCK
278
+vdi_co_create_opts(BlockDriver *drv, const char *filename,
279
+ QemuOpts *opts, Error **errp)
280
{
281
QDict *qdict = NULL;
282
BlockdevCreateOptions *create_options = NULL;
283
diff --git a/block/vhdx.c b/block/vhdx.c
284
index XXXXXXX..XXXXXXX 100644
285
--- a/block/vhdx.c
286
+++ b/block/vhdx.c
287
@@ -XXX,XX +XXX,XX @@ delete_and_exit:
288
return ret;
289
}
290
291
-static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv,
292
- const char *filename,
293
- QemuOpts *opts,
294
- Error **errp)
295
+static int coroutine_fn GRAPH_RDLOCK
296
+vhdx_co_create_opts(BlockDriver *drv, const char *filename,
297
+ QemuOpts *opts, Error **errp)
298
{
299
BlockdevCreateOptions *create_options = NULL;
300
QDict *qdict;
301
diff --git a/block/vmdk.c b/block/vmdk.c
302
index XXXXXXX..XXXXXXX 100644
303
--- a/block/vmdk.c
304
+++ b/block/vmdk.c
305
@@ -XXX,XX +XXX,XX @@ exit:
306
return ret;
307
}
308
309
-static int coroutine_fn vmdk_create_extent(const char *filename,
310
- int64_t filesize, bool flat,
311
- bool compress, bool zeroed_grain,
312
- BlockBackend **pbb,
313
- QemuOpts *opts, Error **errp)
314
+static int coroutine_fn GRAPH_RDLOCK
315
+vmdk_create_extent(const char *filename, int64_t filesize, bool flat,
316
+ bool compress, bool zeroed_grain, BlockBackend **pbb,
317
+ QemuOpts *opts, Error **errp)
318
{
319
int ret;
320
BlockBackend *blk = NULL;
321
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
322
* non-split format.
323
* idx >= 1: get the n-th extent if in a split subformat
28
*/
324
*/
29
-static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms,
325
-typedef BlockBackend * coroutine_fn (*vmdk_create_extent_fn)(int64_t size,
30
+static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
326
- int idx,
31
+ uint64_t cumulative_perms,
327
- bool flat,
32
uint64_t cumulative_shared_perms,
328
- bool split,
33
GSList *ignore_children, Error **errp)
329
- bool compress,
34
{
330
- bool zeroed_grain,
35
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, uint64_t cumulative_perms,
331
- void *opaque,
36
/* Check all children */
332
- Error **errp);
37
QLIST_FOREACH(c, &bs->children, next) {
333
+typedef BlockBackend * coroutine_fn /* GRAPH_RDLOCK */
38
uint64_t cur_perm, cur_shared;
334
+ (*vmdk_create_extent_fn)(int64_t size, int idx, bool flat, bool split,
39
- bdrv_child_perm(bs, c->bs, c, c->role, NULL,
335
+ bool compress, bool zeroed_grain, void *opaque,
40
+ bdrv_child_perm(bs, c->bs, c, c->role, q,
336
+ Error **errp);
41
cumulative_perms, cumulative_shared_perms,
337
42
&cur_perm, &cur_shared);
338
static void vmdk_desc_add_extent(GString *desc,
43
- ret = bdrv_child_check_perm(c, cur_perm, cur_shared, ignore_children,
339
const char *extent_line_fmt,
44
- errp);
340
@@ -XXX,XX +XXX,XX @@ static void vmdk_desc_add_extent(GString *desc,
45
+ ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared,
341
g_free(basename);
46
+ ignore_children, errp);
342
}
47
if (ret < 0) {
343
48
return ret;
344
-static int coroutine_fn vmdk_co_do_create(int64_t size,
49
}
345
- BlockdevVmdkSubformat subformat,
50
@@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm)
346
- BlockdevVmdkAdapterType adapter_type,
51
*
347
- const char *backing_file,
52
* Needs to be followed by a call to either bdrv_set_perm() or
348
- const char *hw_version,
53
* bdrv_abort_perm_update(). */
349
- const char *toolsversion,
54
-static int bdrv_check_update_perm(BlockDriverState *bs, uint64_t new_used_perm,
350
- bool compat6,
55
+static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
351
- bool zeroed_grain,
56
+ uint64_t new_used_perm,
352
- vmdk_create_extent_fn extent_fn,
57
uint64_t new_shared_perm,
353
- void *opaque,
58
GSList *ignore_children, Error **errp)
354
- Error **errp)
59
{
355
+static int coroutine_fn GRAPH_RDLOCK
60
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_update_perm(BlockDriverState *bs, uint64_t new_used_perm,
356
+vmdk_co_do_create(int64_t size,
61
cumulative_shared_perms &= c->shared_perm;
357
+ BlockdevVmdkSubformat subformat,
62
}
358
+ BlockdevVmdkAdapterType adapter_type,
63
359
+ const char *backing_file,
64
- return bdrv_check_perm(bs, cumulative_perms, cumulative_shared_perms,
360
+ const char *hw_version,
65
+ return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms,
361
+ const char *toolsversion,
66
ignore_children, errp);
362
+ bool compat6,
67
}
363
+ bool zeroed_grain,
68
364
+ vmdk_create_extent_fn extent_fn,
69
/* Needs to be followed by a call to either bdrv_child_set_perm() or
365
+ void *opaque,
70
* bdrv_child_abort_perm_update(). */
366
+ Error **errp)
71
-static int bdrv_child_check_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
367
{
72
+static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
368
int extent_idx;
73
+ uint64_t perm, uint64_t shared,
369
BlockBackend *blk = NULL;
74
GSList *ignore_children, Error **errp)
370
@@ -XXX,XX +XXX,XX @@ typedef struct {
75
{
371
QemuOpts *opts;
76
int ret;
372
} VMDKCreateOptsData;
77
373
78
ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c);
374
-static BlockBackend * coroutine_fn vmdk_co_create_opts_cb(int64_t size, int idx,
79
- ret = bdrv_check_update_perm(c->bs, perm, shared, ignore_children, errp);
375
- bool flat, bool split, bool compress,
80
+ ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
376
- bool zeroed_grain, void *opaque,
81
g_slist_free(ignore_children);
377
- Error **errp)
82
378
+static BlockBackend * coroutine_fn GRAPH_RDLOCK
83
return ret;
379
+vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
84
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
380
+ bool compress, bool zeroed_grain, void *opaque,
85
{
381
+ Error **errp)
86
int ret;
382
{
87
383
BlockBackend *blk = NULL;
88
- ret = bdrv_child_check_perm(c, perm, shared, NULL, errp);
384
BlockDriverState *bs = NULL;
89
+ ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, errp);
385
@@ -XXX,XX +XXX,XX @@ exit:
90
if (ret < 0) {
386
return blk;
91
bdrv_child_abort_perm_update(c);
387
}
92
return ret;
388
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
389
-static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
94
* because we're just taking a parent away, so we're loosening
390
- const char *filename,
95
* restrictions. */
391
- QemuOpts *opts,
96
bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
392
- Error **errp)
97
- bdrv_check_perm(old_bs, perm, shared_perm, NULL, &error_abort);
393
+static int coroutine_fn GRAPH_RDLOCK
98
+ bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort);
394
+vmdk_co_create_opts(BlockDriver *drv, const char *filename,
99
bdrv_set_perm(old_bs, perm, shared_perm);
395
+ QemuOpts *opts, Error **errp)
100
}
396
{
101
397
Error *local_err = NULL;
102
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
398
char *desc = NULL;
103
BdrvChild *child;
399
@@ -XXX,XX +XXX,XX @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
104
int ret;
400
return blk;
105
401
}
106
- ret = bdrv_check_update_perm(child_bs, perm, shared_perm, NULL, errp);
402
107
+ ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
403
-static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
108
if (ret < 0) {
404
- Error **errp)
109
bdrv_abort_perm_update(child_bs);
405
+static int coroutine_fn GRAPH_RDLOCK
110
return NULL;
406
+vmdk_co_create(BlockdevCreateOptions *create_options, Error **errp)
111
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
407
{
112
408
BlockdevCreateOptionsVmdk *opts;
113
/* Check whether the required permissions can be granted on @to, ignoring
409
114
* all BdrvChild in @list so that they can't block themselves. */
410
diff --git a/block/vpc.c b/block/vpc.c
115
- ret = bdrv_check_update_perm(to, perm, shared, list, errp);
411
index XXXXXXX..XXXXXXX 100644
116
+ ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp);
412
--- a/block/vpc.c
117
if (ret < 0) {
413
+++ b/block/vpc.c
118
bdrv_abort_perm_update(to);
414
@@ -XXX,XX +XXX,XX @@ out:
119
goto out;
415
return ret;
120
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
416
}
121
417
122
/* Update permissions, they may differ for inactive nodes */
418
-static int coroutine_fn vpc_co_create_opts(BlockDriver *drv,
123
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
419
- const char *filename,
124
- ret = bdrv_check_perm(bs, perm, shared_perm, NULL, &local_err);
420
- QemuOpts *opts,
125
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &local_err);
421
- Error **errp)
126
if (ret < 0) {
422
+static int coroutine_fn GRAPH_RDLOCK
127
bs->open_flags |= BDRV_O_INACTIVE;
423
+vpc_co_create_opts(BlockDriver *drv, const char *filename,
128
error_propagate(errp, local_err);
424
+ QemuOpts *opts, Error **errp)
129
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
425
{
130
426
BlockdevCreateOptions *create_options = NULL;
131
/* Update permissions, they may differ for inactive nodes */
427
QDict *qdict;
132
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
133
- bdrv_check_perm(bs, perm, shared_perm, NULL, &error_abort);
134
+ bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort);
135
bdrv_set_perm(bs, perm, shared_perm);
136
}
137
138
--
428
--
139
2.13.5
429
2.39.2
140
141
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_io_plug() and bdrv_co_io_unplug() need to hold a reader lock for
3
the graph.
2
4
3
Migration capabilities should be enabled on both source and
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
destination qemu processes.
6
Message-Id: <20230203152202.49054-18-kwolf@redhat.com>
5
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
---
9
tests/qemu-iotests/181 | 2 ++
10
include/block/block-io.h | 4 ++--
10
tests/qemu-iotests/181.out | 1 -
11
include/block/block_int-common.h | 5 +++--
11
2 files changed, 2 insertions(+), 1 deletion(-)
12
block/block-backend.c | 2 ++
13
block/io.c | 2 ++
14
4 files changed, 9 insertions(+), 4 deletions(-)
12
15
13
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/181
16
+++ b/tests/qemu-iotests/181
17
@@ -XXX,XX +XXX,XX @@ echo
18
19
# Slow down migration so much that it definitely won't finish before we can
20
# switch to postcopy
21
+# Enable postcopy-ram capability both on source and destination
22
silent=yes
23
+_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)"
24
_send_qemu_cmd $src 'migrate_set_speed 4k' "(qemu)"
25
_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
26
_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
27
diff --git a/tests/qemu-iotests/181.out b/tests/qemu-iotests/181.out
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/181.out
18
--- a/include/block/block-io.h
30
+++ b/tests/qemu-iotests/181.out
19
+++ b/include/block/block-io.h
31
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
20
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
32
21
33
=== Do some I/O on the destination ===
22
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
34
23
35
-QEMU X.Y.Z monitor - type 'help' for more information
24
-void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs);
36
(qemu) qemu-io disk "read -P 0x55 0 64k"
25
-void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs);
37
read 65536/65536 bytes at offset 0
26
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
38
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
27
+void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
28
29
bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
30
const char *name,
31
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/block/block_int-common.h
34
+++ b/include/block/block_int-common.h
35
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
BlkdebugEvent event);
37
38
/* io queue for linux-aio */
39
- void coroutine_fn (*bdrv_co_io_plug)(BlockDriverState *bs);
40
- void coroutine_fn (*bdrv_co_io_unplug)(BlockDriverState *bs);
41
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs);
42
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_unplug)(
43
+ BlockDriverState *bs);
44
45
/**
46
* bdrv_drain_begin is called if implemented in the beginning of a
47
diff --git a/block/block-backend.c b/block/block-backend.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/block-backend.c
50
+++ b/block/block-backend.c
51
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
52
{
53
BlockDriverState *bs = blk_bs(blk);
54
IO_CODE();
55
+ GRAPH_RDLOCK_GUARD();
56
57
if (bs) {
58
bdrv_co_io_plug(bs);
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
60
{
61
BlockDriverState *bs = blk_bs(blk);
62
IO_CODE();
63
+ GRAPH_RDLOCK_GUARD();
64
65
if (bs) {
66
bdrv_co_io_unplug(bs);
67
diff --git a/block/io.c b/block/io.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/block/io.c
70
+++ b/block/io.c
71
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
72
{
73
BdrvChild *child;
74
IO_CODE();
75
+ assert_bdrv_graph_readable();
76
77
QLIST_FOREACH(child, &bs->children, next) {
78
bdrv_co_io_plug(child->bs);
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
80
{
81
BdrvChild *child;
82
IO_CODE();
83
+ assert_bdrv_graph_readable();
84
85
assert(bs->io_plugged);
86
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
39
--
87
--
40
2.13.5
88
2.39.2
41
42
diff view generated by jsdifflib
1
If we switch between read-only and read-write, the permissions that
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
image format drivers need on bs->file change, too. Make sure to update
3
the permissions during bdrv_reopen().
4
2
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
bdrv_co_is_inserted() need to hold a reader lock for the graph.
5
6
blk_is_inserted() is done as a co_wrapper_mixed_bdrv_rdlock (unlike most
7
other blk_* functions) because it is called a lot from other blk_co_*()
8
functions that already hold the lock. These calls go through
9
blk_is_available(), which becomes a co_wrapper_mixed_bdrv_rdlock, too,
10
for the same reason.
11
12
Functions that run in a coroutine and can call bdrv_co_is_available()
13
directly are changed to do so, which results in better TSA coverage.
14
15
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Message-Id: <20230203152202.49054-19-kwolf@redhat.com>
18
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
20
---
8
include/block/block.h | 1 +
21
include/block/block-io.h | 4 ++--
9
block.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++
22
include/block/block_int-common.h | 3 ++-
10
2 files changed, 65 insertions(+)
23
include/sysemu/block-backend-io.h | 7 ++++---
24
block.c | 1 +
25
block/block-backend.c | 25 ++++++++++++++-----------
26
5 files changed, 23 insertions(+), 17 deletions(-)
11
27
12
diff --git a/include/block/block.h b/include/block/block.h
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
13
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block.h
30
--- a/include/block/block-io.h
15
+++ b/include/block/block.h
31
+++ b/include/block/block-io.h
16
@@ -XXX,XX +XXX,XX @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
32
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs);
17
typedef struct BDRVReopenState {
33
bool bdrv_is_sg(BlockDriverState *bs);
18
BlockDriverState *bs;
34
int bdrv_get_flags(BlockDriverState *bs);
19
int flags;
35
20
+ uint64_t perm, shared_perm;
36
-bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs);
21
QDict *options;
37
-bool co_wrapper bdrv_is_inserted(BlockDriverState *bs);
22
QDict *explicit_options;
38
+bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
23
void *opaque;
39
+bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
40
41
void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
42
void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
49
50
/* removable device specific */
51
- bool coroutine_fn (*bdrv_co_is_inserted)(BlockDriverState *bs);
52
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
53
+ BlockDriverState *bs);
54
void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
55
void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
56
57
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/sysemu/block-backend-io.h
60
+++ b/include/sysemu/block-backend-io.h
61
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
62
void blk_inc_in_flight(BlockBackend *blk);
63
void blk_dec_in_flight(BlockBackend *blk);
64
65
-bool coroutine_fn blk_co_is_inserted(BlockBackend *blk);
66
-bool co_wrapper_mixed blk_is_inserted(BlockBackend *blk);
67
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_inserted(BlockBackend *blk);
68
+bool co_wrapper_mixed_bdrv_rdlock blk_is_inserted(BlockBackend *blk);
69
70
-bool blk_is_available(BlockBackend *blk);
71
+bool coroutine_fn GRAPH_RDLOCK blk_co_is_available(BlockBackend *blk);
72
+bool co_wrapper_mixed_bdrv_rdlock blk_is_available(BlockBackend *blk);
73
74
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked);
75
void co_wrapper blk_lock_medium(BlockBackend *blk, bool locked);
24
diff --git a/block.c b/block.c
76
diff --git a/block.c b/block.c
25
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
78
--- a/block.c
27
+++ b/block.c
79
+++ b/block.c
28
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
80
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
29
bs_entry->state.explicit_options = explicit_options;
81
BlockDriver *drv = bs->drv;
30
bs_entry->state.flags = flags;
82
BdrvChild *child;
31
83
IO_CODE();
32
+ /* This needs to be overwritten in bdrv_reopen_prepare() */
84
+ assert_bdrv_graph_readable();
33
+ bs_entry->state.perm = UINT64_MAX;
85
34
+ bs_entry->state.shared_perm = 0;
86
if (!drv) {
35
+
87
return false;
36
QLIST_FOREACH(child, &bs->children, next) {
88
diff --git a/block/block-backend.c b/block/block-backend.c
37
QDict *new_child_options;
89
index XXXXXXX..XXXXXXX 100644
38
char *child_key_dot;
90
--- a/block/block-backend.c
39
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
91
+++ b/block/block-backend.c
40
return ret;
92
@@ -XXX,XX +XXX,XX @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
93
blk->disable_request_queuing = disable;
41
}
94
}
42
95
43
+static BlockReopenQueueEntry *find_parent_in_reopen_queue(BlockReopenQueue *q,
96
-static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
44
+ BdrvChild *c)
97
- int64_t offset, int64_t bytes)
45
+{
98
+static int coroutine_fn GRAPH_RDLOCK
46
+ BlockReopenQueueEntry *entry;
99
+blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
47
+
100
{
48
+ QSIMPLEQ_FOREACH(entry, q, entry) {
101
int64_t len;
49
+ BlockDriverState *bs = entry->state.bs;
102
50
+ BdrvChild *child;
103
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
51
+
104
return -EIO;
52
+ QLIST_FOREACH(child, &bs->children, next) {
53
+ if (child == c) {
54
+ return entry;
55
+ }
56
+ }
57
+ }
58
+
59
+ return NULL;
60
+}
61
+
62
+static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
63
+ uint64_t *perm, uint64_t *shared)
64
+{
65
+ BdrvChild *c;
66
+ BlockReopenQueueEntry *parent;
67
+ uint64_t cumulative_perms = 0;
68
+ uint64_t cumulative_shared_perms = BLK_PERM_ALL;
69
+
70
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
71
+ parent = find_parent_in_reopen_queue(q, c);
72
+ if (!parent) {
73
+ cumulative_perms |= c->perm;
74
+ cumulative_shared_perms &= c->shared_perm;
75
+ } else {
76
+ uint64_t nperm, nshared;
77
+
78
+ bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
79
+ parent->state.perm, parent->state.shared_perm,
80
+ &nperm, &nshared);
81
+
82
+ cumulative_perms |= nperm;
83
+ cumulative_shared_perms &= nshared;
84
+ }
85
+ }
86
+ *perm = cumulative_perms;
87
+ *shared = cumulative_shared_perms;
88
+}
89
90
/*
91
* Prepares a BlockDriverState for reopen. All changes are staged in the
92
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
93
goto error;
94
}
105
}
95
106
96
+ /* Calculate required permissions after reopening */
107
- if (!blk_is_available(blk)) {
97
+ bdrv_reopen_perm(queue, reopen_state->bs,
108
+ if (!blk_co_is_available(blk)) {
98
+ &reopen_state->perm, &reopen_state->shared_perm);
109
return -ENOMEDIUM;
99
100
ret = bdrv_flush(reopen_state->bs);
101
if (ret) {
102
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
103
} while ((entry = qdict_next(reopen_state->options, entry)));
104
}
110
}
105
111
106
+ ret = bdrv_check_perm(reopen_state->bs, queue, reopen_state->perm,
112
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
107
+ reopen_state->shared_perm, NULL, errp);
113
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
108
+ if (ret < 0) {
114
{
109
+ goto error;
115
IO_CODE();
110
+ }
116
+ GRAPH_RDLOCK_GUARD();
111
+
117
112
ret = 0;
118
- if (!blk_is_available(blk)) {
113
119
+ if (!blk_co_is_available(blk)) {
114
error:
120
return -ENOMEDIUM;
115
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
116
117
bdrv_refresh_limits(bs, NULL);
118
119
+ bdrv_set_perm(reopen_state->bs, reopen_state->perm,
120
+ reopen_state->shared_perm);
121
+
122
new_can_write =
123
!bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
124
if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
125
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
126
}
121
}
127
122
128
QDECREF(reopen_state->explicit_options);
123
@@ -XXX,XX +XXX,XX @@ void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
129
+
124
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
130
+ bdrv_abort_perm_update(reopen_state->bs);
125
{
126
IO_CODE();
127
+ GRAPH_RDLOCK_GUARD();
128
129
- if (!blk_is_available(blk)) {
130
+ if (!blk_co_is_available(blk)) {
131
return -ENOMEDIUM;
132
}
133
134
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
135
blk_wait_while_drained(blk);
136
GRAPH_RDLOCK_GUARD();
137
138
- if (!blk_is_available(blk)) {
139
+ if (!blk_co_is_available(blk)) {
140
return -ENOMEDIUM;
141
}
142
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
144
blk_wait_while_drained(blk);
145
GRAPH_RDLOCK_GUARD();
146
147
- if (!blk_is_available(blk)) {
148
+ if (!blk_co_is_available(blk)) {
149
return -ENOMEDIUM;
150
}
151
152
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
153
{
154
BlockDriverState *bs = blk_bs(blk);
155
IO_CODE();
156
+ assert_bdrv_graph_readable();
157
158
return bs && bdrv_co_is_inserted(bs);
131
}
159
}
132
160
133
161
-bool blk_is_available(BlockBackend *blk)
162
+bool coroutine_fn blk_co_is_available(BlockBackend *blk)
163
{
164
IO_CODE();
165
- return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
166
+ return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk);
167
}
168
169
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
170
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
171
{
172
IO_OR_GS_CODE();
173
GRAPH_RDLOCK_GUARD();
174
- if (!blk_is_available(blk)) {
175
+ if (!blk_co_is_available(blk)) {
176
error_setg(errp, "No medium inserted");
177
return -ENOMEDIUM;
178
}
179
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
180
{
181
int r;
182
IO_CODE();
183
+ GRAPH_RDLOCK_GUARD();
184
185
r = blk_check_byte_request(blk_in, off_in, bytes);
186
if (r) {
187
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
188
return r;
189
}
190
191
- GRAPH_RDLOCK_GUARD();
192
return bdrv_co_copy_range(blk_in->root, off_in,
193
blk_out->root, off_out,
194
bytes, read_flags, write_flags);
134
--
195
--
135
2.13.5
196
2.39.2
136
137
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_eject() and bdrv_co_lock_medium() need to hold a reader lock for
3
the graph.
2
4
3
The default cpu model on s390x does not provide zPCI, which is
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
not yet wired up on tcg. Moreover, virtio-ccw is the standard
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
on s390x.
7
Message-Id: <20230203152202.49054-20-kwolf@redhat.com>
6
8
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Using virtio-scsi will implicitly pick the right device, so just
8
switch to that for simplicity.
9
10
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
11
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
12
Reviewed-by: David Hildenbrand <david@redhat.com>
13
Reviewed-by: Thomas Huth <thuth@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
10
---
16
tests/qemu-iotests/067 | 2 +-
11
include/block/block-io.h | 7 +++++--
17
tests/qemu-iotests/067.out | 2 +-
12
include/block/block_int-common.h | 6 ++++--
18
2 files changed, 2 insertions(+), 2 deletions(-)
13
block.c | 2 ++
14
block/block-backend.c | 2 ++
15
block/copy-on-read.c | 6 ++++--
16
block/filter-compress.c | 4 ++--
17
block/raw-format.c | 6 ++++--
18
7 files changed, 23 insertions(+), 10 deletions(-)
19
19
20
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
20
diff --git a/include/block/block-io.h b/include/block/block-io.h
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/067
23
+++ b/tests/qemu-iotests/067
24
@@ -XXX,XX +XXX,XX @@ echo
25
echo === Empty drive with -device and device_del ===
26
echo
27
28
-run_qemu -device virtio-scsi-pci -device scsi-cd,id=cd0 <<EOF
29
+run_qemu -device virtio-scsi -device scsi-cd,id=cd0 <<EOF
30
{ "execute": "qmp_capabilities" }
31
{ "execute": "query-block" }
32
{ "execute": "device_del", "arguments": { "id": "cd0" } }
33
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
34
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
35
--- a/tests/qemu-iotests/067.out
22
--- a/include/block/block-io.h
36
+++ b/tests/qemu-iotests/067.out
23
+++ b/include/block/block-io.h
37
@@ -XXX,XX +XXX,XX @@ Testing:
24
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
38
25
bool coroutine_fn GRAPH_RDLOCK bdrv_co_is_inserted(BlockDriverState *bs);
39
=== Empty drive with -device and device_del ===
26
bool co_wrapper_bdrv_rdlock bdrv_is_inserted(BlockDriverState *bs);
40
27
41
-Testing: -device virtio-scsi-pci -device scsi-cd,id=cd0
28
-void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
42
+Testing: -device virtio-scsi -device scsi-cd,id=cd0
29
-void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
30
+void coroutine_fn GRAPH_RDLOCK
31
+bdrv_co_lock_medium(BlockDriverState *bs, bool locked);
32
+
33
+void coroutine_fn GRAPH_RDLOCK
34
+bdrv_co_eject(BlockDriverState *bs, bool eject_flag);
35
36
const char *bdrv_get_format_name(BlockDriverState *bs);
37
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block_int-common.h
41
+++ b/include/block/block_int-common.h
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
43
/* removable device specific */
44
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
45
BlockDriverState *bs);
46
- void coroutine_fn (*bdrv_co_eject)(BlockDriverState *bs, bool eject_flag);
47
- void coroutine_fn (*bdrv_co_lock_medium)(BlockDriverState *bs, bool locked);
48
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_eject)(
49
+ BlockDriverState *bs, bool eject_flag);
50
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_lock_medium)(
51
+ BlockDriverState *bs, bool locked);
52
53
/* to control generic scsi devices */
54
BlockAIOCB *coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_aio_ioctl)(
55
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
58
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
43
{
60
{
44
QMP_VERSION
61
BlockDriver *drv = bs->drv;
62
IO_CODE();
63
+ assert_bdrv_graph_readable();
64
65
if (drv && drv->bdrv_co_eject) {
66
drv->bdrv_co_eject(bs, eject_flag);
67
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
68
{
69
BlockDriver *drv = bs->drv;
70
IO_CODE();
71
+ assert_bdrv_graph_readable();
72
trace_bdrv_lock_medium(bs, locked);
73
74
if (drv && drv->bdrv_co_lock_medium) {
75
diff --git a/block/block-backend.c b/block/block-backend.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/block-backend.c
78
+++ b/block/block-backend.c
79
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
80
{
81
BlockDriverState *bs = blk_bs(blk);
82
IO_CODE();
83
+ GRAPH_RDLOCK_GUARD();
84
85
if (bs) {
86
bdrv_co_lock_medium(bs, locked);
87
@@ -XXX,XX +XXX,XX @@ void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
88
BlockDriverState *bs = blk_bs(blk);
89
char *id;
90
IO_CODE();
91
+ GRAPH_RDLOCK_GUARD();
92
93
if (bs) {
94
bdrv_co_eject(bs, eject_flag);
95
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/block/copy-on-read.c
98
+++ b/block/copy-on-read.c
99
@@ -XXX,XX +XXX,XX @@ cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
100
}
101
102
103
-static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
104
+static void coroutine_fn GRAPH_RDLOCK
105
+cor_co_eject(BlockDriverState *bs, bool eject_flag)
106
{
107
bdrv_co_eject(bs->file->bs, eject_flag);
108
}
109
110
111
-static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
112
+static void coroutine_fn GRAPH_RDLOCK
113
+cor_co_lock_medium(BlockDriverState *bs, bool locked)
114
{
115
bdrv_co_lock_medium(bs->file->bs, locked);
116
}
117
diff --git a/block/filter-compress.c b/block/filter-compress.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/filter-compress.c
120
+++ b/block/filter-compress.c
121
@@ -XXX,XX +XXX,XX @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
122
}
123
124
125
-static void coroutine_fn
126
+static void coroutine_fn GRAPH_RDLOCK
127
compress_co_eject(BlockDriverState *bs, bool eject_flag)
128
{
129
bdrv_co_eject(bs->file->bs, eject_flag);
130
}
131
132
133
-static void coroutine_fn
134
+static void coroutine_fn GRAPH_RDLOCK
135
compress_co_lock_medium(BlockDriverState *bs, bool locked)
136
{
137
bdrv_co_lock_medium(bs->file->bs, locked);
138
diff --git a/block/raw-format.c b/block/raw-format.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/raw-format.c
141
+++ b/block/raw-format.c
142
@@ -XXX,XX +XXX,XX @@ raw_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
143
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
144
}
145
146
-static void coroutine_fn raw_co_eject(BlockDriverState *bs, bool eject_flag)
147
+static void coroutine_fn GRAPH_RDLOCK
148
+raw_co_eject(BlockDriverState *bs, bool eject_flag)
149
{
150
bdrv_co_eject(bs->file->bs, eject_flag);
151
}
152
153
-static void coroutine_fn raw_co_lock_medium(BlockDriverState *bs, bool locked)
154
+static void coroutine_fn GRAPH_RDLOCK
155
+raw_co_lock_medium(BlockDriverState *bs, bool locked)
156
{
157
bdrv_co_lock_medium(bs->file->bs, locked);
45
}
158
}
46
--
159
--
47
2.13.5
160
2.39.2
48
49
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_register_buf() and bdrv_unregister_buf() need to hold a reader lock
3
for the graph.
2
4
3
Remove the unnecessary home-grown redefinition of the assert() macro here,
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
and remove the unusable debug code at the end of the checkpoint() function.
6
Message-Id: <20230203152202.49054-21-kwolf@redhat.com>
5
The code there uses assert() with side-effects (assignment to the "mapping"
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
variable), which should be avoided. Looking more closely, it seems as it is
7
apparently also only usable for one certain directory layout (with a file
8
named USB.H in it) and thus is of no use for the rest of the world.
9
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
9
---
15
block/vvfat.c | 26 ++------------------------
10
include/block/block_int-common.h | 7 ++++---
16
1 file changed, 2 insertions(+), 24 deletions(-)
11
block/io.c | 14 ++++++++++----
12
2 files changed, 14 insertions(+), 7 deletions(-)
17
13
18
diff --git a/block/vvfat.c b/block/vvfat.c
14
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vvfat.c
16
--- a/include/block/block_int-common.h
21
+++ b/block/vvfat.c
17
+++ b/include/block/block_int-common.h
22
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
23
19
*
24
static void checkpoint(void);
20
* Returns: true on success, false on failure
25
21
*/
26
-#ifdef __MINGW32__
22
- bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size,
27
-void nonono(const char* file, int line, const char* msg) {
23
- Error **errp);
28
- fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);
24
- void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size);
29
- exit(-5);
25
+ bool GRAPH_RDLOCK_PTR (*bdrv_register_buf)(
30
-}
26
+ BlockDriverState *bs, void *host, size_t size, Error **errp);
31
-#undef assert
27
+ void GRAPH_RDLOCK_PTR (*bdrv_unregister_buf)(
32
-#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
28
+ BlockDriverState *bs, void *host, size_t size);
33
-#endif
29
34
-
30
/*
35
#else
31
* This field is modified only under the BQL, and is part of
36
32
diff --git a/block/io.c b/block/io.c
37
#define DLOG(a)
33
index XXXXXXX..XXXXXXX 100644
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_vvfat_init(void)
34
--- a/block/io.c
39
block_init(bdrv_vvfat_init);
35
+++ b/block/io.c
40
36
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
41
#ifdef DEBUG
42
-static void checkpoint(void) {
43
+static void checkpoint(void)
44
+{
45
assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);
46
check1(vvv);
47
check2(vvv);
48
assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
49
-#if 0
50
- if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
51
- fprintf(stderr, "Nonono!\n");
52
- mapping_t* mapping;
53
- direntry_t* direntry;
54
- assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
55
- assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
56
- if (vvv->mapping.next<47)
57
- return;
58
- assert((mapping = array_get(&(vvv->mapping), 47)));
59
- assert(mapping->dir_index < vvv->directory.next);
60
- direntry = array_get(&(vvv->directory), mapping->dir_index);
61
- assert(!memcmp(direntry->name, "USB H ", 11) || direntry->name[0]==0);
62
-#endif
63
}
37
}
64
#endif
38
39
/* Helper that undoes bdrv_register_buf() when it fails partway through */
40
-static void bdrv_register_buf_rollback(BlockDriverState *bs,
41
- void *host,
42
- size_t size,
43
- BdrvChild *final_child)
44
+static void GRAPH_RDLOCK
45
+bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size,
46
+ BdrvChild *final_child)
47
{
48
BdrvChild *child;
49
50
+ GLOBAL_STATE_CODE();
51
+ assert_bdrv_graph_readable();
52
+
53
QLIST_FOREACH(child, &bs->children, next) {
54
if (child == final_child) {
55
break;
56
@@ -XXX,XX +XXX,XX @@ bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
57
BdrvChild *child;
58
59
GLOBAL_STATE_CODE();
60
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
61
+
62
if (bs->drv && bs->drv->bdrv_register_buf) {
63
if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
64
return false;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
66
BdrvChild *child;
67
68
GLOBAL_STATE_CODE();
69
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
70
+
71
if (bs->drv && bs->drv->bdrv_unregister_buf) {
72
bs->drv->bdrv_unregister_buf(bs, host, size);
73
}
65
--
74
--
66
2.13.5
75
2.39.2
67
68
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_co_delete_file() need to hold a reader lock for the graph.
2
3
3
If bkt->max == 0 and bkt->burst_length > 1 then we could have a
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
division by 0 in throttle_do_compute_wait(). That configuration is
5
Message-Id: <20230203152202.49054-22-kwolf@redhat.com>
5
however not permitted and is already detected by throttle_is_valid(),
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
but let's assert it in throttle_compute_wait() to make it explicit.
7
8
Found by Coverity (CID: 1381016).
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
8
---
14
util/throttle.c | 1 +
9
include/block/block-io.h | 8 ++++++--
15
1 file changed, 1 insertion(+)
10
include/block/block_int-common.h | 4 ++--
11
block.c | 1 +
12
3 files changed, 9 insertions(+), 4 deletions(-)
16
13
17
diff --git a/util/throttle.c b/util/throttle.c
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/util/throttle.c
16
--- a/include/block/block-io.h
20
+++ b/util/throttle.c
17
+++ b/include/block/block-io.h
21
@@ -XXX,XX +XXX,XX @@ int64_t throttle_compute_wait(LeakyBucket *bkt)
18
@@ -XXX,XX +XXX,XX @@ int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
22
/* If the main bucket is not full yet we still have to check the
19
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
23
* burst bucket in order to enforce the burst limit */
20
BlockDriverState *in_bs, Error **errp);
24
if (bkt->burst_length > 1) {
21
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
25
+ assert(bkt->max > 0); /* see throttle_is_valid() */
22
-int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
26
extra = bkt->burst_level - burst_bucket_size;
23
-void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs);
27
if (extra > 0) {
24
+
28
return throttle_do_compute_wait(bkt->max, extra);
25
+int coroutine_fn GRAPH_RDLOCK
26
+bdrv_co_delete_file(BlockDriverState *bs, Error **errp);
27
+
28
+void coroutine_fn GRAPH_RDLOCK
29
+bdrv_co_delete_file_noerr(BlockDriverState *bs);
30
31
32
/* async block I/O */
33
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/block_int-common.h
36
+++ b/include/block/block_int-common.h
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_flush)(BlockDriverState *bs);
39
40
/* Delete a created file. */
41
- int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
42
- Error **errp);
43
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_delete_file)(
44
+ BlockDriverState *bs, Error **errp);
45
46
/*
47
* Flushes all data that was already written to the OS all the way down to
48
diff --git a/block.c b/block.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block.c
51
+++ b/block.c
52
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
53
54
IO_CODE();
55
assert(bs != NULL);
56
+ assert_bdrv_graph_readable();
57
58
if (!bs->drv) {
59
error_setg(errp, "Block node '%s' is not opened", bs->filename);
29
--
60
--
30
2.13.5
61
2.39.2
31
32
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_*_dirty_bitmap() need to hold a reader lock for the graph.
2
3
3
So it is easier to copy paste the path.
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
5
Message-Id: <20230203152202.49054-23-kwolf@redhat.com>
5
Signed-off-by: Fam Zheng <famz@redhat.com>
6
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
---
8
tests/qemu-iotests/check | 2 +-
9
include/block/block-io.h | 14 ++++++--------
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
include/block/block_int-common.h | 6 ++++--
11
include/block/dirty-bitmap.h | 12 ++++++------
12
block/dirty-bitmap.c | 2 ++
13
4 files changed, 18 insertions(+), 16 deletions(-)
10
14
11
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
15
diff --git a/include/block/block-io.h b/include/block/block-io.h
12
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/check
17
--- a/include/block/block-io.h
14
+++ b/tests/qemu-iotests/check
18
+++ b/include/block/block-io.h
15
@@ -XXX,XX +XXX,XX @@ do
19
@@ -XXX,XX +XXX,XX @@ AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
16
else
20
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
17
echo " - output mismatch (see $seq.out.bad)"
21
void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
18
mv $tmp.out $seq.out.bad
22
19
- $diff -w "$reference" $seq.out.bad
23
-bool coroutine_fn bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
20
+ $diff -w "$reference" $(realpath $seq.out.bad)
24
- const char *name,
21
err=true
25
- uint32_t granularity,
22
fi
26
- Error **errp);
23
fi
27
-bool co_wrapper bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs,
28
- const char *name,
29
- uint32_t granularity,
30
- Error **errp);
31
+bool coroutine_fn GRAPH_RDLOCK
32
+bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
33
+ uint32_t granularity, Error **errp);
34
+bool co_wrapper_bdrv_rdlock
35
+bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
36
+ uint32_t granularity, Error **errp);
37
38
/**
39
*
40
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int-common.h
43
+++ b/include/block/block_int-common.h
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
45
void (*bdrv_drain_end)(BlockDriverState *bs);
46
47
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
48
- bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
49
+
50
+ bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_can_store_new_dirty_bitmap)(
51
BlockDriverState *bs, const char *name, uint32_t granularity,
52
Error **errp);
53
- int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
54
+
55
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_remove_persistent_dirty_bitmap)(
56
BlockDriverState *bs, const char *name, Error **errp);
57
};
58
59
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/include/block/dirty-bitmap.h
62
+++ b/include/block/dirty-bitmap.h
63
@@ -XXX,XX +XXX,XX @@ int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
64
void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap);
65
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
66
67
-int coroutine_fn bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
68
- const char *name,
69
- Error **errp);
70
-int co_wrapper bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
71
- const char *name,
72
- Error **errp);
73
+int coroutine_fn GRAPH_RDLOCK
74
+bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
75
+ Error **errp);
76
+int co_wrapper_bdrv_rdlock
77
+bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
78
+ Error **errp);
79
80
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
81
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
82
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/block/dirty-bitmap.c
85
+++ b/block/dirty-bitmap.c
86
@@ -XXX,XX +XXX,XX @@ int coroutine_fn
87
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
88
Error **errp)
89
{
90
+ assert_bdrv_graph_readable();
91
if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) {
92
return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
93
}
94
@@ -XXX,XX +XXX,XX @@ bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
95
uint32_t granularity, Error **errp)
96
{
97
BlockDriver *drv = bs->drv;
98
+ assert_bdrv_graph_readable();
99
100
if (!drv) {
101
error_setg_errno(errp, ENOMEDIUM,
24
--
102
--
25
2.13.5
103
2.39.2
26
27
diff view generated by jsdifflib
1
We will calculate the required new permissions in the prepare stage of a
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
reopen. Required permissions of children can be influenced by the
2
bdrv_co_refresh_total_sectors() need to hold a reader lock for the
3
changes made to their parents, but parents are independent from their
3
graph.
4
children. This means that permissions need to be calculated top-down. In
5
order to achieve this, queue parents before their children rather than
6
queuing the children first.
7
4
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-Id: <20230203152202.49054-24-kwolf@redhat.com>
7
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
block.c | 26 +++++++++++++-------------
10
include/block/block-io.h | 8 ++++----
12
1 file changed, 13 insertions(+), 13 deletions(-)
11
include/block/block_int-common.h | 4 +++-
12
include/block/block_int-io.h | 7 ++++---
13
block.c | 3 +++
14
block/blkdebug.c | 3 ++-
15
block/blklogwrites.c | 3 ++-
16
block/blkreplay.c | 3 ++-
17
block/blkverify.c | 3 ++-
18
block/copy-on-read.c | 2 +-
19
block/crypto.c | 3 ++-
20
block/filter-compress.c | 3 ++-
21
block/mirror.c | 3 +++
22
block/preallocate.c | 3 ++-
23
block/quorum.c | 3 ++-
24
block/raw-format.c | 3 ++-
25
block/replication.c | 3 ++-
26
block/stream.c | 8 +++++---
27
block/throttle.c | 3 ++-
28
18 files changed, 45 insertions(+), 23 deletions(-)
13
29
30
diff --git a/include/block/block-io.h b/include/block/block-io.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block-io.h
33
+++ b/include/block/block-io.h
34
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK
35
bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
36
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
37
38
-int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs);
39
-int64_t co_wrapper_mixed bdrv_nb_sectors(BlockDriverState *bs);
40
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_nb_sectors(BlockDriverState *bs);
41
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_nb_sectors(BlockDriverState *bs);
42
43
-int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs);
44
-int64_t co_wrapper_mixed bdrv_getlength(BlockDriverState *bs);
45
+int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs);
46
+int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs);
47
48
int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
49
int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
50
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block_int-common.h
53
+++ b/include/block/block_int-common.h
54
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
55
BlockDriverState *bs, int64_t offset, bool exact,
56
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
57
58
- int64_t coroutine_fn (*bdrv_co_getlength)(BlockDriverState *bs);
59
+ int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_getlength)(
60
+ BlockDriverState *bs);
61
+
62
int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
63
BlockDriverState *bs);
64
65
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/block_int-io.h
68
+++ b/include/block/block_int-io.h
69
@@ -XXX,XX +XXX,XX @@ bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
70
int64_t bytes, BdrvRequestFlags read_flags,
71
BdrvRequestFlags write_flags);
72
73
-int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
74
- int64_t hint);
75
-int co_wrapper_mixed
76
+int coroutine_fn GRAPH_RDLOCK
77
+bdrv_co_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
78
+
79
+int co_wrapper_mixed_bdrv_rdlock
80
bdrv_refresh_total_sectors(BlockDriverState *bs, int64_t hint);
81
82
BdrvChild *bdrv_cow_child(BlockDriverState *bs);
14
diff --git a/block.c b/block.c
83
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
85
--- a/block.c
17
+++ b/block.c
86
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
87
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
19
flags |= BDRV_O_ALLOW_RDWR;
88
{
89
BlockDriver *drv = bs->drv;
90
IO_CODE();
91
+ assert_bdrv_graph_readable();
92
93
if (!drv) {
94
return -ENOMEDIUM;
95
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
96
{
97
BlockDriver *drv = bs->drv;
98
IO_CODE();
99
+ assert_bdrv_graph_readable();
100
101
if (!drv)
102
return -ENOMEDIUM;
103
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
104
{
105
int64_t ret;
106
IO_CODE();
107
+ assert_bdrv_graph_readable();
108
109
ret = bdrv_co_nb_sectors(bs);
110
if (ret < 0) {
111
diff --git a/block/blkdebug.c b/block/blkdebug.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/blkdebug.c
114
+++ b/block/blkdebug.c
115
@@ -XXX,XX +XXX,XX @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
116
return false;
117
}
118
119
-static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
120
+static int64_t coroutine_fn GRAPH_RDLOCK
121
+blkdebug_co_getlength(BlockDriverState *bs)
122
{
123
return bdrv_co_getlength(bs->file->bs);
124
}
125
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/block/blklogwrites.c
128
+++ b/block/blklogwrites.c
129
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_close(BlockDriverState *bs)
130
s->log_file = NULL;
131
}
132
133
-static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
134
+static int64_t coroutine_fn GRAPH_RDLOCK
135
+blk_log_writes_co_getlength(BlockDriverState *bs)
136
{
137
return bdrv_co_getlength(bs->file->bs);
138
}
139
diff --git a/block/blkreplay.c b/block/blkreplay.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/block/blkreplay.c
142
+++ b/block/blkreplay.c
143
@@ -XXX,XX +XXX,XX @@ fail:
144
return ret;
145
}
146
147
-static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
148
+static int64_t coroutine_fn GRAPH_RDLOCK
149
+blkreplay_co_getlength(BlockDriverState *bs)
150
{
151
return bdrv_co_getlength(bs->file->bs);
152
}
153
diff --git a/block/blkverify.c b/block/blkverify.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/blkverify.c
156
+++ b/block/blkverify.c
157
@@ -XXX,XX +XXX,XX @@ static void blkverify_close(BlockDriverState *bs)
158
s->test_file = NULL;
159
}
160
161
-static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
162
+static int64_t coroutine_fn GRAPH_RDLOCK
163
+blkverify_co_getlength(BlockDriverState *bs)
164
{
165
BDRVBlkverifyState *s = bs->opaque;
166
167
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/block/copy-on-read.c
170
+++ b/block/copy-on-read.c
171
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
172
}
173
174
175
-static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
176
+static int64_t coroutine_fn GRAPH_RDLOCK cor_co_getlength(BlockDriverState *bs)
177
{
178
return bdrv_co_getlength(bs->file->bs);
179
}
180
diff --git a/block/crypto.c b/block/crypto.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/block/crypto.c
183
+++ b/block/crypto.c
184
@@ -XXX,XX +XXX,XX @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
185
}
186
187
188
-static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
189
+static int64_t coroutine_fn GRAPH_RDLOCK
190
+block_crypto_co_getlength(BlockDriverState *bs)
191
{
192
BlockCrypto *crypto = bs->opaque;
193
int64_t len = bdrv_co_getlength(bs->file->bs);
194
diff --git a/block/filter-compress.c b/block/filter-compress.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/block/filter-compress.c
197
+++ b/block/filter-compress.c
198
@@ -XXX,XX +XXX,XX @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
199
}
200
201
202
-static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
203
+static int64_t coroutine_fn GRAPH_RDLOCK
204
+compress_co_getlength(BlockDriverState *bs)
205
{
206
return bdrv_co_getlength(bs->file->bs);
207
}
208
diff --git a/block/mirror.c b/block/mirror.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/mirror.c
211
+++ b/block/mirror.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
213
goto immediate_exit;
20
}
214
}
21
215
22
+ if (!bs_entry) {
216
+ bdrv_graph_co_rdlock();
23
+ bs_entry = g_new0(BlockReopenQueueEntry, 1);
217
s->bdev_length = bdrv_co_getlength(bs);
24
+ QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
218
+ bdrv_graph_co_rdunlock();
25
+ } else {
26
+ QDECREF(bs_entry->state.options);
27
+ QDECREF(bs_entry->state.explicit_options);
28
+ }
29
+
219
+
30
+ bs_entry->state.bs = bs;
220
if (s->bdev_length < 0) {
31
+ bs_entry->state.options = options;
221
ret = s->bdev_length;
32
+ bs_entry->state.explicit_options = explicit_options;
222
goto immediate_exit;
33
+ bs_entry->state.flags = flags;
223
diff --git a/block/preallocate.c b/block/preallocate.c
34
+
224
index XXXXXXX..XXXXXXX 100644
35
QLIST_FOREACH(child, &bs->children, next) {
225
--- a/block/preallocate.c
36
QDict *new_child_options;
226
+++ b/block/preallocate.c
37
char *child_key_dot;
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK preallocate_co_flush(BlockDriverState *bs)
38
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
228
return bdrv_co_flush(bs->file->bs);
39
child->role, options, flags);
229
}
230
231
-static int64_t coroutine_fn preallocate_co_getlength(BlockDriverState *bs)
232
+static int64_t coroutine_fn GRAPH_RDLOCK
233
+preallocate_co_getlength(BlockDriverState *bs)
234
{
235
int64_t ret;
236
BDRVPreallocateState *s = bs->opaque;
237
diff --git a/block/quorum.c b/block/quorum.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/quorum.c
240
+++ b/block/quorum.c
241
@@ -XXX,XX +XXX,XX @@ quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
242
flags | BDRV_REQ_ZERO_WRITE);
243
}
244
245
-static int64_t coroutine_fn quorum_co_getlength(BlockDriverState *bs)
246
+static int64_t coroutine_fn GRAPH_RDLOCK
247
+quorum_co_getlength(BlockDriverState *bs)
248
{
249
BDRVQuorumState *s = bs->opaque;
250
int64_t result;
251
diff --git a/block/raw-format.c b/block/raw-format.c
252
index XXXXXXX..XXXXXXX 100644
253
--- a/block/raw-format.c
254
+++ b/block/raw-format.c
255
@@ -XXX,XX +XXX,XX @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
256
return bdrv_co_pdiscard(bs->file, offset, bytes);
257
}
258
259
-static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
260
+static int64_t coroutine_fn GRAPH_RDLOCK
261
+raw_co_getlength(BlockDriverState *bs)
262
{
263
int64_t len;
264
BDRVRawState *s = bs->opaque;
265
diff --git a/block/replication.c b/block/replication.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/replication.c
268
+++ b/block/replication.c
269
@@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
270
return;
271
}
272
273
-static int64_t coroutine_fn replication_co_getlength(BlockDriverState *bs)
274
+static int64_t coroutine_fn GRAPH_RDLOCK
275
+replication_co_getlength(BlockDriverState *bs)
276
{
277
return bdrv_co_getlength(bs->file->bs);
278
}
279
diff --git a/block/stream.c b/block/stream.c
280
index XXXXXXX..XXXXXXX 100644
281
--- a/block/stream.c
282
+++ b/block/stream.c
283
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
284
return 0;
40
}
285
}
41
286
42
- if (!bs_entry) {
287
- len = bdrv_getlength(s->target_bs);
43
- bs_entry = g_new0(BlockReopenQueueEntry, 1);
288
- if (len < 0) {
44
- QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
289
- return len;
45
- } else {
290
+ WITH_GRAPH_RDLOCK_GUARD() {
46
- QDECREF(bs_entry->state.options);
291
+ len = bdrv_co_getlength(s->target_bs);
47
- QDECREF(bs_entry->state.explicit_options);
292
+ if (len < 0) {
48
- }
293
+ return len;
49
-
294
+ }
50
- bs_entry->state.bs = bs;
295
}
51
- bs_entry->state.options = options;
296
job_progress_set_remaining(&s->common.job, len);
52
- bs_entry->state.explicit_options = explicit_options;
297
53
- bs_entry->state.flags = flags;
298
diff --git a/block/throttle.c b/block/throttle.c
54
-
299
index XXXXXXX..XXXXXXX 100644
55
return bs_queue;
300
--- a/block/throttle.c
56
}
301
+++ b/block/throttle.c
57
302
@@ -XXX,XX +XXX,XX @@ static void throttle_close(BlockDriverState *bs)
303
}
304
305
306
-static int64_t coroutine_fn throttle_co_getlength(BlockDriverState *bs)
307
+static int64_t coroutine_fn GRAPH_RDLOCK
308
+throttle_co_getlength(BlockDriverState *bs)
309
{
310
return bdrv_co_getlength(bs->file->bs);
311
}
58
--
312
--
59
2.13.5
313
2.39.2
60
61
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
Block driver documentation is available in qemu-doc.html. It would be
3
If requests are being processed in the IOThread when a SCSIDevice is
4
convenient to have documentation for formats, protocols, and filter
4
unplugged, scsi_device_purge_requests() -> scsi_req_cancel_async() races
5
drivers in a man page.
5
with I/O completion callbacks. Both threads load and store req->aiocb.
6
This can lead to assert(r->req.aiocb == NULL) failures and undefined
7
behavior.
6
8
7
Extract the relevant part of qemu-doc.html into a new file called
9
Protect r->req.aiocb with the AioContext lock to prevent the race.
8
docs/qemu-block-drivers.texi. This file can also be built as a
9
stand-alone document (man, html, etc).
10
10
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230221212218.1378734-2-stefanha@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
16
---
14
Makefile | 6 +-
17
hw/scsi/scsi-disk.c | 23 ++++++++++++++++-------
15
docs/qemu-block-drivers.texi | 804 +++++++++++++++++++++++++++++++++++++++++++
18
hw/scsi/scsi-generic.c | 11 ++++++-----
16
qemu-doc.texi | 781 +----------------------------------------
19
2 files changed, 22 insertions(+), 12 deletions(-)
17
3 files changed, 810 insertions(+), 781 deletions(-)
18
create mode 100644 docs/qemu-block-drivers.texi
19
20
20
diff --git a/Makefile b/Makefile
21
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/Makefile
23
--- a/hw/scsi/scsi-disk.c
23
+++ b/Makefile
24
+++ b/hw/scsi/scsi-disk.c
24
@@ -XXX,XX +XXX,XX @@ ifdef BUILD_DOCS
25
@@ -XXX,XX +XXX,XX @@ static void scsi_aio_complete(void *opaque, int ret)
25
DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
26
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
26
DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7
27
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
27
DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7
28
28
+DOCS+=docs/qemu-block-drivers.7
29
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
29
ifdef CONFIG_VIRTFS
30
DOCS+=fsdev/virtfs-proxy-helper.1
31
endif
32
@@ -XXX,XX +XXX,XX @@ distclean: clean
33
    rm -f docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
34
    rm -f docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf
35
    rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
36
+    rm -f docs/qemu-block-drivers.7
37
    for d in $(TARGET_DIRS); do \
38
    rm -rf $$d || exit 1 ; \
39
done
40
@@ -XXX,XX +XXX,XX @@ ifdef CONFIG_POSIX
41
    $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
42
    $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man7"
43
    $(INSTALL_DATA) docs/interop/qemu-qmp-ref.7 "$(DESTDIR)$(mandir)/man7"
44
+    $(INSTALL_DATA) docs/qemu-block-drivers.7 "$(DESTDIR)$(mandir)/man7"
45
ifneq ($(TOOLS),)
46
    $(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1"
47
    $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
48
@@ -XXX,XX +XXX,XX @@ qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi
49
fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
50
qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
51
qemu-ga.8: qemu-ga.texi
52
+docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi
53
54
html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
55
info: qemu-doc.info docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info
56
@@ -XXX,XX +XXX,XX @@ txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
57
qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
58
    qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
59
    qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
60
-    qemu-monitor-info.texi
61
+    qemu-monitor-info.texi docs/qemu-block-drivers.texi
62
63
docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \
64
docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \
65
diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
66
new file mode 100644
67
index XXXXXXX..XXXXXXX
68
--- /dev/null
69
+++ b/docs/qemu-block-drivers.texi
70
@@ -XXX,XX +XXX,XX @@
71
+@c man begin SYNOPSIS
72
+QEMU block driver reference manual
73
+@c man end
74
+
30
+
75
+@c man begin DESCRIPTION
31
assert(r->req.aiocb != NULL);
32
r->req.aiocb = NULL;
33
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
76
+
34
+
77
+@node disk_images_formats
35
if (scsi_disk_req_check_error(r, ret, true)) {
78
+@subsection Disk image file formats
36
goto done;
37
}
38
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
39
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
40
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
41
42
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
79
+
43
+
80
+QEMU supports many image file formats that can be used with VMs as well as with
44
assert(r->req.aiocb != NULL);
81
+any of the tools (like @code{qemu-img}). This includes the preferred formats
45
r->req.aiocb = NULL;
82
+raw and qcow2 as well as formats that are supported for compatibility with
46
83
+older QEMU versions or other hypervisors.
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
48
if (ret < 0) {
49
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
50
} else {
51
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void *opaque, int ret)
52
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
53
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
54
55
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
84
+
56
+
85
+Depending on the image format, different options can be passed to
57
assert(r->req.aiocb != NULL);
86
+@code{qemu-img create} and @code{qemu-img convert} using the @code{-o} option.
58
r->req.aiocb = NULL;
87
+This section describes each format and the options that are supported for it.
59
60
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
61
if (ret < 0) {
62
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
63
} else {
64
@@ -XXX,XX +XXX,XX @@ static void scsi_do_read_cb(void *opaque, int ret)
65
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
66
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
67
68
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
88
+
69
+
89
+@table @option
70
assert (r->req.aiocb != NULL);
90
+@item raw
71
r->req.aiocb = NULL;
72
73
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
74
if (ret < 0) {
75
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
76
} else {
77
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
78
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
79
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
80
81
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
91
+
82
+
92
+Raw disk image format. This format has the advantage of
83
assert (r->req.aiocb != NULL);
93
+being simple and easily exportable to all other emulators. If your
84
r->req.aiocb = NULL;
94
+file system supports @emph{holes} (for example in ext2 or ext3 on
85
95
+Linux or NTFS on Windows), then only the written sectors will reserve
86
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
96
+space. Use @code{qemu-img info} to know the real size used by the
87
if (ret < 0) {
97
+image or @code{ls -ls} on Unix/Linux.
88
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
89
} else {
90
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
91
SCSIDiskReq *r = data->r;
92
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
93
94
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
98
+
95
+
99
+Supported options:
96
assert(r->req.aiocb != NULL);
100
+@table @code
97
r->req.aiocb = NULL;
101
+@item preallocation
98
102
+Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
99
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
103
+@code{falloc} mode preallocates space for image by calling posix_fallocate().
100
if (scsi_disk_req_check_error(r, ret, true)) {
104
+@code{full} mode preallocates space for image by writing zeros to underlying
101
scsi_req_unref(&r->req);
105
+storage.
102
g_free(data);
106
+@end table
103
@@ -XXX,XX +XXX,XX @@ static void scsi_write_same_complete(void *opaque, int ret)
104
SCSIDiskReq *r = data->r;
105
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
106
107
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
107
+
108
+
108
+@item qcow2
109
assert(r->req.aiocb != NULL);
109
+QEMU image format, the most versatile format. Use it to have smaller
110
r->req.aiocb = NULL;
110
+images (useful if your filesystem does not supports holes, for example
111
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
111
+on Windows), zlib based compression and support of multiple VM
112
+snapshots.
113
+
112
+
114
+Supported options:
113
if (scsi_disk_req_check_error(r, ret, true)) {
115
+@table @code
114
goto done;
116
+@item compat
115
}
117
+Determines the qcow2 version to use. @code{compat=0.10} uses the
116
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
118
+traditional image format that can be read by any QEMU since 0.10.
117
index XXXXXXX..XXXXXXX 100644
119
+@code{compat=1.1} enables image format extensions that only QEMU 1.1 and
118
--- a/hw/scsi/scsi-generic.c
120
+newer understand (this is the default). Amongst others, this includes
119
+++ b/hw/scsi/scsi-generic.c
121
+zero clusters, which allow efficient copy-on-read for sparse images.
120
@@ -XXX,XX +XXX,XX @@ static void scsi_command_complete(void *opaque, int ret)
121
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
122
SCSIDevice *s = r->req.dev;
123
124
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
122
+
125
+
123
+@item backing_file
126
assert(r->req.aiocb != NULL);
124
+File name of a base image (see @option{create} subcommand)
127
r->req.aiocb = NULL;
125
+@item backing_fmt
128
126
+Image format of the base image
129
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
127
+@item encryption
130
scsi_command_complete_noio(r, ret);
128
+This option is deprecated and equivalent to @code{encrypt.format=aes}
131
aio_context_release(blk_get_aio_context(s->conf.blk));
132
}
133
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
134
SCSIDevice *s = r->req.dev;
135
int len;
136
137
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
129
+
138
+
130
+@item encrypt.format
139
assert(r->req.aiocb != NULL);
140
r->req.aiocb = NULL;
141
142
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
143
-
144
if (ret || r->req.io_canceled) {
145
scsi_command_complete_noio(r, ret);
146
goto done;
147
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
148
149
trace_scsi_generic_write_complete(ret);
150
151
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
131
+
152
+
132
+If this is set to @code{luks}, it requests that the qcow2 payload (not
153
assert(r->req.aiocb != NULL);
133
+qcow2 header) be encrypted using the LUKS format. The passphrase to
154
r->req.aiocb = NULL;
134
+use to unlock the LUKS key slot is given by the @code{encrypt.key-secret}
155
135
+parameter. LUKS encryption parameters can be tuned with the other
156
- aio_context_acquire(blk_get_aio_context(s->conf.blk));
136
+@code{encrypt.*} parameters.
137
+
138
+If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
139
+The encryption key is given by the @code{encrypt.key-secret} parameter.
140
+This encryption format is considered to be flawed by modern cryptography
141
+standards, suffering from a number of design problems:
142
+
143
+@itemize @minus
144
+@item The AES-CBC cipher is used with predictable initialization vectors based
145
+on the sector number. This makes it vulnerable to chosen plaintext attacks
146
+which can reveal the existence of encrypted data.
147
+@item The user passphrase is directly used as the encryption key. A poorly
148
+chosen or short passphrase will compromise the security of the encryption.
149
+@item In the event of the passphrase being compromised there is no way to
150
+change the passphrase to protect data in any qcow images. The files must
151
+be cloned, using a different encryption passphrase in the new file. The
152
+original file must then be securely erased using a program like shred,
153
+though even this is ineffective with many modern storage technologies.
154
+@end itemize
155
+
156
+The use of this is no longer supported in system emulators. Support only
157
+remains in the command line utilities, for the purposes of data liberation
158
+and interoperability with old versions of QEMU. The @code{luks} format
159
+should be used instead.
160
+
161
+@item encrypt.key-secret
162
+
163
+Provides the ID of a @code{secret} object that contains the passphrase
164
+(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}).
165
+
166
+@item encrypt.cipher-alg
167
+
168
+Name of the cipher algorithm and key length. Currently defaults
169
+to @code{aes-256}. Only used when @code{encrypt.format=luks}.
170
+
171
+@item encrypt.cipher-mode
172
+
173
+Name of the encryption mode to use. Currently defaults to @code{xts}.
174
+Only used when @code{encrypt.format=luks}.
175
+
176
+@item encrypt.ivgen-alg
177
+
178
+Name of the initialization vector generator algorithm. Currently defaults
179
+to @code{plain64}. Only used when @code{encrypt.format=luks}.
180
+
181
+@item encrypt.ivgen-hash-alg
182
+
183
+Name of the hash algorithm to use with the initialization vector generator
184
+(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
185
+
186
+@item encrypt.hash-alg
187
+
188
+Name of the hash algorithm to use for PBKDF algorithm
189
+Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
190
+
191
+@item encrypt.iter-time
192
+
193
+Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
194
+Defaults to @code{2000}. Only used when @code{encrypt.format=luks}.
195
+
196
+@item cluster_size
197
+Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
198
+sizes can improve the image file size whereas larger cluster sizes generally
199
+provide better performance.
200
+
201
+@item preallocation
202
+Preallocation mode (allowed values: @code{off}, @code{metadata}, @code{falloc},
203
+@code{full}). An image with preallocated metadata is initially larger but can
204
+improve performance when the image needs to grow. @code{falloc} and @code{full}
205
+preallocations are like the same options of @code{raw} format, but sets up
206
+metadata also.
207
+
208
+@item lazy_refcounts
209
+If this option is set to @code{on}, reference count updates are postponed with
210
+the goal of avoiding metadata I/O and improving performance. This is
211
+particularly interesting with @option{cache=writethrough} which doesn't batch
212
+metadata updates. The tradeoff is that after a host crash, the reference count
213
+tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img
214
+check -r all} is required, which may take some time.
215
+
216
+This option can only be enabled if @code{compat=1.1} is specified.
217
+
218
+@item nocow
219
+If this option is set to @code{on}, it will turn off COW of the file. It's only
220
+valid on btrfs, no effect on other file systems.
221
+
222
+Btrfs has low performance when hosting a VM image file, even more when the guest
223
+on the VM also using btrfs as file system. Turning off COW is a way to mitigate
224
+this bad performance. Generally there are two ways to turn off COW on btrfs:
225
+a) Disable it by mounting with nodatacow, then all newly created files will be
226
+NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option
227
+does.
228
+
229
+Note: this option is only valid to new or empty files. If there is an existing
230
+file which is COW and has data blocks already, it couldn't be changed to NOCOW
231
+by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
232
+the NOCOW flag is set or not (Capital 'C' is NOCOW flag).
233
+
234
+@end table
235
+
236
+@item qed
237
+Old QEMU image format with support for backing files and compact image files
238
+(when your filesystem or transport medium does not support holes).
239
+
240
+When converting QED images to qcow2, you might want to consider using the
241
+@code{lazy_refcounts=on} option to get a more QED-like behaviour.
242
+
243
+Supported options:
244
+@table @code
245
+@item backing_file
246
+File name of a base image (see @option{create} subcommand).
247
+@item backing_fmt
248
+Image file format of backing file (optional). Useful if the format cannot be
249
+autodetected because it has no header, like some vhd/vpc files.
250
+@item cluster_size
251
+Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller
252
+cluster sizes can improve the image file size whereas larger cluster sizes
253
+generally provide better performance.
254
+@item table_size
255
+Changes the number of clusters per L1/L2 table (must be power-of-2 between 1
256
+and 16). There is normally no need to change this value but this option can be
257
+used for performance benchmarking.
258
+@end table
259
+
260
+@item qcow
261
+Old QEMU image format with support for backing files, compact image files,
262
+encryption and compression.
263
+
264
+Supported options:
265
+@table @code
266
+@item backing_file
267
+File name of a base image (see @option{create} subcommand)
268
+@item encryption
269
+This option is deprecated and equivalent to @code{encrypt.format=aes}
270
+
271
+@item encrypt.format
272
+If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
273
+The encryption key is given by the @code{encrypt.key-secret} parameter.
274
+This encryption format is considered to be flawed by modern cryptography
275
+standards, suffering from a number of design problems enumerated previously
276
+against the @code{qcow2} image format.
277
+
278
+The use of this is no longer supported in system emulators. Support only
279
+remains in the command line utilities, for the purposes of data liberation
280
+and interoperability with old versions of QEMU.
281
+
282
+Users requiring native encryption should use the @code{qcow2} format
283
+instead with @code{encrypt.format=luks}.
284
+
285
+@item encrypt.key-secret
286
+
287
+Provides the ID of a @code{secret} object that contains the encryption
288
+key (@code{encrypt.format=aes}).
289
+
290
+@end table
291
+
292
+@item luks
293
+
294
+LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup
295
+
296
+Supported options:
297
+@table @code
298
+
299
+@item key-secret
300
+
301
+Provides the ID of a @code{secret} object that contains the passphrase.
302
+
303
+@item cipher-alg
304
+
305
+Name of the cipher algorithm and key length. Currently defaults
306
+to @code{aes-256}.
307
+
308
+@item cipher-mode
309
+
310
+Name of the encryption mode to use. Currently defaults to @code{xts}.
311
+
312
+@item ivgen-alg
313
+
314
+Name of the initialization vector generator algorithm. Currently defaults
315
+to @code{plain64}.
316
+
317
+@item ivgen-hash-alg
318
+
319
+Name of the hash algorithm to use with the initialization vector generator
320
+(if required). Defaults to @code{sha256}.
321
+
322
+@item hash-alg
323
+
324
+Name of the hash algorithm to use for PBKDF algorithm
325
+Defaults to @code{sha256}.
326
+
327
+@item iter-time
328
+
329
+Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
330
+Defaults to @code{2000}.
331
+
332
+@end table
333
+
334
+@item vdi
335
+VirtualBox 1.1 compatible image format.
336
+Supported options:
337
+@table @code
338
+@item static
339
+If this option is set to @code{on}, the image is created with metadata
340
+preallocation.
341
+@end table
342
+
343
+@item vmdk
344
+VMware 3 and 4 compatible image format.
345
+
346
+Supported options:
347
+@table @code
348
+@item backing_file
349
+File name of a base image (see @option{create} subcommand).
350
+@item compat6
351
+Create a VMDK version 6 image (instead of version 4)
352
+@item hwversion
353
+Specify vmdk virtual hardware version. Compat6 flag cannot be enabled
354
+if hwversion is specified.
355
+@item subformat
356
+Specifies which VMDK subformat to use. Valid options are
357
+@code{monolithicSparse} (default),
358
+@code{monolithicFlat},
359
+@code{twoGbMaxExtentSparse},
360
+@code{twoGbMaxExtentFlat} and
361
+@code{streamOptimized}.
362
+@end table
363
+
364
+@item vpc
365
+VirtualPC compatible image format (VHD).
366
+Supported options:
367
+@table @code
368
+@item subformat
369
+Specifies which VHD subformat to use. Valid options are
370
+@code{dynamic} (default) and @code{fixed}.
371
+@end table
372
+
373
+@item VHDX
374
+Hyper-V compatible image format (VHDX).
375
+Supported options:
376
+@table @code
377
+@item subformat
378
+Specifies which VHDX subformat to use. Valid options are
379
+@code{dynamic} (default) and @code{fixed}.
380
+@item block_state_zero
381
+Force use of payload blocks of type 'ZERO'. Can be set to @code{on} (default)
382
+or @code{off}. When set to @code{off}, new blocks will be created as
383
+@code{PAYLOAD_BLOCK_NOT_PRESENT}, which means parsers are free to return
384
+arbitrary data for those blocks. Do not set to @code{off} when using
385
+@code{qemu-img convert} with @code{subformat=dynamic}.
386
+@item block_size
387
+Block size; min 1 MB, max 256 MB. 0 means auto-calculate based on image size.
388
+@item log_size
389
+Log size; min 1 MB.
390
+@end table
391
+@end table
392
+
393
+@subsubsection Read-only formats
394
+More disk image file formats are supported in a read-only mode.
395
+@table @option
396
+@item bochs
397
+Bochs images of @code{growing} type.
398
+@item cloop
399
+Linux Compressed Loop image, useful only to reuse directly compressed
400
+CD-ROM images present for example in the Knoppix CD-ROMs.
401
+@item dmg
402
+Apple disk image.
403
+@item parallels
404
+Parallels disk image format.
405
+@end table
406
+
407
+
408
+@node host_drives
409
+@subsection Using host drives
410
+
411
+In addition to disk image files, QEMU can directly access host
412
+devices. We describe here the usage for QEMU version >= 0.8.3.
413
+
414
+@subsubsection Linux
415
+
416
+On Linux, you can directly use the host device filename instead of a
417
+disk image filename provided you have enough privileges to access
418
+it. For example, use @file{/dev/cdrom} to access to the CDROM.
419
+
420
+@table @code
421
+@item CD
422
+You can specify a CDROM device even if no CDROM is loaded. QEMU has
423
+specific code to detect CDROM insertion or removal. CDROM ejection by
424
+the guest OS is supported. Currently only data CDs are supported.
425
+@item Floppy
426
+You can specify a floppy device even if no floppy is loaded. Floppy
427
+removal is currently not detected accurately (if you change floppy
428
+without doing floppy access while the floppy is not loaded, the guest
429
+OS will think that the same floppy is loaded).
430
+Use of the host's floppy device is deprecated, and support for it will
431
+be removed in a future release.
432
+@item Hard disks
433
+Hard disks can be used. Normally you must specify the whole disk
434
+(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can
435
+see it as a partitioned disk. WARNING: unless you know what you do, it
436
+is better to only make READ-ONLY accesses to the hard disk otherwise
437
+you may corrupt your host data (use the @option{-snapshot} command
438
+line option or modify the device permissions accordingly).
439
+@end table
440
+
441
+@subsubsection Windows
442
+
443
+@table @code
444
+@item CD
445
+The preferred syntax is the drive letter (e.g. @file{d:}). The
446
+alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is
447
+supported as an alias to the first CDROM drive.
448
+
449
+Currently there is no specific code to handle removable media, so it
450
+is better to use the @code{change} or @code{eject} monitor commands to
451
+change or eject media.
452
+@item Hard disks
453
+Hard disks can be used with the syntax: @file{\\.\PhysicalDrive@var{N}}
454
+where @var{N} is the drive number (0 is the first hard disk).
455
+
456
+WARNING: unless you know what you do, it is better to only make
457
+READ-ONLY accesses to the hard disk otherwise you may corrupt your
458
+host data (use the @option{-snapshot} command line so that the
459
+modifications are written in a temporary file).
460
+@end table
461
+
462
+
463
+@subsubsection Mac OS X
464
+
465
+@file{/dev/cdrom} is an alias to the first CDROM.
466
+
467
+Currently there is no specific code to handle removable media, so it
468
+is better to use the @code{change} or @code{eject} monitor commands to
469
+change or eject media.
470
+
471
+@node disk_images_fat_images
472
+@subsection Virtual FAT disk images
473
+
474
+QEMU can automatically create a virtual FAT disk image from a
475
+directory tree. In order to use it, just type:
476
+
477
+@example
478
+qemu-system-i386 linux.img -hdb fat:/my_directory
479
+@end example
480
+
481
+Then you access access to all the files in the @file{/my_directory}
482
+directory without having to copy them in a disk image or to export
483
+them via SAMBA or NFS. The default access is @emph{read-only}.
484
+
485
+Floppies can be emulated with the @code{:floppy:} option:
486
+
487
+@example
488
+qemu-system-i386 linux.img -fda fat:floppy:/my_directory
489
+@end example
490
+
491
+A read/write support is available for testing (beta stage) with the
492
+@code{:rw:} option:
493
+
494
+@example
495
+qemu-system-i386 linux.img -fda fat:floppy:rw:/my_directory
496
+@end example
497
+
498
+What you should @emph{never} do:
499
+@itemize
500
+@item use non-ASCII filenames ;
501
+@item use "-snapshot" together with ":rw:" ;
502
+@item expect it to work when loadvm'ing ;
503
+@item write to the FAT directory on the host system while accessing it with the guest system.
504
+@end itemize
505
+
506
+@node disk_images_nbd
507
+@subsection NBD access
508
+
509
+QEMU can access directly to block device exported using the Network Block Device
510
+protocol.
511
+
512
+@example
513
+qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/
514
+@end example
515
+
516
+If the NBD server is located on the same host, you can use an unix socket instead
517
+of an inet socket:
518
+
519
+@example
520
+qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket
521
+@end example
522
+
523
+In this case, the block device must be exported using qemu-nbd:
524
+
525
+@example
526
+qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
527
+@end example
528
+
529
+The use of qemu-nbd allows sharing of a disk between several guests:
530
+@example
531
+qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
532
+@end example
533
+
534
+@noindent
535
+and then you can use it with two guests:
536
+@example
537
+qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket
538
+qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket
539
+@end example
540
+
541
+If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's
542
+own embedded NBD server), you must specify an export name in the URI:
543
+@example
544
+qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst
545
+qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst
546
+@end example
547
+
548
+The URI syntax for NBD is supported since QEMU 1.3. An alternative syntax is
549
+also available. Here are some example of the older syntax:
550
+@example
551
+qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
552
+qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
553
+qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst
554
+@end example
555
+
556
+@node disk_images_sheepdog
557
+@subsection Sheepdog disk images
558
+
559
+Sheepdog is a distributed storage system for QEMU. It provides highly
560
+available block level storage volumes that can be attached to
561
+QEMU-based virtual machines.
562
+
563
+You can create a Sheepdog disk image with the command:
564
+@example
565
+qemu-img create sheepdog:///@var{image} @var{size}
566
+@end example
567
+where @var{image} is the Sheepdog image name and @var{size} is its
568
+size.
569
+
570
+To import the existing @var{filename} to Sheepdog, you can use a
571
+convert command.
572
+@example
573
+qemu-img convert @var{filename} sheepdog:///@var{image}
574
+@end example
575
+
576
+You can boot from the Sheepdog disk image with the command:
577
+@example
578
+qemu-system-i386 sheepdog:///@var{image}
579
+@end example
580
+
581
+You can also create a snapshot of the Sheepdog image like qcow2.
582
+@example
583
+qemu-img snapshot -c @var{tag} sheepdog:///@var{image}
584
+@end example
585
+where @var{tag} is a tag name of the newly created snapshot.
586
+
587
+To boot from the Sheepdog snapshot, specify the tag name of the
588
+snapshot.
589
+@example
590
+qemu-system-i386 sheepdog:///@var{image}#@var{tag}
591
+@end example
592
+
593
+You can create a cloned image from the existing snapshot.
594
+@example
595
+qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
596
+@end example
597
+where @var{base} is a image name of the source snapshot and @var{tag}
598
+is its tag name.
599
+
600
+You can use an unix socket instead of an inet socket:
601
+
602
+@example
603
+qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path}
604
+@end example
605
+
606
+If the Sheepdog daemon doesn't run on the local host, you need to
607
+specify one of the Sheepdog servers to connect to.
608
+@example
609
+qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size}
610
+qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image}
611
+@end example
612
+
613
+@node disk_images_iscsi
614
+@subsection iSCSI LUNs
615
+
616
+iSCSI is a popular protocol used to access SCSI devices across a computer
617
+network.
618
+
619
+There are two different ways iSCSI devices can be used by QEMU.
620
+
621
+The first method is to mount the iSCSI LUN on the host, and make it appear as
622
+any other ordinary SCSI device on the host and then to access this device as a
623
+/dev/sd device from QEMU. How to do this differs between host OSes.
624
+
625
+The second method involves using the iSCSI initiator that is built into
626
+QEMU. This provides a mechanism that works the same way regardless of which
627
+host OS you are running QEMU on. This section will describe this second method
628
+of using iSCSI together with QEMU.
629
+
630
+In QEMU, iSCSI devices are described using special iSCSI URLs
631
+
632
+@example
633
+URL syntax:
634
+iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
635
+@end example
636
+
637
+Username and password are optional and only used if your target is set up
638
+using CHAP authentication for access control.
639
+Alternatively the username and password can also be set via environment
640
+variables to have these not show up in the process list
641
+
642
+@example
643
+export LIBISCSI_CHAP_USERNAME=<username>
644
+export LIBISCSI_CHAP_PASSWORD=<password>
645
+iscsi://<host>/<target-iqn-name>/<lun>
646
+@end example
647
+
648
+Various session related parameters can be set via special options, either
649
+in a configuration file provided via '-readconfig' or directly on the
650
+command line.
651
+
652
+If the initiator-name is not specified qemu will use a default name
653
+of 'iqn.2008-11.org.linux-kvm[:<uuid>'] where <uuid> is the UUID of the
654
+virtual machine. If the UUID is not specified qemu will use
655
+'iqn.2008-11.org.linux-kvm[:<name>'] where <name> is the name of the
656
+virtual machine.
657
+
658
+@example
659
+Setting a specific initiator name to use when logging in to the target
660
+-iscsi initiator-name=iqn.qemu.test:my-initiator
661
+@end example
662
+
663
+@example
664
+Controlling which type of header digest to negotiate with the target
665
+-iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
666
+@end example
667
+
668
+These can also be set via a configuration file
669
+@example
670
+[iscsi]
671
+ user = "CHAP username"
672
+ password = "CHAP password"
673
+ initiator-name = "iqn.qemu.test:my-initiator"
674
+ # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
675
+ header-digest = "CRC32C"
676
+@end example
677
+
678
+
679
+Setting the target name allows different options for different targets
680
+@example
681
+[iscsi "iqn.target.name"]
682
+ user = "CHAP username"
683
+ password = "CHAP password"
684
+ initiator-name = "iqn.qemu.test:my-initiator"
685
+ # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
686
+ header-digest = "CRC32C"
687
+@end example
688
+
689
+
690
+Howto use a configuration file to set iSCSI configuration options:
691
+@example
692
+cat >iscsi.conf <<EOF
693
+[iscsi]
694
+ user = "me"
695
+ password = "my password"
696
+ initiator-name = "iqn.qemu.test:my-initiator"
697
+ header-digest = "CRC32C"
698
+EOF
699
+
700
+qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
701
+ -readconfig iscsi.conf
702
+@end example
703
+
704
+
705
+Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
706
+@example
707
+This example shows how to set up an iSCSI target with one CDROM and one DISK
708
+using the Linux STGT software target. This target is available on Red Hat based
709
+systems as the package 'scsi-target-utils'.
710
+
711
+tgtd --iscsi portal=127.0.0.1:3260
712
+tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test
713
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \
714
+ -b /IMAGES/disk.img --device-type=disk
715
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
716
+ -b /IMAGES/cd.iso --device-type=cd
717
+tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
718
+
719
+qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
720
+ -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
721
+ -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
722
+@end example
723
+
724
+@node disk_images_gluster
725
+@subsection GlusterFS disk images
726
+
727
+GlusterFS is a user space distributed file system.
728
+
729
+You can boot from the GlusterFS disk image with the command:
730
+@example
731
+URI:
732
+qemu-system-x86_64 -drive file=gluster[+@var{type}]://[@var{host}[:@var{port}]]/@var{volume}/@var{path}
733
+ [?socket=...][,file.debug=9][,file.logfile=...]
734
+
735
+JSON:
736
+qemu-system-x86_64 'json:@{"driver":"qcow2",
737
+ "file":@{"driver":"gluster",
738
+ "volume":"testvol","path":"a.img","debug":9,"logfile":"...",
739
+ "server":[@{"type":"tcp","host":"...","port":"..."@},
740
+ @{"type":"unix","socket":"..."@}]@}@}'
741
+@end example
742
+
743
+@var{gluster} is the protocol.
744
+
745
+@var{type} specifies the transport type used to connect to gluster
746
+management daemon (glusterd). Valid transport types are
747
+tcp and unix. In the URI form, if a transport type isn't specified,
748
+then tcp type is assumed.
749
+
750
+@var{host} specifies the server where the volume file specification for
751
+the given volume resides. This can be either a hostname or an ipv4 address.
752
+If transport type is unix, then @var{host} field should not be specified.
753
+Instead @var{socket} field needs to be populated with the path to unix domain
754
+socket.
755
+
756
+@var{port} is the port number on which glusterd is listening. This is optional
757
+and if not specified, it defaults to port 24007. If the transport type is unix,
758
+then @var{port} should not be specified.
759
+
760
+@var{volume} is the name of the gluster volume which contains the disk image.
761
+
762
+@var{path} is the path to the actual disk image that resides on gluster volume.
763
+
764
+@var{debug} is the logging level of the gluster protocol driver. Debug levels
765
+are 0-9, with 9 being the most verbose, and 0 representing no debugging output.
766
+The default level is 4. The current logging levels defined in the gluster source
767
+are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning,
768
+6 - Notice, 7 - Info, 8 - Debug, 9 - Trace
769
+
770
+@var{logfile} is a commandline option to mention log file path which helps in
771
+logging to the specified file and also help in persisting the gfapi logs. The
772
+default is stderr.
773
+
774
+
775
+
776
+
777
+You can create a GlusterFS disk image with the command:
778
+@example
779
+qemu-img create gluster://@var{host}/@var{volume}/@var{path} @var{size}
780
+@end example
781
+
782
+Examples
783
+@example
784
+qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img
785
+qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img
786
+qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
787
+qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
788
+qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
789
+qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
790
+qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
791
+qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img
792
+qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log
793
+qemu-system-x86_64 'json:@{"driver":"qcow2",
794
+ "file":@{"driver":"gluster",
795
+ "volume":"testvol","path":"a.img",
796
+ "debug":9,"logfile":"/var/log/qemu-gluster.log",
797
+ "server":[@{"type":"tcp","host":"1.2.3.4","port":24007@},
798
+ @{"type":"unix","socket":"/var/run/glusterd.socket"@}]@}@}'
799
+qemu-system-x86_64 -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
800
+ file.debug=9,file.logfile=/var/log/qemu-gluster.log,
801
+ file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
802
+ file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
803
+@end example
804
+
805
+@node disk_images_ssh
806
+@subsection Secure Shell (ssh) disk images
807
+
808
+You can access disk images located on a remote ssh server
809
+by using the ssh protocol:
810
+
811
+@example
812
+qemu-system-x86_64 -drive file=ssh://[@var{user}@@]@var{server}[:@var{port}]/@var{path}[?host_key_check=@var{host_key_check}]
813
+@end example
814
+
815
+Alternative syntax using properties:
816
+
817
+@example
818
+qemu-system-x86_64 -drive file.driver=ssh[,file.user=@var{user}],file.host=@var{server}[,file.port=@var{port}],file.path=@var{path}[,file.host_key_check=@var{host_key_check}]
819
+@end example
820
+
821
+@var{ssh} is the protocol.
822
+
823
+@var{user} is the remote user. If not specified, then the local
824
+username is tried.
825
+
826
+@var{server} specifies the remote ssh server. Any ssh server can be
827
+used, but it must implement the sftp-server protocol. Most Unix/Linux
828
+systems should work without requiring any extra configuration.
829
+
830
+@var{port} is the port number on which sshd is listening. By default
831
+the standard ssh port (22) is used.
832
+
833
+@var{path} is the path to the disk image.
834
+
835
+The optional @var{host_key_check} parameter controls how the remote
836
+host's key is checked. The default is @code{yes} which means to use
837
+the local @file{.ssh/known_hosts} file. Setting this to @code{no}
838
+turns off known-hosts checking. Or you can check that the host key
839
+matches a specific fingerprint:
840
+@code{host_key_check=md5:78:45:8e:14:57:4f:d5:45:83:0a:0e:f3:49:82:c9:c8}
841
+(@code{sha1:} can also be used as a prefix, but note that OpenSSH
842
+tools only use MD5 to print fingerprints).
843
+
844
+Currently authentication must be done using ssh-agent. Other
845
+authentication methods may be supported in future.
846
+
847
+Note: Many ssh servers do not support an @code{fsync}-style operation.
848
+The ssh driver cannot guarantee that disk flush requests are
849
+obeyed, and this causes a risk of disk corruption if the remote
850
+server or network goes down during writes. The driver will
851
+print a warning when @code{fsync} is not supported:
852
+
853
+warning: ssh server @code{ssh.example.com:22} does not support fsync
854
+
855
+With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is
856
+supported.
857
+
858
+@c man end
859
+
860
+@ignore
861
+
862
+@setfilename qemu-block-drivers
863
+@settitle QEMU block drivers reference
864
+
865
+@c man begin SEEALSO
866
+The HTML documentation of QEMU for more precise information and Linux
867
+user mode emulator invocation.
868
+@c man end
869
+
870
+@c man begin AUTHOR
871
+Fabrice Bellard and the QEMU Project developers
872
+@c man end
873
+
874
+@end ignore
875
diff --git a/qemu-doc.texi b/qemu-doc.texi
876
index XXXXXXX..XXXXXXX 100644
877
--- a/qemu-doc.texi
878
+++ b/qemu-doc.texi
879
@@ -XXX,XX +XXX,XX @@ state is not saved or restored properly (in particular USB).
880
881
@include qemu-nbd.texi
882
883
-@node disk_images_formats
884
-@subsection Disk image file formats
885
-
157
-
886
-QEMU supports many image file formats that can be used with VMs as well as with
158
if (ret || r->req.io_canceled) {
887
-any of the tools (like @code{qemu-img}). This includes the preferred formats
159
scsi_command_complete_noio(r, ret);
888
-raw and qcow2 as well as formats that are supported for compatibility with
160
goto done;
889
-older QEMU versions or other hypervisors.
890
-
891
-Depending on the image format, different options can be passed to
892
-@code{qemu-img create} and @code{qemu-img convert} using the @code{-o} option.
893
-This section describes each format and the options that are supported for it.
894
-
895
-@table @option
896
-@item raw
897
-
898
-Raw disk image format. This format has the advantage of
899
-being simple and easily exportable to all other emulators. If your
900
-file system supports @emph{holes} (for example in ext2 or ext3 on
901
-Linux or NTFS on Windows), then only the written sectors will reserve
902
-space. Use @code{qemu-img info} to know the real size used by the
903
-image or @code{ls -ls} on Unix/Linux.
904
-
905
-Supported options:
906
-@table @code
907
-@item preallocation
908
-Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
909
-@code{falloc} mode preallocates space for image by calling posix_fallocate().
910
-@code{full} mode preallocates space for image by writing zeros to underlying
911
-storage.
912
-@end table
913
-
914
-@item qcow2
915
-QEMU image format, the most versatile format. Use it to have smaller
916
-images (useful if your filesystem does not supports holes, for example
917
-on Windows), zlib based compression and support of multiple VM
918
-snapshots.
919
-
920
-Supported options:
921
-@table @code
922
-@item compat
923
-Determines the qcow2 version to use. @code{compat=0.10} uses the
924
-traditional image format that can be read by any QEMU since 0.10.
925
-@code{compat=1.1} enables image format extensions that only QEMU 1.1 and
926
-newer understand (this is the default). Amongst others, this includes
927
-zero clusters, which allow efficient copy-on-read for sparse images.
928
-
929
-@item backing_file
930
-File name of a base image (see @option{create} subcommand)
931
-@item backing_fmt
932
-Image format of the base image
933
-@item encryption
934
-This option is deprecated and equivalent to @code{encrypt.format=aes}
935
-
936
-@item encrypt.format
937
-
938
-If this is set to @code{luks}, it requests that the qcow2 payload (not
939
-qcow2 header) be encrypted using the LUKS format. The passphrase to
940
-use to unlock the LUKS key slot is given by the @code{encrypt.key-secret}
941
-parameter. LUKS encryption parameters can be tuned with the other
942
-@code{encrypt.*} parameters.
943
-
944
-If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
945
-The encryption key is given by the @code{encrypt.key-secret} parameter.
946
-This encryption format is considered to be flawed by modern cryptography
947
-standards, suffering from a number of design problems:
948
-
949
-@itemize @minus
950
-@item The AES-CBC cipher is used with predictable initialization vectors based
951
-on the sector number. This makes it vulnerable to chosen plaintext attacks
952
-which can reveal the existence of encrypted data.
953
-@item The user passphrase is directly used as the encryption key. A poorly
954
-chosen or short passphrase will compromise the security of the encryption.
955
-@item In the event of the passphrase being compromised there is no way to
956
-change the passphrase to protect data in any qcow images. The files must
957
-be cloned, using a different encryption passphrase in the new file. The
958
-original file must then be securely erased using a program like shred,
959
-though even this is ineffective with many modern storage technologies.
960
-@end itemize
961
-
962
-The use of this is no longer supported in system emulators. Support only
963
-remains in the command line utilities, for the purposes of data liberation
964
-and interoperability with old versions of QEMU. The @code{luks} format
965
-should be used instead.
966
-
967
-@item encrypt.key-secret
968
-
969
-Provides the ID of a @code{secret} object that contains the passphrase
970
-(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}).
971
-
972
-@item encrypt.cipher-alg
973
-
974
-Name of the cipher algorithm and key length. Currently defaults
975
-to @code{aes-256}. Only used when @code{encrypt.format=luks}.
976
-
977
-@item encrypt.cipher-mode
978
-
979
-Name of the encryption mode to use. Currently defaults to @code{xts}.
980
-Only used when @code{encrypt.format=luks}.
981
-
982
-@item encrypt.ivgen-alg
983
-
984
-Name of the initialization vector generator algorithm. Currently defaults
985
-to @code{plain64}. Only used when @code{encrypt.format=luks}.
986
-
987
-@item encrypt.ivgen-hash-alg
988
-
989
-Name of the hash algorithm to use with the initialization vector generator
990
-(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
991
-
992
-@item encrypt.hash-alg
993
-
994
-Name of the hash algorithm to use for PBKDF algorithm
995
-Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
996
-
997
-@item encrypt.iter-time
998
-
999
-Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
1000
-Defaults to @code{2000}. Only used when @code{encrypt.format=luks}.
1001
-
1002
-@item cluster_size
1003
-Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
1004
-sizes can improve the image file size whereas larger cluster sizes generally
1005
-provide better performance.
1006
-
1007
-@item preallocation
1008
-Preallocation mode (allowed values: @code{off}, @code{metadata}, @code{falloc},
1009
-@code{full}). An image with preallocated metadata is initially larger but can
1010
-improve performance when the image needs to grow. @code{falloc} and @code{full}
1011
-preallocations are like the same options of @code{raw} format, but sets up
1012
-metadata also.
1013
-
1014
-@item lazy_refcounts
1015
-If this option is set to @code{on}, reference count updates are postponed with
1016
-the goal of avoiding metadata I/O and improving performance. This is
1017
-particularly interesting with @option{cache=writethrough} which doesn't batch
1018
-metadata updates. The tradeoff is that after a host crash, the reference count
1019
-tables must be rebuilt, i.e. on the next open an (automatic) @code{qemu-img
1020
-check -r all} is required, which may take some time.
1021
-
1022
-This option can only be enabled if @code{compat=1.1} is specified.
1023
-
1024
-@item nocow
1025
-If this option is set to @code{on}, it will turn off COW of the file. It's only
1026
-valid on btrfs, no effect on other file systems.
1027
-
1028
-Btrfs has low performance when hosting a VM image file, even more when the guest
1029
-on the VM also using btrfs as file system. Turning off COW is a way to mitigate
1030
-this bad performance. Generally there are two ways to turn off COW on btrfs:
1031
-a) Disable it by mounting with nodatacow, then all newly created files will be
1032
-NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option
1033
-does.
1034
-
1035
-Note: this option is only valid to new or empty files. If there is an existing
1036
-file which is COW and has data blocks already, it couldn't be changed to NOCOW
1037
-by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
1038
-the NOCOW flag is set or not (Capital 'C' is NOCOW flag).
1039
-
1040
-@end table
1041
-
1042
-@item qed
1043
-Old QEMU image format with support for backing files and compact image files
1044
-(when your filesystem or transport medium does not support holes).
1045
-
1046
-When converting QED images to qcow2, you might want to consider using the
1047
-@code{lazy_refcounts=on} option to get a more QED-like behaviour.
1048
-
1049
-Supported options:
1050
-@table @code
1051
-@item backing_file
1052
-File name of a base image (see @option{create} subcommand).
1053
-@item backing_fmt
1054
-Image file format of backing file (optional). Useful if the format cannot be
1055
-autodetected because it has no header, like some vhd/vpc files.
1056
-@item cluster_size
1057
-Changes the cluster size (must be power-of-2 between 4K and 64K). Smaller
1058
-cluster sizes can improve the image file size whereas larger cluster sizes
1059
-generally provide better performance.
1060
-@item table_size
1061
-Changes the number of clusters per L1/L2 table (must be power-of-2 between 1
1062
-and 16). There is normally no need to change this value but this option can be
1063
-used for performance benchmarking.
1064
-@end table
1065
-
1066
-@item qcow
1067
-Old QEMU image format with support for backing files, compact image files,
1068
-encryption and compression.
1069
-
1070
-Supported options:
1071
-@table @code
1072
-@item backing_file
1073
-File name of a base image (see @option{create} subcommand)
1074
-@item encryption
1075
-This option is deprecated and equivalent to @code{encrypt.format=aes}
1076
-
1077
-@item encrypt.format
1078
-If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
1079
-The encryption key is given by the @code{encrypt.key-secret} parameter.
1080
-This encryption format is considered to be flawed by modern cryptography
1081
-standards, suffering from a number of design problems enumerated previously
1082
-against the @code{qcow2} image format.
1083
-
1084
-The use of this is no longer supported in system emulators. Support only
1085
-remains in the command line utilities, for the purposes of data liberation
1086
-and interoperability with old versions of QEMU.
1087
-
1088
-Users requiring native encryption should use the @code{qcow2} format
1089
-instead with @code{encrypt.format=luks}.
1090
-
1091
-@item encrypt.key-secret
1092
-
1093
-Provides the ID of a @code{secret} object that contains the encryption
1094
-key (@code{encrypt.format=aes}).
1095
-
1096
-@end table
1097
-
1098
-@item luks
1099
-
1100
-LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup
1101
-
1102
-Supported options:
1103
-@table @code
1104
-
1105
-@item key-secret
1106
-
1107
-Provides the ID of a @code{secret} object that contains the passphrase.
1108
-
1109
-@item cipher-alg
1110
-
1111
-Name of the cipher algorithm and key length. Currently defaults
1112
-to @code{aes-256}.
1113
-
1114
-@item cipher-mode
1115
-
1116
-Name of the encryption mode to use. Currently defaults to @code{xts}.
1117
-
1118
-@item ivgen-alg
1119
-
1120
-Name of the initialization vector generator algorithm. Currently defaults
1121
-to @code{plain64}.
1122
-
1123
-@item ivgen-hash-alg
1124
-
1125
-Name of the hash algorithm to use with the initialization vector generator
1126
-(if required). Defaults to @code{sha256}.
1127
-
1128
-@item hash-alg
1129
-
1130
-Name of the hash algorithm to use for PBKDF algorithm
1131
-Defaults to @code{sha256}.
1132
-
1133
-@item iter-time
1134
-
1135
-Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
1136
-Defaults to @code{2000}.
1137
-
1138
-@end table
1139
-
1140
-@item vdi
1141
-VirtualBox 1.1 compatible image format.
1142
-Supported options:
1143
-@table @code
1144
-@item static
1145
-If this option is set to @code{on}, the image is created with metadata
1146
-preallocation.
1147
-@end table
1148
-
1149
-@item vmdk
1150
-VMware 3 and 4 compatible image format.
1151
-
1152
-Supported options:
1153
-@table @code
1154
-@item backing_file
1155
-File name of a base image (see @option{create} subcommand).
1156
-@item compat6
1157
-Create a VMDK version 6 image (instead of version 4)
1158
-@item hwversion
1159
-Specify vmdk virtual hardware version. Compat6 flag cannot be enabled
1160
-if hwversion is specified.
1161
-@item subformat
1162
-Specifies which VMDK subformat to use. Valid options are
1163
-@code{monolithicSparse} (default),
1164
-@code{monolithicFlat},
1165
-@code{twoGbMaxExtentSparse},
1166
-@code{twoGbMaxExtentFlat} and
1167
-@code{streamOptimized}.
1168
-@end table
1169
-
1170
-@item vpc
1171
-VirtualPC compatible image format (VHD).
1172
-Supported options:
1173
-@table @code
1174
-@item subformat
1175
-Specifies which VHD subformat to use. Valid options are
1176
-@code{dynamic} (default) and @code{fixed}.
1177
-@end table
1178
-
1179
-@item VHDX
1180
-Hyper-V compatible image format (VHDX).
1181
-Supported options:
1182
-@table @code
1183
-@item subformat
1184
-Specifies which VHDX subformat to use. Valid options are
1185
-@code{dynamic} (default) and @code{fixed}.
1186
-@item block_state_zero
1187
-Force use of payload blocks of type 'ZERO'. Can be set to @code{on} (default)
1188
-or @code{off}. When set to @code{off}, new blocks will be created as
1189
-@code{PAYLOAD_BLOCK_NOT_PRESENT}, which means parsers are free to return
1190
-arbitrary data for those blocks. Do not set to @code{off} when using
1191
-@code{qemu-img convert} with @code{subformat=dynamic}.
1192
-@item block_size
1193
-Block size; min 1 MB, max 256 MB. 0 means auto-calculate based on image size.
1194
-@item log_size
1195
-Log size; min 1 MB.
1196
-@end table
1197
-@end table
1198
-
1199
-@subsubsection Read-only formats
1200
-More disk image file formats are supported in a read-only mode.
1201
-@table @option
1202
-@item bochs
1203
-Bochs images of @code{growing} type.
1204
-@item cloop
1205
-Linux Compressed Loop image, useful only to reuse directly compressed
1206
-CD-ROM images present for example in the Knoppix CD-ROMs.
1207
-@item dmg
1208
-Apple disk image.
1209
-@item parallels
1210
-Parallels disk image format.
1211
-@end table
1212
-
1213
-
1214
-@node host_drives
1215
-@subsection Using host drives
1216
-
1217
-In addition to disk image files, QEMU can directly access host
1218
-devices. We describe here the usage for QEMU version >= 0.8.3.
1219
-
1220
-@subsubsection Linux
1221
-
1222
-On Linux, you can directly use the host device filename instead of a
1223
-disk image filename provided you have enough privileges to access
1224
-it. For example, use @file{/dev/cdrom} to access to the CDROM.
1225
-
1226
-@table @code
1227
-@item CD
1228
-You can specify a CDROM device even if no CDROM is loaded. QEMU has
1229
-specific code to detect CDROM insertion or removal. CDROM ejection by
1230
-the guest OS is supported. Currently only data CDs are supported.
1231
-@item Floppy
1232
-You can specify a floppy device even if no floppy is loaded. Floppy
1233
-removal is currently not detected accurately (if you change floppy
1234
-without doing floppy access while the floppy is not loaded, the guest
1235
-OS will think that the same floppy is loaded).
1236
-Use of the host's floppy device is deprecated, and support for it will
1237
-be removed in a future release.
1238
-@item Hard disks
1239
-Hard disks can be used. Normally you must specify the whole disk
1240
-(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can
1241
-see it as a partitioned disk. WARNING: unless you know what you do, it
1242
-is better to only make READ-ONLY accesses to the hard disk otherwise
1243
-you may corrupt your host data (use the @option{-snapshot} command
1244
-line option or modify the device permissions accordingly).
1245
-@end table
1246
-
1247
-@subsubsection Windows
1248
-
1249
-@table @code
1250
-@item CD
1251
-The preferred syntax is the drive letter (e.g. @file{d:}). The
1252
-alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is
1253
-supported as an alias to the first CDROM drive.
1254
-
1255
-Currently there is no specific code to handle removable media, so it
1256
-is better to use the @code{change} or @code{eject} monitor commands to
1257
-change or eject media.
1258
-@item Hard disks
1259
-Hard disks can be used with the syntax: @file{\\.\PhysicalDrive@var{N}}
1260
-where @var{N} is the drive number (0 is the first hard disk).
1261
-
1262
-WARNING: unless you know what you do, it is better to only make
1263
-READ-ONLY accesses to the hard disk otherwise you may corrupt your
1264
-host data (use the @option{-snapshot} command line so that the
1265
-modifications are written in a temporary file).
1266
-@end table
1267
-
1268
-
1269
-@subsubsection Mac OS X
1270
-
1271
-@file{/dev/cdrom} is an alias to the first CDROM.
1272
-
1273
-Currently there is no specific code to handle removable media, so it
1274
-is better to use the @code{change} or @code{eject} monitor commands to
1275
-change or eject media.
1276
-
1277
-@node disk_images_fat_images
1278
-@subsection Virtual FAT disk images
1279
-
1280
-QEMU can automatically create a virtual FAT disk image from a
1281
-directory tree. In order to use it, just type:
1282
-
1283
-@example
1284
-qemu-system-i386 linux.img -hdb fat:/my_directory
1285
-@end example
1286
-
1287
-Then you access access to all the files in the @file{/my_directory}
1288
-directory without having to copy them in a disk image or to export
1289
-them via SAMBA or NFS. The default access is @emph{read-only}.
1290
-
1291
-Floppies can be emulated with the @code{:floppy:} option:
1292
-
1293
-@example
1294
-qemu-system-i386 linux.img -fda fat:floppy:/my_directory
1295
-@end example
1296
-
1297
-A read/write support is available for testing (beta stage) with the
1298
-@code{:rw:} option:
1299
-
1300
-@example
1301
-qemu-system-i386 linux.img -fda fat:floppy:rw:/my_directory
1302
-@end example
1303
-
1304
-What you should @emph{never} do:
1305
-@itemize
1306
-@item use non-ASCII filenames ;
1307
-@item use "-snapshot" together with ":rw:" ;
1308
-@item expect it to work when loadvm'ing ;
1309
-@item write to the FAT directory on the host system while accessing it with the guest system.
1310
-@end itemize
1311
-
1312
-@node disk_images_nbd
1313
-@subsection NBD access
1314
-
1315
-QEMU can access directly to block device exported using the Network Block Device
1316
-protocol.
1317
-
1318
-@example
1319
-qemu-system-i386 linux.img -hdb nbd://my_nbd_server.mydomain.org:1024/
1320
-@end example
1321
-
1322
-If the NBD server is located on the same host, you can use an unix socket instead
1323
-of an inet socket:
1324
-
1325
-@example
1326
-qemu-system-i386 linux.img -hdb nbd+unix://?socket=/tmp/my_socket
1327
-@end example
1328
-
1329
-In this case, the block device must be exported using qemu-nbd:
1330
-
1331
-@example
1332
-qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
1333
-@end example
1334
-
1335
-The use of qemu-nbd allows sharing of a disk between several guests:
1336
-@example
1337
-qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
1338
-@end example
1339
-
1340
-@noindent
1341
-and then you can use it with two guests:
1342
-@example
1343
-qemu-system-i386 linux1.img -hdb nbd+unix://?socket=/tmp/my_socket
1344
-qemu-system-i386 linux2.img -hdb nbd+unix://?socket=/tmp/my_socket
1345
-@end example
1346
-
1347
-If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's
1348
-own embedded NBD server), you must specify an export name in the URI:
1349
-@example
1350
-qemu-system-i386 -cdrom nbd://localhost/debian-500-ppc-netinst
1351
-qemu-system-i386 -cdrom nbd://localhost/openSUSE-11.1-ppc-netinst
1352
-@end example
1353
-
1354
-The URI syntax for NBD is supported since QEMU 1.3. An alternative syntax is
1355
-also available. Here are some example of the older syntax:
1356
-@example
1357
-qemu-system-i386 linux.img -hdb nbd:my_nbd_server.mydomain.org:1024
1358
-qemu-system-i386 linux2.img -hdb nbd:unix:/tmp/my_socket
1359
-qemu-system-i386 -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst
1360
-@end example
1361
-
1362
-@node disk_images_sheepdog
1363
-@subsection Sheepdog disk images
1364
-
1365
-Sheepdog is a distributed storage system for QEMU. It provides highly
1366
-available block level storage volumes that can be attached to
1367
-QEMU-based virtual machines.
1368
-
1369
-You can create a Sheepdog disk image with the command:
1370
-@example
1371
-qemu-img create sheepdog:///@var{image} @var{size}
1372
-@end example
1373
-where @var{image} is the Sheepdog image name and @var{size} is its
1374
-size.
1375
-
1376
-To import the existing @var{filename} to Sheepdog, you can use a
1377
-convert command.
1378
-@example
1379
-qemu-img convert @var{filename} sheepdog:///@var{image}
1380
-@end example
1381
-
1382
-You can boot from the Sheepdog disk image with the command:
1383
-@example
1384
-qemu-system-i386 sheepdog:///@var{image}
1385
-@end example
1386
-
1387
-You can also create a snapshot of the Sheepdog image like qcow2.
1388
-@example
1389
-qemu-img snapshot -c @var{tag} sheepdog:///@var{image}
1390
-@end example
1391
-where @var{tag} is a tag name of the newly created snapshot.
1392
-
1393
-To boot from the Sheepdog snapshot, specify the tag name of the
1394
-snapshot.
1395
-@example
1396
-qemu-system-i386 sheepdog:///@var{image}#@var{tag}
1397
-@end example
1398
-
1399
-You can create a cloned image from the existing snapshot.
1400
-@example
1401
-qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
1402
-@end example
1403
-where @var{base} is a image name of the source snapshot and @var{tag}
1404
-is its tag name.
1405
-
1406
-You can use an unix socket instead of an inet socket:
1407
-
1408
-@example
1409
-qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path}
1410
-@end example
1411
-
1412
-If the Sheepdog daemon doesn't run on the local host, you need to
1413
-specify one of the Sheepdog servers to connect to.
1414
-@example
1415
-qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size}
1416
-qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image}
1417
-@end example
1418
-
1419
-@node disk_images_iscsi
1420
-@subsection iSCSI LUNs
1421
-
1422
-iSCSI is a popular protocol used to access SCSI devices across a computer
1423
-network.
1424
-
1425
-There are two different ways iSCSI devices can be used by QEMU.
1426
-
1427
-The first method is to mount the iSCSI LUN on the host, and make it appear as
1428
-any other ordinary SCSI device on the host and then to access this device as a
1429
-/dev/sd device from QEMU. How to do this differs between host OSes.
1430
-
1431
-The second method involves using the iSCSI initiator that is built into
1432
-QEMU. This provides a mechanism that works the same way regardless of which
1433
-host OS you are running QEMU on. This section will describe this second method
1434
-of using iSCSI together with QEMU.
1435
-
1436
-In QEMU, iSCSI devices are described using special iSCSI URLs
1437
-
1438
-@example
1439
-URL syntax:
1440
-iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
1441
-@end example
1442
-
1443
-Username and password are optional and only used if your target is set up
1444
-using CHAP authentication for access control.
1445
-Alternatively the username and password can also be set via environment
1446
-variables to have these not show up in the process list
1447
-
1448
-@example
1449
-export LIBISCSI_CHAP_USERNAME=<username>
1450
-export LIBISCSI_CHAP_PASSWORD=<password>
1451
-iscsi://<host>/<target-iqn-name>/<lun>
1452
-@end example
1453
-
1454
-Various session related parameters can be set via special options, either
1455
-in a configuration file provided via '-readconfig' or directly on the
1456
-command line.
1457
-
1458
-If the initiator-name is not specified qemu will use a default name
1459
-of 'iqn.2008-11.org.linux-kvm[:<uuid>'] where <uuid> is the UUID of the
1460
-virtual machine. If the UUID is not specified qemu will use
1461
-'iqn.2008-11.org.linux-kvm[:<name>'] where <name> is the name of the
1462
-virtual machine.
1463
-
1464
-@example
1465
-Setting a specific initiator name to use when logging in to the target
1466
--iscsi initiator-name=iqn.qemu.test:my-initiator
1467
-@end example
1468
-
1469
-@example
1470
-Controlling which type of header digest to negotiate with the target
1471
--iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
1472
-@end example
1473
-
1474
-These can also be set via a configuration file
1475
-@example
1476
-[iscsi]
1477
- user = "CHAP username"
1478
- password = "CHAP password"
1479
- initiator-name = "iqn.qemu.test:my-initiator"
1480
- # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
1481
- header-digest = "CRC32C"
1482
-@end example
1483
-
1484
-
1485
-Setting the target name allows different options for different targets
1486
-@example
1487
-[iscsi "iqn.target.name"]
1488
- user = "CHAP username"
1489
- password = "CHAP password"
1490
- initiator-name = "iqn.qemu.test:my-initiator"
1491
- # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
1492
- header-digest = "CRC32C"
1493
-@end example
1494
-
1495
-
1496
-Howto use a configuration file to set iSCSI configuration options:
1497
-@example
1498
-cat >iscsi.conf <<EOF
1499
-[iscsi]
1500
- user = "me"
1501
- password = "my password"
1502
- initiator-name = "iqn.qemu.test:my-initiator"
1503
- header-digest = "CRC32C"
1504
-EOF
1505
-
1506
-qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
1507
- -readconfig iscsi.conf
1508
-@end example
1509
-
1510
-
1511
-Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
1512
-@example
1513
-This example shows how to set up an iSCSI target with one CDROM and one DISK
1514
-using the Linux STGT software target. This target is available on Red Hat based
1515
-systems as the package 'scsi-target-utils'.
1516
-
1517
-tgtd --iscsi portal=127.0.0.1:3260
1518
-tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test
1519
-tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \
1520
- -b /IMAGES/disk.img --device-type=disk
1521
-tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
1522
- -b /IMAGES/cd.iso --device-type=cd
1523
-tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
1524
-
1525
-qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
1526
- -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
1527
- -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
1528
-@end example
1529
-
1530
-@node disk_images_gluster
1531
-@subsection GlusterFS disk images
1532
-
1533
-GlusterFS is a user space distributed file system.
1534
-
1535
-You can boot from the GlusterFS disk image with the command:
1536
-@example
1537
-URI:
1538
-qemu-system-x86_64 -drive file=gluster[+@var{type}]://[@var{host}[:@var{port}]]/@var{volume}/@var{path}
1539
- [?socket=...][,file.debug=9][,file.logfile=...]
1540
-
1541
-JSON:
1542
-qemu-system-x86_64 'json:@{"driver":"qcow2",
1543
- "file":@{"driver":"gluster",
1544
- "volume":"testvol","path":"a.img","debug":9,"logfile":"...",
1545
- "server":[@{"type":"tcp","host":"...","port":"..."@},
1546
- @{"type":"unix","socket":"..."@}]@}@}'
1547
-@end example
1548
-
1549
-@var{gluster} is the protocol.
1550
-
1551
-@var{type} specifies the transport type used to connect to gluster
1552
-management daemon (glusterd). Valid transport types are
1553
-tcp and unix. In the URI form, if a transport type isn't specified,
1554
-then tcp type is assumed.
1555
-
1556
-@var{host} specifies the server where the volume file specification for
1557
-the given volume resides. This can be either a hostname or an ipv4 address.
1558
-If transport type is unix, then @var{host} field should not be specified.
1559
-Instead @var{socket} field needs to be populated with the path to unix domain
1560
-socket.
1561
-
1562
-@var{port} is the port number on which glusterd is listening. This is optional
1563
-and if not specified, it defaults to port 24007. If the transport type is unix,
1564
-then @var{port} should not be specified.
1565
-
1566
-@var{volume} is the name of the gluster volume which contains the disk image.
1567
-
1568
-@var{path} is the path to the actual disk image that resides on gluster volume.
1569
-
1570
-@var{debug} is the logging level of the gluster protocol driver. Debug levels
1571
-are 0-9, with 9 being the most verbose, and 0 representing no debugging output.
1572
-The default level is 4. The current logging levels defined in the gluster source
1573
-are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning,
1574
-6 - Notice, 7 - Info, 8 - Debug, 9 - Trace
1575
-
1576
-@var{logfile} is a commandline option to mention log file path which helps in
1577
-logging to the specified file and also help in persisting the gfapi logs. The
1578
-default is stderr.
1579
-
1580
-
1581
-
1582
-
1583
-You can create a GlusterFS disk image with the command:
1584
-@example
1585
-qemu-img create gluster://@var{host}/@var{volume}/@var{path} @var{size}
1586
-@end example
1587
-
1588
-Examples
1589
-@example
1590
-qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img
1591
-qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4/testvol/a.img
1592
-qemu-system-x86_64 -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
1593
-qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
1594
-qemu-system-x86_64 -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
1595
-qemu-system-x86_64 -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
1596
-qemu-system-x86_64 -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
1597
-qemu-system-x86_64 -drive file=gluster+rdma://1.2.3.4:24007/testvol/a.img
1598
-qemu-system-x86_64 -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log
1599
-qemu-system-x86_64 'json:@{"driver":"qcow2",
1600
- "file":@{"driver":"gluster",
1601
- "volume":"testvol","path":"a.img",
1602
- "debug":9,"logfile":"/var/log/qemu-gluster.log",
1603
- "server":[@{"type":"tcp","host":"1.2.3.4","port":24007@},
1604
- @{"type":"unix","socket":"/var/run/glusterd.socket"@}]@}@}'
1605
-qemu-system-x86_64 -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
1606
- file.debug=9,file.logfile=/var/log/qemu-gluster.log,
1607
- file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
1608
- file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
1609
-@end example
1610
-
1611
-@node disk_images_ssh
1612
-@subsection Secure Shell (ssh) disk images
1613
-
1614
-You can access disk images located on a remote ssh server
1615
-by using the ssh protocol:
1616
-
1617
-@example
1618
-qemu-system-x86_64 -drive file=ssh://[@var{user}@@]@var{server}[:@var{port}]/@var{path}[?host_key_check=@var{host_key_check}]
1619
-@end example
1620
-
1621
-Alternative syntax using properties:
1622
-
1623
-@example
1624
-qemu-system-x86_64 -drive file.driver=ssh[,file.user=@var{user}],file.host=@var{server}[,file.port=@var{port}],file.path=@var{path}[,file.host_key_check=@var{host_key_check}]
1625
-@end example
1626
-
1627
-@var{ssh} is the protocol.
1628
-
1629
-@var{user} is the remote user. If not specified, then the local
1630
-username is tried.
1631
-
1632
-@var{server} specifies the remote ssh server. Any ssh server can be
1633
-used, but it must implement the sftp-server protocol. Most Unix/Linux
1634
-systems should work without requiring any extra configuration.
1635
-
1636
-@var{port} is the port number on which sshd is listening. By default
1637
-the standard ssh port (22) is used.
1638
-
1639
-@var{path} is the path to the disk image.
1640
-
1641
-The optional @var{host_key_check} parameter controls how the remote
1642
-host's key is checked. The default is @code{yes} which means to use
1643
-the local @file{.ssh/known_hosts} file. Setting this to @code{no}
1644
-turns off known-hosts checking. Or you can check that the host key
1645
-matches a specific fingerprint:
1646
-@code{host_key_check=md5:78:45:8e:14:57:4f:d5:45:83:0a:0e:f3:49:82:c9:c8}
1647
-(@code{sha1:} can also be used as a prefix, but note that OpenSSH
1648
-tools only use MD5 to print fingerprints).
1649
-
1650
-Currently authentication must be done using ssh-agent. Other
1651
-authentication methods may be supported in future.
1652
-
1653
-Note: Many ssh servers do not support an @code{fsync}-style operation.
1654
-The ssh driver cannot guarantee that disk flush requests are
1655
-obeyed, and this causes a risk of disk corruption if the remote
1656
-server or network goes down during writes. The driver will
1657
-print a warning when @code{fsync} is not supported:
1658
-
1659
-warning: ssh server @code{ssh.example.com:22} does not support fsync
1660
-
1661
-With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is
1662
-supported.
1663
+@include docs/qemu-block-drivers.texi
1664
1665
@node pcsys_network
1666
@section Network emulation
1667
--
161
--
1668
2.13.5
162
2.39.2
1669
1670
diff view generated by jsdifflib
1
A basic set of qemu options is initialised in ./common:
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
export QEMU_OPTIONS="-nodefaults -machine accel=qtest"
3
dma_blk_cb() only takes the AioContext lock around ->io_func(). That
4
means the rest of dma_blk_cb() is not protected. In particular, the
5
DMAAIOCB field accesses happen outside the lock.
4
6
5
However, two test cases (172 and 186) overwrite QEMU_OPTIONS and neglect
7
There is a race when the main loop thread holds the AioContext lock and
6
to manually set '-machine accel=qtest'. Add the missing option for 172.
8
invokes scsi_device_purge_requests() -> bdrv_aio_cancel() ->
7
186 probably only copied the code from 172, it doesn't actually need to
9
dma_aio_cancel() while an IOThread executes dma_blk_cb(). The dbs->acb
8
overwrite QEMU_OPTIONS, so remove that in 186.
10
field determines how cancellation proceeds. If dma_aio_cancel() sees
11
dbs->acb == NULL while dma_blk_cb() is still running, the request can be
12
completed twice (-ECANCELED and the actual return value).
9
13
14
The following assertion can occur with virtio-scsi when an IOThread is
15
used:
16
17
../hw/scsi/scsi-disk.c:368: scsi_dma_complete: Assertion `r->req.aiocb != NULL' failed.
18
19
Fix the race by holding the AioContext across dma_blk_cb(). Now
20
dma_aio_cancel() under the AioContext lock will not see
21
inconsistent/intermediate states.
22
23
Cc: Paolo Bonzini <pbonzini@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Message-Id: <20230221212218.1378734-3-stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Tested-by: Cornelia Huck <cohuck@redhat.com>
12
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
13
---
28
---
14
tests/qemu-iotests/172 | 2 +-
29
hw/scsi/scsi-disk.c | 4 +---
15
tests/qemu-iotests/186 | 6 +++---
30
softmmu/dma-helpers.c | 12 +++++++-----
16
2 files changed, 4 insertions(+), 4 deletions(-)
31
2 files changed, 8 insertions(+), 8 deletions(-)
17
32
18
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
33
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
19
index XXXXXXX..XXXXXXX 100755
34
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/172
35
--- a/hw/scsi/scsi-disk.c
21
+++ b/tests/qemu-iotests/172
36
+++ b/hw/scsi/scsi-disk.c
22
@@ -XXX,XX +XXX,XX @@ function do_run_qemu()
37
@@ -XXX,XX +XXX,XX @@ done:
23
done
38
scsi_req_unref(&r->req);
24
fi
25
echo quit
26
- ) | $QEMU -nographic -monitor stdio -serial none "$@"
27
+ ) | $QEMU -machine accel=qtest -nographic -monitor stdio -serial none "$@"
28
echo
29
}
39
}
30
40
31
diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186
41
+/* Called with AioContext lock held */
32
index XXXXXXX..XXXXXXX 100755
42
static void scsi_dma_complete(void *opaque, int ret)
33
--- a/tests/qemu-iotests/186
43
{
34
+++ b/tests/qemu-iotests/186
44
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
35
@@ -XXX,XX +XXX,XX @@ function do_run_qemu()
45
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
36
done
46
37
fi
47
- aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
38
echo quit
48
-
39
- ) | $QEMU -S -nodefaults -display none -device virtio-scsi-pci -monitor stdio "$@" 2>&1
49
assert(r->req.aiocb != NULL);
40
+ ) | $QEMU -S -display none -device virtio-scsi-pci -monitor stdio "$@" 2>&1
50
r->req.aiocb = NULL;
41
echo
51
52
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
53
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
54
}
55
scsi_dma_complete_noio(r, ret);
56
- aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
42
}
57
}
43
58
44
function check_info_block()
59
static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
60
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/softmmu/dma-helpers.c
63
+++ b/softmmu/dma-helpers.c
64
@@ -XXX,XX +XXX,XX @@ static void dma_complete(DMAAIOCB *dbs, int ret)
65
static void dma_blk_cb(void *opaque, int ret)
45
{
66
{
46
echo "info block" |
67
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
47
- QEMU_OPTIONS="" do_run_qemu "$@" | _filter_win32 | _filter_hmp |
68
+ AioContext *ctx = dbs->ctx;
48
- _filter_qemu | _filter_generated_node_ids
69
dma_addr_t cur_addr, cur_len;
49
+ do_run_qemu "$@" | _filter_win32 | _filter_hmp | _filter_qemu |
70
void *mem;
50
+ _filter_generated_node_ids
71
72
trace_dma_blk_cb(dbs, ret);
73
74
+ aio_context_acquire(ctx);
75
dbs->acb = NULL;
76
dbs->offset += dbs->iov.size;
77
78
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
79
dma_complete(dbs, ret);
80
- return;
81
+ goto out;
82
}
83
dma_blk_unmap(dbs);
84
85
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
86
87
if (dbs->iov.size == 0) {
88
trace_dma_map_wait(dbs);
89
- dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs);
90
+ dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs);
91
cpu_register_map_client(dbs->bh);
92
- return;
93
+ goto out;
94
}
95
96
if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) {
97
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
98
QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align));
99
}
100
101
- aio_context_acquire(dbs->ctx);
102
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
103
dma_blk_cb, dbs, dbs->io_func_opaque);
104
- aio_context_release(dbs->ctx);
105
assert(dbs->acb);
106
+out:
107
+ aio_context_release(ctx);
51
}
108
}
52
109
53
110
static void dma_aio_cancel(BlockAIOCB *acb)
54
--
111
--
55
2.13.5
112
2.39.2
56
57
diff view generated by jsdifflib
1
This involves a temporary read-write reopen if the backing file link in
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
the middle of a backing file chain should be changed and is therefore a
2
3
good test for the latest bdrv_reopen() vs. op blockers fixes.
3
When an IOThread is configured, the ctrl virtqueue is processed in the
4
4
IOThread. TMFs that reset SCSI devices are currently called directly
5
from the IOThread and trigger an assertion failure in blk_drain() from
6
the following call stack:
7
8
virtio_scsi_handle_ctrl_req -> virtio_scsi_do_tmf -> device_code_reset
9
-> scsi_disk_reset -> scsi_device_purge_requests -> blk_drain
10
11
../block/block-backend.c:1780: void blk_drain(BlockBackend *): Assertion `qemu_in_main_thread()' failed.
12
13
The blk_drain() function is not designed to be called from an IOThread
14
because it needs the Big QEMU Lock (BQL).
15
16
This patch defers TMFs that reset SCSI devices to a Bottom Half (BH)
17
that runs in the main loop thread under the BQL. This way it's safe to
18
call blk_drain() and the assertion failure is avoided.
19
20
Introduce s->tmf_bh_list for tracking TMF requests that have been
21
deferred to the BH. When the BH runs it will grab the entire list and
22
process all requests. Care must be taken to clear the list when the
23
virtio-scsi device is reset or unrealized. Otherwise deferred TMF
24
requests could execute later and lead to use-after-free or other
25
undefined behavior.
26
27
The s->resetting counter that's used by TMFs that reset SCSI devices is
28
accessed from multiple threads. This patch makes that explicit by using
29
atomic accessor functions. With this patch applied the counter is only
30
modified by the main loop thread under the BQL but can be read by any
31
thread.
32
33
Reported-by: Qing Wang <qinwang@redhat.com>
34
Cc: Paolo Bonzini <pbonzini@redhat.com>
35
Reviewed-by: Eric Blake <eblake@redhat.com>
36
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
37
Message-Id: <20230221212218.1378734-4-stefanha@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
39
---
7
tests/qemu-iotests/195 | 92 ++++++++++++++++++++++++++++++++++++++++++++++
40
include/hw/virtio/virtio-scsi.h | 11 ++-
8
tests/qemu-iotests/195.out | 78 +++++++++++++++++++++++++++++++++++++++
41
hw/scsi/virtio-scsi.c | 169 +++++++++++++++++++++++++-------
9
tests/qemu-iotests/group | 1 +
42
2 files changed, 143 insertions(+), 37 deletions(-)
10
3 files changed, 171 insertions(+)
43
11
create mode 100755 tests/qemu-iotests/195
44
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
12
create mode 100644 tests/qemu-iotests/195.out
45
index XXXXXXX..XXXXXXX 100644
13
46
--- a/include/hw/virtio/virtio-scsi.h
14
diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195
47
+++ b/include/hw/virtio/virtio-scsi.h
15
new file mode 100755
48
@@ -XXX,XX +XXX,XX @@ struct VirtIOSCSICommon {
16
index XXXXXXX..XXXXXXX
49
VirtQueue **cmd_vqs;
17
--- /dev/null
50
};
18
+++ b/tests/qemu-iotests/195
51
19
@@ -XXX,XX +XXX,XX @@
52
+struct VirtIOSCSIReq;
20
+#!/bin/bash
53
+
21
+#
54
struct VirtIOSCSI {
22
+# Test change-backing-file command
55
VirtIOSCSICommon parent_obj;
23
+#
56
24
+# Copyright (C) 2017 Red Hat, Inc.
57
SCSIBus bus;
25
+#
58
- int resetting;
26
+# This program is free software; you can redistribute it and/or modify
59
+ int resetting; /* written from main loop thread, read from any thread */
27
+# it under the terms of the GNU General Public License as published by
60
bool events_dropped;
28
+# the Free Software Foundation; either version 2 of the License, or
61
29
+# (at your option) any later version.
62
+ /*
30
+#
63
+ * TMFs deferred to main loop BH. These fields are protected by
31
+# This program is distributed in the hope that it will be useful,
64
+ * virtio_scsi_acquire().
32
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
65
+ */
33
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66
+ QEMUBH *tmf_bh;
34
+# GNU General Public License for more details.
67
+ QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list;
35
+#
68
+
36
+# You should have received a copy of the GNU General Public License
69
/* Fields for dataplane below */
37
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
70
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
38
+#
71
39
+
72
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
40
+# creator
73
index XXXXXXX..XXXXXXX 100644
41
+owner=kwolf@redhat.com
74
--- a/hw/scsi/virtio-scsi.c
42
+
75
+++ b/hw/scsi/virtio-scsi.c
43
+seq=`basename $0`
76
@@ -XXX,XX +XXX,XX @@ typedef struct VirtIOSCSIReq {
44
+echo "QA output created by $seq"
77
QEMUSGList qsgl;
45
+
78
QEMUIOVector resp_iov;
46
+here=`pwd`
79
47
+status=1 # failure is the default!
80
- union {
48
+
81
- /* Used for two-stage request submission */
49
+_cleanup()
82
- QTAILQ_ENTRY(VirtIOSCSIReq) next;
83
+ /* Used for two-stage request submission and TMFs deferred to BH */
84
+ QTAILQ_ENTRY(VirtIOSCSIReq) next;
85
86
- /* Used for cancellation of request during TMFs */
87
- int remaining;
88
- };
89
+ /* Used for cancellation of request during TMFs */
90
+ int remaining;
91
92
SCSIRequest *sreq;
93
size_t resp_size;
94
@@ -XXX,XX +XXX,XX @@ static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
95
}
96
}
97
98
+static void virtio_scsi_do_one_tmf_bh(VirtIOSCSIReq *req)
50
+{
99
+{
51
+ _cleanup_test_img
100
+ VirtIOSCSI *s = req->dev;
52
+ rm -f "$TEST_IMG.mid"
101
+ SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
102
+ BusChild *kid;
103
+ int target;
104
+
105
+ switch (req->req.tmf.subtype) {
106
+ case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
107
+ if (!d) {
108
+ req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
109
+ goto out;
110
+ }
111
+ if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
112
+ req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
113
+ goto out;
114
+ }
115
+ qatomic_inc(&s->resetting);
116
+ device_cold_reset(&d->qdev);
117
+ qatomic_dec(&s->resetting);
118
+ break;
119
+
120
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
121
+ target = req->req.tmf.lun[1];
122
+ qatomic_inc(&s->resetting);
123
+
124
+ rcu_read_lock();
125
+ QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
126
+ SCSIDevice *d1 = SCSI_DEVICE(kid->child);
127
+ if (d1->channel == 0 && d1->id == target) {
128
+ device_cold_reset(&d1->qdev);
129
+ }
130
+ }
131
+ rcu_read_unlock();
132
+
133
+ qatomic_dec(&s->resetting);
134
+ break;
135
+
136
+ default:
137
+ g_assert_not_reached();
138
+ break;
139
+ }
140
+
141
+out:
142
+ object_unref(OBJECT(d));
143
+
144
+ virtio_scsi_acquire(s);
145
+ virtio_scsi_complete_req(req);
146
+ virtio_scsi_release(s);
53
+}
147
+}
54
+trap "_cleanup; exit \$status" 0 1 2 3 15
148
+
55
+
149
+/* Some TMFs must be processed from the main loop thread */
56
+# get standard environment, filters and checks
150
+static void virtio_scsi_do_tmf_bh(void *opaque)
57
+. ./common.rc
58
+. ./common.filter
59
+
60
+_supported_fmt qcow2
61
+_supported_proto file
62
+_supported_os Linux
63
+
64
+function do_run_qemu()
65
+{
151
+{
66
+ echo Testing: "$@" | _filter_imgfmt
152
+ VirtIOSCSI *s = opaque;
67
+ $QEMU -nographic -qmp-pretty stdio -serial none "$@"
153
+ QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
68
+ echo
154
+ VirtIOSCSIReq *req;
155
+ VirtIOSCSIReq *tmp;
156
+
157
+ GLOBAL_STATE_CODE();
158
+
159
+ virtio_scsi_acquire(s);
160
+
161
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
162
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
163
+ QTAILQ_INSERT_TAIL(&reqs, req, next);
164
+ }
165
+
166
+ qemu_bh_delete(s->tmf_bh);
167
+ s->tmf_bh = NULL;
168
+
169
+ virtio_scsi_release(s);
170
+
171
+ QTAILQ_FOREACH_SAFE(req, &reqs, next, tmp) {
172
+ QTAILQ_REMOVE(&reqs, req, next);
173
+ virtio_scsi_do_one_tmf_bh(req);
174
+ }
69
+}
175
+}
70
+
176
+
71
+function run_qemu()
177
+static void virtio_scsi_reset_tmf_bh(VirtIOSCSI *s)
72
+{
178
+{
73
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp \
179
+ VirtIOSCSIReq *req;
74
+ | _filter_qemu_io | _filter_generated_node_ids
180
+ VirtIOSCSIReq *tmp;
181
+
182
+ GLOBAL_STATE_CODE();
183
+
184
+ virtio_scsi_acquire(s);
185
+
186
+ if (s->tmf_bh) {
187
+ qemu_bh_delete(s->tmf_bh);
188
+ s->tmf_bh = NULL;
189
+ }
190
+
191
+ QTAILQ_FOREACH_SAFE(req, &s->tmf_bh_list, next, tmp) {
192
+ QTAILQ_REMOVE(&s->tmf_bh_list, req, next);
193
+
194
+ /* SAM-6 6.3.2 Hard reset */
195
+ req->resp.tmf.response = VIRTIO_SCSI_S_TARGET_FAILURE;
196
+ virtio_scsi_complete_req(req);
197
+ }
198
+
199
+ virtio_scsi_release(s);
75
+}
200
+}
76
+
201
+
77
+size=64M
202
+static void virtio_scsi_defer_tmf_to_bh(VirtIOSCSIReq *req)
78
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
79
+TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
80
+_make_test_img -b "$TEST_IMG.mid"
81
+
82
+echo
83
+echo "Change backing file of mid (opened read-only)"
84
+echo
85
+
86
+run_qemu -drive if=none,file="$TEST_IMG",backing.node-name=mid <<EOF
87
+{"execute":"qmp_capabilities"}
88
+{"execute":"change-backing-file", "arguments":{"device":"none0","image-node-name":"mid","backing-file":"/dev/null"}}
89
+{"execute":"quit"}
90
+EOF
91
+
92
+TEST_IMG="$TEST_IMG.mid" _img_info
93
+
94
+echo
95
+echo "Change backing file of top (opened writable)"
96
+echo
97
+
98
+TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
99
+
100
+run_qemu -drive if=none,file="$TEST_IMG",node-name=top <<EOF
101
+{"execute":"qmp_capabilities"}
102
+{"execute":"change-backing-file", "arguments":{"device":"none0","image-node-name":"top","backing-file":"/dev/null"}}
103
+{"execute":"quit"}
104
+EOF
105
+
106
+_img_info
107
+
108
+# success, all done
109
+echo "*** done"
110
+rm -f $seq.full
111
+status=0
112
diff --git a/tests/qemu-iotests/195.out b/tests/qemu-iotests/195.out
113
new file mode 100644
114
index XXXXXXX..XXXXXXX
115
--- /dev/null
116
+++ b/tests/qemu-iotests/195.out
117
@@ -XXX,XX +XXX,XX @@
118
+QA output created by 195
119
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
120
+Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
121
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid
122
+
123
+Change backing file of mid (opened read-only)
124
+
125
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid
126
+{
203
+{
127
+ QMP_VERSION
204
+ VirtIOSCSI *s = req->dev;
205
+
206
+ QTAILQ_INSERT_TAIL(&s->tmf_bh_list, req, next);
207
+
208
+ if (!s->tmf_bh) {
209
+ s->tmf_bh = qemu_bh_new(virtio_scsi_do_tmf_bh, s);
210
+ qemu_bh_schedule(s->tmf_bh);
211
+ }
128
+}
212
+}
129
+{
213
+
130
+ "return": {
214
/* Return 0 if the request is ready to be completed and return to guest;
131
+ }
215
* -EINPROGRESS if the request is submitted and will be completed later, in the
132
+}
216
* case of async cancellation. */
133
+{
217
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
134
+ "return": {
218
{
135
+ }
219
SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
136
+}
220
SCSIRequest *r, *next;
137
+{
221
- BusChild *kid;
138
+ "return": {
222
- int target;
139
+ }
223
int ret = 0;
140
+}
224
141
+{
225
virtio_scsi_ctx_check(s, d);
142
+ "timestamp": {
226
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
143
+ "seconds": TIMESTAMP,
227
break;
144
+ "microseconds": TIMESTAMP
228
145
+ },
229
case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
146
+ "event": "SHUTDOWN",
230
- if (!d) {
147
+ "data": {
231
- goto fail;
148
+ "guest": false
232
- }
149
+ }
233
- if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
150
+}
234
- goto incorrect_lun;
151
+
235
- }
152
+image: TEST_DIR/t.IMGFMT.mid
236
- s->resetting++;
153
+file format: IMGFMT
237
- device_cold_reset(&d->qdev);
154
+virtual size: 64M (67108864 bytes)
238
- s->resetting--;
155
+cluster_size: 65536
239
+ case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
156
+backing file: /dev/null
240
+ virtio_scsi_defer_tmf_to_bh(req);
157
+backing file format: IMGFMT
241
+ ret = -EINPROGRESS;
158
+
242
break;
159
+Change backing file of top (opened writable)
243
160
+
244
case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
161
+Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
245
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
162
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top
246
}
163
+{
247
break;
164
+ QMP_VERSION
248
165
+}
249
- case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
166
+{
250
- target = req->req.tmf.lun[1];
167
+ "return": {
251
- s->resetting++;
168
+ }
252
-
169
+}
253
- rcu_read_lock();
170
+{
254
- QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
171
+ "return": {
255
- SCSIDevice *d1 = SCSI_DEVICE(kid->child);
172
+ }
256
- if (d1->channel == 0 && d1->id == target) {
173
+}
257
- device_cold_reset(&d1->qdev);
174
+{
258
- }
175
+ "return": {
259
- }
176
+ }
260
- rcu_read_unlock();
177
+}
261
-
178
+{
262
- s->resetting--;
179
+ "timestamp": {
263
- break;
180
+ "seconds": TIMESTAMP,
264
-
181
+ "microseconds": TIMESTAMP
265
case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
182
+ },
266
default:
183
+ "event": "SHUTDOWN",
267
req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
184
+ "data": {
268
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_request_cancelled(SCSIRequest *r)
185
+ "guest": false
269
if (!req) {
186
+ }
270
return;
187
+}
271
}
188
+
272
- if (req->dev->resetting) {
189
+image: TEST_DIR/t.IMGFMT
273
+ if (qatomic_read(&req->dev->resetting)) {
190
+file format: IMGFMT
274
req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
191
+virtual size: 64M (67108864 bytes)
275
} else {
192
+cluster_size: 65536
276
req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
193
+backing file: /dev/null
277
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_reset(VirtIODevice *vdev)
194
+backing file format: IMGFMT
278
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
195
+*** done
279
196
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
280
assert(!s->dataplane_started);
197
index XXXXXXX..XXXXXXX 100644
281
- s->resetting++;
198
--- a/tests/qemu-iotests/group
282
+
199
+++ b/tests/qemu-iotests/group
283
+ virtio_scsi_reset_tmf_bh(s);
200
@@ -XXX,XX +XXX,XX @@
284
+
201
190 rw auto quick
285
+ qatomic_inc(&s->resetting);
202
192 rw auto quick
286
bus_cold_reset(BUS(&s->bus));
203
194 rw auto migration quick
287
- s->resetting--;
204
+195 rw auto quick
288
+ qatomic_dec(&s->resetting);
289
290
vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
291
vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
292
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
293
VirtIOSCSI *s = VIRTIO_SCSI(dev);
294
Error *err = NULL;
295
296
+ QTAILQ_INIT(&s->tmf_bh_list);
297
+
298
virtio_scsi_common_realize(dev,
299
virtio_scsi_handle_ctrl,
300
virtio_scsi_handle_event,
301
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
302
{
303
VirtIOSCSI *s = VIRTIO_SCSI(dev);
304
305
+ virtio_scsi_reset_tmf_bh(s);
306
+
307
qbus_set_hotplug_handler(BUS(&s->bus), NULL);
308
virtio_scsi_common_unrealize(dev);
309
}
205
--
310
--
206
2.13.5
311
2.39.2
207
208
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
From: Or Ozeri <oro@il.ibm.com>
2
2
3
The default cpu model on s390x does not provide zPCI, which is
3
Signed-off-by: Or Ozeri <oro@il.ibm.com>
4
not yet wired up on tcg. Moreover, virtio-ccw is the standard
4
Message-Id: <20230129113120.722708-2-oro@oro.sl.cloud9.ibm.com>
5
on s390x, so use the -ccw instead of the -pci versions of virtio
5
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
6
devices on s390x.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
9
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
10
Reviewed-by: David Hildenbrand <david@redhat.com>
11
Reviewed-by: Thomas Huth <thuth@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
8
---
14
tests/qemu-iotests/051 | 12 +++++++++++-
9
block/rbd.c | 16 ++++++----------
15
tests/qemu-iotests/051.out | 2 +-
10
1 file changed, 6 insertions(+), 10 deletions(-)
16
tests/qemu-iotests/051.pc.out | 2 +-
17
3 files changed, 13 insertions(+), 3 deletions(-)
18
11
19
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
12
diff --git a/block/rbd.c b/block/rbd.c
20
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/051
22
+++ b/tests/qemu-iotests/051
23
@@ -XXX,XX +XXX,XX @@ echo
24
echo === Device without drive ===
25
echo
26
27
-run_qemu -device virtio-scsi-pci -device scsi-hd
28
+case "$QEMU_DEFAULT_MACHINE" in
29
+ s390-ccw-virtio)
30
+ virtio_scsi=virtio-scsi-ccw
31
+ ;;
32
+ *)
33
+ virtio_scsi=virtio-scsi-pci
34
+ ;;
35
+esac
36
+
37
+run_qemu -device $virtio_scsi -device scsi-hd |
38
+ sed -e "s/$virtio_scsi/VIRTIO_SCSI/"
39
40
echo
41
echo === Overriding backing file ===
42
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
43
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
44
--- a/tests/qemu-iotests/051.out
14
--- a/block/rbd.c
45
+++ b/tests/qemu-iotests/051.out
15
+++ b/block/rbd.c
46
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specif
16
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
47
17
{
48
=== Device without drive ===
18
int r = 0;
49
19
g_autofree char *passphrase = NULL;
50
-Testing: -device virtio-scsi-pci -device scsi-hd
20
- size_t passphrase_len;
51
+Testing: -device VIRTIO_SCSI -device scsi-hd
21
rbd_encryption_format_t format;
52
QEMU X.Y.Z monitor - type 'help' for more information
22
rbd_encryption_options_t opts;
53
(qemu) QEMU_PROG: -device scsi-hd: drive property not set
23
rbd_encryption_luks1_format_options_t luks_opts;
54
24
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
55
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
25
opts_size = sizeof(luks_opts);
56
index XXXXXXX..XXXXXXX 100644
26
r = qemu_rbd_convert_luks_create_options(
57
--- a/tests/qemu-iotests/051.pc.out
27
qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks),
58
+++ b/tests/qemu-iotests/051.pc.out
28
- &luks_opts.alg, &passphrase, &passphrase_len, errp);
59
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specif
29
+ &luks_opts.alg, &passphrase, &luks_opts.passphrase_size,
60
30
+ errp);
61
=== Device without drive ===
31
if (r < 0) {
62
32
return r;
63
-Testing: -device virtio-scsi-pci -device scsi-hd
33
}
64
+Testing: -device VIRTIO_SCSI -device scsi-hd
34
luks_opts.passphrase = passphrase;
65
QEMU X.Y.Z monitor - type 'help' for more information
35
- luks_opts.passphrase_size = passphrase_len;
66
(qemu) QEMU_PROG: -device scsi-hd: drive property not set
36
break;
67
37
}
38
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
39
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_format(rbd_image_t image,
40
r = qemu_rbd_convert_luks_create_options(
41
qapi_RbdEncryptionCreateOptionsLUKS2_base(
42
&encrypt->u.luks2),
43
- &luks2_opts.alg, &passphrase, &passphrase_len, errp);
44
+ &luks2_opts.alg, &passphrase, &luks2_opts.passphrase_size,
45
+ errp);
46
if (r < 0) {
47
return r;
48
}
49
luks2_opts.passphrase = passphrase;
50
- luks2_opts.passphrase_size = passphrase_len;
51
break;
52
}
53
default: {
54
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
55
{
56
int r = 0;
57
g_autofree char *passphrase = NULL;
58
- size_t passphrase_len;
59
rbd_encryption_luks1_format_options_t luks_opts;
60
rbd_encryption_luks2_format_options_t luks2_opts;
61
rbd_encryption_format_t format;
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
63
opts_size = sizeof(luks_opts);
64
r = qemu_rbd_convert_luks_options(
65
qapi_RbdEncryptionOptionsLUKS_base(&encrypt->u.luks),
66
- &passphrase, &passphrase_len, errp);
67
+ &passphrase, &luks_opts.passphrase_size, errp);
68
if (r < 0) {
69
return r;
70
}
71
luks_opts.passphrase = passphrase;
72
- luks_opts.passphrase_size = passphrase_len;
73
break;
74
}
75
case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
76
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
77
opts_size = sizeof(luks2_opts);
78
r = qemu_rbd_convert_luks_options(
79
qapi_RbdEncryptionOptionsLUKS2_base(&encrypt->u.luks2),
80
- &passphrase, &passphrase_len, errp);
81
+ &passphrase, &luks2_opts.passphrase_size, errp);
82
if (r < 0) {
83
return r;
84
}
85
luks2_opts.passphrase = passphrase;
86
- luks2_opts.passphrase_size = passphrase_len;
87
break;
88
}
89
default: {
68
--
90
--
69
2.13.5
91
2.39.2
70
71
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
From: Or Ozeri <oro@il.ibm.com>
2
2
3
The default cpu model on s390x does not provide zPCI, which is
3
Ceph RBD encryption API required specifying the encryption format
4
not yet wired up on tcg. Moreover, virtio-ccw is the standard
4
for loading encryption. The supported formats were LUKS (v1) and LUKS2.
5
on s390x, so use the -ccw instead of the -pci versions of virtio
6
devices on s390x.
7
5
6
Starting from Reef release, RBD also supports loading with "luks-any" format,
7
which works for both versions of LUKS.
8
9
This commit extends the qemu rbd driver API to enable qemu users to use
10
this luks-any wildcard format.
11
12
Signed-off-by: Or Ozeri <oro@il.ibm.com>
13
Message-Id: <20230129113120.722708-3-oro@oro.sl.cloud9.ibm.com>
14
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
10
Reviewed-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
17
---
13
tests/qemu-iotests/040 | 6 +++++-
18
qapi/block-core.json | 16 ++++++++++++++--
14
tests/qemu-iotests/139 | 12 ++++++++++--
19
block/rbd.c | 19 +++++++++++++++++++
15
tests/qemu-iotests/182 | 13 +++++++++++--
20
2 files changed, 33 insertions(+), 2 deletions(-)
16
3 files changed, 26 insertions(+), 5 deletions(-)
17
21
18
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
19
index XXXXXXX..XXXXXXX 100755
23
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/040
24
--- a/qapi/block-core.json
21
+++ b/tests/qemu-iotests/040
25
+++ b/qapi/block-core.json
22
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
26
@@ -XXX,XX +XXX,XX @@
23
qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
27
##
24
qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
28
# @RbdImageEncryptionFormat:
25
self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
29
#
26
- self.vm.add_device("virtio-scsi-pci")
30
+# @luks-any: Used for opening either luks or luks2 (Since 8.0)
27
+ if iotests.qemu_default_machine == 's390-ccw-virtio':
31
+#
28
+ self.vm.add_device("virtio-scsi-ccw")
32
# Since: 6.1
29
+ else:
33
##
30
+ self.vm.add_device("virtio-scsi-pci")
34
{ 'enum': 'RbdImageEncryptionFormat',
35
- 'data': [ 'luks', 'luks2' ] }
36
+ 'data': [ 'luks', 'luks2', 'luks-any' ] }
37
38
##
39
# @RbdEncryptionOptionsLUKSBase:
40
@@ -XXX,XX +XXX,XX @@
41
'base': 'RbdEncryptionOptionsLUKSBase',
42
'data': { } }
43
44
+##
45
+# @RbdEncryptionOptionsLUKSAny:
46
+#
47
+# Since: 8.0
48
+##
49
+{ 'struct': 'RbdEncryptionOptionsLUKSAny',
50
+ 'base': 'RbdEncryptionOptionsLUKSBase',
51
+ 'data': { } }
31
+
52
+
32
self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
53
##
33
self.vm.launch()
54
# @RbdEncryptionCreateOptionsLUKS:
34
55
#
35
diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
56
@@ -XXX,XX +XXX,XX @@
57
'base': { 'format': 'RbdImageEncryptionFormat' },
58
'discriminator': 'format',
59
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
60
- 'luks2': 'RbdEncryptionOptionsLUKS2' } }
61
+ 'luks2': 'RbdEncryptionOptionsLUKS2',
62
+ 'luks-any': 'RbdEncryptionOptionsLUKSAny'} }
63
64
##
65
# @RbdEncryptionCreateOptions:
66
diff --git a/block/rbd.c b/block/rbd.c
36
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
37
--- a/tests/qemu-iotests/139
68
--- a/block/rbd.c
38
+++ b/tests/qemu-iotests/139
69
+++ b/block/rbd.c
39
@@ -XXX,XX +XXX,XX @@ import time
70
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
40
71
g_autofree char *passphrase = NULL;
41
base_img = os.path.join(iotests.test_dir, 'base.img')
72
rbd_encryption_luks1_format_options_t luks_opts;
42
new_img = os.path.join(iotests.test_dir, 'new.img')
73
rbd_encryption_luks2_format_options_t luks2_opts;
43
+if iotests.qemu_default_machine == 's390-ccw-virtio':
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
44
+ default_virtio_blk = 'virtio-blk-ccw'
75
+ rbd_encryption_luks_format_options_t luks_any_opts;
45
+else:
76
+#endif
46
+ default_virtio_blk = 'virtio-blk-pci'
77
rbd_encryption_format_t format;
47
78
rbd_encryption_options_t opts;
48
class TestBlockdevDel(iotests.QMPTestCase):
79
size_t opts_size;
49
80
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
50
def setUp(self):
81
luks2_opts.passphrase = passphrase;
51
iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
82
break;
52
self.vm = iotests.VM()
83
}
53
- self.vm.add_device("virtio-scsi-pci,id=virtio-scsi")
84
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
54
+ if iotests.qemu_default_machine == 's390-ccw-virtio':
85
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
55
+ self.vm.add_device("virtio-scsi-ccw,id=virtio-scsi")
86
+ memset(&luks_any_opts, 0, sizeof(luks_any_opts));
56
+ else:
87
+ format = RBD_ENCRYPTION_FORMAT_LUKS;
57
+ self.vm.add_device("virtio-scsi-pci,id=virtio-scsi")
88
+ opts = &luks_any_opts;
58
+
89
+ opts_size = sizeof(luks_any_opts);
59
self.vm.launch()
90
+ r = qemu_rbd_convert_luks_options(
60
91
+ qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any),
61
def tearDown(self):
92
+ &passphrase, &luks_any_opts.passphrase_size, errp);
62
@@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase):
93
+ if (r < 0) {
63
self.checkBlockDriverState(node, expect_error)
94
+ return r;
64
95
+ }
65
# Add a device model
96
+ luks_any_opts.passphrase = passphrase;
66
- def addDeviceModel(self, device, backend, driver = 'virtio-blk-pci'):
97
+ break;
67
+ def addDeviceModel(self, device, backend, driver = default_virtio_blk):
98
+ }
68
result = self.vm.qmp('device_add', id = device,
99
+#endif
69
driver = driver, drive = backend)
100
default: {
70
self.assert_qmp(result, 'return', {})
101
r = -ENOTSUP;
71
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
102
error_setg_errno(
72
index XXXXXXX..XXXXXXX 100755
73
--- a/tests/qemu-iotests/182
74
+++ b/tests/qemu-iotests/182
75
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
76
77
size=32M
78
79
+case "$QEMU_DEFAULT_MACHINE" in
80
+ s390-ccw-virtio)
81
+ virtioblk=virtio-blk-ccw
82
+ ;;
83
+ *)
84
+ virtioblk=virtio-blk-pci
85
+ ;;
86
+esac
87
+
88
_make_test_img $size
89
90
echo "Starting QEMU"
91
_launch_qemu -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
92
- -device virtio-blk-pci,drive=drive0
93
+ -device $virtioblk,drive=drive0
94
95
echo
96
echo "Starting a second QEMU using the same image should fail"
97
echo 'quit' | $QEMU -monitor stdio \
98
-drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
99
- -device virtio-blk-pci,drive=drive0 2>&1 | _filter_testdir 2>&1 |
100
+ -device $virtioblk,drive=drive0 2>&1 | _filter_testdir 2>&1 |
101
_filter_qemu |
102
sed -e '/falling back to POSIX file/d' \
103
-e '/locks can be lost unexpectedly/d'
104
--
103
--
105
2.13.5
104
2.39.2
106
107
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Or Ozeri <oro@il.ibm.com>
2
2
3
It's not too surprising when a user specifies the backing file relative
3
Starting from ceph Reef, RBD has built-in support for layered encryption,
4
to the current working directory instead of the top layer image. This
4
where each ancestor image (in a cloned image setting) can be possibly
5
causes error when they differ. Though the error message has enough
5
encrypted using a unique passphrase.
6
information to infer the fact about the misunderstanding, it is better
6
7
if we document this explicitly, so that users don't have to learn from
7
A new function, rbd_encryption_load2, was added to librbd API.
8
mistakes.
8
This new function supports an array of passphrases (via "spec" structs).
9
9
10
Signed-off-by: Fam Zheng <famz@redhat.com>
10
This commit extends the qemu rbd driver API to use this new librbd API,
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
in order to support this new layered encryption feature.
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
12
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Or Ozeri <oro@il.ibm.com>
14
Message-Id: <20230129113120.722708-4-oro@oro.sl.cloud9.ibm.com>
15
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
18
---
16
qemu-img.texi | 9 +++++++++
19
qapi/block-core.json | 11 +++-
17
1 file changed, 9 insertions(+)
20
block/rbd.c | 153 ++++++++++++++++++++++++++++++++++++++++++-
18
21
2 files changed, 162 insertions(+), 2 deletions(-)
19
diff --git a/qemu-img.texi b/qemu-img.texi
22
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/qemu-img.texi
25
--- a/qapi/block-core.json
22
+++ b/qemu-img.texi
26
+++ b/qapi/block-core.json
23
@@ -XXX,XX +XXX,XX @@ only the differences from @var{backing_file}. No size needs to be specified in
27
@@ -XXX,XX +XXX,XX @@
24
this case. @var{backing_file} will never be modified unless you use the
28
##
25
@code{commit} monitor command (or qemu-img commit).
29
# @RbdEncryptionOptions:
26
30
#
27
+If a relative path name is given, the backing file is looked up relative to
31
+# @format: Encryption format.
28
+the directory containing @var{filename}.
32
+#
29
+
33
+# @parent: Parent image encryption options (for cloned images).
30
Note that a given backing file will be opened to check that it is valid. Use
34
+# Can be left unspecified if this cloned image is encrypted
31
the @code{-u} option to enable unsafe backing file mode, which means that the
35
+# using the same format and secret as its parent image (i.e.
32
image will be created even if the associated backing file cannot be opened. A
36
+# not explicitly formatted) or if its parent image is not
33
@@ -XXX,XX +XXX,XX @@ created as a copy on write image of the specified base image; the
37
+# encrypted. (Since 8.0)
34
@var{backing_file} should have the same content as the input's base image,
38
+#
35
however the path, image format, etc may differ.
39
# Since: 6.1
36
40
##
37
+If a relative path name is given, the backing file is looked up relative to
41
{ 'union': 'RbdEncryptionOptions',
38
+the directory containing @var{output_filename}.
42
- 'base': { 'format': 'RbdImageEncryptionFormat' },
39
+
43
+ 'base': { 'format': 'RbdImageEncryptionFormat',
40
If the @code{-n} option is specified, the target volume creation will be
44
+ '*parent': 'RbdEncryptionOptions' },
41
skipped. This is useful for formats such as @code{rbd} if the target
45
'discriminator': 'format',
42
volume has already been created with site specific options that cannot
46
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
43
@@ -XXX,XX +XXX,XX @@ The backing file is changed to @var{backing_file} and (if the image format of
47
'luks2': 'RbdEncryptionOptionsLUKS2',
44
string), then the image is rebased onto no backing file (i.e. it will exist
48
diff --git a/block/rbd.c b/block/rbd.c
45
independently of any backing file).
49
index XXXXXXX..XXXXXXX 100644
46
50
--- a/block/rbd.c
47
+If a relative path name is given, the backing file is looked up relative to
51
+++ b/block/rbd.c
48
+the directory containing @var{filename}.
52
@@ -XXX,XX +XXX,XX @@ static const char rbd_luks2_header_verification[
49
+
53
'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
50
@var{cache} specifies the cache mode to be used for @var{filename}, whereas
54
};
51
@var{src_cache} specifies the cache mode for reading backing files.
55
52
56
+static const char rbd_layered_luks_header_verification[
57
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
58
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1
59
+};
60
+
61
+static const char rbd_layered_luks2_header_verification[
62
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
63
+ 'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2
64
+};
65
+
66
typedef enum {
67
RBD_AIO_READ,
68
RBD_AIO_WRITE,
69
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_encryption_load(rbd_image_t image,
70
71
return 0;
72
}
73
+
74
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
75
+static int qemu_rbd_encryption_load2(rbd_image_t image,
76
+ RbdEncryptionOptions *encrypt,
77
+ Error **errp)
78
+{
79
+ int r = 0;
80
+ int encrypt_count = 1;
81
+ int i;
82
+ RbdEncryptionOptions *curr_encrypt;
83
+ rbd_encryption_spec_t *specs;
84
+ rbd_encryption_luks1_format_options_t *luks_opts;
85
+ rbd_encryption_luks2_format_options_t *luks2_opts;
86
+ rbd_encryption_luks_format_options_t *luks_any_opts;
87
+
88
+ /* count encryption options */
89
+ for (curr_encrypt = encrypt->parent; curr_encrypt;
90
+ curr_encrypt = curr_encrypt->parent) {
91
+ ++encrypt_count;
92
+ }
93
+
94
+ specs = g_new0(rbd_encryption_spec_t, encrypt_count);
95
+
96
+ curr_encrypt = encrypt;
97
+ for (i = 0; i < encrypt_count; ++i) {
98
+ switch (curr_encrypt->format) {
99
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: {
100
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS1;
101
+
102
+ luks_opts = g_new0(rbd_encryption_luks1_format_options_t, 1);
103
+ specs[i].opts = luks_opts;
104
+ specs[i].opts_size = sizeof(*luks_opts);
105
+
106
+ r = qemu_rbd_convert_luks_options(
107
+ qapi_RbdEncryptionOptionsLUKS_base(
108
+ &curr_encrypt->u.luks),
109
+ (char **)&luks_opts->passphrase,
110
+ &luks_opts->passphrase_size,
111
+ errp);
112
+ break;
113
+ }
114
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: {
115
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS2;
116
+
117
+ luks2_opts = g_new0(rbd_encryption_luks2_format_options_t, 1);
118
+ specs[i].opts = luks2_opts;
119
+ specs[i].opts_size = sizeof(*luks2_opts);
120
+
121
+ r = qemu_rbd_convert_luks_options(
122
+ qapi_RbdEncryptionOptionsLUKS2_base(
123
+ &curr_encrypt->u.luks2),
124
+ (char **)&luks2_opts->passphrase,
125
+ &luks2_opts->passphrase_size,
126
+ errp);
127
+ break;
128
+ }
129
+ case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
130
+ specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS;
131
+
132
+ luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1);
133
+ specs[i].opts = luks_any_opts;
134
+ specs[i].opts_size = sizeof(*luks_any_opts);
135
+
136
+ r = qemu_rbd_convert_luks_options(
137
+ qapi_RbdEncryptionOptionsLUKSAny_base(
138
+ &curr_encrypt->u.luks_any),
139
+ (char **)&luks_any_opts->passphrase,
140
+ &luks_any_opts->passphrase_size,
141
+ errp);
142
+ break;
143
+ }
144
+ default: {
145
+ r = -ENOTSUP;
146
+ error_setg_errno(
147
+ errp, -r, "unknown image encryption format: %u",
148
+ curr_encrypt->format);
149
+ }
150
+ }
151
+
152
+ if (r < 0) {
153
+ goto exit;
154
+ }
155
+
156
+ curr_encrypt = curr_encrypt->parent;
157
+ }
158
+
159
+ r = rbd_encryption_load2(image, specs, encrypt_count);
160
+ if (r < 0) {
161
+ error_setg_errno(errp, -r, "layered encryption load fail");
162
+ goto exit;
163
+ }
164
+
165
+exit:
166
+ for (i = 0; i < encrypt_count; ++i) {
167
+ if (!specs[i].opts) {
168
+ break;
169
+ }
170
+
171
+ switch (specs[i].format) {
172
+ case RBD_ENCRYPTION_FORMAT_LUKS1: {
173
+ luks_opts = specs[i].opts;
174
+ g_free((void *)luks_opts->passphrase);
175
+ break;
176
+ }
177
+ case RBD_ENCRYPTION_FORMAT_LUKS2: {
178
+ luks2_opts = specs[i].opts;
179
+ g_free((void *)luks2_opts->passphrase);
180
+ break;
181
+ }
182
+ case RBD_ENCRYPTION_FORMAT_LUKS: {
183
+ luks_any_opts = specs[i].opts;
184
+ g_free((void *)luks_any_opts->passphrase);
185
+ break;
186
+ }
187
+ }
188
+
189
+ g_free(specs[i].opts);
190
+ }
191
+ g_free(specs);
192
+ return r;
193
+}
194
+#endif
195
#endif
196
197
/* FIXME Deprecate and remove keypairs or make it available in QMP. */
198
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
199
200
if (opts->encrypt) {
201
#ifdef LIBRBD_SUPPORTS_ENCRYPTION
202
- r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
203
+ if (opts->encrypt->parent) {
204
+#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
205
+ r = qemu_rbd_encryption_load2(s->image, opts->encrypt, errp);
206
+#else
207
+ r = -ENOTSUP;
208
+ error_setg(errp, "RBD library does not support layered encryption");
209
+#endif
210
+ } else {
211
+ r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp);
212
+ }
213
if (r < 0) {
214
goto failed_post_open;
215
}
216
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs,
217
spec_info->u.rbd.data->encryption_format =
218
RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
219
spec_info->u.rbd.data->has_encryption_format = true;
220
+ } else if (memcmp(buf, rbd_layered_luks_header_verification,
221
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
222
+ spec_info->u.rbd.data->encryption_format =
223
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS;
224
+ spec_info->u.rbd.data->has_encryption_format = true;
225
+ } else if (memcmp(buf, rbd_layered_luks2_header_verification,
226
+ RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) {
227
+ spec_info->u.rbd.data->encryption_format =
228
+ RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2;
229
+ spec_info->u.rbd.data->has_encryption_format = true;
230
} else {
231
spec_info->u.rbd.data->has_encryption_format = false;
232
}
53
--
233
--
54
2.13.5
234
2.39.2
55
56
diff view generated by jsdifflib