1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
1
The following changes since commit ac5f7bf8e208cd7893dbb1a9520559e569a4677c:
2
2
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
3
Merge tag 'migration-20230424-pull-request' of https://gitlab.com/juan.quintela/qemu into staging (2023-04-24 15:00:39 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
9
for you to fetch changes up to 8c1e8fb2e7fc2cbeb57703e143965a4cd3ad301a:
10
10
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
11
block/monitor: Fix crash when executing HMP commit (2023-04-25 15:11:57 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Fix resize (extending) of short overlays
16
- Protect BlockBackend.queued_requests with its own lock
17
- nvme: introduce PMR support from NVMe 1.4 spec
17
- Switch to AIO_WAIT_WHILE_UNLOCKED() where possible
18
- qemu-storage-daemon: Fix non-string --object properties
18
- AioContext removal: LinuxAioState/LuringState/ThreadPool
19
- Add more coroutine_fn annotations, use bdrv/blk_co_*
20
- Fix crash when execute hmp_commit
19
21
20
----------------------------------------------------------------
22
----------------------------------------------------------------
21
Alberto Garcia (1):
23
Emanuele Giuseppe Esposito (4):
22
qcow2: Add incompatibility note between backing files and raw external data files
24
linux-aio: use LinuxAioState from the running thread
25
io_uring: use LuringState from the running thread
26
thread-pool: use ThreadPool from the running thread
27
thread-pool: avoid passing the pool parameter every time
23
28
24
Andrzej Jakowski (1):
29
Paolo Bonzini (9):
25
nvme: introduce PMR support from NVMe 1.4 spec
30
vvfat: mark various functions as coroutine_fn
31
blkdebug: add missing coroutine_fn annotation
32
mirror: make mirror_flush a coroutine_fn, do not use co_wrappers
33
nbd: mark more coroutine_fns, do not use co_wrappers
34
9pfs: mark more coroutine_fns
35
qemu-pr-helper: mark more coroutine_fns
36
tests: mark more coroutine_fns
37
qcow2: mark various functions as coroutine_fn and GRAPH_RDLOCK
38
vmdk: make vmdk_is_cid_valid a coroutine_fn
26
39
27
Kevin Wolf (12):
40
Stefan Hajnoczi (10):
28
block: Add flags to BlockDriver.bdrv_co_truncate()
41
block: make BlockBackend->quiesce_counter atomic
29
block: Add flags to bdrv(_co)_truncate()
42
block: make BlockBackend->disable_request_queuing atomic
30
block-backend: Add flags to blk_truncate()
43
block: protect BlockBackend->queued_requests with a lock
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
44
block: don't acquire AioContext lock in bdrv_drain_all()
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
45
block: convert blk_exp_close_all_type() to AIO_WAIT_WHILE_UNLOCKED()
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
46
block: convert bdrv_graph_wrlock() to AIO_WAIT_WHILE_UNLOCKED()
34
block: truncate: Don't make backing file data visible
47
block: convert bdrv_drain_all_begin() to AIO_WAIT_WHILE_UNLOCKED()
35
iotests: Filter testfiles out in filter_img_info()
48
hmp: convert handle_hmp_command() to AIO_WAIT_WHILE_UNLOCKED()
36
iotests: Test committing to short backing file
49
monitor: convert monitor_cleanup() to AIO_WAIT_WHILE_UNLOCKED()
37
qcow2: Forward ZERO_WRITE flag for full preallocation
50
block: add missing coroutine_fn to bdrv_sum_allocated_file_size()
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
40
51
41
Paolo Bonzini (1):
52
Wang Liang (1):
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
53
block/monitor: Fix crash when executing HMP commit
43
54
44
docs/interop/qcow2.txt | 3 +
55
Wilfred Mallawa (1):
45
hw/block/nvme.h | 2 +
56
include/block: fixup typos
46
include/block/block.h | 5 +-
47
include/block/block_int.h | 10 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
include/qom/object_interfaces.h | 16 +++
50
include/sysemu/block-backend.h | 2 +-
51
block.c | 3 +-
52
block/block-backend.c | 4 +-
53
block/commit.c | 4 +-
54
block/crypto.c | 7 +-
55
block/file-posix.c | 6 +-
56
block/file-win32.c | 2 +-
57
block/gluster.c | 1 +
58
block/io.c | 43 ++++++-
59
block/iscsi.c | 2 +-
60
block/mirror.c | 2 +-
61
block/nfs.c | 3 +-
62
block/parallels.c | 6 +-
63
block/qcow.c | 4 +-
64
block/qcow2-cluster.c | 2 +-
65
block/qcow2-refcount.c | 2 +-
66
block/qcow2.c | 73 +++++++++--
67
block/qed.c | 3 +-
68
block/raw-format.c | 6 +-
69
block/rbd.c | 1 +
70
block/sheepdog.c | 4 +-
71
block/ssh.c | 2 +-
72
block/vdi.c | 2 +-
73
block/vhdx-log.c | 2 +-
74
block/vhdx.c | 6 +-
75
block/vmdk.c | 8 +-
76
block/vpc.c | 2 +-
77
blockdev.c | 2 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
79
qemu-img.c | 2 +-
80
qemu-io-cmds.c | 2 +-
81
qemu-storage-daemon.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
83
qom/qom-qmp-cmds.c | 24 +---
84
tests/test-block-iothread.c | 9 +-
85
tests/qemu-iotests/iotests.py | 5 +-
86
hw/block/Makefile.objs | 2 +-
87
hw/block/trace-events | 4 +
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
96
57
97
58
block/qcow2.h | 15 +++++-----
59
hw/9pfs/9p.h | 4 +--
60
include/block/aio-wait.h | 2 +-
61
include/block/aio.h | 8 ------
62
include/block/block_int-common.h | 2 +-
63
include/block/raw-aio.h | 33 +++++++++++++++-------
64
include/block/thread-pool.h | 15 ++++++----
65
include/sysemu/block-backend-io.h | 5 ++++
66
backends/tpm/tpm_backend.c | 4 +--
67
block.c | 2 +-
68
block/blkdebug.c | 4 +--
69
block/block-backend.c | 45 ++++++++++++++++++------------
70
block/export/export.c | 2 +-
71
block/file-posix.c | 45 ++++++++++++------------------
72
block/file-win32.c | 4 +--
73
block/graph-lock.c | 2 +-
74
block/io.c | 2 +-
75
block/io_uring.c | 23 ++++++++++------
76
block/linux-aio.c | 29 ++++++++++++--------
77
block/mirror.c | 4 +--
78
block/monitor/block-hmp-cmds.c | 10 ++++---
79
block/qcow2-bitmap.c | 2 +-
80
block/qcow2-cluster.c | 21 ++++++++------
81
block/qcow2-refcount.c | 8 +++---
82
block/qcow2-snapshot.c | 25 +++++++++--------
83
block/qcow2-threads.c | 3 +-
84
block/qcow2.c | 27 +++++++++---------
85
block/vmdk.c | 2 +-
86
block/vvfat.c | 58 ++++++++++++++++++++-------------------
87
hw/9pfs/codir.c | 6 ++--
88
hw/9pfs/coth.c | 3 +-
89
hw/ppc/spapr_nvdimm.c | 6 ++--
90
hw/virtio/virtio-pmem.c | 3 +-
91
monitor/hmp.c | 2 +-
92
monitor/monitor.c | 4 +--
93
nbd/server.c | 48 ++++++++++++++++----------------
94
scsi/pr-manager.c | 3 +-
95
scsi/qemu-pr-helper.c | 25 ++++++++---------
96
tests/unit/test-thread-pool.c | 14 ++++------
97
util/thread-pool.c | 25 ++++++++---------
98
40 files changed, 283 insertions(+), 262 deletions(-)
diff view generated by jsdifflib
1
We want to keep TEST_IMG for the full path of the main test image, but
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
5
2
6
Insert a filter_testfiles() call between both.
3
The main loop thread increments/decrements BlockBackend->quiesce_counter
4
when drained sections begin/end. The counter is read in the I/O code
5
path. Therefore this field is used to communicate between threads
6
without a lock.
7
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Acquire/release are not necessary because the BlockBackend->in_flight
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
counter already uses sequentially consistent accesses and running I/O
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
requests hold that counter when blk_wait_while_drained() is called.
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
11
qatomic_read() can be used.
12
13
Use qatomic_fetch_inc()/qatomic_fetch_dec() for modifications even
14
though sequentially consistent atomic accesses are not strictly required
15
here. They are, however, nicer to read than multiple calls to
16
qatomic_read() and qatomic_set(). Since beginning and ending drain is
17
not a hot path the extra cost doesn't matter.
18
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Message-Id: <20230307210427.269214-2-stefanha@redhat.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
24
---
14
tests/qemu-iotests/iotests.py | 5 +++--
25
block/block-backend.c | 14 +++++++-------
15
1 file changed, 3 insertions(+), 2 deletions(-)
26
1 file changed, 7 insertions(+), 7 deletions(-)
16
27
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
28
diff --git a/block/block-backend.c b/block/block-backend.c
18
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
30
--- a/block/block-backend.c
20
+++ b/tests/qemu-iotests/iotests.py
31
+++ b/block/block-backend.c
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
32
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
22
for line in output.split('\n'):
33
NotifierList remove_bs_notifiers, insert_bs_notifiers;
23
if 'disk size' in line or 'actual-size' in line:
34
QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
24
continue
35
25
- line = line.replace(filename, 'TEST_IMG') \
36
- int quiesce_counter;
26
- .replace(imgfmt, 'IMGFMT')
37
+ int quiesce_counter; /* atomic: written under BQL, read by other threads */
27
+ line = line.replace(filename, 'TEST_IMG')
38
CoQueue queued_requests;
28
+ line = filter_testfiles(line)
39
bool disable_request_queuing;
29
+ line = line.replace(imgfmt, 'IMGFMT')
40
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
41
@@ -XXX,XX +XXX,XX @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
42
blk->dev_opaque = opaque;
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
43
44
/* Are we currently quiesced? Should we enforce this right now? */
45
- if (blk->quiesce_counter && ops && ops->drained_begin) {
46
+ if (qatomic_read(&blk->quiesce_counter) && ops && ops->drained_begin) {
47
ops->drained_begin(opaque);
48
}
49
}
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
51
{
52
assert(blk->in_flight > 0);
53
54
- if (blk->quiesce_counter && !blk->disable_request_queuing) {
55
+ if (qatomic_read(&blk->quiesce_counter) && !blk->disable_request_queuing) {
56
blk_dec_in_flight(blk);
57
qemu_co_queue_wait(&blk->queued_requests, NULL);
58
blk_inc_in_flight(blk);
59
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_begin(BdrvChild *child)
60
BlockBackend *blk = child->opaque;
61
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
62
63
- if (++blk->quiesce_counter == 1) {
64
+ if (qatomic_fetch_inc(&blk->quiesce_counter) == 0) {
65
if (blk->dev_ops && blk->dev_ops->drained_begin) {
66
blk->dev_ops->drained_begin(blk->dev_opaque);
67
}
68
@@ -XXX,XX +XXX,XX @@ static bool blk_root_drained_poll(BdrvChild *child)
69
{
70
BlockBackend *blk = child->opaque;
71
bool busy = false;
72
- assert(blk->quiesce_counter);
73
+ assert(qatomic_read(&blk->quiesce_counter));
74
75
if (blk->dev_ops && blk->dev_ops->drained_poll) {
76
busy = blk->dev_ops->drained_poll(blk->dev_opaque);
77
@@ -XXX,XX +XXX,XX @@ static bool blk_root_drained_poll(BdrvChild *child)
78
static void blk_root_drained_end(BdrvChild *child)
79
{
80
BlockBackend *blk = child->opaque;
81
- assert(blk->quiesce_counter);
82
+ assert(qatomic_read(&blk->quiesce_counter));
83
84
assert(blk->public.throttle_group_member.io_limits_disabled);
85
qatomic_dec(&blk->public.throttle_group_member.io_limits_disabled);
86
87
- if (--blk->quiesce_counter == 0) {
88
+ if (qatomic_fetch_dec(&blk->quiesce_counter) == 1) {
89
if (blk->dev_ops && blk->dev_ops->drained_end) {
90
blk->dev_ops->drained_end(blk->dev_opaque);
91
}
33
--
92
--
34
2.25.3
93
2.40.0
35
94
36
95
diff view generated by jsdifflib
1
Now that node level interface bdrv_truncate() supports passing request
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
flags to the block driver, expose this on the BlockBackend level, too.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
This field is accessed by multiple threads without a lock. Use explicit
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
qatomic_read()/qatomic_set() calls. There is no need for acquire/release
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
because blk_set_disable_request_queuing() doesn't provide any
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
guarantees (it helps that it's used at BlockBackend creation time and
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
7
not when there is I/O in flight).
8
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
11
Message-Id: <20230307210427.269214-3-stefanha@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
include/sysemu/block-backend.h | 2 +-
16
block/block-backend.c | 7 ++++---
12
block.c | 3 ++-
17
1 file changed, 4 insertions(+), 3 deletions(-)
13
block/block-backend.c | 4 ++--
14
block/commit.c | 4 ++--
15
block/crypto.c | 2 +-
16
block/mirror.c | 2 +-
17
block/qcow2.c | 4 ++--
18
block/qed.c | 2 +-
19
block/vdi.c | 2 +-
20
block/vhdx.c | 4 ++--
21
block/vmdk.c | 6 +++---
22
block/vpc.c | 2 +-
23
blockdev.c | 2 +-
24
qemu-img.c | 2 +-
25
qemu-io-cmds.c | 2 +-
26
15 files changed, 22 insertions(+), 21 deletions(-)
27
18
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend.h
31
+++ b/include/sysemu/block-backend.h
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
34
int bytes);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
- PreallocMode prealloc, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
40
int64_t pos, int size);
41
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
44
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
46
int64_t size;
47
int ret;
48
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
51
+ &local_err);
52
if (ret < 0 && ret != -ENOTSUP) {
53
error_propagate(errp, local_err);
54
return ret;
55
diff --git a/block/block-backend.c b/block/block-backend.c
19
diff --git a/block/block-backend.c b/block/block-backend.c
56
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
57
--- a/block/block-backend.c
21
--- a/block/block-backend.c
58
+++ b/block/block-backend.c
22
+++ b/block/block-backend.c
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
23
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
24
25
int quiesce_counter; /* atomic: written under BQL, read by other threads */
26
CoQueue queued_requests;
27
- bool disable_request_queuing;
28
+ bool disable_request_queuing; /* atomic */
29
30
VMChangeStateEntry *vmsh;
31
bool force_allow_inactivate;
32
@@ -XXX,XX +XXX,XX @@ void blk_set_allow_aio_context_change(BlockBackend *blk, bool allow)
33
void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
34
{
35
IO_CODE();
36
- blk->disable_request_queuing = disable;
37
+ qatomic_set(&blk->disable_request_queuing, disable);
60
}
38
}
61
39
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
40
static int coroutine_fn GRAPH_RDLOCK
63
- PreallocMode prealloc, Error **errp)
41
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
65
{
42
{
66
if (!blk_is_available(blk)) {
43
assert(blk->in_flight > 0);
67
error_setg(errp, "No medium inserted");
44
68
return -ENOMEDIUM;
45
- if (qatomic_read(&blk->quiesce_counter) && !blk->disable_request_queuing) {
69
}
46
+ if (qatomic_read(&blk->quiesce_counter) &&
70
47
+ !qatomic_read(&blk->disable_request_queuing)) {
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
48
blk_dec_in_flight(blk);
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
49
qemu_co_queue_wait(&blk->queued_requests, NULL);
73
}
50
blk_inc_in_flight(blk);
74
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
76
diff --git a/block/commit.c b/block/commit.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/commit.c
79
+++ b/block/commit.c
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
81
}
82
83
if (base_len < len) {
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
86
if (ret) {
87
goto out;
88
}
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
90
* grow the backing file image if possible. If not possible,
91
* we must return an error */
92
if (length > backing_length) {
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
95
&local_err);
96
if (ret < 0) {
97
error_report_err(local_err);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
108
}
109
110
111
diff --git a/block/mirror.c b/block/mirror.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/mirror.c
114
+++ b/block/mirror.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
116
117
if (s->bdev_length > base_length) {
118
ret = blk_truncate(s->target, s->bdev_length, false,
119
- PREALLOC_MODE_OFF, NULL);
120
+ PREALLOC_MODE_OFF, 0, NULL);
121
if (ret < 0) {
122
goto immediate_exit;
123
}
124
diff --git a/block/qcow2.c b/block/qcow2.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/block/qcow2.c
127
+++ b/block/qcow2.c
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
129
130
/* Okay, now that we have a valid image, let's give it the right size */
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
132
- errp);
133
+ 0, errp);
134
if (ret < 0) {
135
error_prepend(errp, "Could not resize image: ");
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
236
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
239
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
241
}
242
243
bdrv_drained_begin(bs);
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
246
bdrv_drained_end(bs);
247
248
out:
249
diff --git a/qemu-img.c b/qemu-img.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/qemu-img.c
252
+++ b/qemu-img.c
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
254
* resizing, so pass @exact=true. It is of no use to report
255
* success when the image has not actually been resized.
256
*/
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
259
if (!ret) {
260
qprintf(quiet, "Image resized.\n");
261
} else {
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/qemu-io-cmds.c
265
+++ b/qemu-io-cmds.c
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
267
* exact=true. It is better to err on the "emit more errors" side
268
* than to be overly permissive.
269
*/
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
272
if (ret < 0) {
273
error_report_err(local_err);
274
return ret;
275
--
51
--
276
2.25.3
52
2.40.0
277
53
278
54
diff view generated by jsdifflib
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
4
2
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
The CoQueue API offers thread-safety via the lock argument that
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
qemu_co_queue_wait() and qemu_co_enter_next() take. BlockBackend
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
currently does not make use of the lock argument. This means that
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
multiple threads submitting I/O requests can corrupt the CoQueue's
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
7
QSIMPLEQ.
8
9
Add a QemuMutex and pass it to CoQueue APIs so that the queue is
10
protected. While we're at it, also assert that the queue is empty when
11
the BlockBackend is deleted.
12
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
15
Message-Id: <20230307210427.269214-4-stefanha@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
18
---
12
include/block/block.h | 5 +++--
19
block/block-backend.c | 18 ++++++++++++++++--
13
block/block-backend.c | 2 +-
20
1 file changed, 16 insertions(+), 2 deletions(-)
14
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
16
block/parallels.c | 6 +++---
17
block/qcow.c | 4 ++--
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
26
21
27
diff --git a/include/block/block.h b/include/block/block.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block.h
30
+++ b/include/block/block.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
32
void bdrv_refresh_filename(BlockDriverState *bs);
33
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
35
- PreallocMode prealloc, Error **errp);
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
37
+ Error **errp);
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
39
- PreallocMode prealloc, Error **errp);
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
44
diff --git a/block/block-backend.c b/block/block-backend.c
22
diff --git a/block/block-backend.c b/block/block-backend.c
45
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
24
--- a/block/block-backend.c
47
+++ b/block/block-backend.c
25
+++ b/block/block-backend.c
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
26
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
49
return -ENOMEDIUM;
27
QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
28
29
int quiesce_counter; /* atomic: written under BQL, read by other threads */
30
+ QemuMutex queued_requests_lock; /* protects queued_requests */
31
CoQueue queued_requests;
32
bool disable_request_queuing; /* atomic */
33
34
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
35
36
block_acct_init(&blk->stats);
37
38
+ qemu_mutex_init(&blk->queued_requests_lock);
39
qemu_co_queue_init(&blk->queued_requests);
40
notifier_list_init(&blk->remove_bs_notifiers);
41
notifier_list_init(&blk->insert_bs_notifiers);
42
@@ -XXX,XX +XXX,XX @@ static void blk_delete(BlockBackend *blk)
43
assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
44
assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
45
assert(QLIST_EMPTY(&blk->aio_notifiers));
46
+ assert(qemu_co_queue_empty(&blk->queued_requests));
47
+ qemu_mutex_destroy(&blk->queued_requests_lock);
48
QTAILQ_REMOVE(&block_backends, blk, link);
49
drive_info_del(blk->legacy_dinfo);
50
block_acct_cleanup(&blk->stats);
51
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
52
53
if (qatomic_read(&blk->quiesce_counter) &&
54
!qatomic_read(&blk->disable_request_queuing)) {
55
+ /*
56
+ * Take lock before decrementing in flight counter so main loop thread
57
+ * waits for us to enqueue ourselves before it can leave the drained
58
+ * section.
59
+ */
60
+ qemu_mutex_lock(&blk->queued_requests_lock);
61
blk_dec_in_flight(blk);
62
- qemu_co_queue_wait(&blk->queued_requests, NULL);
63
+ qemu_co_queue_wait(&blk->queued_requests, &blk->queued_requests_lock);
64
blk_inc_in_flight(blk);
65
+ qemu_mutex_unlock(&blk->queued_requests_lock);
50
}
66
}
51
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
54
}
67
}
55
68
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
69
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_end(BdrvChild *child)
57
diff --git a/block/crypto.c b/block/crypto.c
70
if (blk->dev_ops && blk->dev_ops->drained_end) {
58
index XXXXXXX..XXXXXXX 100644
71
blk->dev_ops->drained_end(blk->dev_opaque);
59
--- a/block/crypto.c
72
}
60
+++ b/block/crypto.c
73
- while (qemu_co_enter_next(&blk->queued_requests, NULL)) {
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
74
+ qemu_mutex_lock(&blk->queued_requests_lock);
62
75
+ while (qemu_co_enter_next(&blk->queued_requests,
63
offset += payload_offset;
76
+ &blk->queued_requests_lock)) {
64
77
/* Resume all queued requests */
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
78
}
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
79
+ qemu_mutex_unlock(&blk->queued_requests_lock);
80
}
67
}
81
}
68
82
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
81
{
82
BlockDriverState *bs = child->bs;
83
BlockDriver *drv = bs->drv;
84
BdrvTrackedRequest req;
85
- BdrvRequestFlags flags = 0;
86
int64_t old_size, new_bytes;
87
int ret;
88
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
90
}
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
92
} else if (bs->file && drv->is_filter) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
307
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/tests/test-block-iothread.c
311
+++ b/tests/test-block-iothread.c
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
334
--
83
--
335
2.25.3
84
2.40.0
336
337
diff view generated by jsdifflib
New patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
2
3
There is no need for the AioContext lock in bdrv_drain_all() because
4
nothing in AIO_WAIT_WHILE() needs the lock and the condition is atomic.
5
6
AIO_WAIT_WHILE_UNLOCKED() has no use for the AioContext parameter other
7
than performing a check that is nowadays already done by the
8
GLOBAL_STATE_CODE()/IO_CODE() macros. Set the ctx argument to NULL here
9
to help us keep track of all converted callers. Eventually all callers
10
will have been converted and then the argument can be dropped entirely.
11
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230309190855.414275-2-stefanha@redhat.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/block-backend.c | 8 +-------
20
1 file changed, 1 insertion(+), 7 deletions(-)
21
22
diff --git a/block/block-backend.c b/block/block-backend.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/block-backend.c
25
+++ b/block/block-backend.c
26
@@ -XXX,XX +XXX,XX @@ void blk_drain_all(void)
27
bdrv_drain_all_begin();
28
29
while ((blk = blk_all_next(blk)) != NULL) {
30
- AioContext *ctx = blk_get_aio_context(blk);
31
-
32
- aio_context_acquire(ctx);
33
-
34
/* We may have -ENOMEDIUM completions in flight */
35
- AIO_WAIT_WHILE(ctx, qatomic_read(&blk->in_flight) > 0);
36
-
37
- aio_context_release(ctx);
38
+ AIO_WAIT_WHILE_UNLOCKED(NULL, qatomic_read(&blk->in_flight) > 0);
39
}
40
41
bdrv_drain_all_end();
42
--
43
2.40.0
diff view generated by jsdifflib
1
The raw format driver can simply forward the flag and let its bs->file
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
child take care of actually providing the zeros.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
There is no change in behavior. Switch to AIO_WAIT_WHILE_UNLOCKED()
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
instead of AIO_WAIT_WHILE() to document that this code has already been
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
audited and converted. The AioContext argument is already NULL so
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
aio_context_release() is never called anyway.
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
7
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20230309190855.414275-3-stefanha@redhat.com>
13
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
block/raw-format.c | 4 +++-
16
block/export/export.c | 2 +-
12
1 file changed, 3 insertions(+), 1 deletion(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
18
14
diff --git a/block/raw-format.c b/block/raw-format.c
19
diff --git a/block/export/export.c b/block/export/export.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/block/raw-format.c
21
--- a/block/export/export.c
17
+++ b/block/raw-format.c
22
+++ b/block/export/export.c
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
23
@@ -XXX,XX +XXX,XX @@ void blk_exp_close_all_type(BlockExportType type)
19
24
blk_exp_request_shutdown(exp);
20
s->size = offset;
25
}
21
offset += s->offset;
26
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
27
- AIO_WAIT_WHILE(NULL, blk_exp_has_type(type));
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
28
+ AIO_WAIT_WHILE_UNLOCKED(NULL, blk_exp_has_type(type));
24
}
29
}
25
30
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
31
void blk_exp_close_all(void)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
30
bs->file->bs->supported_zero_flags);
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
32
+ BDRV_REQ_ZERO_WRITE;
33
34
if (bs->probed && !bdrv_is_read_only(bs)) {
35
bdrv_refresh_filename(bs->file->bs);
36
--
32
--
37
2.25.3
33
2.40.0
38
34
39
35
diff view generated by jsdifflib
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
image is possibly preallocated and then the zero flag is added to all
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
6
2
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
3
The following conversion is safe and does not change behavior:
8
and if the protocol driver can ensure that the new area reads as zeros,
9
we can skip setting the zero flag in the qcow2 layer.
10
4
11
Unfortunately, the same approach doesn't work for metadata
5
GLOBAL_STATE_CODE();
12
preallocation, so we'll still set the zero flag there.
6
...
7
- AIO_WAIT_WHILE(qemu_get_aio_context(), ...);
8
+ AIO_WAIT_WHILE_UNLOCKED(NULL, ...);
13
9
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Since we're in GLOBAL_STATE_CODE(), qemu_get_aio_context() is our home
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
thread's AioContext. Thus AIO_WAIT_WHILE() does not unlock the
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
12
AioContext:
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
14
if (ctx_ && in_aio_context_home_thread(ctx_)) { \
15
while ((cond)) { \
16
aio_poll(ctx_, true); \
17
waited_ = true; \
18
} \
19
20
And that means AIO_WAIT_WHILE_UNLOCKED(NULL, ...) can be substituted.
21
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Message-Id: <20230309190855.414275-4-stefanha@redhat.com>
27
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
29
---
20
block/qcow2.c | 22 +++++++++++++++++++---
30
block/graph-lock.c | 2 +-
21
tests/qemu-iotests/274.out | 4 ++--
31
1 file changed, 1 insertion(+), 1 deletion(-)
22
2 files changed, 21 insertions(+), 5 deletions(-)
23
32
24
diff --git a/block/qcow2.c b/block/qcow2.c
33
diff --git a/block/graph-lock.c b/block/graph-lock.c
25
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.c
35
--- a/block/graph-lock.c
27
+++ b/block/qcow2.c
36
+++ b/block/graph-lock.c
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
37
@@ -XXX,XX +XXX,XX @@ void bdrv_graph_wrlock(void)
29
/* Allocate the data area */
38
* reader lock.
30
new_file_size = allocation_start +
39
*/
31
nb_new_data_clusters * s->cluster_size;
40
qatomic_set(&has_writer, 0);
32
- /* Image file grows, so @exact does not matter */
41
- AIO_WAIT_WHILE(qemu_get_aio_context(), reader_count() >= 1);
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
42
+ AIO_WAIT_WHILE_UNLOCKED(NULL, reader_count() >= 1);
34
- errp);
43
qatomic_set(&has_writer, 1);
35
+ /*
44
36
+ * Image file grows, so @exact does not matter.
45
/*
37
+ *
38
+ * If we need to zero out the new area, try first whether the protocol
39
+ * driver can already take care of this.
40
+ */
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
43
+ BDRV_REQ_ZERO_WRITE, NULL);
44
+ if (ret >= 0) {
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
46
+ }
47
+ } else {
48
+ ret = -1;
49
+ }
50
+ if (ret < 0) {
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
52
+ errp);
53
+ }
54
if (ret < 0) {
55
error_prepend(errp, "Failed to resize underlying file: ");
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/274.out
60
+++ b/tests/qemu-iotests/274.out
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
63
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
79
--
46
--
80
2.25.3
47
2.40.0
81
48
82
49
diff view generated by jsdifflib
1
When extending the size of an image that has a backing file larger than
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
4
2
5
Consider the following scenario where the overlay is shorter than its
3
Since the AioContext argument was already NULL, AIO_WAIT_WHILE() was
6
backing file:
4
never going to unlock the AioContext. Therefore it is possible to
5
replace AIO_WAIT_WHILE() with AIO_WAIT_WHILE_UNLOCKED().
7
6
8
base.qcow2: AAAAAAAA
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
overlay.qcow2: BBBB
8
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
unallocated and make the additional As from base.qcow2 visible like
11
Message-Id: <20230309190855.414275-5-stefanha@redhat.com>
13
before this patch, but zeros should be read.
12
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
14
---
36
block/io.c | 25 +++++++++++++++++++++++++
15
block/io.c | 2 +-
37
1 file changed, 25 insertions(+)
16
1 file changed, 1 insertion(+), 1 deletion(-)
38
17
39
diff --git a/block/io.c b/block/io.c
18
diff --git a/block/io.c b/block/io.c
40
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
41
--- a/block/io.c
20
--- a/block/io.c
42
+++ b/block/io.c
21
+++ b/block/io.c
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
22
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
44
goto out;
23
bdrv_drain_all_begin_nopoll();
45
}
24
46
25
/* Now poll the in-flight requests */
47
+ /*
26
- AIO_WAIT_WHILE(NULL, bdrv_drain_all_poll());
48
+ * If the image has a backing file that is large enough that it would
27
+ AIO_WAIT_WHILE_UNLOCKED(NULL, bdrv_drain_all_poll());
49
+ * provide data for the new area, we cannot leave it unallocated because
28
50
+ * then the backing file content would become visible. Instead, zero-fill
29
while ((bs = bdrv_next_all_states(bs))) {
51
+ * the new area.
30
bdrv_drain_assert_idle(bs);
52
+ *
53
+ * Note that if the image has a backing file, but was opened without the
54
+ * backing file, taking care of keeping things consistent with that backing
55
+ * file is the user's responsibility.
56
+ */
57
+ if (new_bytes && bs->backing) {
58
+ int64_t backing_len;
59
+
60
+ backing_len = bdrv_getlength(backing_bs(bs));
61
+ if (backing_len < 0) {
62
+ ret = backing_len;
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
64
+ goto out;
65
+ }
66
+
67
+ if (backing_len > old_size) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
69
+ }
70
+ }
71
+
72
if (drv->bdrv_co_truncate) {
73
if (flags & ~bs->supported_truncate_flags) {
74
error_setg(errp, "Block driver does not support requested flags");
75
--
31
--
76
2.25.3
32
2.40.0
77
33
78
34
diff view generated by jsdifflib
1
The QMP handler qmp_object_add() and the implementation of --object in
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
5
2
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
3
The HMP monitor runs in the main loop thread. Calling
7
new function user_creatable_add_dict() that can get an additional
4
AIO_WAIT_WHILE(qemu_get_aio_context(), ...) from the main loop thread is
8
parameter. The handling of "props" is only required for compatibility
5
equivalent to AIO_WAIT_WHILE_UNLOCKED(NULL, ...) because neither unlocks
9
and not required for the qemu-storage-daemon command line, so it stays
6
the AioContext and the latter's assertion that we're in the main loop
10
in qmp_object_add().
7
succeeds.
11
8
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Markus Armbruster <armbru@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230309190855.414275-6-stefanha@redhat.com>
15
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
17
---
14
include/qom/object_interfaces.h | 12 ++++++++++++
18
monitor/hmp.c | 2 +-
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
19
1 file changed, 1 insertion(+), 1 deletion(-)
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
18
20
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
21
diff --git a/monitor/hmp.c b/monitor/hmp.c
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qom/object_interfaces.h
23
--- a/monitor/hmp.c
22
+++ b/include/qom/object_interfaces.h
24
+++ b/monitor/hmp.c
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
25
@@ -XXX,XX +XXX,XX @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
24
const QDict *qdict,
26
Coroutine *co = qemu_coroutine_create(handle_hmp_command_co, &data);
25
Visitor *v, Error **errp);
27
monitor_set_cur(co, &mon->common);
26
28
aio_co_enter(qemu_get_aio_context(), co);
27
+/**
29
- AIO_WAIT_WHILE(qemu_get_aio_context(), !data.done);
28
+ * user_creatable_add_dict:
30
+ AIO_WAIT_WHILE_UNLOCKED(NULL, !data.done);
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
56
}
57
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
59
+{
60
+ Visitor *v;
61
+ Object *obj;
62
+ g_autofree char *type = NULL;
63
+ g_autofree char *id = NULL;
64
+
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
86
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
90
+++ b/qom/qom-qmp-cmds.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/qapi-commands-qom.h"
93
#include "qapi/qmp/qdict.h"
94
#include "qapi/qmp/qerror.h"
95
-#include "qapi/qobject-input-visitor.h"
96
#include "qemu/cutils.h"
97
#include "qom/object_interfaces.h"
98
#include "qom/qom-qobject.h"
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
126
}
31
}
127
32
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
33
qobject_unref(qdict);
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
133
}
134
135
void qmp_object_del(const char *id, Error **errp)
136
--
34
--
137
2.25.3
35
2.40.0
138
36
139
37
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
Backing files and raw external data files are mutually exclusive.
3
monitor_cleanup() is called from the main loop thread. Calling
4
The documentation of the raw external data bit (in autoclear_features)
4
AIO_WAIT_WHILE(qemu_get_aio_context(), ...) from the main loop thread is
5
already indicates that, but we should also mention it on the other
5
equivalent to AIO_WAIT_WHILE_UNLOCKED(NULL, ...) because neither unlocks
6
side.
6
the AioContext and the latter's assertion that we're in the main loop
7
succeeds.
7
8
8
Suggested-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
11
Reviewed-by: Markus Armbruster <armbru@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20230309190855.414275-7-stefanha@redhat.com>
15
Reviewed-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
17
---
14
docs/interop/qcow2.txt | 3 +++
18
monitor/monitor.c | 4 ++--
15
1 file changed, 3 insertions(+)
19
1 file changed, 2 insertions(+), 2 deletions(-)
16
20
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
21
diff --git a/monitor/monitor.c b/monitor/monitor.c
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
23
--- a/monitor/monitor.c
20
+++ b/docs/interop/qcow2.txt
24
+++ b/monitor/monitor.c
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
25
@@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void)
22
is stored (NB: The string is not null terminated). 0 if the
26
* We need to poll both qemu_aio_context and iohandler_ctx to make
23
image doesn't have a backing file.
27
* sure that the dispatcher coroutine keeps making progress and
24
28
* eventually terminates. qemu_aio_context is automatically
25
+ Note: backing files are incompatible with raw external data
29
- * polled by calling AIO_WAIT_WHILE on it, but we must poll
26
+ files (auto-clear feature bit 1).
30
+ * polled by calling AIO_WAIT_WHILE_UNLOCKED on it, but we must poll
27
+
31
* iohandler_ctx manually.
28
16 - 19: backing_file_size
32
*
29
Length of the backing file name in bytes. Must not be
33
* Letting the iothread continue while shutting down the dispatcher
30
longer than 1023 bytes. Undefined if the image doesn't have
34
@@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void)
35
aio_co_wake(qmp_dispatcher_co);
36
}
37
38
- AIO_WAIT_WHILE(qemu_get_aio_context(),
39
+ AIO_WAIT_WHILE_UNLOCKED(NULL,
40
(aio_poll(iohandler_get_aio_context(), false),
41
qatomic_mb_read(&qmp_dispatcher_co_busy)));
42
31
--
43
--
32
2.25.3
44
2.40.0
33
45
34
46
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
2
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
3
Fixup a few minor typos
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
5
Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
6
Message-Id: <20230313003744.55476-1-wilfred.mallawa@opensource.wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
10
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
11
include/block/aio-wait.h | 2 +-
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
12
include/block/block_int-common.h | 2 +-
9
tests/qemu-iotests/group | 1 +
13
2 files changed, 2 insertions(+), 2 deletions(-)
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
13
14
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
15
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
21
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+#
24
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
28
+#
29
+# This program is distributed in the hope that it will be useful,
30
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+# GNU General Public License for more details.
33
+#
34
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
41
+import iotests
42
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
176
new file mode 100644
177
index XXXXXXX..XXXXXXX
178
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
180
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
183
+
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
185
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
450
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
451
--- a/tests/qemu-iotests/group
17
--- a/include/block/aio-wait.h
452
+++ b/tests/qemu-iotests/group
18
+++ b/include/block/aio-wait.h
453
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
454
270 rw backing quick
20
* @ctx: the aio context, or NULL if multiple aio contexts (for which the
455
272 rw
21
* caller does not hold a lock) are involved in the polling condition.
456
273 backing quick
22
* @cond: wait while this conditional expression is true
457
+274 rw backing
23
- * @unlock: whether to unlock and then lock again @ctx. This apples
458
277 rw quick
24
+ * @unlock: whether to unlock and then lock again @ctx. This applies
459
279 rw backing quick
25
* only when waiting for another AioContext from the main loop.
460
280 rw migration quick
26
* Otherwise it's ignored.
27
*
28
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block_int-common.h
31
+++ b/include/block/block_int-common.h
32
@@ -XXX,XX +XXX,XX @@ extern QemuOptsList bdrv_create_opts_simple;
33
/*
34
* Common functions that are neither I/O nor Global State.
35
*
36
- * See include/block/block-commmon.h for more information about
37
+ * See include/block/block-common.h for more information about
38
* the Common API.
39
*/
40
461
--
41
--
462
2.25.3
42
2.40.0
463
43
464
44
diff view generated by jsdifflib
New patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
2
3
Not a coroutine_fn, you say?
4
5
static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
6
{
7
BdrvChild *child;
8
int64_t child_size, sum = 0;
9
10
QLIST_FOREACH(child, &bs->children, next) {
11
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
12
BDRV_CHILD_FILTERED))
13
{
14
child_size = bdrv_co_get_allocated_file_size(child->bs);
15
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16
17
Well what do we have here?!
18
19
I rest my case, your honor.
20
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Message-Id: <20230308211435.346375-1-stefanha@redhat.com>
23
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
26
block.c | 2 +-
27
1 file changed, 1 insertion(+), 1 deletion(-)
28
29
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
32
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ exit:
34
* sums the size of all data-bearing children. (This excludes backing
35
* children.)
36
*/
37
-static int64_t bdrv_sum_allocated_file_size(BlockDriverState *bs)
38
+static int64_t coroutine_fn bdrv_sum_allocated_file_size(BlockDriverState *bs)
39
{
40
BdrvChild *child;
41
int64_t child_size, sum = 0;
42
--
43
2.40.0
diff view generated by jsdifflib
New patch
1
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
3
Remove usage of aio_context_acquire by always submitting asynchronous
4
AIO to the current thread's LinuxAioState.
5
6
In order to prevent mistakes from the caller side, avoid passing LinuxAioState
7
in laio_io_{plug/unplug} and laio_co_submit, and document the functions
8
to make clear that they work in the current thread's AioContext.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20230203131731.851116-2-eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
include/block/aio.h | 4 ----
17
include/block/raw-aio.h | 18 ++++++++++++------
18
include/sysemu/block-backend-io.h | 5 +++++
19
block/file-posix.c | 10 +++-------
20
block/linux-aio.c | 29 +++++++++++++++++------------
21
5 files changed, 37 insertions(+), 29 deletions(-)
22
23
diff --git a/include/block/aio.h b/include/block/aio.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/aio.h
26
+++ b/include/block/aio.h
27
@@ -XXX,XX +XXX,XX @@ struct AioContext {
28
struct ThreadPool *thread_pool;
29
30
#ifdef CONFIG_LINUX_AIO
31
- /*
32
- * State for native Linux AIO. Uses aio_context_acquire/release for
33
- * locking.
34
- */
35
struct LinuxAioState *linux_aio;
36
#endif
37
#ifdef CONFIG_LINUX_IO_URING
38
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/raw-aio.h
41
+++ b/include/block/raw-aio.h
42
@@ -XXX,XX +XXX,XX @@
43
typedef struct LinuxAioState LinuxAioState;
44
LinuxAioState *laio_init(Error **errp);
45
void laio_cleanup(LinuxAioState *s);
46
-int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
47
- uint64_t offset, QEMUIOVector *qiov, int type,
48
- uint64_t dev_max_batch);
49
+
50
+/* laio_co_submit: submit I/O requests in the thread's current AioContext. */
51
+int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
52
+ int type, uint64_t dev_max_batch);
53
+
54
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
55
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
56
-void laio_io_plug(BlockDriverState *bs, LinuxAioState *s);
57
-void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s,
58
- uint64_t dev_max_batch);
59
+
60
+/*
61
+ * laio_io_plug/unplug work in the thread's current AioContext, therefore the
62
+ * caller must ensure that they are paired in the same IOThread.
63
+ */
64
+void laio_io_plug(void);
65
+void laio_io_unplug(uint64_t dev_max_batch);
66
#endif
67
/* io_uring.c - Linux io_uring implementation */
68
#ifdef CONFIG_LINUX_IO_URING
69
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
70
index XXXXXXX..XXXXXXX 100644
71
--- a/include/sysemu/block-backend-io.h
72
+++ b/include/sysemu/block-backend-io.h
73
@@ -XXX,XX +XXX,XX @@ void blk_iostatus_set_err(BlockBackend *blk, int error);
74
int blk_get_max_iov(BlockBackend *blk);
75
int blk_get_max_hw_iov(BlockBackend *blk);
76
77
+/*
78
+ * blk_io_plug/unplug are thread-local operations. This means that multiple
79
+ * IOThreads can simultaneously call plug/unplug, but the caller must ensure
80
+ * that each unplug() is called in the same IOThread of the matching plug().
81
+ */
82
void coroutine_fn blk_co_io_plug(BlockBackend *blk);
83
void co_wrapper blk_io_plug(BlockBackend *blk);
84
85
diff --git a/block/file-posix.c b/block/file-posix.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/block/file-posix.c
88
+++ b/block/file-posix.c
89
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
90
#endif
91
#ifdef CONFIG_LINUX_AIO
92
} else if (s->use_linux_aio) {
93
- LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
94
assert(qiov->size == bytes);
95
- return laio_co_submit(bs, aio, s->fd, offset, qiov, type,
96
- s->aio_max_batch);
97
+ return laio_co_submit(s->fd, offset, qiov, type, s->aio_max_batch);
98
#endif
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
102
BDRVRawState __attribute__((unused)) *s = bs->opaque;
103
#ifdef CONFIG_LINUX_AIO
104
if (s->use_linux_aio) {
105
- LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
106
- laio_io_plug(bs, aio);
107
+ laio_io_plug();
108
}
109
#endif
110
#ifdef CONFIG_LINUX_IO_URING
111
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
112
BDRVRawState __attribute__((unused)) *s = bs->opaque;
113
#ifdef CONFIG_LINUX_AIO
114
if (s->use_linux_aio) {
115
- LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
116
- laio_io_unplug(bs, aio, s->aio_max_batch);
117
+ laio_io_unplug(s->aio_max_batch);
118
}
119
#endif
120
#ifdef CONFIG_LINUX_IO_URING
121
diff --git a/block/linux-aio.c b/block/linux-aio.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/block/linux-aio.c
124
+++ b/block/linux-aio.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/coroutine.h"
127
#include "qapi/error.h"
128
129
+/* Only used for assertions. */
130
+#include "qemu/coroutine_int.h"
131
+
132
#include <libaio.h>
133
134
/*
135
@@ -XXX,XX +XXX,XX @@ struct LinuxAioState {
136
io_context_t ctx;
137
EventNotifier e;
138
139
- /* io queue for submit at batch. Protected by AioContext lock. */
140
+ /* No locking required, only accessed from AioContext home thread */
141
LaioQueue io_q;
142
-
143
- /* I/O completion processing. Only runs in I/O thread. */
144
QEMUBH *completion_bh;
145
int event_idx;
146
int event_max;
147
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
148
* later. Coroutines cannot be entered recursively so avoid doing
149
* that!
150
*/
151
+ assert(laiocb->co->ctx == laiocb->ctx->aio_context);
152
if (!qemu_coroutine_entered(laiocb->co)) {
153
aio_co_wake(laiocb->co);
154
}
155
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completions(LinuxAioState *s)
156
157
static void qemu_laio_process_completions_and_submit(LinuxAioState *s)
158
{
159
- aio_context_acquire(s->aio_context);
160
qemu_laio_process_completions(s);
161
162
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
163
ioq_submit(s);
164
}
165
- aio_context_release(s->aio_context);
166
}
167
168
static void qemu_laio_completion_bh(void *opaque)
169
@@ -XXX,XX +XXX,XX @@ static uint64_t laio_max_batch(LinuxAioState *s, uint64_t dev_max_batch)
170
return max_batch;
171
}
172
173
-void laio_io_plug(BlockDriverState *bs, LinuxAioState *s)
174
+void laio_io_plug(void)
175
{
176
+ AioContext *ctx = qemu_get_current_aio_context();
177
+ LinuxAioState *s = aio_get_linux_aio(ctx);
178
+
179
s->io_q.plugged++;
180
}
181
182
-void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s,
183
- uint64_t dev_max_batch)
184
+void laio_io_unplug(uint64_t dev_max_batch)
185
{
186
+ AioContext *ctx = qemu_get_current_aio_context();
187
+ LinuxAioState *s = aio_get_linux_aio(ctx);
188
+
189
assert(s->io_q.plugged);
190
s->io_q.plugged--;
191
192
@@ -XXX,XX +XXX,XX @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
193
return 0;
194
}
195
196
-int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
197
- uint64_t offset, QEMUIOVector *qiov, int type,
198
- uint64_t dev_max_batch)
199
+int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
200
+ int type, uint64_t dev_max_batch)
201
{
202
int ret;
203
+ AioContext *ctx = qemu_get_current_aio_context();
204
struct qemu_laiocb laiocb = {
205
.co = qemu_coroutine_self(),
206
.nbytes = qiov->size,
207
- .ctx = s,
208
+ .ctx = aio_get_linux_aio(ctx),
209
.ret = -EINPROGRESS,
210
.is_read = (type == QEMU_AIO_READ),
211
.qiov = qiov,
212
--
213
2.40.0
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Remove usage of aio_context_acquire by always submitting asynchronous
4
AIO to the current thread's LuringState.
5
6
In order to prevent mistakes from the caller side, avoid passing LuringState
7
in luring_io_{plug/unplug} and luring_co_submit, and document the functions
8
to make clear that they work in the current thread's AioContext.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20230203131731.851116-3-eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
include/block/aio.h | 4 ----
17
include/block/raw-aio.h | 15 +++++++++++----
18
block/file-posix.c | 12 ++++--------
19
block/io_uring.c | 23 +++++++++++++++--------
20
4 files changed, 30 insertions(+), 24 deletions(-)
21
22
diff --git a/include/block/aio.h b/include/block/aio.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/aio.h
25
+++ b/include/block/aio.h
26
@@ -XXX,XX +XXX,XX @@ struct AioContext {
27
struct LinuxAioState *linux_aio;
28
#endif
29
#ifdef CONFIG_LINUX_IO_URING
30
- /*
31
- * State for Linux io_uring. Uses aio_context_acquire/release for
32
- * locking.
33
- */
34
struct LuringState *linux_io_uring;
35
36
/* State for file descriptor monitoring using Linux io_uring */
37
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/raw-aio.h
40
+++ b/include/block/raw-aio.h
41
@@ -XXX,XX +XXX,XX @@ void laio_io_unplug(uint64_t dev_max_batch);
42
typedef struct LuringState LuringState;
43
LuringState *luring_init(Error **errp);
44
void luring_cleanup(LuringState *s);
45
-int coroutine_fn luring_co_submit(BlockDriverState *bs, LuringState *s, int fd,
46
- uint64_t offset, QEMUIOVector *qiov, int type);
47
+
48
+/* luring_co_submit: submit I/O requests in the thread's current AioContext. */
49
+int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
50
+ QEMUIOVector *qiov, int type);
51
void luring_detach_aio_context(LuringState *s, AioContext *old_context);
52
void luring_attach_aio_context(LuringState *s, AioContext *new_context);
53
-void luring_io_plug(BlockDriverState *bs, LuringState *s);
54
-void luring_io_unplug(BlockDriverState *bs, LuringState *s);
55
+
56
+/*
57
+ * luring_io_plug/unplug work in the thread's current AioContext, therefore the
58
+ * caller must ensure that they are paired in the same IOThread.
59
+ */
60
+void luring_io_plug(void);
61
+void luring_io_unplug(void);
62
#endif
63
64
#ifdef _WIN32
65
diff --git a/block/file-posix.c b/block/file-posix.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/block/file-posix.c
68
+++ b/block/file-posix.c
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
70
type |= QEMU_AIO_MISALIGNED;
71
#ifdef CONFIG_LINUX_IO_URING
72
} else if (s->use_linux_io_uring) {
73
- LuringState *aio = aio_get_linux_io_uring(bdrv_get_aio_context(bs));
74
assert(qiov->size == bytes);
75
- return luring_co_submit(bs, aio, s->fd, offset, qiov, type);
76
+ return luring_co_submit(bs, s->fd, offset, qiov, type);
77
#endif
78
#ifdef CONFIG_LINUX_AIO
79
} else if (s->use_linux_aio) {
80
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
81
#endif
82
#ifdef CONFIG_LINUX_IO_URING
83
if (s->use_linux_io_uring) {
84
- LuringState *aio = aio_get_linux_io_uring(bdrv_get_aio_context(bs));
85
- luring_io_plug(bs, aio);
86
+ luring_io_plug();
87
}
88
#endif
89
}
90
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
91
#endif
92
#ifdef CONFIG_LINUX_IO_URING
93
if (s->use_linux_io_uring) {
94
- LuringState *aio = aio_get_linux_io_uring(bdrv_get_aio_context(bs));
95
- luring_io_unplug(bs, aio);
96
+ luring_io_unplug();
97
}
98
#endif
99
}
100
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
101
102
#ifdef CONFIG_LINUX_IO_URING
103
if (s->use_linux_io_uring) {
104
- LuringState *aio = aio_get_linux_io_uring(bdrv_get_aio_context(bs));
105
- return luring_co_submit(bs, aio, s->fd, 0, NULL, QEMU_AIO_FLUSH);
106
+ return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
107
}
108
#endif
109
return raw_thread_pool_submit(bs, handle_aiocb_flush, &acb);
110
diff --git a/block/io_uring.c b/block/io_uring.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/io_uring.c
113
+++ b/block/io_uring.c
114
@@ -XXX,XX +XXX,XX @@
115
#include "qapi/error.h"
116
#include "trace.h"
117
118
+/* Only used for assertions. */
119
+#include "qemu/coroutine_int.h"
120
+
121
/* io_uring ring size */
122
#define MAX_ENTRIES 128
123
124
@@ -XXX,XX +XXX,XX @@ typedef struct LuringState {
125
126
struct io_uring ring;
127
128
- /* io queue for submit at batch. Protected by AioContext lock. */
129
+ /* No locking required, only accessed from AioContext home thread */
130
LuringQueue io_q;
131
132
- /* I/O completion processing. Only runs in I/O thread. */
133
QEMUBH *completion_bh;
134
} LuringState;
135
136
@@ -XXX,XX +XXX,XX @@ end:
137
* eventually runs later. Coroutines cannot be entered recursively
138
* so avoid doing that!
139
*/
140
+ assert(luringcb->co->ctx == s->aio_context);
141
if (!qemu_coroutine_entered(luringcb->co)) {
142
aio_co_wake(luringcb->co);
143
}
144
@@ -XXX,XX +XXX,XX @@ static int ioq_submit(LuringState *s)
145
146
static void luring_process_completions_and_submit(LuringState *s)
147
{
148
- aio_context_acquire(s->aio_context);
149
luring_process_completions(s);
150
151
if (!s->io_q.plugged && s->io_q.in_queue > 0) {
152
ioq_submit(s);
153
}
154
- aio_context_release(s->aio_context);
155
}
156
157
static void qemu_luring_completion_bh(void *opaque)
158
@@ -XXX,XX +XXX,XX @@ static void ioq_init(LuringQueue *io_q)
159
io_q->blocked = false;
160
}
161
162
-void luring_io_plug(BlockDriverState *bs, LuringState *s)
163
+void luring_io_plug(void)
164
{
165
+ AioContext *ctx = qemu_get_current_aio_context();
166
+ LuringState *s = aio_get_linux_io_uring(ctx);
167
trace_luring_io_plug(s);
168
s->io_q.plugged++;
169
}
170
171
-void luring_io_unplug(BlockDriverState *bs, LuringState *s)
172
+void luring_io_unplug(void)
173
{
174
+ AioContext *ctx = qemu_get_current_aio_context();
175
+ LuringState *s = aio_get_linux_io_uring(ctx);
176
assert(s->io_q.plugged);
177
trace_luring_io_unplug(s, s->io_q.blocked, s->io_q.plugged,
178
s->io_q.in_queue, s->io_q.in_flight);
179
@@ -XXX,XX +XXX,XX @@ static int luring_do_submit(int fd, LuringAIOCB *luringcb, LuringState *s,
180
return 0;
181
}
182
183
-int coroutine_fn luring_co_submit(BlockDriverState *bs, LuringState *s, int fd,
184
- uint64_t offset, QEMUIOVector *qiov, int type)
185
+int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
186
+ QEMUIOVector *qiov, int type)
187
{
188
int ret;
189
+ AioContext *ctx = qemu_get_current_aio_context();
190
+ LuringState *s = aio_get_linux_io_uring(ctx);
191
LuringAIOCB luringcb = {
192
.co = qemu_coroutine_self(),
193
.ret = -EINPROGRESS,
194
--
195
2.40.0
diff view generated by jsdifflib
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
driver callbacks, and a supported_truncate_flags field in
2
3
BlockDriverState that allows drivers to advertise support for request
3
Use qemu_get_current_aio_context() where possible, since we always
4
flags in the context of truncate.
4
submit work to the current thread anyways.
5
5
6
For now, we always pass 0 and no drivers declare support for any flag.
6
We want to also be sure that the thread submitting the work is
7
7
the same as the one processing the pool, to avoid adding
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
synchronization to the pool list.
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20230203131731.851116-4-eesposit@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
---
15
include/block/block_int.h | 10 +++++++++-
16
include/block/thread-pool.h | 5 +++++
16
block/crypto.c | 3 ++-
17
block/file-posix.c | 21 ++++++++++-----------
17
block/file-posix.c | 2 +-
18
block/file-win32.c | 2 +-
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
19
block/qcow2-threads.c | 2 +-
20
block/io.c | 8 +++++++-
20
util/thread-pool.c | 9 ++++-----
21
block/iscsi.c | 2 +-
21
5 files changed, 21 insertions(+), 18 deletions(-)
22
block/nfs.c | 3 ++-
22
23
block/qcow2.c | 2 +-
23
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
24
block/qed.c | 1 +
24
index XXXXXXX..XXXXXXX 100644
25
block/raw-format.c | 2 +-
25
--- a/include/block/thread-pool.h
26
block/rbd.c | 1 +
26
+++ b/include/block/thread-pool.h
27
block/sheepdog.c | 4 ++--
27
@@ -XXX,XX +XXX,XX @@ typedef struct ThreadPool ThreadPool;
28
block/ssh.c | 2 +-
28
ThreadPool *thread_pool_new(struct AioContext *ctx);
29
tests/test-block-iothread.c | 3 ++-
29
void thread_pool_free(ThreadPool *pool);
30
15 files changed, 33 insertions(+), 13 deletions(-)
30
31
31
+/*
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
32
+ * thread_pool_submit* API: submit I/O requests in the thread's
33
index XXXXXXX..XXXXXXX 100644
33
+ * current AioContext.
34
--- a/include/block/block_int.h
34
+ */
35
+++ b/include/block/block_int.h
35
BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
ThreadPoolFunc *func, void *arg,
37
*/
37
BlockCompletionFunc *cb, void *opaque);
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
38
int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
39
bool exact, PreallocMode prealloc,
39
ThreadPoolFunc *func, void *arg);
40
- Error **errp);
40
void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
41
+ BdrvRequestFlags flags, Error **errp);
41
+
42
42
void thread_pool_update_params(ThreadPool *pool, struct AioContext *ctx);
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
43
44
bool has_variable_length;
44
#endif
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
63
+++ b/block/crypto.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
66
static int coroutine_fn
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
45
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
47
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
48
+++ b/block/file-posix.c
49
@@ -XXX,XX +XXX,XX @@ out:
50
return result;
51
}
52
53
-static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
54
- ThreadPoolFunc func, void *arg)
55
+static int coroutine_fn raw_thread_pool_submit(ThreadPoolFunc func, void *arg)
56
{
57
/* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
58
- ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
59
+ ThreadPool *pool = aio_get_thread_pool(qemu_get_current_aio_context());
60
return thread_pool_submit_co(pool, func, arg);
61
}
62
63
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
64
};
65
66
assert(qiov->size == bytes);
67
- return raw_thread_pool_submit(bs, handle_aiocb_rw, &acb);
68
+ return raw_thread_pool_submit(handle_aiocb_rw, &acb);
69
}
70
71
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
72
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
73
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
74
}
75
#endif
76
- return raw_thread_pool_submit(bs, handle_aiocb_flush, &acb);
77
+ return raw_thread_pool_submit(handle_aiocb_flush, &acb);
78
}
79
80
static void raw_aio_attach_aio_context(BlockDriverState *bs,
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
81
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
82
},
83
};
84
85
- return raw_thread_pool_submit(bs, handle_aiocb_truncate, &acb);
86
+ return raw_thread_pool_submit(handle_aiocb_truncate, &acb);
87
}
79
88
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
89
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
90
@@ -XXX,XX +XXX,XX @@ raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes,
82
- Error **errp)
91
acb.aio_type |= QEMU_AIO_BLKDEV;
83
+ BdrvRequestFlags flags, Error **errp)
92
}
84
{
93
85
BDRVRawState *s = bs->opaque;
94
- ret = raw_thread_pool_submit(bs, handle_aiocb_discard, &acb);
86
struct stat st;
95
+ ret = raw_thread_pool_submit(handle_aiocb_discard, &acb);
96
raw_account_discard(s, bytes, ret);
97
return ret;
98
}
99
@@ -XXX,XX +XXX,XX @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
100
handler = handle_aiocb_write_zeroes;
101
}
102
103
- return raw_thread_pool_submit(bs, handler, &acb);
104
+ return raw_thread_pool_submit(handler, &acb);
105
}
106
107
static int coroutine_fn raw_co_pwrite_zeroes(
108
@@ -XXX,XX +XXX,XX @@ raw_co_copy_range_to(BlockDriverState *bs,
109
},
110
};
111
112
- return raw_thread_pool_submit(bs, handle_aiocb_copy_range, &acb);
113
+ return raw_thread_pool_submit(handle_aiocb_copy_range, &acb);
114
}
115
116
BlockDriver bdrv_file = {
117
@@ -XXX,XX +XXX,XX @@ hdev_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
118
struct sg_io_hdr *io_hdr = buf;
119
if (io_hdr->cmdp[0] == PERSISTENT_RESERVE_OUT ||
120
io_hdr->cmdp[0] == PERSISTENT_RESERVE_IN) {
121
- return pr_manager_execute(s->pr_mgr, bdrv_get_aio_context(bs),
122
+ return pr_manager_execute(s->pr_mgr, qemu_get_current_aio_context(),
123
s->fd, io_hdr);
124
}
125
}
126
@@ -XXX,XX +XXX,XX @@ hdev_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
127
},
128
};
129
130
- return raw_thread_pool_submit(bs, handle_aiocb_ioctl, &acb);
131
+ return raw_thread_pool_submit(handle_aiocb_ioctl, &acb);
132
}
133
#endif /* linux */
134
87
diff --git a/block/file-win32.c b/block/file-win32.c
135
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
136
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
137
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
138
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
139
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
92
140
acb->aio_offset = offset;
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
141
94
bool exact, PreallocMode prealloc,
142
trace_file_paio_submit(acb, opaque, offset, count, type);
95
- Error **errp)
143
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
96
+ BdrvRequestFlags flags, Error **errp)
144
+ pool = aio_get_thread_pool(qemu_get_current_aio_context());
145
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
146
}
147
148
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/qcow2-threads.c
151
+++ b/block/qcow2-threads.c
152
@@ -XXX,XX +XXX,XX @@ qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
97
{
153
{
98
BDRVRawState *s = bs->opaque;
154
int ret;
99
LONG low, high;
155
BDRVQcow2State *s = bs->opaque;
100
diff --git a/block/gluster.c b/block/gluster.c
156
- ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
101
index XXXXXXX..XXXXXXX 100644
157
+ ThreadPool *pool = aio_get_thread_pool(qemu_get_current_aio_context());
102
--- a/block/gluster.c
158
103
+++ b/block/gluster.c
159
qemu_co_mutex_lock(&s->lock);
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
160
while (s->nb_threads >= QCOW2_MAX_THREADS) {
105
int64_t offset,
161
diff --git a/util/thread-pool.c b/util/thread-pool.c
106
bool exact,
162
index XXXXXXX..XXXXXXX 100644
107
PreallocMode prealloc,
163
--- a/util/thread-pool.c
108
+ BdrvRequestFlags flags,
164
+++ b/util/thread-pool.c
109
Error **errp)
165
@@ -XXX,XX +XXX,XX @@ struct ThreadPoolElement {
166
/* Access to this list is protected by lock. */
167
QTAILQ_ENTRY(ThreadPoolElement) reqs;
168
169
- /* Access to this list is protected by the global mutex. */
170
+ /* This list is only written by the thread pool's mother thread. */
171
QLIST_ENTRY(ThreadPoolElement) all;
172
};
173
174
@@ -XXX,XX +XXX,XX @@ static void thread_pool_completion_bh(void *opaque)
175
ThreadPool *pool = opaque;
176
ThreadPoolElement *elem, *next;
177
178
- aio_context_acquire(pool->ctx);
179
restart:
180
QLIST_FOREACH_SAFE(elem, &pool->head, all, next) {
181
if (elem->state != THREAD_DONE) {
182
@@ -XXX,XX +XXX,XX @@ restart:
183
*/
184
qemu_bh_schedule(pool->completion_bh);
185
186
- aio_context_release(pool->ctx);
187
elem->common.cb(elem->common.opaque, elem->ret);
188
- aio_context_acquire(pool->ctx);
189
190
/* We can safely cancel the completion_bh here regardless of someone
191
* else having scheduled it meanwhile because we reenter the
192
@@ -XXX,XX +XXX,XX @@ restart:
193
qemu_aio_unref(elem);
194
}
195
}
196
- aio_context_release(pool->ctx);
197
}
198
199
static void thread_pool_cancel(BlockAIOCB *acb)
200
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
110
{
201
{
111
BDRVGlusterState *s = bs->opaque;
202
ThreadPoolElement *req;
112
diff --git a/block/io.c b/block/io.c
203
113
index XXXXXXX..XXXXXXX 100644
204
+ /* Assert that the thread submitting work is the same running the pool */
114
--- a/block/io.c
205
+ assert(pool->ctx == qemu_get_current_aio_context());
115
+++ b/block/io.c
206
+
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
207
req = qemu_aio_get(&thread_pool_aiocb_info, NULL, cb, opaque);
117
BlockDriverState *bs = child->bs;
208
req->func = func;
118
BlockDriver *drv = bs->drv;
209
req->arg = arg;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
126
127
if (drv->bdrv_co_truncate) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
133
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
135
} else if (bs->file && drv->is_filter) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
264
--
210
--
265
2.25.3
211
2.40.0
266
267
diff view generated by jsdifflib
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
OS, so we can advertise the flag and just ignore it.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
thread_pool_submit_aio() is always called on a pool taken from
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
qemu_get_current_aio_context(), and that is the only intended
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
use: each pool runs only in the same thread that is submitting
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
work to it, it can't run anywhere else.
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
7
8
Therefore simplify the thread_pool_submit* API and remove the
9
ThreadPool function parameter.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Message-Id: <20230203131731.851116-5-eesposit@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
16
---
11
block/file-posix.c | 4 ++++
17
include/block/thread-pool.h | 10 ++++------
12
1 file changed, 4 insertions(+)
18
backends/tpm/tpm_backend.c | 4 +---
19
block/file-posix.c | 4 +---
20
block/file-win32.c | 4 +---
21
block/qcow2-threads.c | 3 +--
22
hw/9pfs/coth.c | 3 +--
23
hw/ppc/spapr_nvdimm.c | 6 ++----
24
hw/virtio/virtio-pmem.c | 3 +--
25
scsi/pr-manager.c | 3 +--
26
scsi/qemu-pr-helper.c | 3 +--
27
tests/unit/test-thread-pool.c | 12 +++++-------
28
util/thread-pool.c | 16 ++++++++--------
29
12 files changed, 27 insertions(+), 44 deletions(-)
13
30
31
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/block/thread-pool.h
34
+++ b/include/block/thread-pool.h
35
@@ -XXX,XX +XXX,XX @@ void thread_pool_free(ThreadPool *pool);
36
* thread_pool_submit* API: submit I/O requests in the thread's
37
* current AioContext.
38
*/
39
-BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
40
- ThreadPoolFunc *func, void *arg,
41
- BlockCompletionFunc *cb, void *opaque);
42
-int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
43
- ThreadPoolFunc *func, void *arg);
44
-void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
45
+BlockAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
46
+ BlockCompletionFunc *cb, void *opaque);
47
+int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg);
48
+void thread_pool_submit(ThreadPoolFunc *func, void *arg);
49
50
void thread_pool_update_params(ThreadPool *pool, struct AioContext *ctx);
51
52
diff --git a/backends/tpm/tpm_backend.c b/backends/tpm/tpm_backend.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/backends/tpm/tpm_backend.c
55
+++ b/backends/tpm/tpm_backend.c
56
@@ -XXX,XX +XXX,XX @@ bool tpm_backend_had_startup_error(TPMBackend *s)
57
58
void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd)
59
{
60
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
61
-
62
if (s->cmd != NULL) {
63
error_report("There is a TPM request pending");
64
return;
65
@@ -XXX,XX +XXX,XX @@ void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd)
66
67
s->cmd = cmd;
68
object_ref(OBJECT(s));
69
- thread_pool_submit_aio(pool, tpm_backend_worker_thread, s,
70
+ thread_pool_submit_aio(tpm_backend_worker_thread, s,
71
tpm_backend_request_completed, s);
72
}
73
14
diff --git a/block/file-posix.c b/block/file-posix.c
74
diff --git a/block/file-posix.c b/block/file-posix.c
15
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
16
--- a/block/file-posix.c
76
--- a/block/file-posix.c
17
+++ b/block/file-posix.c
77
+++ b/block/file-posix.c
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
78
@@ -XXX,XX +XXX,XX @@ out:
19
#endif
79
20
80
static int coroutine_fn raw_thread_pool_submit(ThreadPoolFunc func, void *arg)
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
81
{
22
+ if (S_ISREG(st.st_mode)) {
82
- /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
23
+ /* When extending regular files, we get zeros from the OS */
83
- ThreadPool *pool = aio_get_thread_pool(qemu_get_current_aio_context());
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
84
- return thread_pool_submit_co(pool, func, arg);
25
+ }
85
+ return thread_pool_submit_co(func, arg);
26
ret = 0;
86
}
27
fail:
87
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
88
/*
89
diff --git a/block/file-win32.c b/block/file-win32.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/file-win32.c
92
+++ b/block/file-win32.c
93
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
94
BlockCompletionFunc *cb, void *opaque, int type)
95
{
96
RawWin32AIOData *acb = g_new(RawWin32AIOData, 1);
97
- ThreadPool *pool;
98
99
acb->bs = bs;
100
acb->hfile = hfile;
101
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
102
acb->aio_offset = offset;
103
104
trace_file_paio_submit(acb, opaque, offset, count, type);
105
- pool = aio_get_thread_pool(qemu_get_current_aio_context());
106
- return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
107
+ return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
108
}
109
110
int qemu_ftruncate64(int fd, int64_t length)
111
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/qcow2-threads.c
114
+++ b/block/qcow2-threads.c
115
@@ -XXX,XX +XXX,XX @@ qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
116
{
117
int ret;
118
BDRVQcow2State *s = bs->opaque;
119
- ThreadPool *pool = aio_get_thread_pool(qemu_get_current_aio_context());
120
121
qemu_co_mutex_lock(&s->lock);
122
while (s->nb_threads >= QCOW2_MAX_THREADS) {
123
@@ -XXX,XX +XXX,XX @@ qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
124
s->nb_threads++;
125
qemu_co_mutex_unlock(&s->lock);
126
127
- ret = thread_pool_submit_co(pool, func, arg);
128
+ ret = thread_pool_submit_co(func, arg);
129
130
qemu_co_mutex_lock(&s->lock);
131
s->nb_threads--;
132
diff --git a/hw/9pfs/coth.c b/hw/9pfs/coth.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/9pfs/coth.c
135
+++ b/hw/9pfs/coth.c
136
@@ -XXX,XX +XXX,XX @@ static int coroutine_enter_func(void *arg)
137
void co_run_in_worker_bh(void *opaque)
138
{
139
Coroutine *co = opaque;
140
- thread_pool_submit_aio(aio_get_thread_pool(qemu_get_aio_context()),
141
- coroutine_enter_func, co, coroutine_enter_cb, co);
142
+ thread_pool_submit_aio(coroutine_enter_func, co, coroutine_enter_cb, co);
143
}
144
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/hw/ppc/spapr_nvdimm.c
147
+++ b/hw/ppc/spapr_nvdimm.c
148
@@ -XXX,XX +XXX,XX @@ static int spapr_nvdimm_flush_post_load(void *opaque, int version_id)
149
{
150
SpaprNVDIMMDevice *s_nvdimm = (SpaprNVDIMMDevice *)opaque;
151
SpaprNVDIMMDeviceFlushState *state;
152
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
153
HostMemoryBackend *backend = MEMORY_BACKEND(PC_DIMM(s_nvdimm)->hostmem);
154
bool is_pmem = object_property_get_bool(OBJECT(backend), "pmem", NULL);
155
bool pmem_override = object_property_get_bool(OBJECT(s_nvdimm),
156
@@ -XXX,XX +XXX,XX @@ static int spapr_nvdimm_flush_post_load(void *opaque, int version_id)
157
}
158
159
QLIST_FOREACH(state, &s_nvdimm->pending_nvdimm_flush_states, node) {
160
- thread_pool_submit_aio(pool, flush_worker_cb, state,
161
+ thread_pool_submit_aio(flush_worker_cb, state,
162
spapr_nvdimm_flush_completion_cb, state);
163
}
164
165
@@ -XXX,XX +XXX,XX @@ static target_ulong h_scm_flush(PowerPCCPU *cpu, SpaprMachineState *spapr,
166
PCDIMMDevice *dimm;
167
HostMemoryBackend *backend = NULL;
168
SpaprNVDIMMDeviceFlushState *state;
169
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
170
int fd;
171
172
if (!drc || !drc->dev ||
173
@@ -XXX,XX +XXX,XX @@ static target_ulong h_scm_flush(PowerPCCPU *cpu, SpaprMachineState *spapr,
174
175
state->drcidx = drc_index;
176
177
- thread_pool_submit_aio(pool, flush_worker_cb, state,
178
+ thread_pool_submit_aio(flush_worker_cb, state,
179
spapr_nvdimm_flush_completion_cb, state);
180
181
continue_token = state->continue_token;
182
diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/hw/virtio/virtio-pmem.c
185
+++ b/hw/virtio/virtio-pmem.c
186
@@ -XXX,XX +XXX,XX @@ static void virtio_pmem_flush(VirtIODevice *vdev, VirtQueue *vq)
187
VirtIODeviceRequest *req_data;
188
VirtIOPMEM *pmem = VIRTIO_PMEM(vdev);
189
HostMemoryBackend *backend = MEMORY_BACKEND(pmem->memdev);
190
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
191
192
trace_virtio_pmem_flush_request();
193
req_data = virtqueue_pop(vq, sizeof(VirtIODeviceRequest));
194
@@ -XXX,XX +XXX,XX @@ static void virtio_pmem_flush(VirtIODevice *vdev, VirtQueue *vq)
195
req_data->fd = memory_region_get_fd(&backend->mr);
196
req_data->pmem = pmem;
197
req_data->vdev = vdev;
198
- thread_pool_submit_aio(pool, worker_cb, req_data, done_cb, req_data);
199
+ thread_pool_submit_aio(worker_cb, req_data, done_cb, req_data);
200
}
201
202
static void virtio_pmem_get_config(VirtIODevice *vdev, uint8_t *config)
203
diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/scsi/pr-manager.c
206
+++ b/scsi/pr-manager.c
207
@@ -XXX,XX +XXX,XX @@ static int pr_manager_worker(void *opaque)
208
int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
209
struct sg_io_hdr *hdr)
210
{
211
- ThreadPool *pool = aio_get_thread_pool(ctx);
212
PRManagerData data = {
213
.pr_mgr = pr_mgr,
214
.fd = fd,
215
@@ -XXX,XX +XXX,XX @@ int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
216
217
/* The matching object_unref is in pr_manager_worker. */
218
object_ref(OBJECT(pr_mgr));
219
- return thread_pool_submit_co(pool, pr_manager_worker, &data);
220
+ return thread_pool_submit_co(pr_manager_worker, &data);
221
}
222
223
bool pr_manager_is_connected(PRManager *pr_mgr)
224
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/scsi/qemu-pr-helper.c
227
+++ b/scsi/qemu-pr-helper.c
228
@@ -XXX,XX +XXX,XX @@ static int do_sgio_worker(void *opaque)
229
static int do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
230
uint8_t *buf, int *sz, int dir)
231
{
232
- ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
233
int r;
234
235
PRHelperSGIOData data = {
236
@@ -XXX,XX +XXX,XX @@ static int do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
237
.dir = dir,
238
};
239
240
- r = thread_pool_submit_co(pool, do_sgio_worker, &data);
241
+ r = thread_pool_submit_co(do_sgio_worker, &data);
242
*sz = data.sz;
243
return r;
244
}
245
diff --git a/tests/unit/test-thread-pool.c b/tests/unit/test-thread-pool.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/tests/unit/test-thread-pool.c
248
+++ b/tests/unit/test-thread-pool.c
249
@@ -XXX,XX +XXX,XX @@
250
#include "qemu/main-loop.h"
251
252
static AioContext *ctx;
253
-static ThreadPool *pool;
254
static int active;
255
256
typedef struct {
257
@@ -XXX,XX +XXX,XX @@ static void done_cb(void *opaque, int ret)
258
static void test_submit(void)
259
{
260
WorkerTestData data = { .n = 0 };
261
- thread_pool_submit(pool, worker_cb, &data);
262
+ thread_pool_submit(worker_cb, &data);
263
while (data.n == 0) {
264
aio_poll(ctx, true);
265
}
266
@@ -XXX,XX +XXX,XX @@ static void test_submit(void)
267
static void test_submit_aio(void)
268
{
269
WorkerTestData data = { .n = 0, .ret = -EINPROGRESS };
270
- data.aiocb = thread_pool_submit_aio(pool, worker_cb, &data,
271
+ data.aiocb = thread_pool_submit_aio(worker_cb, &data,
272
done_cb, &data);
273
274
/* The callbacks are not called until after the first wait. */
275
@@ -XXX,XX +XXX,XX @@ static void co_test_cb(void *opaque)
276
active = 1;
277
data->n = 0;
278
data->ret = -EINPROGRESS;
279
- thread_pool_submit_co(pool, worker_cb, data);
280
+ thread_pool_submit_co(worker_cb, data);
281
282
/* The test continues in test_submit_co, after qemu_coroutine_enter... */
283
284
@@ -XXX,XX +XXX,XX @@ static void test_submit_many(void)
285
for (i = 0; i < 100; i++) {
286
data[i].n = 0;
287
data[i].ret = -EINPROGRESS;
288
- thread_pool_submit_aio(pool, worker_cb, &data[i], done_cb, &data[i]);
289
+ thread_pool_submit_aio(worker_cb, &data[i], done_cb, &data[i]);
290
}
291
292
active = 100;
293
@@ -XXX,XX +XXX,XX @@ static void do_test_cancel(bool sync)
294
for (i = 0; i < 100; i++) {
295
data[i].n = 0;
296
data[i].ret = -EINPROGRESS;
297
- data[i].aiocb = thread_pool_submit_aio(pool, long_cb, &data[i],
298
+ data[i].aiocb = thread_pool_submit_aio(long_cb, &data[i],
299
done_cb, &data[i]);
300
}
301
302
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
303
{
304
qemu_init_main_loop(&error_abort);
305
ctx = qemu_get_current_aio_context();
306
- pool = aio_get_thread_pool(ctx);
307
308
g_test_init(&argc, &argv, NULL);
309
g_test_add_func("/thread-pool/submit", test_submit);
310
diff --git a/util/thread-pool.c b/util/thread-pool.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/util/thread-pool.c
313
+++ b/util/thread-pool.c
314
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo thread_pool_aiocb_info = {
315
.get_aio_context = thread_pool_get_aio_context,
316
};
317
318
-BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
319
- ThreadPoolFunc *func, void *arg,
320
- BlockCompletionFunc *cb, void *opaque)
321
+BlockAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
322
+ BlockCompletionFunc *cb, void *opaque)
323
{
324
ThreadPoolElement *req;
325
+ AioContext *ctx = qemu_get_current_aio_context();
326
+ ThreadPool *pool = aio_get_thread_pool(ctx);
327
328
/* Assert that the thread submitting work is the same running the pool */
329
assert(pool->ctx == qemu_get_current_aio_context());
330
@@ -XXX,XX +XXX,XX @@ static void thread_pool_co_cb(void *opaque, int ret)
331
aio_co_wake(co->co);
332
}
333
334
-int coroutine_fn thread_pool_submit_co(ThreadPool *pool, ThreadPoolFunc *func,
335
- void *arg)
336
+int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg)
337
{
338
ThreadPoolCo tpc = { .co = qemu_coroutine_self(), .ret = -EINPROGRESS };
339
assert(qemu_in_coroutine());
340
- thread_pool_submit_aio(pool, func, arg, thread_pool_co_cb, &tpc);
341
+ thread_pool_submit_aio(func, arg, thread_pool_co_cb, &tpc);
342
qemu_coroutine_yield();
343
return tpc.ret;
344
}
345
346
-void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg)
347
+void thread_pool_submit(ThreadPoolFunc *func, void *arg)
348
{
349
- thread_pool_submit_aio(pool, func, arg, NULL, NULL);
350
+ thread_pool_submit_aio(func, arg, NULL, NULL);
351
}
352
353
void thread_pool_update_params(ThreadPool *pool, AioContext *ctx)
29
--
354
--
30
2.25.3
355
2.40.0
31
32
diff view generated by jsdifflib
New patch
1
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
3
Functions that can do I/O are prime candidates for being coroutine_fns. Make the
4
change for those that are themselves called only from coroutine_fns.
5
6
In addition, coroutine_fns should do I/O using bdrv_co_*() functions, for
7
which it is required to hold the BlockDriverState graph lock. So also nnotate
8
functions on the I/O path with TSA attributes, making it possible to
9
switch them to use bdrv_co_*() functions.
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-Id: <20230309084456.304669-2-pbonzini@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/vvfat.c | 58 ++++++++++++++++++++++++++-------------------------
17
1 file changed, 30 insertions(+), 28 deletions(-)
18
19
diff --git a/block/vvfat.c b/block/vvfat.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/vvfat.c
22
+++ b/block/vvfat.c
23
@@ -XXX,XX +XXX,XX @@ static BDRVVVFATState *vvv = NULL;
24
#endif
25
26
static int enable_write_target(BlockDriverState *bs, Error **errp);
27
-static int is_consistent(BDRVVVFATState *s);
28
+static int coroutine_fn is_consistent(BDRVVVFATState *s);
29
30
static QemuOptsList runtime_opts = {
31
.name = "vvfat",
32
@@ -XXX,XX +XXX,XX @@ static void print_mapping(const mapping_t* mapping)
33
}
34
#endif
35
36
-static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
37
- uint8_t *buf, int nb_sectors)
38
+static int coroutine_fn GRAPH_RDLOCK
39
+vvfat_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors)
40
{
41
BDRVVVFATState *s = bs->opaque;
42
int i;
43
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
44
DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
45
" allocated\n", sector_num,
46
n >> BDRV_SECTOR_BITS));
47
- if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
48
- buf + i * 0x200, 0) < 0) {
49
+ if (bdrv_co_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
50
+ buf + i * 0x200, 0) < 0) {
51
return -1;
52
}
53
i += (n >> BDRV_SECTOR_BITS) - 1;
54
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
55
return 0;
56
}
57
58
-static int coroutine_fn
59
+static int coroutine_fn GRAPH_RDLOCK
60
vvfat_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
61
QEMUIOVector *qiov, BdrvRequestFlags flags)
62
{
63
@@ -XXX,XX +XXX,XX @@ static inline uint32_t modified_fat_get(BDRVVVFATState* s,
64
}
65
}
66
67
-static inline bool cluster_was_modified(BDRVVVFATState *s,
68
- uint32_t cluster_num)
69
+static inline bool coroutine_fn GRAPH_RDLOCK
70
+cluster_was_modified(BDRVVVFATState *s, uint32_t cluster_num)
71
{
72
int was_modified = 0;
73
int i;
74
@@ -XXX,XX +XXX,XX @@ typedef enum {
75
* Further, the files/directories handled by this function are
76
* assumed to be *not* deleted (and *only* those).
77
*/
78
-static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
79
- direntry_t* direntry, const char* path)
80
+static uint32_t coroutine_fn GRAPH_RDLOCK
81
+get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const char* path)
82
{
83
/*
84
* This is a little bit tricky:
85
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
86
if (res) {
87
return -1;
88
}
89
- res = bdrv_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
90
- BDRV_SECTOR_SIZE, s->cluster_buffer,
91
- 0);
92
+ res = bdrv_co_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
93
+ BDRV_SECTOR_SIZE, s->cluster_buffer,
94
+ 0);
95
if (res < 0) {
96
return -2;
97
}
98
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
99
* It returns 0 upon inconsistency or error, and the number of clusters
100
* used by the directory, its subdirectories and their files.
101
*/
102
-static int check_directory_consistency(BDRVVVFATState *s,
103
- int cluster_num, const char* path)
104
+static int coroutine_fn GRAPH_RDLOCK
105
+check_directory_consistency(BDRVVVFATState *s, int cluster_num, const char* path)
106
{
107
int ret = 0;
108
unsigned char* cluster = g_malloc(s->cluster_size);
109
@@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i))
110
}
111
112
/* returns 1 on success */
113
-static int is_consistent(BDRVVVFATState* s)
114
+static int coroutine_fn GRAPH_RDLOCK
115
+is_consistent(BDRVVVFATState* s)
116
{
117
int i, check;
118
int used_clusters_count = 0;
119
@@ -XXX,XX +XXX,XX @@ static int commit_mappings(BDRVVVFATState* s,
120
return 0;
121
}
122
123
-static int commit_direntries(BDRVVVFATState* s,
124
- int dir_index, int parent_mapping_index)
125
+static int coroutine_fn GRAPH_RDLOCK
126
+commit_direntries(BDRVVVFATState* s, int dir_index, int parent_mapping_index)
127
{
128
direntry_t* direntry = array_get(&(s->directory), dir_index);
129
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
130
@@ -XXX,XX +XXX,XX @@ static int commit_direntries(BDRVVVFATState* s,
131
132
/* commit one file (adjust contents, adjust mapping),
133
return first_mapping_index */
134
-static int commit_one_file(BDRVVVFATState* s,
135
- int dir_index, uint32_t offset)
136
+static int coroutine_fn GRAPH_RDLOCK
137
+commit_one_file(BDRVVVFATState* s, int dir_index, uint32_t offset)
138
{
139
direntry_t* direntry = array_get(&(s->directory), dir_index);
140
uint32_t c = begin_of_direntry(direntry);
141
@@ -XXX,XX +XXX,XX @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
142
/*
143
* TODO: make sure that the short name is not matching *another* file
144
*/
145
-static int handle_commits(BDRVVVFATState* s)
146
+static int coroutine_fn GRAPH_RDLOCK handle_commits(BDRVVVFATState* s)
147
{
148
int i, fail = 0;
149
150
@@ -XXX,XX +XXX,XX @@ static int handle_deletes(BDRVVVFATState* s)
151
* - recurse direntries from root (using bs->bdrv_pread)
152
* - delete files corresponding to mappings marked as deleted
153
*/
154
-static int do_commit(BDRVVVFATState* s)
155
+static int coroutine_fn GRAPH_RDLOCK do_commit(BDRVVVFATState* s)
156
{
157
int ret = 0;
158
159
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
160
return 0;
161
}
162
163
-static int try_commit(BDRVVVFATState* s)
164
+static int coroutine_fn GRAPH_RDLOCK try_commit(BDRVVVFATState* s)
165
{
166
vvfat_close_current_file(s);
167
DLOG(checkpoint());
168
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
169
return do_commit(s);
170
}
171
172
-static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
173
- const uint8_t *buf, int nb_sectors)
174
+static int coroutine_fn GRAPH_RDLOCK
175
+vvfat_write(BlockDriverState *bs, int64_t sector_num,
176
+ const uint8_t *buf, int nb_sectors)
177
{
178
BDRVVVFATState *s = bs->opaque;
179
int i, ret;
180
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
181
* Use qcow backend. Commit later.
182
*/
183
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
184
- ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
185
- nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
186
+ ret = bdrv_co_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
187
+ nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
188
if (ret < 0) {
189
fprintf(stderr, "Error writing to qcow backend\n");
190
return ret;
191
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
192
return 0;
193
}
194
195
-static int coroutine_fn
196
+static int coroutine_fn GRAPH_RDLOCK
197
vvfat_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
198
QEMUIOVector *qiov, BdrvRequestFlags flags)
199
{
200
--
201
2.40.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Message-Id: <20230309084456.304669-3-pbonzini@redhat.com>
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
block/blkdebug.c | 4 ++--
9
1 file changed, 2 insertions(+), 2 deletions(-)
10
11
diff --git a/block/blkdebug.c b/block/blkdebug.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/blkdebug.c
14
+++ b/block/blkdebug.c
15
@@ -XXX,XX +XXX,XX @@ out:
16
return ret;
17
}
18
19
-static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
20
- BlkdebugIOType iotype)
21
+static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset,
22
+ uint64_t bytes, BlkdebugIOType iotype)
23
{
24
BDRVBlkdebugState *s = bs->opaque;
25
BlkdebugRule *rule = NULL;
26
--
27
2.40.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
mirror_flush calls a mixed function blk_flush but it is only called
4
from mirror_run; so call the coroutine version and make mirror_flush
5
a coroutine_fn too.
6
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-Id: <20230309084456.304669-4-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/mirror.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/block/mirror.c b/block/mirror.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/mirror.c
18
+++ b/block/mirror.c
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
20
/* Called when going out of the streaming phase to flush the bulk of the
21
* data to the medium, or just before completing.
22
*/
23
-static int mirror_flush(MirrorBlockJob *s)
24
+static int coroutine_fn mirror_flush(MirrorBlockJob *s)
25
{
26
- int ret = blk_flush(s->target);
27
+ int ret = blk_co_flush(s->target);
28
if (ret < 0) {
29
if (mirror_error_action(s, false, -ret) == BLOCK_ERROR_ACTION_REPORT) {
30
s->ret = ret;
31
--
32
2.40.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
nbd/server.c | 48 ++++++++++++++++++++++++------------------------
8
1 file changed, 24 insertions(+), 24 deletions(-)
9
10
diff --git a/nbd/server.c b/nbd/server.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/nbd/server.c
13
+++ b/nbd/server.c
14
@@ -XXX,XX +XXX,XX @@ nbd_read_eof(NBDClient *client, void *buffer, size_t size, Error **errp)
15
return 1;
16
}
17
18
-static int nbd_receive_request(NBDClient *client, NBDRequest *request,
19
- Error **errp)
20
+static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *request,
21
+ Error **errp)
22
{
23
uint8_t buf[NBD_REQUEST_SIZE];
24
uint32_t magic;
25
@@ -XXX,XX +XXX,XX @@ static inline void set_be_simple_reply(NBDSimpleReply *reply, uint64_t error,
26
stq_be_p(&reply->handle, handle);
27
}
28
29
-static int nbd_co_send_simple_reply(NBDClient *client,
30
- uint64_t handle,
31
- uint32_t error,
32
- void *data,
33
- size_t len,
34
- Error **errp)
35
+static int coroutine_fn nbd_co_send_simple_reply(NBDClient *client,
36
+ uint64_t handle,
37
+ uint32_t error,
38
+ void *data,
39
+ size_t len,
40
+ Error **errp)
41
{
42
NBDSimpleReply reply;
43
int nbd_err = system_errno_to_nbd_errno(error);
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
45
stl_be_p(&chunk.length, pnum);
46
ret = nbd_co_send_iov(client, iov, 1, errp);
47
} else {
48
- ret = blk_pread(exp->common.blk, offset + progress, pnum,
49
- data + progress, 0);
50
+ ret = blk_co_pread(exp->common.blk, offset + progress, pnum,
51
+ data + progress, 0);
52
if (ret < 0) {
53
error_setg_errno(errp, -ret, "reading from file failed");
54
break;
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockalloc_to_extents(BlockBackend *blk,
56
* @ea is converted to BE by the function
57
* @last controls whether NBD_REPLY_FLAG_DONE is sent.
58
*/
59
-static int nbd_co_send_extents(NBDClient *client, uint64_t handle,
60
- NBDExtentArray *ea,
61
- bool last, uint32_t context_id, Error **errp)
62
+static int coroutine_fn
63
+nbd_co_send_extents(NBDClient *client, uint64_t handle, NBDExtentArray *ea,
64
+ bool last, uint32_t context_id, Error **errp)
65
{
66
NBDStructuredMeta chunk;
67
struct iovec iov[] = {
68
@@ -XXX,XX +XXX,XX @@ static void bitmap_to_extents(BdrvDirtyBitmap *bitmap,
69
bdrv_dirty_bitmap_unlock(bitmap);
70
}
71
72
-static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
73
- BdrvDirtyBitmap *bitmap, uint64_t offset,
74
- uint32_t length, bool dont_fragment, bool last,
75
- uint32_t context_id, Error **errp)
76
+static int coroutine_fn nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
77
+ BdrvDirtyBitmap *bitmap, uint64_t offset,
78
+ uint32_t length, bool dont_fragment, bool last,
79
+ uint32_t context_id, Error **errp)
80
{
81
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
82
g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);
83
@@ -XXX,XX +XXX,XX @@ static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
84
* to the client (although the caller may still need to disconnect after
85
* reporting the error).
86
*/
87
-static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
88
- Error **errp)
89
+static int coroutine_fn nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
90
+ Error **errp)
91
{
92
NBDClient *client = req->client;
93
int valid_flags;
94
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
95
data, request->len, errp);
96
}
97
98
- ret = blk_pread(exp->common.blk, request->from, request->len, data, 0);
99
+ ret = blk_co_pread(exp->common.blk, request->from, request->len, data, 0);
100
if (ret < 0) {
101
return nbd_send_generic_reply(client, request->handle, ret,
102
"reading from file failed", errp);
103
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
104
if (request->flags & NBD_CMD_FLAG_FUA) {
105
flags |= BDRV_REQ_FUA;
106
}
107
- ret = blk_pwrite(exp->common.blk, request->from, request->len, data,
108
- flags);
109
+ ret = blk_co_pwrite(exp->common.blk, request->from, request->len, data,
110
+ flags);
111
return nbd_send_generic_reply(client, request->handle, ret,
112
"writing to file failed", errp);
113
114
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
115
if (request->flags & NBD_CMD_FLAG_FAST_ZERO) {
116
flags |= BDRV_REQ_NO_FALLBACK;
117
}
118
- ret = blk_pwrite_zeroes(exp->common.blk, request->from, request->len,
119
- flags);
120
+ ret = blk_co_pwrite_zeroes(exp->common.blk, request->from, request->len,
121
+ flags);
122
return nbd_send_generic_reply(client, request->handle, ret,
123
"writing to file failed", errp);
124
125
--
126
2.40.0
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Message-Id: <20230309084456.304669-6-pbonzini@redhat.com>
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
hw/9pfs/9p.h | 4 ++--
9
hw/9pfs/codir.c | 6 +++---
10
2 files changed, 5 insertions(+), 5 deletions(-)
11
12
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/9pfs/9p.h
15
+++ b/hw/9pfs/9p.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct V9fsDir {
17
QemuMutex readdir_mutex_L;
18
} V9fsDir;
19
20
-static inline void v9fs_readdir_lock(V9fsDir *dir)
21
+static inline void coroutine_fn v9fs_readdir_lock(V9fsDir *dir)
22
{
23
if (dir->proto_version == V9FS_PROTO_2000U) {
24
qemu_co_mutex_lock(&dir->readdir_mutex_u);
25
@@ -XXX,XX +XXX,XX @@ static inline void v9fs_readdir_lock(V9fsDir *dir)
26
}
27
}
28
29
-static inline void v9fs_readdir_unlock(V9fsDir *dir)
30
+static inline void coroutine_fn v9fs_readdir_unlock(V9fsDir *dir)
31
{
32
if (dir->proto_version == V9FS_PROTO_2000U) {
33
qemu_co_mutex_unlock(&dir->readdir_mutex_u);
34
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/9pfs/codir.c
37
+++ b/hw/9pfs/codir.c
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
39
*
40
* See v9fs_co_readdir_many() (as its only user) below for details.
41
*/
42
-static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp,
43
- struct V9fsDirEnt **entries, off_t offset,
44
- int32_t maxsize, bool dostat)
45
+static int coroutine_fn
46
+do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, struct V9fsDirEnt **entries,
47
+ off_t offset, int32_t maxsize, bool dostat)
48
{
49
V9fsState *s = pdu->s;
50
V9fsString name;
51
--
52
2.40.0
diff view generated by jsdifflib
1
After processing the option string with the keyval parser, we get a
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
4
2
5
qmp_object_add(), however, uses the normal QObject input visitor, which
3
do_sgio can suspend via the coroutine function thread_pool_submit_co, so it
6
expects a QDict where all properties already have the QType that matches
4
has to be coroutine_fn as well---and the same is true of all its direct and
7
the data type required by the QOM object type.
5
indirect callers.
8
6
9
Change the --object implementation in qemu-storage-daemon so that it
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
8
Message-Id: <20230309084456.304669-7-pbonzini@redhat.com>
11
directly instead and pass it a new keyval boolean that decides which
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
11
---
17
include/qom/object_interfaces.h | 6 +++++-
12
scsi/qemu-pr-helper.c | 22 +++++++++++-----------
18
qemu-storage-daemon.c | 4 +---
13
1 file changed, 11 insertions(+), 11 deletions(-)
19
qom/object_interfaces.c | 8 ++++++--
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
22
14
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
15
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/include/qom/object_interfaces.h
17
--- a/scsi/qemu-pr-helper.c
26
+++ b/include/qom/object_interfaces.h
18
+++ b/scsi/qemu-pr-helper.c
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
19
@@ -XXX,XX +XXX,XX @@ static int do_sgio_worker(void *opaque)
28
/**
20
return status;
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
76
}
21
}
77
22
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
23
-static int do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
24
- uint8_t *buf, int *sz, int dir)
25
+static int coroutine_fn do_sgio(int fd, const uint8_t *cdb, uint8_t *sense,
26
+ uint8_t *buf, int *sz, int dir)
80
{
27
{
81
Visitor *v;
28
int r;
82
Object *obj;
29
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
30
@@ -XXX,XX +XXX,XX @@ static SCSISense mpath_generic_sense(int r)
84
}
31
}
85
qdict_del(qdict, "id");
32
}
86
33
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
34
-static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
88
+ if (keyval) {
35
+static int coroutine_fn mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
36
{
90
+ } else {
37
switch (r) {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
38
case MPATH_PR_SUCCESS:
92
+ }
39
@@ -XXX,XX +XXX,XX @@ static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
40
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
106
}
41
}
107
42
108
void qmp_object_del(const char *id, Error **errp)
43
-static int multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
44
- uint8_t *data, int sz)
45
+static int coroutine_fn multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
46
+ uint8_t *data, int sz)
47
{
48
int rq_servact = cdb[1];
49
struct prin_resp resp;
50
@@ -XXX,XX +XXX,XX @@ static int multipath_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
51
return mpath_reconstruct_sense(fd, r, sense);
52
}
53
54
-static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
55
- const uint8_t *param, int sz)
56
+static int coroutine_fn multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
57
+ const uint8_t *param, int sz)
58
{
59
int rq_servact = cdb[1];
60
int rq_scope = cdb[2] >> 4;
61
@@ -XXX,XX +XXX,XX @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
62
}
63
#endif
64
65
-static int do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
66
- uint8_t *data, int *resp_sz)
67
+static int coroutine_fn do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
68
+ uint8_t *data, int *resp_sz)
69
{
70
#ifdef CONFIG_MPATH
71
if (is_mpath(fd)) {
72
@@ -XXX,XX +XXX,XX @@ static int do_pr_in(int fd, const uint8_t *cdb, uint8_t *sense,
73
SG_DXFER_FROM_DEV);
74
}
75
76
-static int do_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
77
- const uint8_t *param, int sz)
78
+static int coroutine_fn do_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
79
+ const uint8_t *param, int sz)
80
{
81
int resp_sz;
82
109
--
83
--
110
2.25.3
84
2.40.0
111
112
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Message-Id: <20230309084456.304669-8-pbonzini@redhat.com>
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/unit/test-thread-pool.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/tests/unit/test-thread-pool.c b/tests/unit/test-thread-pool.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/unit/test-thread-pool.c
14
+++ b/tests/unit/test-thread-pool.c
15
@@ -XXX,XX +XXX,XX @@ static void test_submit_aio(void)
16
g_assert_cmpint(data.ret, ==, 0);
17
}
18
19
-static void co_test_cb(void *opaque)
20
+static void coroutine_fn co_test_cb(void *opaque)
21
{
22
WorkerTestData *data = opaque;
23
24
--
25
2.40.0
diff view generated by jsdifflib
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
6
2
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Functions that can do I/O (including calling bdrv_is_allocated
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
4
and bdrv_block_status functions) are prime candidates for being
9
Reviewed-by: Eric Blake <eblake@redhat.com>
5
coroutine_fns. Make the change for those that are themselves called
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
only from coroutine_fns. Also annotate that they are called with the
7
graph rdlock taken, thus allowing them to call bdrv_co_*() functions
8
for I/O.
9
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Message-Id: <20230309084456.304669-9-pbonzini@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
block/qcow2-cluster.c | 2 +-
15
block/qcow2.h | 15 ++++++++-------
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
16
block/qcow2-bitmap.c | 2 +-
15
2 files changed, 35 insertions(+), 1 deletion(-)
17
block/qcow2-cluster.c | 21 +++++++++++++--------
18
block/qcow2-refcount.c | 8 ++++----
19
block/qcow2-snapshot.c | 25 +++++++++++++------------
20
block/qcow2.c | 27 ++++++++++++++-------------
21
6 files changed, 53 insertions(+), 45 deletions(-)
16
22
23
diff --git a/block/qcow2.h b/block/qcow2.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2.h
26
+++ b/block/qcow2.h
27
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
28
uint64_t new_refblock_offset);
29
30
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
31
-int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
32
- int64_t nb_clusters);
33
-int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
34
+int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
35
+ int64_t nb_clusters);
36
+int64_t coroutine_fn qcow2_alloc_bytes(BlockDriverState *bs, int size);
37
void qcow2_free_clusters(BlockDriverState *bs,
38
int64_t offset, int64_t size,
39
enum qcow2_discard_type type);
40
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
41
BlockDriverAmendStatusCB *status_cb,
42
void *cb_opaque, Error **errp);
43
int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
44
-int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
45
+int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
46
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
47
48
/* qcow2-cluster.c functions */
49
@@ -XXX,XX +XXX,XX @@ void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
50
int coroutine_fn GRAPH_RDLOCK
51
qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
52
53
-void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
54
+void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
55
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
56
uint64_t bytes, enum qcow2_discard_type type,
57
bool full_discard);
58
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
59
Error **errp);
60
61
void qcow2_free_snapshots(BlockDriverState *bs);
62
-int qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
63
+int coroutine_fn GRAPH_RDLOCK
64
+qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
65
int qcow2_write_snapshots(BlockDriverState *bs);
66
67
int coroutine_fn GRAPH_RDLOCK
68
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
69
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
70
Qcow2BitmapInfoList **info_list, Error **errp);
71
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
72
-int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
73
+int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
74
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
75
bool release_stored, Error **errp);
76
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
77
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/qcow2-bitmap.c
80
+++ b/block/qcow2-bitmap.c
81
@@ -XXX,XX +XXX,XX @@ out:
82
}
83
84
/* Checks to see if it's safe to resize bitmaps */
85
-int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp)
86
+int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp)
87
{
88
BDRVQcow2State *s = bs->opaque;
89
Qcow2BitmapList *bm_list;
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
90
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
18
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
92
--- a/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
93
+++ b/block/qcow2-cluster.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
94
@@ -XXX,XX +XXX,XX @@ err:
22
/* Caller must pass aligned values, except at image end */
95
* Frees the allocated clusters because the request failed and they won't
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
96
* actually be linked.
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
97
*/
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
98
-void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
99
+void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
27
100
{
28
/* The zero flag is only supported by version 3 and newer */
101
BDRVQcow2State *s = bs->opaque;
29
if (s->qcow_version < 3) {
102
if (!has_data_file(bs) && !m->keep_old_clusters) {
103
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
104
*
105
* Returns 0 on success, -errno on failure.
106
*/
107
-static int calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
108
- uint64_t guest_offset, unsigned bytes,
109
- uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
110
+static int coroutine_fn calculate_l2_meta(BlockDriverState *bs,
111
+ uint64_t host_cluster_offset,
112
+ uint64_t guest_offset, unsigned bytes,
113
+ uint64_t *l2_slice, QCowL2Meta **m,
114
+ bool keep_old)
115
{
116
BDRVQcow2State *s = bs->opaque;
117
int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
118
@@ -XXX,XX +XXX,XX @@ out:
119
* function has been waiting for another request and the allocation must be
120
* restarted, but the whole request should not be failed.
121
*/
122
-static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
123
- uint64_t *host_offset, uint64_t *nb_clusters)
124
+static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
125
+ uint64_t guest_offset,
126
+ uint64_t *host_offset,
127
+ uint64_t *nb_clusters)
128
{
129
BDRVQcow2State *s = bs->opaque;
130
131
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
132
return nb_clusters;
133
}
134
135
-static int zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
136
- unsigned nb_subclusters)
137
+static int coroutine_fn
138
+zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
139
+ unsigned nb_subclusters)
140
{
141
BDRVQcow2State *s = bs->opaque;
142
uint64_t *l2_slice;
143
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/block/qcow2-refcount.c
146
+++ b/block/qcow2-refcount.c
147
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
148
return offset;
149
}
150
151
-int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
152
- int64_t nb_clusters)
153
+int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
154
+ int64_t nb_clusters)
155
{
156
BDRVQcow2State *s = bs->opaque;
157
uint64_t cluster_index, refcount;
158
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
159
160
/* only used to allocate compressed sectors. We try to allocate
161
contiguous sectors. size must be <= cluster_size */
162
-int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
163
+int64_t coroutine_fn qcow2_alloc_bytes(BlockDriverState *bs, int size)
164
{
165
BDRVQcow2State *s = bs->opaque;
166
int64_t offset;
167
@@ -XXX,XX +XXX,XX @@ out:
168
return ret;
169
}
170
171
-int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
172
+int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
173
{
174
BDRVQcow2State *s = bs->opaque;
175
int64_t i;
176
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/block/qcow2-snapshot.c
179
+++ b/block/qcow2-snapshot.c
180
@@ -XXX,XX +XXX,XX @@ void qcow2_free_snapshots(BlockDriverState *bs)
181
* qcow2_check_refcounts() does not do anything with snapshots'
182
* extra data.)
183
*/
184
-static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
185
- int *nb_clusters_reduced,
186
- int *extra_data_dropped,
187
- Error **errp)
188
+static coroutine_fn GRAPH_RDLOCK
189
+int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
190
+ int *nb_clusters_reduced,
191
+ int *extra_data_dropped,
192
+ Error **errp)
193
{
194
BDRVQcow2State *s = bs->opaque;
195
QCowSnapshotHeader h;
196
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
197
198
/* Read statically sized part of the snapshot header */
199
offset = ROUND_UP(offset, 8);
200
- ret = bdrv_pread(bs->file, offset, sizeof(h), &h, 0);
201
+ ret = bdrv_co_pread(bs->file, offset, sizeof(h), &h, 0);
202
if (ret < 0) {
203
error_setg_errno(errp, -ret, "Failed to read snapshot table");
204
goto fail;
205
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
206
}
207
208
/* Read known extra data */
209
- ret = bdrv_pread(bs->file, offset,
210
- MIN(sizeof(extra), sn->extra_data_size), &extra, 0);
211
+ ret = bdrv_co_pread(bs->file, offset,
212
+ MIN(sizeof(extra), sn->extra_data_size), &extra, 0);
213
if (ret < 0) {
214
error_setg_errno(errp, -ret, "Failed to read snapshot table");
215
goto fail;
216
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
217
/* Store unknown extra data */
218
unknown_extra_data_size = sn->extra_data_size - sizeof(extra);
219
sn->unknown_extra_data = g_malloc(unknown_extra_data_size);
220
- ret = bdrv_pread(bs->file, offset, unknown_extra_data_size,
221
- sn->unknown_extra_data, 0);
222
+ ret = bdrv_co_pread(bs->file, offset, unknown_extra_data_size,
223
+ sn->unknown_extra_data, 0);
224
if (ret < 0) {
225
error_setg_errno(errp, -ret,
226
"Failed to read snapshot table");
227
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
228
229
/* Read snapshot ID */
230
sn->id_str = g_malloc(id_str_size + 1);
231
- ret = bdrv_pread(bs->file, offset, id_str_size, sn->id_str, 0);
232
+ ret = bdrv_co_pread(bs->file, offset, id_str_size, sn->id_str, 0);
233
if (ret < 0) {
234
error_setg_errno(errp, -ret, "Failed to read snapshot table");
235
goto fail;
236
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
237
238
/* Read snapshot name */
239
sn->name = g_malloc(name_size + 1);
240
- ret = bdrv_pread(bs->file, offset, name_size, sn->name, 0);
241
+ ret = bdrv_co_pread(bs->file, offset, name_size, sn->name, 0);
242
if (ret < 0) {
243
error_setg_errno(errp, -ret, "Failed to read snapshot table");
244
goto fail;
245
@@ -XXX,XX +XXX,XX @@ fail:
246
return ret;
247
}
248
249
-int qcow2_read_snapshots(BlockDriverState *bs, Error **errp)
250
+int coroutine_fn qcow2_read_snapshots(BlockDriverState *bs, Error **errp)
251
{
252
return qcow2_do_read_snapshots(bs, false, NULL, NULL, errp);
253
}
30
diff --git a/block/qcow2.c b/block/qcow2.c
254
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
255
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
256
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
257
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
258
@@ -XXX,XX +XXX,XX @@ qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp)
35
259
* unknown magic is skipped (future extension this version knows nothing about)
36
bs->supported_zero_flags = header.version >= 3 ?
260
* return 0 upon success, non-0 otherwise
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
261
*/
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
262
-static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
39
263
- uint64_t end_offset, void **p_feature_table,
40
/* Repair image if dirty */
264
- int flags, bool *need_update_header,
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
265
- Error **errp)
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
266
+static int coroutine_fn GRAPH_RDLOCK
43
g_assert_not_reached();
267
+qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
44
}
268
+ uint64_t end_offset, void **p_feature_table,
45
269
+ int flags, bool *need_update_header, Error **errp)
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
270
{
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
271
BDRVQcow2State *s = bs->opaque;
48
+
272
QCowExtension ext;
49
+ /*
273
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
274
printf("attempting to read extended header in offset %lu\n", offset);
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
275
#endif
52
+ * at the end of the image (which it is here).
276
53
+ */
277
- ret = bdrv_pread(bs->file, offset, sizeof(ext), &ext, 0);
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
278
+ ret = bdrv_co_pread(bs->file, offset, sizeof(ext), &ext, 0);
55
+ if (ret < 0) {
279
if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
280
error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "
57
+ goto fail;
281
"pread fail from offset %" PRIu64, offset);
58
+ }
282
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
59
+
283
sizeof(bs->backing_format));
60
+ /* Write explicit zeros for the unaligned head */
284
return 2;
61
+ if (zero_start > old_length) {
285
}
62
+ uint64_t len = zero_start - old_length;
286
- ret = bdrv_pread(bs->file, offset, ext.len, bs->backing_format, 0);
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
287
+ ret = bdrv_co_pread(bs->file, offset, ext.len, bs->backing_format, 0);
64
+ QEMUIOVector qiov;
288
if (ret < 0) {
65
+ qemu_iovec_init_buf(&qiov, buf, len);
289
error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "
66
+
290
"Could not read format name");
67
+ qemu_co_mutex_unlock(&s->lock);
291
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
292
case QCOW2_EXT_MAGIC_FEATURE_TABLE:
69
+ qemu_co_mutex_lock(&s->lock);
293
if (p_feature_table != NULL) {
70
+
294
void *feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));
71
+ qemu_vfree(buf);
295
- ret = bdrv_pread(bs->file, offset, ext.len, feature_table, 0);
72
+ if (ret < 0) {
296
+ ret = bdrv_co_pread(bs->file, offset, ext.len, feature_table, 0);
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
297
if (ret < 0) {
74
+ goto fail;
298
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
75
+ }
299
"Could not read table");
76
+ }
300
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
77
+ }
301
return -EINVAL;
78
+
302
}
79
if (prealloc != PREALLOC_MODE_OFF) {
303
80
/* Flush metadata before actually changing the image size */
304
- ret = bdrv_pread(bs->file, offset, ext.len, &s->crypto_header, 0);
81
ret = qcow2_write_caches(bs);
305
+ ret = bdrv_co_pread(bs->file, offset, ext.len, &s->crypto_header, 0);
306
if (ret < 0) {
307
error_setg_errno(errp, -ret,
308
"Unable to read CRYPTO header extension");
309
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
310
break;
311
}
312
313
- ret = bdrv_pread(bs->file, offset, ext.len, &bitmaps_ext, 0);
314
+ ret = bdrv_co_pread(bs->file, offset, ext.len, &bitmaps_ext, 0);
315
if (ret < 0) {
316
error_setg_errno(errp, -ret, "bitmaps_ext: "
317
"Could not read ext header");
318
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
319
case QCOW2_EXT_MAGIC_DATA_FILE:
320
{
321
s->image_data_file = g_malloc0(ext.len + 1);
322
- ret = bdrv_pread(bs->file, offset, ext.len, s->image_data_file, 0);
323
+ ret = bdrv_co_pread(bs->file, offset, ext.len, s->image_data_file, 0);
324
if (ret < 0) {
325
error_setg_errno(errp, -ret,
326
"ERROR: Could not read data file name");
327
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
328
uext->len = ext.len;
329
QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);
330
331
- ret = bdrv_pread(bs->file, offset, uext->len, uext->data, 0);
332
+ ret = bdrv_co_pread(bs->file, offset, uext->len, uext->data, 0);
333
if (ret < 0) {
334
error_setg_errno(errp, -ret, "ERROR: unknown extension: "
335
"Could not read data");
336
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
337
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
338
}
339
340
-static int qcow2_update_options(BlockDriverState *bs, QDict *options,
341
- int flags, Error **errp)
342
+static int coroutine_fn
343
+qcow2_update_options(BlockDriverState *bs, QDict *options, int flags,
344
+ Error **errp)
345
{
346
Qcow2ReopenState r = {};
347
int ret;
82
--
348
--
83
2.25.3
349
2.40.0
84
85
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Test 244 checks the expected behavior of qcow2 external data files
3
Functions that can do I/O are prime candidates for being coroutine_fns. Make the
4
with respect to zero and discarded clusters. Filesystems however
4
change for the one that is itself called only from coroutine_fns. Unfortunately
5
are free to ignore discard requests, and this seems to be the
5
vmdk does not use a coroutine_fn for the bulk of the open (like qcow2 does) so
6
case for overlayfs. Relax the tests to skip checks on the
6
vmdk_read_cid cannot have the same treatment.
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
9
7
10
This fixes docker tests on RHEL8.
11
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
9
Message-Id: <20230309084456.304669-10-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
12
---
18
tests/qemu-iotests/244 | 10 ++++++++--
13
block/vmdk.c | 2 +-
19
tests/qemu-iotests/244.out | 9 ++++++---
14
1 file changed, 1 insertion(+), 1 deletion(-)
20
2 files changed, 14 insertions(+), 5 deletions(-)
21
15
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
16
diff --git a/block/vmdk.c b/block/vmdk.c
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
52
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/244.out
18
--- a/block/vmdk.c
54
+++ b/tests/qemu-iotests/244.out
19
+++ b/block/vmdk.c
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
20
@@ -XXX,XX +XXX,XX @@ out:
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
21
return ret;
57
read 1048576/1048576 bytes at offset 1048576
22
}
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
23
59
-read 2097152/2097152 bytes at offset 2097152
24
-static int vmdk_is_cid_valid(BlockDriverState *bs)
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
25
+static int coroutine_fn vmdk_is_cid_valid(BlockDriverState *bs)
61
read 1048576/1048576 bytes at offset 4194304
26
{
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
27
BDRVVmdkState *s = bs->opaque;
63
read 1048576/1048576 bytes at offset 5242880
28
uint32_t cur_pcid;
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
65
read 4194304/4194304 bytes at offset 2097152
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
68
-Images are identical.
69
+read 1048576/1048576 bytes at offset 0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+read 1048576/1048576 bytes at offset 1048576
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+read 3145728/3145728 bytes at offset 3145728
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
qcow2 file size after I/O: 327680
76
77
=== bdrv_co_block_status test for file and offset=0 ===
78
--
29
--
79
2.25.3
30
2.40.0
80
81
diff view generated by jsdifflib
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
1
From: Wang Liang <wangliangzz@inspur.com>
2
2
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
3
hmp_commit() calls blk_is_available() from a non-coroutine context (and in
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
4
the main loop). blk_is_available() is a co_wrapper_mixed_bdrv_rdlock
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
5
function, and in the non-coroutine context it calls AIO_WAIT_WHILE(),
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
6
which crashes if the aio_context lock is not taken before.
7
persistent across system reboot.
8
7
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1615
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
9
Signed-off-by: Wang Liang <wangliangzz@inspur.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20230424103902.45265-1-wangliangzz@126.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
11
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
14
---
16
hw/block/nvme.h | 2 +
15
block/monitor/block-hmp-cmds.c | 10 ++++++----
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
16
1 file changed, 6 insertions(+), 4 deletions(-)
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
22
17
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
18
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/block/nvme.h
20
--- a/block/monitor/block-hmp-cmds.c
26
+++ b/hw/block/nvme.h
21
+++ b/block/monitor/block-hmp-cmds.c
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
22
@@ -XXX,XX +XXX,XX @@ void hmp_commit(Monitor *mon, const QDict *qdict)
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
23
error_report("Device '%s' not found", device);
29
24
return;
30
char *serial;
25
}
31
+ HostMemoryBackend *pmrdev;
26
- if (!blk_is_available(blk)) {
32
+
27
- error_report("Device '%s' has no medium", device);
33
NvmeNamespace *namespaces;
28
- return;
34
NvmeSQueue **sq;
29
- }
35
NvmeCQueue **cq;
30
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
31
bs = bdrv_skip_implicit_filters(blk_bs(blk));
37
index XXXXXXX..XXXXXXX 100644
32
aio_context = bdrv_get_aio_context(bs);
38
--- a/include/block/nvme.h
33
aio_context_acquire(aio_context);
39
+++ b/include/block/nvme.h
34
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
35
+ if (!blk_is_available(blk)) {
41
uint64_t acq;
36
+ error_report("Device '%s' has no medium", device);
42
uint32_t cmbloc;
37
+ aio_context_release(aio_context);
43
uint32_t cmbsz;
44
+ uint8_t padding[3520]; /* not used by QEMU */
45
+ uint32_t pmrcap;
46
+ uint32_t pmrctl;
47
+ uint32_t pmrsts;
48
+ uint32_t pmrebs;
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
309
}
310
311
if (addr < sizeof(n->bar)) {
312
+ /*
313
+ * When PMRWBM bit 1 is set then read from
314
+ * from PMRSTS should ensure prior writes
315
+ * made it to persistent media
316
+ */
317
+ if (addr == 0xE08 &&
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
320
+ 0, n->pmrdev->size);
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
328
}
329
+
330
+ if (!n->cmb_size_mb && n->pmrdev) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
334
+ g_free(path);
335
+ return;
38
+ return;
336
+ }
39
+ }
337
+
40
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
41
ret = bdrv_commit(bs);
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
42
340
+ return;
43
aio_context_release(aio_context);
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
344
+ }
345
+
346
blkconf_blocksizes(&n->conf);
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
348
false, errp)) {
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
352
353
+ } else if (n->pmrdev) {
354
+ /* Controller Capabilities register */
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
356
+
357
+ /* PMR Capabities register */
358
+ n->bar.pmrcap = 0;
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
398
}
399
400
for (i = 0; i < n->num_namespaces; i++) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
402
if (n->cmb_size_mb) {
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
410
}
411
412
static Property nvme_props[] = {
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
420
index XXXXXXX..XXXXXXX 100644
421
--- a/hw/block/Makefile.objs
422
+++ b/hw/block/Makefile.objs
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
424
common-obj-$(CONFIG_XEN) += xen-block.o
425
common-obj-$(CONFIG_ECC) += ecc.o
426
common-obj-$(CONFIG_ONENAND) += onenand.o
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
428
common-obj-$(CONFIG_SWIM) += swim.o
429
430
common-obj-$(CONFIG_SH4) += tc58128.o
431
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
435
436
obj-y += dataplane/
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/block/trace-events
440
+++ b/hw/block/trace-events
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
452
--
44
--
453
2.25.3
45
2.40.0
454
455
diff view generated by jsdifflib