1
The following changes since commit dd25f97c66a75d1508f1d4c6478ed2c95bec428f:
1
The following changes since commit 9cf289af47bcfae5c75de37d8e5d6fd23705322c:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190913' into staging (2019-09-16 10:15:15 +0100)
3
Merge tag 'qga-pull-request' of gitlab.com:marcandre.lureau/qemu into staging (2022-05-04 03:42:49 -0700)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-09-16
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 1825cc0783ccf0ec5d9f0b225a99b340bdd4c68f:
9
for you to fetch changes up to bef2e050d6a7feb865854c65570c496ac5a8cf53:
10
10
11
qemu-iotests: Add test for bz #1745922 (2019-09-16 15:37:12 +0200)
11
util/event-loop-base: Introduce options to set the thread pool size (2022-05-04 17:02:19 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Fix for block jobs when used with I/O threads
15
16
- Fix for a corruption when using qcow2's LUKS encryption mode
16
Add new thread-pool-min/thread-pool-max parameters to control the thread pool
17
- cURL fix
17
used for async I/O.
18
- check-block.sh cleanups (for make check)
19
- Refactoring
20
18
21
----------------------------------------------------------------
19
----------------------------------------------------------------
22
Max Reitz (7):
23
curl: Keep pointer to the CURLState in CURLSocket
24
curl: Keep *socket until the end of curl_sock_cb()
25
curl: Check completion in curl_multi_do()
26
curl: Pass CURLSocket to curl_multi_do()
27
curl: Report only ready sockets
28
curl: Handle success in multi_check_completion
29
curl: Check curl_multi_add_handle()'s return code
30
20
31
Maxim Levitsky (3):
21
Nicolas Saenz Julienne (3):
32
block/qcow2: Fix corruption introduced by commit 8ac0f15f335
22
Introduce event-loop-base abstract class
33
block/qcow2: refactor encryption code
23
util/main-loop: Introduce the main loop into QOM
34
qemu-iotests: Add test for bz #1745922
24
util/event-loop-base: Introduce options to set the thread pool size
35
25
36
Nir Soffer (2):
26
qapi/qom.json | 43 ++++++++--
37
block: Use QEMU_IS_ALIGNED
27
meson.build | 26 +++---
38
block: Remove unused masks
28
include/block/aio.h | 10 +++
39
29
include/block/thread-pool.h | 3 +
40
Sergio Lopez (1):
30
include/qemu/main-loop.h | 10 +++
41
blockjob: update nodes head while removing all bdrv
31
include/sysemu/event-loop-base.h | 41 +++++++++
42
32
include/sysemu/iothread.h | 6 +-
43
Thomas Huth (2):
33
event-loop-base.c | 140 +++++++++++++++++++++++++++++++
44
tests/qemu-iotests/check: Replace "tests" with "iotests" in final
34
iothread.c | 68 +++++----------
45
status text
35
util/aio-posix.c | 1 +
46
tests/Makefile: Do not print the name of the check-block.sh shell
36
util/async.c | 20 +++++
47
script
37
util/main-loop.c | 65 ++++++++++++++
48
38
util/thread-pool.c | 55 +++++++++++-
49
Vladimir Sementsov-Ogievskiy (1):
39
13 files changed, 419 insertions(+), 69 deletions(-)
50
tests/qemu-iotests: Fix qemu-io related output in 026.out.nocache
40
create mode 100644 include/sysemu/event-loop-base.h
51
41
create mode 100644 event-loop-base.c
52
tests/Makefile.include | 2 +-
53
block/qcow2.h | 8 +-
54
include/block/block.h | 2 -
55
block/bochs.c | 4 +-
56
block/cloop.c | 4 +-
57
block/curl.c | 133 ++++++++++-------------
58
block/dmg.c | 4 +-
59
block/io.c | 8 +-
60
block/qcow2-cluster.c | 40 +++----
61
block/qcow2-threads.c | 63 ++++++++---
62
block/qcow2.c | 9 +-
63
block/vvfat.c | 8 +-
64
blockjob.c | 17 ++-
65
migration/block.c | 2 +-
66
qemu-img.c | 2 +-
67
tests/qemu-iotests/026.out.nocache | 168 ++++++++++++++---------------
68
tests/qemu-iotests/263 | 91 ++++++++++++++++
69
tests/qemu-iotests/263.out | 40 +++++++
70
tests/qemu-iotests/check | 8 +-
71
tests/qemu-iotests/group | 1 +
72
20 files changed, 380 insertions(+), 234 deletions(-)
73
create mode 100755 tests/qemu-iotests/263
74
create mode 100644 tests/qemu-iotests/263.out
75
42
76
--
43
--
77
2.21.0
44
2.35.1
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Nir Soffer <nirsof@gmail.com>
2
1
3
Replace instances of:
4
5
(n & (BDRV_SECTOR_SIZE - 1)) == 0
6
7
And:
8
9
(n & ~BDRV_SECTOR_MASK) == 0
10
11
With:
12
13
QEMU_IS_ALIGNED(n, BDRV_SECTOR_SIZE)
14
15
Which reveals the intent of the code better, and makes it easier to
16
locate the code checking alignment.
17
18
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
19
Message-id: 20190827185913.27427-2-nsoffer@redhat.com
20
Reviewed-by: John Snow <jsnow@redhat.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
23
block/bochs.c | 4 ++--
24
block/cloop.c | 4 ++--
25
block/dmg.c | 4 ++--
26
block/io.c | 8 ++++----
27
block/qcow2-cluster.c | 4 ++--
28
block/qcow2.c | 4 ++--
29
block/vvfat.c | 8 ++++----
30
qemu-img.c | 2 +-
31
8 files changed, 19 insertions(+), 19 deletions(-)
32
33
diff --git a/block/bochs.c b/block/bochs.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/bochs.c
36
+++ b/block/bochs.c
37
@@ -XXX,XX +XXX,XX @@ bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
38
QEMUIOVector local_qiov;
39
int ret;
40
41
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
42
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
43
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
44
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
45
46
qemu_iovec_init(&local_qiov, qiov->niov);
47
qemu_co_mutex_lock(&s->lock);
48
diff --git a/block/cloop.c b/block/cloop.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/cloop.c
51
+++ b/block/cloop.c
52
@@ -XXX,XX +XXX,XX @@ cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
53
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
54
int ret, i;
55
56
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
57
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
58
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
59
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
60
61
qemu_co_mutex_lock(&s->lock);
62
63
diff --git a/block/dmg.c b/block/dmg.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/dmg.c
66
+++ b/block/dmg.c
67
@@ -XXX,XX +XXX,XX @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
68
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
69
int ret, i;
70
71
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
72
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
73
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
74
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
75
76
qemu_co_mutex_lock(&s->lock);
77
78
diff --git a/block/io.c b/block/io.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/block/io.c
81
+++ b/block/io.c
82
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
83
sector_num = offset >> BDRV_SECTOR_BITS;
84
nb_sectors = bytes >> BDRV_SECTOR_BITS;
85
86
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
87
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
88
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
89
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
90
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
91
assert(drv->bdrv_co_readv);
92
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
94
sector_num = offset >> BDRV_SECTOR_BITS;
95
nb_sectors = bytes >> BDRV_SECTOR_BITS;
96
97
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
98
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
99
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
100
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
101
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
102
103
assert(drv->bdrv_co_writev);
104
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/block/qcow2-cluster.c
107
+++ b/block/qcow2-cluster.c
108
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
109
{
110
if (bytes && bs->encrypted) {
111
BDRVQcow2State *s = bs->opaque;
112
- assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
113
- assert((bytes & ~BDRV_SECTOR_MASK) == 0);
114
+ assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
115
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
116
assert(s->crypto);
117
if (qcow2_co_encrypt(bs, cluster_offset,
118
src_cluster_offset + offset_in_cluster,
119
diff --git a/block/qcow2.c b/block/qcow2.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/block/qcow2.c
122
+++ b/block/qcow2.c
123
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
124
goto fail;
125
}
126
127
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
128
- assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
129
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
130
+ assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE));
131
if (qcow2_co_decrypt(bs, cluster_offset, offset,
132
cluster_data, cur_bytes) < 0) {
133
ret = -EIO;
134
diff --git a/block/vvfat.c b/block/vvfat.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/block/vvfat.c
137
+++ b/block/vvfat.c
138
@@ -XXX,XX +XXX,XX @@ vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
139
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
140
void *buf;
141
142
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
143
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
144
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
145
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
146
147
buf = g_try_malloc(bytes);
148
if (bytes && buf == NULL) {
149
@@ -XXX,XX +XXX,XX @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
150
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
151
void *buf;
152
153
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
154
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
155
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
156
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
157
158
buf = g_try_malloc(bytes);
159
if (bytes && buf == NULL) {
160
diff --git a/qemu-img.c b/qemu-img.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/qemu-img.c
163
+++ b/qemu-img.c
164
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
165
int64_t sval;
166
167
sval = cvtnum(optarg);
168
- if (sval < 0 || sval & (BDRV_SECTOR_SIZE - 1) ||
169
+ if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
170
sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) {
171
error_report("Invalid buffer size for sparse output specified. "
172
"Valid sizes are multiples of %llu up to %llu. Select "
173
--
174
2.21.0
175
176
diff view generated by jsdifflib
Deleted patch
1
From: Nir Soffer <nirsof@gmail.com>
2
1
3
Replace confusing usage:
4
5
~BDRV_SECTOR_MASK
6
7
With more clear:
8
9
(BDRV_SECTOR_SIZE - 1)
10
11
Remove BDRV_SECTOR_MASK and the unused BDRV_BLOCK_OFFSET_MASK which was
12
it's last user.
13
14
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
15
Message-id: 20190827185913.27427-3-nsoffer@redhat.com
16
Reviewed-by: Juan Quintela <quintela@redhat.com>
17
Reviewed-by: John Snow <jsnow@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
include/block/block.h | 2 --
21
migration/block.c | 2 +-
22
2 files changed, 1 insertion(+), 3 deletions(-)
23
24
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
27
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
29
30
#define BDRV_SECTOR_BITS 9
31
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
32
-#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)
33
34
#define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \
35
INT_MAX >> BDRV_SECTOR_BITS)
36
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
37
#define BDRV_BLOCK_ALLOCATED 0x10
38
#define BDRV_BLOCK_EOF 0x20
39
#define BDRV_BLOCK_RECURSE 0x40
40
-#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK
41
42
typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
43
44
diff --git a/migration/block.c b/migration/block.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/migration/block.c
47
+++ b/migration/block.c
48
@@ -XXX,XX +XXX,XX @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
49
do {
50
addr = qemu_get_be64(f);
51
52
- flags = addr & ~BDRV_SECTOR_MASK;
53
+ flags = addr & (BDRV_SECTOR_SIZE - 1);
54
addr >>= BDRV_SECTOR_BITS;
55
56
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
57
--
58
2.21.0
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
When running "make check -j8" or something similar, the iotests are
4
running in parallel with the other tests. So when they are printing
5
out "Passed all xx tests" or a similar status message at the end,
6
it might not be quite clear that this message belongs to the iotests,
7
since the output might be mixed with the other tests. Thus change the
8
word "tests" here to "iotests" instead to avoid confusion.
9
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 20190906113920.11271-1-thuth@redhat.com
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/check | 8 ++++----
16
1 file changed, 4 insertions(+), 4 deletions(-)
17
18
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/check
21
+++ b/tests/qemu-iotests/check
22
@@ -XXX,XX +XXX,XX @@ END { if (NR > 0) {
23
if [ ! -z "$n_bad" -a $n_bad != 0 ]
24
then
25
echo "Failures:$bad"
26
- echo "Failed $n_bad of $try tests"
27
+ echo "Failed $n_bad of $try iotests"
28
echo "Failures:$bad" | fmt >>check.log
29
- echo "Failed $n_bad of $try tests" >>check.log
30
+ echo "Failed $n_bad of $try iotests" >>check.log
31
else
32
- echo "Passed all $try tests"
33
- echo "Passed all $try tests" >>check.log
34
+ echo "Passed all $try iotests"
35
+ echo "Passed all $try iotests" >>check.log
36
fi
37
needwrap=false
38
fi
39
--
40
2.21.0
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
The check script is already printing out which iotest is currently
4
running, so printing out the name of the check-block.sh shell script
5
looks superfluous here.
6
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Message-id: 20190906113534.10907-1-thuth@redhat.com
9
Acked-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/Makefile.include | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/Makefile.include
19
+++ b/tests/Makefile.include
20
@@ -XXX,XX +XXX,XX @@ QEMU_IOTESTS_HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = tests/qemu
21
check-tests/check-block.sh: tests/check-block.sh qemu-img$(EXESUF) \
22
        qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \
23
        $(patsubst %,%/all,$(filter %-softmmu,$(TARGET_DIRS)))
24
-    $<
25
+    @$<
26
27
.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
28
$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
29
--
30
2.21.0
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
qemu-io now prefixes its error and warnings with "qemu-io:".
4
36b9986b08787019e fixed a lot of iotests output but forget about
5
026.out.nocache. Fix it too.
6
7
Fixes: 99e98d7c9fc1a1639fad ("qemu-io: Use error_[gs]et_progname()")
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-id: 20190816153015.447957-2-vsementsov@virtuozzo.com
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/026.out.nocache | 168 ++++++++++++++---------------
14
1 file changed, 84 insertions(+), 84 deletions(-)
15
16
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/026.out.nocache
19
+++ b/tests/qemu-iotests/026.out.nocache
20
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
21
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
22
23
Event: l1_update; errno: 5; imm: off; once: off; write
24
-Failed to flush the L2 table cache: Input/output error
25
-Failed to flush the refcount block cache: Input/output error
26
+qemu-io: Failed to flush the L2 table cache: Input/output error
27
+qemu-io: Failed to flush the refcount block cache: Input/output error
28
write failed: Input/output error
29
30
1 leaked clusters were found on the image.
31
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
32
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
33
34
Event: l1_update; errno: 5; imm: off; once: off; write -b
35
-Failed to flush the L2 table cache: Input/output error
36
-Failed to flush the refcount block cache: Input/output error
37
+qemu-io: Failed to flush the L2 table cache: Input/output error
38
+qemu-io: Failed to flush the refcount block cache: Input/output error
39
write failed: Input/output error
40
41
1 leaked clusters were found on the image.
42
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
43
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
44
45
Event: l1_update; errno: 28; imm: off; once: off; write
46
-Failed to flush the L2 table cache: No space left on device
47
-Failed to flush the refcount block cache: No space left on device
48
+qemu-io: Failed to flush the L2 table cache: No space left on device
49
+qemu-io: Failed to flush the refcount block cache: No space left on device
50
write failed: No space left on device
51
52
1 leaked clusters were found on the image.
53
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
54
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
55
56
Event: l1_update; errno: 28; imm: off; once: off; write -b
57
-Failed to flush the L2 table cache: No space left on device
58
-Failed to flush the refcount block cache: No space left on device
59
+qemu-io: Failed to flush the L2 table cache: No space left on device
60
+qemu-io: Failed to flush the refcount block cache: No space left on device
61
write failed: No space left on device
62
63
1 leaked clusters were found on the image.
64
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
65
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
66
67
Event: l2_update; errno: 5; imm: off; once: off; write
68
-Failed to flush the L2 table cache: Input/output error
69
-Failed to flush the refcount block cache: Input/output error
70
+qemu-io: Failed to flush the L2 table cache: Input/output error
71
+qemu-io: Failed to flush the refcount block cache: Input/output error
72
wrote 131072/131072 bytes at offset 0
73
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
74
75
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
76
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
77
78
Event: l2_update; errno: 5; imm: off; once: off; write -b
79
-Failed to flush the L2 table cache: Input/output error
80
-Failed to flush the refcount block cache: Input/output error
81
+qemu-io: Failed to flush the L2 table cache: Input/output error
82
+qemu-io: Failed to flush the refcount block cache: Input/output error
83
wrote 131072/131072 bytes at offset 0
84
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
85
86
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
87
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
88
89
Event: l2_update; errno: 28; imm: off; once: off; write
90
-Failed to flush the L2 table cache: No space left on device
91
-Failed to flush the refcount block cache: No space left on device
92
+qemu-io: Failed to flush the L2 table cache: No space left on device
93
+qemu-io: Failed to flush the refcount block cache: No space left on device
94
wrote 131072/131072 bytes at offset 0
95
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
96
97
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
98
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
99
100
Event: l2_update; errno: 28; imm: off; once: off; write -b
101
-Failed to flush the L2 table cache: No space left on device
102
-Failed to flush the refcount block cache: No space left on device
103
+qemu-io: Failed to flush the L2 table cache: No space left on device
104
+qemu-io: Failed to flush the refcount block cache: No space left on device
105
wrote 131072/131072 bytes at offset 0
106
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
107
108
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
109
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
110
111
Event: l2_alloc_write; errno: 5; imm: off; once: off; write
112
-Failed to flush the L2 table cache: Input/output error
113
-Failed to flush the refcount block cache: Input/output error
114
+qemu-io: Failed to flush the L2 table cache: Input/output error
115
+qemu-io: Failed to flush the refcount block cache: Input/output error
116
write failed: Input/output error
117
No errors were found on the image.
118
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
119
120
Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b
121
-Failed to flush the L2 table cache: Input/output error
122
-Failed to flush the refcount block cache: Input/output error
123
+qemu-io: Failed to flush the L2 table cache: Input/output error
124
+qemu-io: Failed to flush the refcount block cache: Input/output error
125
write failed: Input/output error
126
127
1 leaked clusters were found on the image.
128
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
129
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
130
131
Event: l2_alloc_write; errno: 28; imm: off; once: off; write
132
-Failed to flush the L2 table cache: No space left on device
133
-Failed to flush the refcount block cache: No space left on device
134
+qemu-io: Failed to flush the L2 table cache: No space left on device
135
+qemu-io: Failed to flush the refcount block cache: No space left on device
136
write failed: No space left on device
137
No errors were found on the image.
138
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
139
140
Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b
141
-Failed to flush the L2 table cache: No space left on device
142
-Failed to flush the refcount block cache: No space left on device
143
+qemu-io: Failed to flush the L2 table cache: No space left on device
144
+qemu-io: Failed to flush the refcount block cache: No space left on device
145
write failed: No space left on device
146
147
1 leaked clusters were found on the image.
148
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
149
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
150
151
Event: write_aio; errno: 5; imm: off; once: off; write
152
-Failed to flush the L2 table cache: Input/output error
153
-Failed to flush the refcount block cache: Input/output error
154
+qemu-io: Failed to flush the L2 table cache: Input/output error
155
+qemu-io: Failed to flush the refcount block cache: Input/output error
156
write failed: Input/output error
157
No errors were found on the image.
158
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
159
160
Event: write_aio; errno: 5; imm: off; once: off; write -b
161
-Failed to flush the L2 table cache: Input/output error
162
-Failed to flush the refcount block cache: Input/output error
163
+qemu-io: Failed to flush the L2 table cache: Input/output error
164
+qemu-io: Failed to flush the refcount block cache: Input/output error
165
write failed: Input/output error
166
No errors were found on the image.
167
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
168
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
169
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
170
171
Event: write_aio; errno: 28; imm: off; once: off; write
172
-Failed to flush the L2 table cache: No space left on device
173
-Failed to flush the refcount block cache: No space left on device
174
+qemu-io: Failed to flush the L2 table cache: No space left on device
175
+qemu-io: Failed to flush the refcount block cache: No space left on device
176
write failed: No space left on device
177
No errors were found on the image.
178
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
179
180
Event: write_aio; errno: 28; imm: off; once: off; write -b
181
-Failed to flush the L2 table cache: No space left on device
182
-Failed to flush the refcount block cache: No space left on device
183
+qemu-io: Failed to flush the L2 table cache: No space left on device
184
+qemu-io: Failed to flush the refcount block cache: No space left on device
185
write failed: No space left on device
186
No errors were found on the image.
187
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
188
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
189
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
190
191
Event: refblock_load; errno: 5; imm: off; once: off; write
192
-Failed to flush the L2 table cache: Input/output error
193
-Failed to flush the refcount block cache: Input/output error
194
+qemu-io: Failed to flush the L2 table cache: Input/output error
195
+qemu-io: Failed to flush the refcount block cache: Input/output error
196
write failed: Input/output error
197
No errors were found on the image.
198
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
199
200
Event: refblock_load; errno: 5; imm: off; once: off; write -b
201
-Failed to flush the L2 table cache: Input/output error
202
-Failed to flush the refcount block cache: Input/output error
203
+qemu-io: Failed to flush the L2 table cache: Input/output error
204
+qemu-io: Failed to flush the refcount block cache: Input/output error
205
write failed: Input/output error
206
No errors were found on the image.
207
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
208
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
209
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
210
211
Event: refblock_load; errno: 28; imm: off; once: off; write
212
-Failed to flush the L2 table cache: No space left on device
213
-Failed to flush the refcount block cache: No space left on device
214
+qemu-io: Failed to flush the L2 table cache: No space left on device
215
+qemu-io: Failed to flush the refcount block cache: No space left on device
216
write failed: No space left on device
217
No errors were found on the image.
218
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
219
220
Event: refblock_load; errno: 28; imm: off; once: off; write -b
221
-Failed to flush the L2 table cache: No space left on device
222
-Failed to flush the refcount block cache: No space left on device
223
+qemu-io: Failed to flush the L2 table cache: No space left on device
224
+qemu-io: Failed to flush the refcount block cache: No space left on device
225
write failed: No space left on device
226
No errors were found on the image.
227
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
228
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
229
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
230
231
Event: refblock_update_part; errno: 5; imm: off; once: off; write
232
-Failed to flush the L2 table cache: Input/output error
233
-Failed to flush the refcount block cache: Input/output error
234
+qemu-io: Failed to flush the L2 table cache: Input/output error
235
+qemu-io: Failed to flush the refcount block cache: Input/output error
236
write failed: Input/output error
237
No errors were found on the image.
238
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
239
240
Event: refblock_update_part; errno: 5; imm: off; once: off; write -b
241
-Failed to flush the L2 table cache: Input/output error
242
-Failed to flush the refcount block cache: Input/output error
243
+qemu-io: Failed to flush the L2 table cache: Input/output error
244
+qemu-io: Failed to flush the refcount block cache: Input/output error
245
write failed: Input/output error
246
No errors were found on the image.
247
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
248
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
249
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
250
251
Event: refblock_update_part; errno: 28; imm: off; once: off; write
252
-Failed to flush the L2 table cache: No space left on device
253
-Failed to flush the refcount block cache: No space left on device
254
+qemu-io: Failed to flush the L2 table cache: No space left on device
255
+qemu-io: Failed to flush the refcount block cache: No space left on device
256
write failed: No space left on device
257
No errors were found on the image.
258
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
259
260
Event: refblock_update_part; errno: 28; imm: off; once: off; write -b
261
-Failed to flush the L2 table cache: No space left on device
262
-Failed to flush the refcount block cache: No space left on device
263
+qemu-io: Failed to flush the L2 table cache: No space left on device
264
+qemu-io: Failed to flush the refcount block cache: No space left on device
265
write failed: No space left on device
266
No errors were found on the image.
267
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
268
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
269
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
270
271
Event: refblock_alloc; errno: 5; imm: off; once: off; write
272
-Failed to flush the L2 table cache: Input/output error
273
-Failed to flush the refcount block cache: Input/output error
274
+qemu-io: Failed to flush the L2 table cache: Input/output error
275
+qemu-io: Failed to flush the refcount block cache: Input/output error
276
write failed: Input/output error
277
No errors were found on the image.
278
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
279
280
Event: refblock_alloc; errno: 5; imm: off; once: off; write -b
281
-Failed to flush the L2 table cache: Input/output error
282
-Failed to flush the refcount block cache: Input/output error
283
+qemu-io: Failed to flush the L2 table cache: Input/output error
284
+qemu-io: Failed to flush the refcount block cache: Input/output error
285
write failed: Input/output error
286
No errors were found on the image.
287
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
288
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
289
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
290
291
Event: refblock_alloc; errno: 28; imm: off; once: off; write
292
-Failed to flush the L2 table cache: No space left on device
293
-Failed to flush the refcount block cache: No space left on device
294
+qemu-io: Failed to flush the L2 table cache: No space left on device
295
+qemu-io: Failed to flush the refcount block cache: No space left on device
296
write failed: No space left on device
297
No errors were found on the image.
298
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
299
300
Event: refblock_alloc; errno: 28; imm: off; once: off; write -b
301
-Failed to flush the L2 table cache: No space left on device
302
-Failed to flush the refcount block cache: No space left on device
303
+qemu-io: Failed to flush the L2 table cache: No space left on device
304
+qemu-io: Failed to flush the refcount block cache: No space left on device
305
write failed: No space left on device
306
No errors were found on the image.
307
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
308
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
309
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
310
311
Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write
312
-Failed to flush the L2 table cache: No space left on device
313
-Failed to flush the refcount block cache: No space left on device
314
+qemu-io: Failed to flush the L2 table cache: No space left on device
315
+qemu-io: Failed to flush the refcount block cache: No space left on device
316
write failed: No space left on device
317
318
55 leaked clusters were found on the image.
319
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
320
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
321
322
Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b
323
-Failed to flush the L2 table cache: No space left on device
324
-Failed to flush the refcount block cache: No space left on device
325
+qemu-io: Failed to flush the L2 table cache: No space left on device
326
+qemu-io: Failed to flush the refcount block cache: No space left on device
327
write failed: No space left on device
328
329
251 leaked clusters were found on the image.
330
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
331
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
332
333
Event: refblock_alloc_write; errno: 28; imm: off; once: off; write
334
-Failed to flush the L2 table cache: No space left on device
335
-Failed to flush the refcount block cache: No space left on device
336
+qemu-io: Failed to flush the L2 table cache: No space left on device
337
+qemu-io: Failed to flush the refcount block cache: No space left on device
338
write failed: No space left on device
339
No errors were found on the image.
340
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
341
342
Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -b
343
-Failed to flush the L2 table cache: No space left on device
344
-Failed to flush the refcount block cache: No space left on device
345
+qemu-io: Failed to flush the L2 table cache: No space left on device
346
+qemu-io: Failed to flush the refcount block cache: No space left on device
347
write failed: No space left on device
348
No errors were found on the image.
349
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
350
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
351
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
352
353
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
354
-Failed to flush the L2 table cache: No space left on device
355
-Failed to flush the refcount block cache: No space left on device
356
+qemu-io: Failed to flush the L2 table cache: No space left on device
357
+qemu-io: Failed to flush the refcount block cache: No space left on device
358
write failed: No space left on device
359
360
10 leaked clusters were found on the image.
361
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
362
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
363
364
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
365
-Failed to flush the L2 table cache: No space left on device
366
-Failed to flush the refcount block cache: No space left on device
367
+qemu-io: Failed to flush the L2 table cache: No space left on device
368
+qemu-io: Failed to flush the refcount block cache: No space left on device
369
write failed: No space left on device
370
371
23 leaked clusters were found on the image.
372
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
373
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
374
375
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
376
-Failed to flush the L2 table cache: No space left on device
377
-Failed to flush the refcount block cache: No space left on device
378
+qemu-io: Failed to flush the L2 table cache: No space left on device
379
+qemu-io: Failed to flush the refcount block cache: No space left on device
380
write failed: No space left on device
381
382
10 leaked clusters were found on the image.
383
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
384
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
385
386
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
387
-Failed to flush the L2 table cache: No space left on device
388
-Failed to flush the refcount block cache: No space left on device
389
+qemu-io: Failed to flush the L2 table cache: No space left on device
390
+qemu-io: Failed to flush the refcount block cache: No space left on device
391
write failed: No space left on device
392
393
23 leaked clusters were found on the image.
394
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
395
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
396
397
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write
398
-Failed to flush the L2 table cache: No space left on device
399
-Failed to flush the refcount block cache: No space left on device
400
+qemu-io: Failed to flush the L2 table cache: No space left on device
401
+qemu-io: Failed to flush the refcount block cache: No space left on device
402
write failed: No space left on device
403
404
10 leaked clusters were found on the image.
405
@@ -XXX,XX +XXX,XX @@ This means waste of disk space, but no harm to data.
406
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
407
408
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b
409
-Failed to flush the L2 table cache: No space left on device
410
-Failed to flush the refcount block cache: No space left on device
411
+qemu-io: Failed to flush the L2 table cache: No space left on device
412
+qemu-io: Failed to flush the refcount block cache: No space left on device
413
write failed: No space left on device
414
415
23 leaked clusters were found on the image.
416
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
417
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
418
419
Event: l1_grow_write_table; errno: 5; imm: off; once: off
420
-Failed to flush the L2 table cache: Input/output error
421
-Failed to flush the refcount block cache: Input/output error
422
+qemu-io: Failed to flush the L2 table cache: Input/output error
423
+qemu-io: Failed to flush the refcount block cache: Input/output error
424
write failed: Input/output error
425
No errors were found on the image.
426
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
427
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
428
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
429
430
Event: l1_grow_write_table; errno: 28; imm: off; once: off
431
-Failed to flush the L2 table cache: No space left on device
432
-Failed to flush the refcount block cache: No space left on device
433
+qemu-io: Failed to flush the L2 table cache: No space left on device
434
+qemu-io: Failed to flush the refcount block cache: No space left on device
435
write failed: No space left on device
436
No errors were found on the image.
437
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
438
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
439
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
440
441
Event: l1_grow_activate_table; errno: 5; imm: off; once: off
442
-Failed to flush the L2 table cache: Input/output error
443
-Failed to flush the refcount block cache: Input/output error
444
+qemu-io: Failed to flush the L2 table cache: Input/output error
445
+qemu-io: Failed to flush the refcount block cache: Input/output error
446
write failed: Input/output error
447
448
96 leaked clusters were found on the image.
449
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
450
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
451
452
Event: l1_grow_activate_table; errno: 28; imm: off; once: off
453
-Failed to flush the L2 table cache: No space left on device
454
-Failed to flush the refcount block cache: No space left on device
455
+qemu-io: Failed to flush the L2 table cache: No space left on device
456
+qemu-io: Failed to flush the refcount block cache: No space left on device
457
write failed: No space left on device
458
459
96 leaked clusters were found on the image.
460
--
461
2.21.0
462
463
diff view generated by jsdifflib
Deleted patch
1
A follow-up patch will make curl_multi_do() and curl_multi_read() take a
2
CURLSocket instead of the CURLState. They still need the latter,
3
though, so add a pointer to it to the former.
4
1
5
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190910124136.10565-2-mreitz@redhat.com
9
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/curl.c | 3 +++
13
1 file changed, 3 insertions(+)
14
15
diff --git a/block/curl.c b/block/curl.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/curl.c
18
+++ b/block/curl.c
19
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
20
#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
21
22
struct BDRVCURLState;
23
+struct CURLState;
24
25
static bool libcurl_initialized;
26
27
@@ -XXX,XX +XXX,XX @@ typedef struct CURLAIOCB {
28
29
typedef struct CURLSocket {
30
int fd;
31
+ struct CURLState *state;
32
QLIST_ENTRY(CURLSocket) next;
33
} CURLSocket;
34
35
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
36
if (!socket) {
37
socket = g_new0(CURLSocket, 1);
38
socket->fd = fd;
39
+ socket->state = state;
40
QLIST_INSERT_HEAD(&state->sockets, socket, next);
41
}
42
socket = NULL;
43
--
44
2.21.0
45
46
diff view generated by jsdifflib
1
From: Maxim Levitsky <mlevitsk@redhat.com>
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
2
3
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
3
Introduce the 'event-loop-base' abstract class, it'll hold the
4
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
properties common to all event loops and provide the necessary hooks for
5
Message-id: 20190915203655.21638-4-mlevitsk@redhat.com
5
their creation and maintenance. Then have iothread inherit from it.
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
EventLoopBaseClass is defined as user creatable and provides a hook for
8
its children to attach themselves to the user creatable class 'complete'
9
function. It also provides an update_params() callback to propagate
10
property changes onto its children.
11
12
The new 'event-loop-base' class will live in the root directory. It is
13
built on its own using the 'link_whole' option (there are no direct
14
function dependencies between the class and its children, it all happens
15
trough 'constructor' magic). And also imposes new compilation
16
dependencies:
17
18
qom <- event-loop-base <- blockdev (iothread.c)
19
20
And in subsequent patches:
21
22
qom <- event-loop-base <- qemuutil (util/main-loop.c)
23
24
All this forced some amount of reordering in meson.build:
25
26
- Moved qom build definition before qemuutil. Doing it the other way
27
around (i.e. moving qemuutil after qom) isn't possible as a lot of
28
core libraries that live in between the two depend on it.
29
30
- Process the 'hw' subdir earlier, as it introduces files into the
31
'qom' source set.
32
33
No functional changes intended.
34
35
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
36
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
37
Acked-by: Markus Armbruster <armbru@redhat.com>
38
Message-id: 20220425075723.20019-2-nsaenzju@redhat.com
39
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
40
---
9
tests/qemu-iotests/263 | 91 ++++++++++++++++++++++++++++++++++++++
41
qapi/qom.json | 22 +++++--
10
tests/qemu-iotests/263.out | 40 +++++++++++++++++
42
meson.build | 23 ++++---
11
tests/qemu-iotests/group | 1 +
43
include/sysemu/event-loop-base.h | 36 +++++++++++
12
3 files changed, 132 insertions(+)
44
include/sysemu/iothread.h | 6 +-
13
create mode 100755 tests/qemu-iotests/263
45
event-loop-base.c | 104 +++++++++++++++++++++++++++++++
14
create mode 100644 tests/qemu-iotests/263.out
46
iothread.c | 65 ++++++-------------
15
47
6 files changed, 192 insertions(+), 64 deletions(-)
16
diff --git a/tests/qemu-iotests/263 b/tests/qemu-iotests/263
48
create mode 100644 include/sysemu/event-loop-base.h
17
new file mode 100755
49
create mode 100644 event-loop-base.c
18
index XXXXXXX..XXXXXXX
50
19
--- /dev/null
51
diff --git a/qapi/qom.json b/qapi/qom.json
20
+++ b/tests/qemu-iotests/263
52
index XXXXXXX..XXXXXXX 100644
21
@@ -XXX,XX +XXX,XX @@
53
--- a/qapi/qom.json
22
+#!/usr/bin/env bash
54
+++ b/qapi/qom.json
55
@@ -XXX,XX +XXX,XX @@
56
'*repeat': 'bool',
57
'*grab-toggle': 'GrabToggleKeys' } }
58
59
+##
60
+# @EventLoopBaseProperties:
23
+#
61
+#
24
+# Test encrypted write that crosses cluster boundary of two unallocated clusters
62
+# Common properties for event loops
25
+# Based on 188
26
+#
63
+#
27
+# Copyright (C) 2019 Red Hat, Inc.
64
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
65
+# 0 means that the engine will use its default.
66
+# (default: 0)
28
+#
67
+#
29
+# This program is free software; you can redistribute it and/or modify
68
+# Since: 7.1
30
+# it under the terms of the GNU General Public License as published by
69
+##
31
+# the Free Software Foundation; either version 2 of the License, or
70
+{ 'struct': 'EventLoopBaseProperties',
32
+# (at your option) any later version.
71
+ 'data': { '*aio-max-batch': 'int' } }
33
+#
72
+
34
+# This program is distributed in the hope that it will be useful,
73
##
35
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
74
# @IothreadProperties:
36
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
#
37
+# GNU General Public License for more details.
76
@@ -XXX,XX +XXX,XX @@
38
+#
77
# algorithm detects it is spending too long polling without
39
+# You should have received a copy of the GNU General Public License
78
# encountering events. 0 selects a default behaviour (default: 0)
40
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
79
#
41
+#
80
-# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
42
+
81
-# 0 means that the engine will use its default
43
+# creator
82
-# (default:0, since 6.1)
44
+owner=mlevitsk@redhat.com
83
+# The @aio-max-batch option is available since 6.1.
45
+
84
#
46
+seq=`basename $0`
85
# Since: 2.0
47
+echo "QA output created by $seq"
86
##
48
+
87
{ 'struct': 'IothreadProperties',
49
+status=1    # failure is the default!
88
+ 'base': 'EventLoopBaseProperties',
50
+
89
'data': { '*poll-max-ns': 'int',
51
+_cleanup()
90
'*poll-grow': 'int',
52
+{
91
- '*poll-shrink': 'int',
53
+    _cleanup_test_img
92
- '*aio-max-batch': 'int' } }
54
+}
93
+ '*poll-shrink': 'int' } }
55
+trap "_cleanup; exit \$status" 0 1 2 3 15
94
56
+
95
##
57
+# get standard environment, filters and checks
96
# @MemoryBackendProperties:
58
+. ./common.rc
97
diff --git a/meson.build b/meson.build
59
+. ./common.filter
98
index XXXXXXX..XXXXXXX 100644
60
+
99
--- a/meson.build
61
+_supported_fmt qcow2
100
+++ b/meson.build
62
+_supported_proto generic
101
@@ -XXX,XX +XXX,XX @@ subdir('qom')
63
+_supported_os Linux
102
subdir('authz')
64
+
103
subdir('crypto')
65
+
104
subdir('ui')
66
+size=1M
105
+subdir('hw')
67
+
106
68
+SECRET="secret,id=sec0,data=astrochicken"
107
69
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
108
if enable_modules
70
+
109
@@ -XXX,XX +XXX,XX @@ if enable_modules
71
+
110
modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
72
+_run_test()
111
endif
73
+{
112
74
+    echo "== reading the whole image =="
113
+qom_ss = qom_ss.apply(config_host, strict: false)
75
+    $QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts "$1" | _filter_qemu_io | _filter_testdir
114
+libqom = static_library('qom', qom_ss.sources() + genh,
76
+
115
+ dependencies: [qom_ss.dependencies()],
77
+    echo
116
+ name_suffix: 'fa')
78
+    echo "== write two 512 byte sectors on a cluster boundary =="
117
+qom = declare_dependency(link_whole: libqom)
79
+    $QEMU_IO --object $SECRET -c "write -P 0xAA 0xFE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir
118
+
80
+
119
+event_loop_base = files('event-loop-base.c')
81
+    echo
120
+event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
82
+    echo "== verify that the rest of the image is not changed =="
121
+ build_by_default: true)
83
+    $QEMU_IO --object $SECRET -c "read -P 0x00 0x00000 0xFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir
122
+event_loop_base = declare_dependency(link_whole: event_loop_base,
84
+    $QEMU_IO --object $SECRET -c "read -P 0xAA 0x0FE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir
123
+ dependencies: [qom])
85
+    $QEMU_IO --object $SECRET -c "read -P 0x00 0x10200 0xEFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir
124
+
86
+
125
stub_ss = stub_ss.apply(config_all, strict: false)
87
+}
126
88
+
127
util_ss.add_all(trace_ss)
89
+
128
@@ -XXX,XX +XXX,XX @@ subdir('monitor')
90
+echo
129
subdir('net')
91
+echo "testing LUKS qcow2 encryption"
130
subdir('replay')
92
+echo
131
subdir('semihosting')
93
+
132
-subdir('hw')
94
+_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=64K" $size
133
subdir('tcg')
95
+_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
134
subdir('fpu')
96
+_cleanup_test_img
135
subdir('accel')
97
+
136
@@ -XXX,XX +XXX,XX @@ qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
98
+echo
137
capture: true,
99
+echo "testing legacy AES qcow2 encryption"
138
command: [undefsym, nm, '@INPUT@'])
100
+echo
139
101
+
140
-qom_ss = qom_ss.apply(config_host, strict: false)
102
+
141
-libqom = static_library('qom', qom_ss.sources() + genh,
103
+_make_test_img --object $SECRET -o "encrypt.format=aes,encrypt.key-secret=sec0,cluster_size=64K" $size
142
- dependencies: [qom_ss.dependencies()],
104
+_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
143
- name_suffix: 'fa')
105
+_cleanup_test_img
144
-
106
+
145
-qom = declare_dependency(link_whole: libqom)
107
+
146
-
108
+
147
authz_ss = authz_ss.apply(config_host, strict: false)
109
+# success, all done
148
libauthz = static_library('authz', authz_ss.sources() + genh,
110
+echo "*** done"
149
dependencies: [authz_ss.dependencies()],
111
+rm -f $seq.full
150
@@ -XXX,XX +XXX,XX @@ libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
112
+status=0
151
build_by_default: false)
113
diff --git a/tests/qemu-iotests/263.out b/tests/qemu-iotests/263.out
152
153
blockdev = declare_dependency(link_whole: [libblockdev],
154
- dependencies: [block])
155
+ dependencies: [block, event_loop_base])
156
157
qmp_ss = qmp_ss.apply(config_host, strict: false)
158
libqmp = static_library('qmp', qmp_ss.sources() + genh,
159
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
114
new file mode 100644
160
new file mode 100644
115
index XXXXXXX..XXXXXXX
161
index XXXXXXX..XXXXXXX
116
--- /dev/null
162
--- /dev/null
117
+++ b/tests/qemu-iotests/263.out
163
+++ b/include/sysemu/event-loop-base.h
118
@@ -XXX,XX +XXX,XX @@
164
@@ -XXX,XX +XXX,XX @@
119
+QA output created by 263
165
+/*
120
+
166
+ * QEMU event-loop backend
121
+testing LUKS qcow2 encryption
167
+ *
122
+
168
+ * Copyright (C) 2022 Red Hat Inc
123
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
169
+ *
124
+== reading the whole image ==
170
+ * Authors:
125
+read 1048576/1048576 bytes at offset 0
171
+ * Nicolas Saenz Julienne <nsaenzju@redhat.com>
126
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
172
+ *
127
+
173
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
128
+== write two 512 byte sectors on a cluster boundary ==
174
+ * See the COPYING file in the top-level directory.
129
+wrote 1024/1024 bytes at offset 65024
175
+ */
130
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
176
+#ifndef QEMU_EVENT_LOOP_BASE_H
131
+
177
+#define QEMU_EVENT_LOOP_BASE_H
132
+== verify that the rest of the image is not changed ==
178
+
133
+read 65024/65024 bytes at offset 0
179
+#include "qom/object.h"
134
+63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
180
+#include "block/aio.h"
135
+read 1024/1024 bytes at offset 65024
181
+#include "qemu/typedefs.h"
136
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
182
+
137
+read 982528/982528 bytes at offset 66048
183
+#define TYPE_EVENT_LOOP_BASE "event-loop-base"
138
+959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
184
+OBJECT_DECLARE_TYPE(EventLoopBase, EventLoopBaseClass,
139
+
185
+ EVENT_LOOP_BASE)
140
+testing legacy AES qcow2 encryption
186
+
141
+
187
+struct EventLoopBaseClass {
142
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=aes encrypt.key-secret=sec0
188
+ ObjectClass parent_class;
143
+== reading the whole image ==
189
+
144
+read 1048576/1048576 bytes at offset 0
190
+ void (*init)(EventLoopBase *base, Error **errp);
145
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
191
+ void (*update_params)(EventLoopBase *base, Error **errp);
146
+
192
+};
147
+== write two 512 byte sectors on a cluster boundary ==
193
+
148
+wrote 1024/1024 bytes at offset 65024
194
+struct EventLoopBase {
149
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
195
+ Object parent;
150
+
196
+
151
+== verify that the rest of the image is not changed ==
197
+ /* AioContext AIO engine parameters */
152
+read 65024/65024 bytes at offset 0
198
+ int64_t aio_max_batch;
153
+63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
199
+};
154
+read 1024/1024 bytes at offset 65024
200
+#endif
155
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
201
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
156
+read 982528/982528 bytes at offset 66048
157
+959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
158
+*** done
159
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
160
index XXXXXXX..XXXXXXX 100644
202
index XXXXXXX..XXXXXXX 100644
161
--- a/tests/qemu-iotests/group
203
--- a/include/sysemu/iothread.h
162
+++ b/tests/qemu-iotests/group
204
+++ b/include/sysemu/iothread.h
163
@@ -XXX,XX +XXX,XX @@
205
@@ -XXX,XX +XXX,XX @@
164
257 rw
206
#include "block/aio.h"
165
258 rw quick
207
#include "qemu/thread.h"
166
262 rw quick migration
208
#include "qom/object.h"
167
+263 rw quick
209
+#include "sysemu/event-loop-base.h"
168
265 rw auto quick
210
169
266 rw quick
211
#define TYPE_IOTHREAD "iothread"
212
213
struct IOThread {
214
- Object parent_obj;
215
+ EventLoopBase parent_obj;
216
217
QemuThread thread;
218
AioContext *ctx;
219
@@ -XXX,XX +XXX,XX @@ struct IOThread {
220
int64_t poll_max_ns;
221
int64_t poll_grow;
222
int64_t poll_shrink;
223
-
224
- /* AioContext AIO engine parameters */
225
- int64_t aio_max_batch;
226
};
227
typedef struct IOThread IOThread;
228
229
diff --git a/event-loop-base.c b/event-loop-base.c
230
new file mode 100644
231
index XXXXXXX..XXXXXXX
232
--- /dev/null
233
+++ b/event-loop-base.c
234
@@ -XXX,XX +XXX,XX @@
235
+/*
236
+ * QEMU event-loop base
237
+ *
238
+ * Copyright (C) 2022 Red Hat Inc
239
+ *
240
+ * Authors:
241
+ * Stefan Hajnoczi <stefanha@redhat.com>
242
+ * Nicolas Saenz Julienne <nsaenzju@redhat.com>
243
+ *
244
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
245
+ * See the COPYING file in the top-level directory.
246
+ */
247
+
248
+#include "qemu/osdep.h"
249
+#include "qom/object_interfaces.h"
250
+#include "qapi/error.h"
251
+#include "sysemu/event-loop-base.h"
252
+
253
+typedef struct {
254
+ const char *name;
255
+ ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
256
+} EventLoopBaseParamInfo;
257
+
258
+static EventLoopBaseParamInfo aio_max_batch_info = {
259
+ "aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
260
+};
261
+
262
+static void event_loop_base_get_param(Object *obj, Visitor *v,
263
+ const char *name, void *opaque, Error **errp)
264
+{
265
+ EventLoopBase *event_loop_base = EVENT_LOOP_BASE(obj);
266
+ EventLoopBaseParamInfo *info = opaque;
267
+ int64_t *field = (void *)event_loop_base + info->offset;
268
+
269
+ visit_type_int64(v, name, field, errp);
270
+}
271
+
272
+static void event_loop_base_set_param(Object *obj, Visitor *v,
273
+ const char *name, void *opaque, Error **errp)
274
+{
275
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(obj);
276
+ EventLoopBase *base = EVENT_LOOP_BASE(obj);
277
+ EventLoopBaseParamInfo *info = opaque;
278
+ int64_t *field = (void *)base + info->offset;
279
+ int64_t value;
280
+
281
+ if (!visit_type_int64(v, name, &value, errp)) {
282
+ return;
283
+ }
284
+
285
+ if (value < 0) {
286
+ error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
287
+ info->name, INT64_MAX);
288
+ return;
289
+ }
290
+
291
+ *field = value;
292
+
293
+ if (bc->update_params) {
294
+ bc->update_params(base, errp);
295
+ }
296
+
297
+ return;
298
+}
299
+
300
+static void event_loop_base_complete(UserCreatable *uc, Error **errp)
301
+{
302
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
303
+ EventLoopBase *base = EVENT_LOOP_BASE(uc);
304
+
305
+ if (bc->init) {
306
+ bc->init(base, errp);
307
+ }
308
+}
309
+
310
+static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
311
+{
312
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
313
+ ucc->complete = event_loop_base_complete;
314
+
315
+ object_class_property_add(klass, "aio-max-batch", "int",
316
+ event_loop_base_get_param,
317
+ event_loop_base_set_param,
318
+ NULL, &aio_max_batch_info);
319
+}
320
+
321
+static const TypeInfo event_loop_base_info = {
322
+ .name = TYPE_EVENT_LOOP_BASE,
323
+ .parent = TYPE_OBJECT,
324
+ .instance_size = sizeof(EventLoopBase),
325
+ .class_size = sizeof(EventLoopBaseClass),
326
+ .class_init = event_loop_base_class_init,
327
+ .abstract = true,
328
+ .interfaces = (InterfaceInfo[]) {
329
+ { TYPE_USER_CREATABLE },
330
+ { }
331
+ }
332
+};
333
+
334
+static void register_types(void)
335
+{
336
+ type_register_static(&event_loop_base_info);
337
+}
338
+type_init(register_types);
339
diff --git a/iothread.c b/iothread.c
340
index XXXXXXX..XXXXXXX 100644
341
--- a/iothread.c
342
+++ b/iothread.c
343
@@ -XXX,XX +XXX,XX @@
344
#include "qemu/module.h"
345
#include "block/aio.h"
346
#include "block/block.h"
347
+#include "sysemu/event-loop-base.h"
348
#include "sysemu/iothread.h"
349
#include "qapi/error.h"
350
#include "qapi/qapi-commands-misc.h"
351
@@ -XXX,XX +XXX,XX @@ static void iothread_init_gcontext(IOThread *iothread)
352
iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
353
}
354
355
-static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
356
+static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
357
{
358
+ IOThread *iothread = IOTHREAD(base);
359
ERRP_GUARD();
360
361
+ if (!iothread->ctx) {
362
+ return;
363
+ }
364
+
365
aio_context_set_poll_params(iothread->ctx,
366
iothread->poll_max_ns,
367
iothread->poll_grow,
368
@@ -XXX,XX +XXX,XX @@ static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
369
}
370
371
aio_context_set_aio_params(iothread->ctx,
372
- iothread->aio_max_batch,
373
+ iothread->parent_obj.aio_max_batch,
374
errp);
375
}
376
377
-static void iothread_complete(UserCreatable *obj, Error **errp)
378
+
379
+static void iothread_init(EventLoopBase *base, Error **errp)
380
{
381
Error *local_error = NULL;
382
- IOThread *iothread = IOTHREAD(obj);
383
+ IOThread *iothread = IOTHREAD(base);
384
char *thread_name;
385
386
iothread->stopping = false;
387
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
388
*/
389
iothread_init_gcontext(iothread);
390
391
- iothread_set_aio_context_params(iothread, &local_error);
392
+ iothread_set_aio_context_params(base, &local_error);
393
if (local_error) {
394
error_propagate(errp, local_error);
395
aio_context_unref(iothread->ctx);
396
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
397
* to inherit.
398
*/
399
thread_name = g_strdup_printf("IO %s",
400
- object_get_canonical_path_component(OBJECT(obj)));
401
+ object_get_canonical_path_component(OBJECT(base)));
402
qemu_thread_create(&iothread->thread, thread_name, iothread_run,
403
iothread, QEMU_THREAD_JOINABLE);
404
g_free(thread_name);
405
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo poll_grow_info = {
406
static IOThreadParamInfo poll_shrink_info = {
407
"poll-shrink", offsetof(IOThread, poll_shrink),
408
};
409
-static IOThreadParamInfo aio_max_batch_info = {
410
- "aio-max-batch", offsetof(IOThread, aio_max_batch),
411
-};
412
413
static void iothread_get_param(Object *obj, Visitor *v,
414
const char *name, IOThreadParamInfo *info, Error **errp)
415
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
416
}
417
}
418
419
-static void iothread_get_aio_param(Object *obj, Visitor *v,
420
- const char *name, void *opaque, Error **errp)
421
-{
422
- IOThreadParamInfo *info = opaque;
423
-
424
- iothread_get_param(obj, v, name, info, errp);
425
-}
426
-
427
-static void iothread_set_aio_param(Object *obj, Visitor *v,
428
- const char *name, void *opaque, Error **errp)
429
-{
430
- IOThread *iothread = IOTHREAD(obj);
431
- IOThreadParamInfo *info = opaque;
432
-
433
- if (!iothread_set_param(obj, v, name, info, errp)) {
434
- return;
435
- }
436
-
437
- if (iothread->ctx) {
438
- aio_context_set_aio_params(iothread->ctx,
439
- iothread->aio_max_batch,
440
- errp);
441
- }
442
-}
443
-
444
static void iothread_class_init(ObjectClass *klass, void *class_data)
445
{
446
- UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
447
- ucc->complete = iothread_complete;
448
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(klass);
449
+
450
+ bc->init = iothread_init;
451
+ bc->update_params = iothread_set_aio_context_params;
452
453
object_class_property_add(klass, "poll-max-ns", "int",
454
iothread_get_poll_param,
455
@@ -XXX,XX +XXX,XX @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
456
iothread_get_poll_param,
457
iothread_set_poll_param,
458
NULL, &poll_shrink_info);
459
- object_class_property_add(klass, "aio-max-batch", "int",
460
- iothread_get_aio_param,
461
- iothread_set_aio_param,
462
- NULL, &aio_max_batch_info);
463
}
464
465
static const TypeInfo iothread_info = {
466
.name = TYPE_IOTHREAD,
467
- .parent = TYPE_OBJECT,
468
+ .parent = TYPE_EVENT_LOOP_BASE,
469
.class_init = iothread_class_init,
470
.instance_size = sizeof(IOThread),
471
.instance_init = iothread_instance_init,
472
.instance_finalize = iothread_instance_finalize,
473
- .interfaces = (InterfaceInfo[]) {
474
- {TYPE_USER_CREATABLE},
475
- {}
476
- },
477
};
478
479
static void iothread_register_types(void)
480
@@ -XXX,XX +XXX,XX @@ static int query_one_iothread(Object *object, void *opaque)
481
info->poll_max_ns = iothread->poll_max_ns;
482
info->poll_grow = iothread->poll_grow;
483
info->poll_shrink = iothread->poll_shrink;
484
- info->aio_max_batch = iothread->aio_max_batch;
485
+ info->aio_max_batch = iothread->parent_obj.aio_max_batch;
486
487
QAPI_LIST_APPEND(*tail, info);
488
return 0;
170
--
489
--
171
2.21.0
490
2.35.1
172
173
diff view generated by jsdifflib
1
This does not really change anything, but it makes the code a bit easier
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
to follow once we use @socket as the opaque pointer for
2
3
aio_set_fd_handler().
3
'event-loop-base' provides basic property handling for all 'AioContext'
4
4
based event loops. So let's define a new 'MainLoopClass' that inherits
5
Cc: qemu-stable@nongnu.org
5
from it. This will permit tweaking the main loop's properties through
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
qapi as well as through the command line using the '-object' keyword[1].
7
Message-id: 20190910124136.10565-3-mreitz@redhat.com
7
Only one instance of 'MainLoopClass' might be created at any time.
8
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
8
9
Reviewed-by: John Snow <jsnow@redhat.com>
9
'EventLoopBaseClass' learns a new callback, 'can_be_deleted()' so as to
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
mark 'MainLoop' as non-deletable.
11
12
[1] For example:
13
-object main-loop,id=main-loop,aio-max-batch=<value>
14
15
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Acked-by: Markus Armbruster <armbru@redhat.com>
18
Message-id: 20220425075723.20019-3-nsaenzju@redhat.com
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
20
---
12
block/curl.c | 10 +++++-----
21
qapi/qom.json | 13 ++++++++
13
1 file changed, 5 insertions(+), 5 deletions(-)
22
meson.build | 3 +-
14
23
include/qemu/main-loop.h | 10 ++++++
15
diff --git a/block/curl.c b/block/curl.c
24
include/sysemu/event-loop-base.h | 1 +
16
index XXXXXXX..XXXXXXX 100644
25
event-loop-base.c | 13 ++++++++
17
--- a/block/curl.c
26
util/main-loop.c | 56 ++++++++++++++++++++++++++++++++
18
+++ b/block/curl.c
27
6 files changed, 95 insertions(+), 1 deletion(-)
19
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
28
20
29
diff --git a/qapi/qom.json b/qapi/qom.json
21
QLIST_FOREACH(socket, &state->sockets, next) {
30
index XXXXXXX..XXXXXXX 100644
22
if (socket->fd == fd) {
31
--- a/qapi/qom.json
23
- if (action == CURL_POLL_REMOVE) {
32
+++ b/qapi/qom.json
24
- QLIST_REMOVE(socket, next);
33
@@ -XXX,XX +XXX,XX @@
25
- g_free(socket);
34
'*poll-grow': 'int',
26
- }
35
'*poll-shrink': 'int' } }
27
break;
36
28
}
37
+##
38
+# @MainLoopProperties:
39
+#
40
+# Properties for the main-loop object.
41
+#
42
+# Since: 7.1
43
+##
44
+{ 'struct': 'MainLoopProperties',
45
+ 'base': 'EventLoopBaseProperties',
46
+ 'data': {} }
47
+
48
##
49
# @MemoryBackendProperties:
50
#
51
@@ -XXX,XX +XXX,XX @@
52
{ 'name': 'input-linux',
53
'if': 'CONFIG_LINUX' },
54
'iothread',
55
+ 'main-loop',
56
{ 'name': 'memory-backend-epc',
57
'if': 'CONFIG_LINUX' },
58
'memory-backend-file',
59
@@ -XXX,XX +XXX,XX @@
60
'input-linux': { 'type': 'InputLinuxProperties',
61
'if': 'CONFIG_LINUX' },
62
'iothread': 'IothreadProperties',
63
+ 'main-loop': 'MainLoopProperties',
64
'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties',
65
'if': 'CONFIG_LINUX' },
66
'memory-backend-file': 'MemoryBackendFileProperties',
67
diff --git a/meson.build b/meson.build
68
index XXXXXXX..XXXXXXX 100644
69
--- a/meson.build
70
+++ b/meson.build
71
@@ -XXX,XX +XXX,XX @@ libqemuutil = static_library('qemuutil',
72
sources: util_ss.sources() + stub_ss.sources() + genh,
73
dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
74
qemuutil = declare_dependency(link_with: libqemuutil,
75
- sources: genh + version_res)
76
+ sources: genh + version_res,
77
+ dependencies: [event_loop_base])
78
79
if have_system or have_user
80
decodetree = generator(find_program('scripts/decodetree.py'),
81
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
82
index XXXXXXX..XXXXXXX 100644
83
--- a/include/qemu/main-loop.h
84
+++ b/include/qemu/main-loop.h
85
@@ -XXX,XX +XXX,XX @@
86
#define QEMU_MAIN_LOOP_H
87
88
#include "block/aio.h"
89
+#include "qom/object.h"
90
+#include "sysemu/event-loop-base.h"
91
92
#define SIG_IPI SIGUSR1
93
94
+#define TYPE_MAIN_LOOP "main-loop"
95
+OBJECT_DECLARE_TYPE(MainLoop, MainLoopClass, MAIN_LOOP)
96
+
97
+struct MainLoop {
98
+ EventLoopBase parent_obj;
99
+};
100
+typedef struct MainLoop MainLoop;
101
+
102
/**
103
* qemu_init_main_loop: Set up the process so that it can run the main loop.
104
*
105
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
106
index XXXXXXX..XXXXXXX 100644
107
--- a/include/sysemu/event-loop-base.h
108
+++ b/include/sysemu/event-loop-base.h
109
@@ -XXX,XX +XXX,XX @@ struct EventLoopBaseClass {
110
111
void (*init)(EventLoopBase *base, Error **errp);
112
void (*update_params)(EventLoopBase *base, Error **errp);
113
+ bool (*can_be_deleted)(EventLoopBase *base);
114
};
115
116
struct EventLoopBase {
117
diff --git a/event-loop-base.c b/event-loop-base.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/event-loop-base.c
120
+++ b/event-loop-base.c
121
@@ -XXX,XX +XXX,XX @@ static void event_loop_base_complete(UserCreatable *uc, Error **errp)
29
}
122
}
30
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
123
}
31
socket->state = state;
124
32
QLIST_INSERT_HEAD(&state->sockets, socket, next);
125
+static bool event_loop_base_can_be_deleted(UserCreatable *uc)
33
}
126
+{
34
- socket = NULL;
127
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
35
128
+ EventLoopBase *backend = EVENT_LOOP_BASE(uc);
36
trace_curl_sock_cb(action, (int)fd);
129
+
37
switch (action) {
130
+ if (bc->can_be_deleted) {
38
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
131
+ return bc->can_be_deleted(backend);
39
break;
40
}
41
42
+ if (action == CURL_POLL_REMOVE) {
43
+ QLIST_REMOVE(socket, next);
44
+ g_free(socket);
45
+ }
132
+ }
46
+
133
+
134
+ return true;
135
+}
136
+
137
static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
138
{
139
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
140
ucc->complete = event_loop_base_complete;
141
+ ucc->can_be_deleted = event_loop_base_can_be_deleted;
142
143
object_class_property_add(klass, "aio-max-batch", "int",
144
event_loop_base_get_param,
145
diff --git a/util/main-loop.c b/util/main-loop.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/util/main-loop.c
148
+++ b/util/main-loop.c
149
@@ -XXX,XX +XXX,XX @@
150
#include "qemu/error-report.h"
151
#include "qemu/queue.h"
152
#include "qemu/compiler.h"
153
+#include "qom/object.h"
154
155
#ifndef _WIN32
156
#include <sys/wait.h>
157
@@ -XXX,XX +XXX,XX @@ int qemu_init_main_loop(Error **errp)
47
return 0;
158
return 0;
48
}
159
}
49
160
161
+static void main_loop_update_params(EventLoopBase *base, Error **errp)
162
+{
163
+ if (!qemu_aio_context) {
164
+ error_setg(errp, "qemu aio context not ready");
165
+ return;
166
+ }
167
+
168
+ aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
169
+}
170
+
171
+MainLoop *mloop;
172
+
173
+static void main_loop_init(EventLoopBase *base, Error **errp)
174
+{
175
+ MainLoop *m = MAIN_LOOP(base);
176
+
177
+ if (mloop) {
178
+ error_setg(errp, "only one main-loop instance allowed");
179
+ return;
180
+ }
181
+
182
+ main_loop_update_params(base, errp);
183
+
184
+ mloop = m;
185
+ return;
186
+}
187
+
188
+static bool main_loop_can_be_deleted(EventLoopBase *base)
189
+{
190
+ return false;
191
+}
192
+
193
+static void main_loop_class_init(ObjectClass *oc, void *class_data)
194
+{
195
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(oc);
196
+
197
+ bc->init = main_loop_init;
198
+ bc->update_params = main_loop_update_params;
199
+ bc->can_be_deleted = main_loop_can_be_deleted;
200
+}
201
+
202
+static const TypeInfo main_loop_info = {
203
+ .name = TYPE_MAIN_LOOP,
204
+ .parent = TYPE_EVENT_LOOP_BASE,
205
+ .class_init = main_loop_class_init,
206
+ .instance_size = sizeof(MainLoop),
207
+};
208
+
209
+static void main_loop_register_types(void)
210
+{
211
+ type_register_static(&main_loop_info);
212
+}
213
+
214
+type_init(main_loop_register_types)
215
+
216
static int max_priority;
217
218
#ifndef _WIN32
50
--
219
--
51
2.21.0
220
2.35.1
52
53
diff view generated by jsdifflib
Deleted patch
1
While it is more likely that transfers complete after some file
2
descriptor has data ready to read, we probably should not rely on it.
3
Better be safe than sorry and call curl_multi_check_completion() in
4
curl_multi_do(), too, just like it is done in curl_multi_read().
5
1
6
With this change, curl_multi_do() and curl_multi_read() are actually the
7
same, so drop curl_multi_read() and use curl_multi_do() as the sole FD
8
handler.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20190910124136.10565-4-mreitz@redhat.com
12
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/curl.c | 14 ++------------
17
1 file changed, 2 insertions(+), 12 deletions(-)
18
19
diff --git a/block/curl.c b/block/curl.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/curl.c
22
+++ b/block/curl.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVCURLState {
24
25
static void curl_clean_state(CURLState *s);
26
static void curl_multi_do(void *arg);
27
-static void curl_multi_read(void *arg);
28
29
#ifdef NEED_CURL_TIMER_CALLBACK
30
/* Called from curl_multi_do_locked, with s->mutex held. */
31
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
32
switch (action) {
33
case CURL_POLL_IN:
34
aio_set_fd_handler(s->aio_context, fd, false,
35
- curl_multi_read, NULL, NULL, state);
36
+ curl_multi_do, NULL, NULL, state);
37
break;
38
case CURL_POLL_OUT:
39
aio_set_fd_handler(s->aio_context, fd, false,
40
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
41
break;
42
case CURL_POLL_INOUT:
43
aio_set_fd_handler(s->aio_context, fd, false,
44
- curl_multi_read, curl_multi_do, NULL, state);
45
+ curl_multi_do, curl_multi_do, NULL, state);
46
break;
47
case CURL_POLL_REMOVE:
48
aio_set_fd_handler(s->aio_context, fd, false,
49
@@ -XXX,XX +XXX,XX @@ static void curl_multi_do(void *arg)
50
{
51
CURLState *s = (CURLState *)arg;
52
53
- qemu_mutex_lock(&s->s->mutex);
54
- curl_multi_do_locked(s);
55
- qemu_mutex_unlock(&s->s->mutex);
56
-}
57
-
58
-static void curl_multi_read(void *arg)
59
-{
60
- CURLState *s = (CURLState *)arg;
61
-
62
qemu_mutex_lock(&s->s->mutex);
63
curl_multi_do_locked(s);
64
curl_multi_check_completion(s->s);
65
--
66
2.21.0
67
68
diff view generated by jsdifflib
Deleted patch
1
curl_multi_do_locked() currently marks all sockets as ready. That is
2
not only inefficient, but in fact unsafe (the loop is). A follow-up
3
patch will change that, but to do so, curl_multi_do_locked() needs to
4
know exactly which socket is ready; and that is accomplished by this
5
patch here.
6
1
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20190910124136.10565-5-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/curl.c | 20 +++++++++++---------
15
1 file changed, 11 insertions(+), 9 deletions(-)
16
17
diff --git a/block/curl.c b/block/curl.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/curl.c
20
+++ b/block/curl.c
21
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
22
switch (action) {
23
case CURL_POLL_IN:
24
aio_set_fd_handler(s->aio_context, fd, false,
25
- curl_multi_do, NULL, NULL, state);
26
+ curl_multi_do, NULL, NULL, socket);
27
break;
28
case CURL_POLL_OUT:
29
aio_set_fd_handler(s->aio_context, fd, false,
30
- NULL, curl_multi_do, NULL, state);
31
+ NULL, curl_multi_do, NULL, socket);
32
break;
33
case CURL_POLL_INOUT:
34
aio_set_fd_handler(s->aio_context, fd, false,
35
- curl_multi_do, curl_multi_do, NULL, state);
36
+ curl_multi_do, curl_multi_do, NULL, socket);
37
break;
38
case CURL_POLL_REMOVE:
39
aio_set_fd_handler(s->aio_context, fd, false,
40
@@ -XXX,XX +XXX,XX @@ static void curl_multi_check_completion(BDRVCURLState *s)
41
}
42
43
/* Called with s->mutex held. */
44
-static void curl_multi_do_locked(CURLState *s)
45
+static void curl_multi_do_locked(CURLSocket *ready_socket)
46
{
47
CURLSocket *socket, *next_socket;
48
+ CURLState *s = ready_socket->state;
49
int running;
50
int r;
51
52
@@ -XXX,XX +XXX,XX @@ static void curl_multi_do_locked(CURLState *s)
53
54
static void curl_multi_do(void *arg)
55
{
56
- CURLState *s = (CURLState *)arg;
57
+ CURLSocket *socket = arg;
58
+ BDRVCURLState *s = socket->state->s;
59
60
- qemu_mutex_lock(&s->s->mutex);
61
- curl_multi_do_locked(s);
62
- curl_multi_check_completion(s->s);
63
- qemu_mutex_unlock(&s->s->mutex);
64
+ qemu_mutex_lock(&s->mutex);
65
+ curl_multi_do_locked(socket);
66
+ curl_multi_check_completion(s);
67
+ qemu_mutex_unlock(&s->mutex);
68
}
69
70
static void curl_multi_timeout_do(void *arg)
71
--
72
2.21.0
73
74
diff view generated by jsdifflib
1
Instead of reporting all sockets to cURL, only report the one that has
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
caused curl_multi_do_locked() to be called. This lets us get rid of the
3
QLIST_FOREACH_SAFE() list, which was actually wrong: SAFE foreaches are
4
only safe when the current element is removed in each iteration. If it
5
possible for the list to be concurrently modified, we cannot guarantee
6
that only the current element will be removed. Therefore, we must not
7
use QLIST_FOREACH_SAFE() here.
8
2
9
Fixes: ff5ca1664af85b24a4180d595ea6873fd3deac57
3
The thread pool regulates itself: when idle, it kills threads until
10
Cc: qemu-stable@nongnu.org
4
empty, when in demand, it creates new threads until full. This behaviour
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
doesn't play well with latency sensitive workloads where the price of
12
Message-id: 20190910124136.10565-6-mreitz@redhat.com
6
creating a new thread is too high. For example, when paired with qemu's
13
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
'-mlock', or using safety features like SafeStack, creating a new thread
14
Reviewed-by: John Snow <jsnow@redhat.com>
8
has been measured take multiple milliseconds.
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
10
In order to mitigate this let's introduce a new 'EventLoopBase'
11
property to set the thread pool size. The threads will be created during
12
the pool's initialization or upon updating the property's value, remain
13
available during its lifetime regardless of demand, and destroyed upon
14
freeing it. A properly characterized workload will then be able to
15
configure the pool to avoid any latency spikes.
16
17
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Acked-by: Markus Armbruster <armbru@redhat.com>
20
Message-id: 20220425075723.20019-4-nsaenzju@redhat.com
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
22
---
17
block/curl.c | 17 ++++++-----------
23
qapi/qom.json | 10 +++++-
18
1 file changed, 6 insertions(+), 11 deletions(-)
24
include/block/aio.h | 10 ++++++
25
include/block/thread-pool.h | 3 ++
26
include/sysemu/event-loop-base.h | 4 +++
27
event-loop-base.c | 23 +++++++++++++
28
iothread.c | 3 ++
29
util/aio-posix.c | 1 +
30
util/async.c | 20 ++++++++++++
31
util/main-loop.c | 9 ++++++
32
util/thread-pool.c | 55 +++++++++++++++++++++++++++++---
33
10 files changed, 133 insertions(+), 5 deletions(-)
19
34
20
diff --git a/block/curl.c b/block/curl.c
35
diff --git a/qapi/qom.json b/qapi/qom.json
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/block/curl.c
37
--- a/qapi/qom.json
23
+++ b/block/curl.c
38
+++ b/qapi/qom.json
24
@@ -XXX,XX +XXX,XX @@ static void curl_multi_check_completion(BDRVCURLState *s)
39
@@ -XXX,XX +XXX,XX @@
25
}
40
# 0 means that the engine will use its default.
26
41
# (default: 0)
27
/* Called with s->mutex held. */
42
#
28
-static void curl_multi_do_locked(CURLSocket *ready_socket)
43
+# @thread-pool-min: minimum number of threads reserved in the thread pool
29
+static void curl_multi_do_locked(CURLSocket *socket)
44
+# (default:0)
45
+#
46
+# @thread-pool-max: maximum number of threads the thread pool can contain
47
+# (default:64)
48
+#
49
# Since: 7.1
50
##
51
{ 'struct': 'EventLoopBaseProperties',
52
- 'data': { '*aio-max-batch': 'int' } }
53
+ 'data': { '*aio-max-batch': 'int',
54
+ '*thread-pool-min': 'int',
55
+ '*thread-pool-max': 'int' } }
56
57
##
58
# @IothreadProperties:
59
diff --git a/include/block/aio.h b/include/block/aio.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/include/block/aio.h
62
+++ b/include/block/aio.h
63
@@ -XXX,XX +XXX,XX @@ struct AioContext {
64
QSLIST_HEAD(, Coroutine) scheduled_coroutines;
65
QEMUBH *co_schedule_bh;
66
67
+ int thread_pool_min;
68
+ int thread_pool_max;
69
/* Thread pool for performing work and receiving completion callbacks.
70
* Has its own locking.
71
*/
72
@@ -XXX,XX +XXX,XX @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
73
void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
74
Error **errp);
75
76
+/**
77
+ * aio_context_set_thread_pool_params:
78
+ * @ctx: the aio context
79
+ * @min: min number of threads to have readily available in the thread pool
80
+ * @min: max number of threads the thread pool can contain
81
+ */
82
+void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
83
+ int64_t max, Error **errp);
84
#endif
85
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/block/thread-pool.h
88
+++ b/include/block/thread-pool.h
89
@@ -XXX,XX +XXX,XX @@
90
91
#include "block/block.h"
92
93
+#define THREAD_POOL_MAX_THREADS_DEFAULT 64
94
+
95
typedef int ThreadPoolFunc(void *opaque);
96
97
typedef struct ThreadPool ThreadPool;
98
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
99
int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
100
ThreadPoolFunc *func, void *arg);
101
void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
102
+void thread_pool_update_params(ThreadPool *pool, struct AioContext *ctx);
103
104
#endif
105
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
106
index XXXXXXX..XXXXXXX 100644
107
--- a/include/sysemu/event-loop-base.h
108
+++ b/include/sysemu/event-loop-base.h
109
@@ -XXX,XX +XXX,XX @@ struct EventLoopBase {
110
111
/* AioContext AIO engine parameters */
112
int64_t aio_max_batch;
113
+
114
+ /* AioContext thread pool parameters */
115
+ int64_t thread_pool_min;
116
+ int64_t thread_pool_max;
117
};
118
#endif
119
diff --git a/event-loop-base.c b/event-loop-base.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/event-loop-base.c
122
+++ b/event-loop-base.c
123
@@ -XXX,XX +XXX,XX @@
124
#include "qemu/osdep.h"
125
#include "qom/object_interfaces.h"
126
#include "qapi/error.h"
127
+#include "block/thread-pool.h"
128
#include "sysemu/event-loop-base.h"
129
130
typedef struct {
131
@@ -XXX,XX +XXX,XX @@ typedef struct {
132
ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
133
} EventLoopBaseParamInfo;
134
135
+static void event_loop_base_instance_init(Object *obj)
136
+{
137
+ EventLoopBase *base = EVENT_LOOP_BASE(obj);
138
+
139
+ base->thread_pool_max = THREAD_POOL_MAX_THREADS_DEFAULT;
140
+}
141
+
142
static EventLoopBaseParamInfo aio_max_batch_info = {
143
"aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
144
};
145
+static EventLoopBaseParamInfo thread_pool_min_info = {
146
+ "thread-pool-min", offsetof(EventLoopBase, thread_pool_min),
147
+};
148
+static EventLoopBaseParamInfo thread_pool_max_info = {
149
+ "thread-pool-max", offsetof(EventLoopBase, thread_pool_max),
150
+};
151
152
static void event_loop_base_get_param(Object *obj, Visitor *v,
153
const char *name, void *opaque, Error **errp)
154
@@ -XXX,XX +XXX,XX @@ static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
155
event_loop_base_get_param,
156
event_loop_base_set_param,
157
NULL, &aio_max_batch_info);
158
+ object_class_property_add(klass, "thread-pool-min", "int",
159
+ event_loop_base_get_param,
160
+ event_loop_base_set_param,
161
+ NULL, &thread_pool_min_info);
162
+ object_class_property_add(klass, "thread-pool-max", "int",
163
+ event_loop_base_get_param,
164
+ event_loop_base_set_param,
165
+ NULL, &thread_pool_max_info);
166
}
167
168
static const TypeInfo event_loop_base_info = {
169
.name = TYPE_EVENT_LOOP_BASE,
170
.parent = TYPE_OBJECT,
171
.instance_size = sizeof(EventLoopBase),
172
+ .instance_init = event_loop_base_instance_init,
173
.class_size = sizeof(EventLoopBaseClass),
174
.class_init = event_loop_base_class_init,
175
.abstract = true,
176
diff --git a/iothread.c b/iothread.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/iothread.c
179
+++ b/iothread.c
180
@@ -XXX,XX +XXX,XX @@ static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
181
aio_context_set_aio_params(iothread->ctx,
182
iothread->parent_obj.aio_max_batch,
183
errp);
184
+
185
+ aio_context_set_thread_pool_params(iothread->ctx, base->thread_pool_min,
186
+ base->thread_pool_max, errp);
187
}
188
189
190
diff --git a/util/aio-posix.c b/util/aio-posix.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/util/aio-posix.c
193
+++ b/util/aio-posix.c
194
@@ -XXX,XX +XXX,XX @@
195
196
#include "qemu/osdep.h"
197
#include "block/block.h"
198
+#include "block/thread-pool.h"
199
#include "qemu/main-loop.h"
200
#include "qemu/rcu.h"
201
#include "qemu/rcu_queue.h"
202
diff --git a/util/async.c b/util/async.c
203
index XXXXXXX..XXXXXXX 100644
204
--- a/util/async.c
205
+++ b/util/async.c
206
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
207
208
ctx->aio_max_batch = 0;
209
210
+ ctx->thread_pool_min = 0;
211
+ ctx->thread_pool_max = THREAD_POOL_MAX_THREADS_DEFAULT;
212
+
213
return ctx;
214
fail:
215
g_source_destroy(&ctx->source);
216
@@ -XXX,XX +XXX,XX @@ void qemu_set_current_aio_context(AioContext *ctx)
217
assert(!get_my_aiocontext());
218
set_my_aiocontext(ctx);
219
}
220
+
221
+void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
222
+ int64_t max, Error **errp)
223
+{
224
+
225
+ if (min > max || !max || min > INT_MAX || max > INT_MAX) {
226
+ error_setg(errp, "bad thread-pool-min/thread-pool-max values");
227
+ return;
228
+ }
229
+
230
+ ctx->thread_pool_min = min;
231
+ ctx->thread_pool_max = max;
232
+
233
+ if (ctx->thread_pool) {
234
+ thread_pool_update_params(ctx->thread_pool, ctx);
235
+ }
236
+}
237
diff --git a/util/main-loop.c b/util/main-loop.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/util/main-loop.c
240
+++ b/util/main-loop.c
241
@@ -XXX,XX +XXX,XX @@
242
#include "sysemu/replay.h"
243
#include "qemu/main-loop.h"
244
#include "block/aio.h"
245
+#include "block/thread-pool.h"
246
#include "qemu/error-report.h"
247
#include "qemu/queue.h"
248
#include "qemu/compiler.h"
249
@@ -XXX,XX +XXX,XX @@ int qemu_init_main_loop(Error **errp)
250
251
static void main_loop_update_params(EventLoopBase *base, Error **errp)
30
{
252
{
31
- CURLSocket *socket, *next_socket;
253
+ ERRP_GUARD();
32
- CURLState *s = ready_socket->state;
254
+
33
+ BDRVCURLState *s = socket->state->s;
255
if (!qemu_aio_context) {
34
int running;
256
error_setg(errp, "qemu aio context not ready");
35
int r;
36
37
- if (!s->s->multi) {
38
+ if (!s->multi) {
39
return;
257
return;
40
}
258
}
41
259
42
- /* Need to use _SAFE because curl_multi_socket_action() may trigger
260
aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
43
- * curl_sock_cb() which might modify this list */
261
+ if (*errp) {
44
- QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) {
262
+ return;
45
- do {
263
+ }
46
- r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running);
264
+
47
- } while (r == CURLM_CALL_MULTI_PERFORM);
265
+ aio_context_set_thread_pool_params(qemu_aio_context, base->thread_pool_min,
48
- }
266
+ base->thread_pool_max, errp);
49
+ do {
267
}
50
+ r = curl_multi_socket_action(s->multi, socket->fd, 0, &running);
268
51
+ } while (r == CURLM_CALL_MULTI_PERFORM);
269
MainLoop *mloop;
52
}
270
diff --git a/util/thread-pool.c b/util/thread-pool.c
53
271
index XXXXXXX..XXXXXXX 100644
54
static void curl_multi_do(void *arg)
272
--- a/util/thread-pool.c
273
+++ b/util/thread-pool.c
274
@@ -XXX,XX +XXX,XX @@ struct ThreadPool {
275
QemuMutex lock;
276
QemuCond worker_stopped;
277
QemuSemaphore sem;
278
- int max_threads;
279
QEMUBH *new_thread_bh;
280
281
/* The following variables are only accessed from one AioContext. */
282
@@ -XXX,XX +XXX,XX @@ struct ThreadPool {
283
int new_threads; /* backlog of threads we need to create */
284
int pending_threads; /* threads created but not running yet */
285
bool stopping;
286
+ int min_threads;
287
+ int max_threads;
288
};
289
290
+static inline bool back_to_sleep(ThreadPool *pool, int ret)
291
+{
292
+ /*
293
+ * The semaphore timed out, we should exit the loop except when:
294
+ * - There is work to do, we raced with the signal.
295
+ * - The max threads threshold just changed, we raced with the signal.
296
+ * - The thread pool forces a minimum number of readily available threads.
297
+ */
298
+ if (ret == -1 && (!QTAILQ_EMPTY(&pool->request_list) ||
299
+ pool->cur_threads > pool->max_threads ||
300
+ pool->cur_threads <= pool->min_threads)) {
301
+ return true;
302
+ }
303
+
304
+ return false;
305
+}
306
+
307
static void *worker_thread(void *opaque)
308
{
309
ThreadPool *pool = opaque;
310
@@ -XXX,XX +XXX,XX @@ static void *worker_thread(void *opaque)
311
ret = qemu_sem_timedwait(&pool->sem, 10000);
312
qemu_mutex_lock(&pool->lock);
313
pool->idle_threads--;
314
- } while (ret == -1 && !QTAILQ_EMPTY(&pool->request_list));
315
- if (ret == -1 || pool->stopping) {
316
+ } while (back_to_sleep(pool, ret));
317
+ if (ret == -1 || pool->stopping ||
318
+ pool->cur_threads > pool->max_threads) {
319
break;
320
}
321
322
@@ -XXX,XX +XXX,XX @@ void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg)
323
thread_pool_submit_aio(pool, func, arg, NULL, NULL);
324
}
325
326
+void thread_pool_update_params(ThreadPool *pool, AioContext *ctx)
327
+{
328
+ qemu_mutex_lock(&pool->lock);
329
+
330
+ pool->min_threads = ctx->thread_pool_min;
331
+ pool->max_threads = ctx->thread_pool_max;
332
+
333
+ /*
334
+ * We either have to:
335
+ * - Increase the number available of threads until over the min_threads
336
+ * threshold.
337
+ * - Decrease the number of available threads until under the max_threads
338
+ * threshold.
339
+ * - Do nothing. The current number of threads fall in between the min and
340
+ * max thresholds. We'll let the pool manage itself.
341
+ */
342
+ for (int i = pool->cur_threads; i < pool->min_threads; i++) {
343
+ spawn_thread(pool);
344
+ }
345
+
346
+ for (int i = pool->cur_threads; i > pool->max_threads; i--) {
347
+ qemu_sem_post(&pool->sem);
348
+ }
349
+
350
+ qemu_mutex_unlock(&pool->lock);
351
+}
352
+
353
static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
354
{
355
if (!ctx) {
356
@@ -XXX,XX +XXX,XX @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
357
qemu_mutex_init(&pool->lock);
358
qemu_cond_init(&pool->worker_stopped);
359
qemu_sem_init(&pool->sem, 0);
360
- pool->max_threads = 64;
361
pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool);
362
363
QLIST_INIT(&pool->head);
364
QTAILQ_INIT(&pool->request_list);
365
+
366
+ thread_pool_update_params(pool, ctx);
367
}
368
369
ThreadPool *thread_pool_new(AioContext *ctx)
55
--
370
--
56
2.21.0
371
2.35.1
57
58
diff view generated by jsdifflib
Deleted patch
1
Background: As of cURL 7.59.0, it verifies that several functions are
2
not called from within a callback. Among these functions is
3
curl_multi_add_handle().
4
1
5
curl_read_cb() is a callback from cURL and not a coroutine. Waking up
6
acb->co will lead to entering it then and there, which means the current
7
request will settle and the caller (if it runs in the same coroutine)
8
may then issue the next request. In such a case, we will enter
9
curl_setup_preadv() effectively from within curl_read_cb().
10
11
Calling curl_multi_add_handle() will then fail and the new request will
12
not be processed.
13
14
Fix this by not letting curl_read_cb() wake up acb->co. Instead, leave
15
the whole business of settling the AIOCB objects to
16
curl_multi_check_completion() (which is called from our timer callback
17
and our FD handler, so not from any cURL callbacks).
18
19
Reported-by: Natalie Gavrielov <ngavrilo@redhat.com>
20
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193
21
Cc: qemu-stable@nongnu.org
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
Message-id: 20190910124136.10565-7-mreitz@redhat.com
24
Reviewed-by: John Snow <jsnow@redhat.com>
25
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
block/curl.c | 69 ++++++++++++++++++++++------------------------------
29
1 file changed, 29 insertions(+), 40 deletions(-)
30
31
diff --git a/block/curl.c b/block/curl.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/curl.c
34
+++ b/block/curl.c
35
@@ -XXX,XX +XXX,XX @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
36
{
37
CURLState *s = ((CURLState*)opaque);
38
size_t realsize = size * nmemb;
39
- int i;
40
41
trace_curl_read_cb(realsize);
42
43
@@ -XXX,XX +XXX,XX @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
44
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
45
s->buf_off += realsize;
46
47
- for(i=0; i<CURL_NUM_ACB; i++) {
48
- CURLAIOCB *acb = s->acb[i];
49
-
50
- if (!acb)
51
- continue;
52
-
53
- if ((s->buf_off >= acb->end)) {
54
- size_t request_length = acb->bytes;
55
-
56
- qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
57
- acb->end - acb->start);
58
-
59
- if (acb->end - acb->start < request_length) {
60
- size_t offset = acb->end - acb->start;
61
- qemu_iovec_memset(acb->qiov, offset, 0,
62
- request_length - offset);
63
- }
64
-
65
- acb->ret = 0;
66
- s->acb[i] = NULL;
67
- qemu_mutex_unlock(&s->s->mutex);
68
- aio_co_wake(acb->co);
69
- qemu_mutex_lock(&s->s->mutex);
70
- }
71
- }
72
-
73
read_end:
74
/* curl will error out if we do not return this value */
75
return size * nmemb;
76
@@ -XXX,XX +XXX,XX @@ static void curl_multi_check_completion(BDRVCURLState *s)
77
break;
78
79
if (msg->msg == CURLMSG_DONE) {
80
+ int i;
81
CURLState *state = NULL;
82
+ bool error = msg->data.result != CURLE_OK;
83
+
84
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
85
(char **)&state);
86
87
- /* ACBs for successful messages get completed in curl_read_cb */
88
- if (msg->data.result != CURLE_OK) {
89
- int i;
90
+ if (error) {
91
static int errcount = 100;
92
93
/* Don't lose the original error message from curl, since
94
@@ -XXX,XX +XXX,XX @@ static void curl_multi_check_completion(BDRVCURLState *s)
95
error_report("curl: further errors suppressed");
96
}
97
}
98
+ }
99
100
- for (i = 0; i < CURL_NUM_ACB; i++) {
101
- CURLAIOCB *acb = state->acb[i];
102
+ for (i = 0; i < CURL_NUM_ACB; i++) {
103
+ CURLAIOCB *acb = state->acb[i];
104
105
- if (acb == NULL) {
106
- continue;
107
- }
108
+ if (acb == NULL) {
109
+ continue;
110
+ }
111
+
112
+ if (!error) {
113
+ /* Assert that we have read all data */
114
+ assert(state->buf_off >= acb->end);
115
+
116
+ qemu_iovec_from_buf(acb->qiov, 0,
117
+ state->orig_buf + acb->start,
118
+ acb->end - acb->start);
119
120
- acb->ret = -EIO;
121
- state->acb[i] = NULL;
122
- qemu_mutex_unlock(&s->mutex);
123
- aio_co_wake(acb->co);
124
- qemu_mutex_lock(&s->mutex);
125
+ if (acb->end - acb->start < acb->bytes) {
126
+ size_t offset = acb->end - acb->start;
127
+ qemu_iovec_memset(acb->qiov, offset, 0,
128
+ acb->bytes - offset);
129
+ }
130
}
131
+
132
+ acb->ret = error ? -EIO : 0;
133
+ state->acb[i] = NULL;
134
+ qemu_mutex_unlock(&s->mutex);
135
+ aio_co_wake(acb->co);
136
+ qemu_mutex_lock(&s->mutex);
137
}
138
139
curl_clean_state(state);
140
--
141
2.21.0
142
143
diff view generated by jsdifflib
Deleted patch
1
If we had done that all along, debugging would have been much simpler.
2
(Also, I/O errors are better than hangs.)
3
1
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Message-id: 20190910124136.10565-8-mreitz@redhat.com
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/curl.c | 8 +++++++-
11
1 file changed, 7 insertions(+), 1 deletion(-)
12
13
diff --git a/block/curl.c b/block/curl.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/curl.c
16
+++ b/block/curl.c
17
@@ -XXX,XX +XXX,XX @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
18
trace_curl_setup_preadv(acb->bytes, start, state->range);
19
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
20
21
- curl_multi_add_handle(s->multi, state->curl);
22
+ if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) {
23
+ state->acb[0] = NULL;
24
+ acb->ret = -EIO;
25
+
26
+ curl_clean_state(state);
27
+ goto out;
28
+ }
29
30
/* Tell curl it needs to kick things off */
31
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
32
--
33
2.21.0
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Sergio Lopez <slp@redhat.com>
2
1
3
block_job_remove_all_bdrv() iterates through job->nodes, calling
4
bdrv_root_unref_child() for each entry. The call to the latter may
5
reach child_job_[can_]set_aio_ctx(), which will also attempt to
6
traverse job->nodes, potentially finding entries that where freed
7
on previous iterations.
8
9
To avoid this situation, update job->nodes head on each iteration to
10
ensure that already freed entries are no longer linked to the list.
11
12
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631
13
Signed-off-by: Sergio Lopez <slp@redhat.com>
14
Cc: qemu-stable@nongnu.org
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-id: 20190911100316.32282-1-mreitz@redhat.com
17
Reviewed-by: Sergio Lopez <slp@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
blockjob.c | 17 +++++++++++++----
21
1 file changed, 13 insertions(+), 4 deletions(-)
22
23
diff --git a/blockjob.c b/blockjob.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/blockjob.c
26
+++ b/blockjob.c
27
@@ -XXX,XX +XXX,XX @@ static const BdrvChildRole child_job = {
28
29
void block_job_remove_all_bdrv(BlockJob *job)
30
{
31
- GSList *l;
32
- for (l = job->nodes; l; l = l->next) {
33
+ /*
34
+ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(),
35
+ * which will also traverse job->nodes, so consume the list one by
36
+ * one to make sure that such a concurrent access does not attempt
37
+ * to process an already freed BdrvChild.
38
+ */
39
+ while (job->nodes) {
40
+ GSList *l = job->nodes;
41
BdrvChild *c = l->data;
42
+
43
+ job->nodes = l->next;
44
+
45
bdrv_op_unblock_all(c->bs, job->blocker);
46
bdrv_root_unref_child(c);
47
+
48
+ g_slist_free_1(l);
49
}
50
- g_slist_free(job->nodes);
51
- job->nodes = NULL;
52
}
53
54
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs)
55
--
56
2.21.0
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
1
3
This fixes subtle corruption introduced by luks threaded encryption
4
in commit 8ac0f15f335
5
6
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922
7
8
The corruption happens when we do a write that
9
* writes to two or more unallocated clusters at once
10
* doesn't fully cover the first sector
11
* doesn't fully cover the last sector
12
* uses luks encryption
13
14
In this case, when allocating the new clusters we COW both areas
15
prior to the write and after the write, and we encrypt them.
16
17
The above mentioned commit accidentally made it so we encrypt the
18
second COW area using the physical cluster offset of the first area.
19
20
The problem is that offset_in_cluster in do_perform_cow_encrypt
21
can be larger that the cluster size, thus cluster_offset
22
will no longer point to the start of the cluster at which encrypted
23
area starts.
24
25
Next patch in this series will refactor the code to avoid all these
26
assumptions.
27
28
In the bugreport that was triggered by rebasing a luks image to new,
29
zero filled base, which lot of such writes, and causes some files
30
with zero areas to contain garbage there instead.
31
But as described above it can happen elsewhere as well
32
33
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
34
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
35
Message-id: 20190915203655.21638-2-mlevitsk@redhat.com
36
Reviewed-by: Max Reitz <mreitz@redhat.com>
37
Signed-off-by: Max Reitz <mreitz@redhat.com>
38
---
39
block/qcow2-cluster.c | 7 ++++---
40
1 file changed, 4 insertions(+), 3 deletions(-)
41
42
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/qcow2-cluster.c
45
+++ b/block/qcow2-cluster.c
46
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
47
assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
48
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
49
assert(s->crypto);
50
- if (qcow2_co_encrypt(bs, cluster_offset,
51
- src_cluster_offset + offset_in_cluster,
52
- buffer, bytes) < 0) {
53
+ if (qcow2_co_encrypt(bs,
54
+ start_of_cluster(s, cluster_offset + offset_in_cluster),
55
+ src_cluster_offset + offset_in_cluster,
56
+ buffer, bytes) < 0) {
57
return false;
58
}
59
}
60
--
61
2.21.0
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
1
3
* Change the qcow2_co_{encrypt|decrypt} to just receive full host and
4
guest offsets and use this function directly instead of calling
5
do_perform_cow_encrypt (which is removed by that patch).
6
7
* Adjust qcow2_co_encdec to take full host and guest offsets as well.
8
9
* Document the qcow2_co_{encrypt|decrypt} arguments
10
to prevent the bug fixed in former commit from hopefully
11
happening again.
12
13
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
14
Message-id: 20190915203655.21638-3-mlevitsk@redhat.com
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
[mreitz: Let perform_cow() return the error value returned by
17
qcow2_co_encrypt(), as proposed by Vladimir]
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block/qcow2.h | 8 +++---
21
block/qcow2-cluster.c | 41 +++++++++-------------------
22
block/qcow2-threads.c | 63 +++++++++++++++++++++++++++++++++----------
23
block/qcow2.c | 5 ++--
24
4 files changed, 69 insertions(+), 48 deletions(-)
25
26
diff --git a/block/qcow2.h b/block/qcow2.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/qcow2.h
29
+++ b/block/qcow2.h
30
@@ -XXX,XX +XXX,XX @@ ssize_t coroutine_fn
31
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
32
const void *src, size_t src_size);
33
int coroutine_fn
34
-qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
35
- uint64_t offset, void *buf, size_t len);
36
+qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
37
+ uint64_t guest_offset, void *buf, size_t len);
38
int coroutine_fn
39
-qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
40
- uint64_t offset, void *buf, size_t len);
41
+qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
42
+ uint64_t guest_offset, void *buf, size_t len);
43
44
#endif
45
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2-cluster.c
48
+++ b/block/qcow2-cluster.c
49
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
50
return 0;
51
}
52
53
-static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
54
- uint64_t src_cluster_offset,
55
- uint64_t cluster_offset,
56
- unsigned offset_in_cluster,
57
- uint8_t *buffer,
58
- unsigned bytes)
59
-{
60
- if (bytes && bs->encrypted) {
61
- BDRVQcow2State *s = bs->opaque;
62
- assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
63
- assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
64
- assert(s->crypto);
65
- if (qcow2_co_encrypt(bs,
66
- start_of_cluster(s, cluster_offset + offset_in_cluster),
67
- src_cluster_offset + offset_in_cluster,
68
- buffer, bytes) < 0) {
69
- return false;
70
- }
71
- }
72
- return true;
73
-}
74
-
75
static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
76
uint64_t cluster_offset,
77
unsigned offset_in_cluster,
78
@@ -XXX,XX +XXX,XX @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
79
80
/* Encrypt the data if necessary before writing it */
81
if (bs->encrypted) {
82
- if (!do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
83
- start->offset, start_buffer,
84
- start->nb_bytes) ||
85
- !do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
86
- end->offset, end_buffer, end->nb_bytes)) {
87
- ret = -EIO;
88
+ ret = qcow2_co_encrypt(bs,
89
+ m->alloc_offset + start->offset,
90
+ m->offset + start->offset,
91
+ start_buffer, start->nb_bytes);
92
+ if (ret < 0) {
93
+ goto fail;
94
+ }
95
+
96
+ ret = qcow2_co_encrypt(bs,
97
+ m->alloc_offset + end->offset,
98
+ m->offset + end->offset,
99
+ end_buffer, end->nb_bytes);
100
+ if (ret < 0) {
101
goto fail;
102
}
103
}
104
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/block/qcow2-threads.c
107
+++ b/block/qcow2-threads.c
108
@@ -XXX,XX +XXX,XX @@ static int qcow2_encdec_pool_func(void *opaque)
109
}
110
111
static int coroutine_fn
112
-qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset,
113
- uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func)
114
+qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset,
115
+ uint64_t guest_offset, void *buf, size_t len,
116
+ Qcow2EncDecFunc func)
117
{
118
BDRVQcow2State *s = bs->opaque;
119
Qcow2EncDecData arg = {
120
.block = s->crypto,
121
- .offset = s->crypt_physical_offset ?
122
- file_cluster_offset + offset_into_cluster(s, offset) :
123
- offset,
124
+ .offset = s->crypt_physical_offset ? host_offset : guest_offset,
125
.buf = buf,
126
.len = len,
127
.func = func,
128
};
129
130
- return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
131
+ assert(QEMU_IS_ALIGNED(guest_offset, BDRV_SECTOR_SIZE));
132
+ assert(QEMU_IS_ALIGNED(host_offset, BDRV_SECTOR_SIZE));
133
+ assert(QEMU_IS_ALIGNED(len, BDRV_SECTOR_SIZE));
134
+ assert(s->crypto);
135
+
136
+ return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
137
}
138
139
+/*
140
+ * qcow2_co_encrypt()
141
+ *
142
+ * Encrypts one or more contiguous aligned sectors
143
+ *
144
+ * @host_offset - underlying storage offset of the first sector of the
145
+ * data to be encrypted
146
+ *
147
+ * @guest_offset - guest (virtual) offset of the first sector of the
148
+ * data to be encrypted
149
+ *
150
+ * @buf - buffer with the data to encrypt, that after encryption
151
+ * will be written to the underlying storage device at
152
+ * @host_offset
153
+ *
154
+ * @len - length of the buffer (must be a BDRV_SECTOR_SIZE multiple)
155
+ *
156
+ * Depending on the encryption method, @host_offset and/or @guest_offset
157
+ * may be used for generating the initialization vector for
158
+ * encryption.
159
+ *
160
+ * Note that while the whole range must be aligned on sectors, it
161
+ * does not have to be aligned on clusters and can also cross cluster
162
+ * boundaries
163
+ */
164
int coroutine_fn
165
-qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
166
- uint64_t offset, void *buf, size_t len)
167
+qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
168
+ uint64_t guest_offset, void *buf, size_t len)
169
{
170
- return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
171
- qcrypto_block_encrypt);
172
+ return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
173
+ qcrypto_block_encrypt);
174
}
175
176
+/*
177
+ * qcow2_co_decrypt()
178
+ *
179
+ * Decrypts one or more contiguous aligned sectors
180
+ * Similar to qcow2_co_encrypt
181
+ */
182
int coroutine_fn
183
-qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
184
- uint64_t offset, void *buf, size_t len)
185
+qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
186
+ uint64_t guest_offset, void *buf, size_t len)
187
{
188
- return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
189
- qcrypto_block_decrypt);
190
+ return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
191
+ qcrypto_block_decrypt);
192
}
193
diff --git a/block/qcow2.c b/block/qcow2.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/block/qcow2.c
196
+++ b/block/qcow2.c
197
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
198
199
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
200
assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE));
201
- if (qcow2_co_decrypt(bs, cluster_offset, offset,
202
+ if (qcow2_co_decrypt(bs, cluster_offset + offset_in_cluster,
203
+ offset,
204
cluster_data, cur_bytes) < 0) {
205
ret = -EIO;
206
goto fail;
207
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
208
qemu_iovec_to_buf(qiov, qiov_offset + bytes_done,
209
cluster_data, cur_bytes);
210
211
- if (qcow2_co_encrypt(bs, cluster_offset, offset,
212
+ if (qcow2_co_encrypt(bs, cluster_offset + offset_in_cluster, offset,
213
cluster_data, cur_bytes) < 0) {
214
ret = -EIO;
215
goto out_unlocked;
216
--
217
2.21.0
218
219
diff view generated by jsdifflib