1
The following changes since commit 96662996eda78c48aadddd4e76d8615c7eb72d80:
1
The following changes since commit c6a5fc2ac76c5ab709896ee1b0edd33685a67ed1:
2
2
3
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20210513a' into staging (2021-05-14 12:03:47 +0100)
3
decodetree: Add --output-null for meson testing (2023-05-31 19:56:42 -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-2021-05-14
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to c61ebf362d0abf288ce266845519d5a550a1d89f:
9
for you to fetch changes up to 98b126f5e3228a346c774e569e26689943b401dd:
10
10
11
write-threshold: deal with includes (2021-05-14 16:14:10 +0200)
11
qapi: add '@fdset' feature for BlockdevOptionsVirtioBlkVhostVdpa (2023-06-01 11:08:21 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- drop block/io write notifiers
15
16
- qemu-iotests enhancements to make debugging easier
16
- Stefano Garzarella's blkio block driver 'fd' parameter
17
- rbd parsing fix
17
- My thread-local blk_io_plug() series
18
- HMP qemu-io fix (for iothreads)
19
- mirror job cancel relaxation (do not cancel in-flight requests when a
20
READY mirror job is canceled with force=false)
21
- document qcow2's data_file and data_file_raw features
22
- fix iotest 297 for pylint 2.8
23
- block/copy-on-read refactoring
24
18
25
----------------------------------------------------------------
19
----------------------------------------------------------------
26
Connor Kuehl (3):
27
iotests/231: Update expected deprecation message
28
block/rbd: Add an escape-aware strchr helper
29
Document qemu-img options data_file and data_file_raw
30
20
31
Emanuele Giuseppe Esposito (1):
21
Stefan Hajnoczi (6):
32
qemu-iotests: fix pylint 2.8 consider-using-with error
22
block: add blk_io_plug_call() API
23
block/nvme: convert to blk_io_plug_call() API
24
block/blkio: convert to blk_io_plug_call() API
25
block/io_uring: convert to blk_io_plug_call() API
26
block/linux-aio: convert to blk_io_plug_call() API
27
block: remove bdrv_co_io_plug() API
33
28
34
Paolo Bonzini (5):
29
Stefano Garzarella (2):
35
qemu-iotests: do not buffer the test output
30
block/blkio: use qemu_open() to support fd passing for virtio-blk
36
qemu-iotests: allow passing unittest.main arguments to the test
31
qapi: add '@fdset' feature for BlockdevOptionsVirtioBlkVhostVdpa
37
scripts
38
qemu-iotests: move command line and environment handling from
39
TestRunner to TestEnv
40
qemu-iotests: let "check" spawn an arbitrary test command
41
qemu-iotests: fix case of SOCK_DIR already in the environment
42
32
43
Vladimir Sementsov-Ogievskiy (10):
33
MAINTAINERS | 1 +
44
monitor: hmp_qemu_io: acquire aio contex, fix crash
34
qapi/block-core.json | 6 ++
45
mirror: stop cancelling in-flight requests on non-force cancel in
35
meson.build | 4 +
46
READY
36
include/block/block-io.h | 3 -
47
block/copy-on-read: use bdrv_drop_filter() and drop s->active
37
include/block/block_int-common.h | 11 ---
48
block/write-threshold: don't use write notifiers
38
include/block/raw-aio.h | 14 ---
49
block: drop write notifiers
39
include/sysemu/block-backend-io.h | 13 +--
50
test-write-threshold: rewrite test_threshold_(not_)trigger tests
40
block/blkio.c | 96 ++++++++++++------
51
block/write-threshold: drop extra APIs
41
block/block-backend.c | 22 -----
52
test-write-threshold: drop extra tests
42
block/file-posix.c | 38 -------
53
test-write-threshold: drop extra TestStruct structure
43
block/io.c | 37 -------
54
write-threshold: deal with includes
44
block/io_uring.c | 44 ++++-----
55
45
block/linux-aio.c | 41 +++-----
56
docs/tools/qemu-img.rst | 31 +++++++
46
block/nvme.c | 44 +++------
57
include/block/block_int.h | 15 +---
47
block/plug.c | 159 ++++++++++++++++++++++++++++++
58
include/block/write-threshold.h | 27 ++----
48
hw/block/dataplane/xen-block.c | 8 +-
59
include/qemu/job.h | 2 +-
49
hw/block/virtio-blk.c | 4 +-
60
block.c | 1 -
50
hw/scsi/virtio-scsi.c | 6 +-
61
block/backup.c | 2 +-
51
block/meson.build | 1 +
62
block/copy-on-read.c | 33 +------
52
block/trace-events | 6 +-
63
block/io.c | 11 +--
53
20 files changed, 293 insertions(+), 265 deletions(-)
64
block/mirror.c | 6 +-
54
create mode 100644 block/plug.c
65
block/monitor/block-hmp-cmds.c | 31 ++++---
66
block/rbd.c | 32 ++++---
67
block/write-threshold.c | 91 ++++---------------
68
job.c | 2 +-
69
qemu-io-cmds.c | 8 +-
70
qemu-io.c | 17 +++-
71
tests/unit/test-write-threshold.c | 90 ++-----------------
72
tests/qemu-iotests/231 | 4 +
73
tests/qemu-iotests/231.out | 7 +-
74
tests/qemu-iotests/240.out | 8 +-
75
tests/qemu-iotests/245.out | 8 +-
76
tests/qemu-iotests/264 | 2 +-
77
tests/qemu-iotests/295.out | 6 +-
78
tests/qemu-iotests/296.out | 8 +-
79
tests/qemu-iotests/check | 19 +++-
80
tests/qemu-iotests/iotests.py | 145 +++++++++++++++++-------------
81
tests/qemu-iotests/pylintrc | 3 +
82
tests/qemu-iotests/testenv.py | 22 ++++-
83
tests/qemu-iotests/testrunner.py | 37 +++-----
84
28 files changed, 289 insertions(+), 379 deletions(-)
85
55
86
--
56
--
87
2.31.1
57
2.40.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Connor Kuehl <ckuehl@redhat.com>
2
1
3
The deprecation message in the expected output has technically been
4
wrong since the wrong version of a patch was applied to it. Because of
5
this, the test fails. Correct the expected output so that it passes.
6
7
Signed-off-by: Connor Kuehl <ckuehl@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-Id: <20210421212343.85524-2-ckuehl@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/231.out | 4 +---
14
1 file changed, 1 insertion(+), 3 deletions(-)
15
16
diff --git a/tests/qemu-iotests/231.out b/tests/qemu-iotests/231.out
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/231.out
19
+++ b/tests/qemu-iotests/231.out
20
@@ -XXX,XX +XXX,XX @@
21
QA output created by 231
22
-qemu-img: RBD options encoded in the filename as keyvalue pairs is deprecated. Future versions may cease to parse these options in the future.
23
+qemu-img: warning: RBD options encoded in the filename as keyvalue pairs is deprecated
24
unable to get monitor info from DNS SRV with service name: ceph-mon
25
-no monitors specified to connect to.
26
qemu-img: Could not open 'json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=BOGUS_CONF'}': error connecting: No such file or directory
27
unable to get monitor info from DNS SRV with service name: ceph-mon
28
-no monitors specified to connect to.
29
qemu-img: Could not open 'json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'BOGUS_CONF'}': error connecting: No such file or directory
30
*** done
31
--
32
2.31.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Connor Kuehl <ckuehl@redhat.com>
2
1
3
Sometimes the parser needs to further split a token it has collected
4
from the token input stream. Right now, it does a cursory check to see
5
if the relevant characters appear in the token to determine if it should
6
break it down further.
7
8
However, qemu_rbd_next_tok() will escape characters as it removes tokens
9
from the token stream and plain strchr() won't. This can make the
10
initial strchr() check slightly misleading since it implies
11
qemu_rbd_next_tok() will find the token and split on it, except the
12
reality is that qemu_rbd_next_tok() will pass over it if it is escaped.
13
14
Use a custom strchr to avoid mixing escaped and unescaped string
15
operations. Furthermore, this code is identical to how
16
qemu_rbd_next_tok() seeks its next token, so incorporate this custom
17
strchr into the body of that function to reduce duplication.
18
19
Reported-by: Han Han <hhan@redhat.com>
20
Fixes: https://bugzilla.redhat.com/1873913
21
Signed-off-by: Connor Kuehl <ckuehl@redhat.com>
22
Message-Id: <20210421212343.85524-3-ckuehl@redhat.com>
23
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
block/rbd.c | 32 +++++++++++++++++++++-----------
27
tests/qemu-iotests/231 | 4 ++++
28
tests/qemu-iotests/231.out | 3 +++
29
3 files changed, 28 insertions(+), 11 deletions(-)
30
31
diff --git a/block/rbd.c b/block/rbd.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/rbd.c
34
+++ b/block/rbd.c
35
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
36
const char *keypairs, const char *secretid,
37
Error **errp);
38
39
+static char *qemu_rbd_strchr(char *src, char delim)
40
+{
41
+ char *p;
42
+
43
+ for (p = src; *p; ++p) {
44
+ if (*p == delim) {
45
+ return p;
46
+ }
47
+ if (*p == '\\' && p[1] != '\0') {
48
+ ++p;
49
+ }
50
+ }
51
+
52
+ return NULL;
53
+}
54
+
55
+
56
static char *qemu_rbd_next_tok(char *src, char delim, char **p)
57
{
58
char *end;
59
60
*p = NULL;
61
62
- for (end = src; *end; ++end) {
63
- if (*end == delim) {
64
- break;
65
- }
66
- if (*end == '\\' && end[1] != '\0') {
67
- end++;
68
- }
69
- }
70
- if (*end == delim) {
71
+ end = qemu_rbd_strchr(src, delim);
72
+ if (end) {
73
*p = end + 1;
74
*end = '\0';
75
}
76
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
77
qemu_rbd_unescape(found_str);
78
qdict_put_str(options, "pool", found_str);
79
80
- if (strchr(p, '@')) {
81
+ if (qemu_rbd_strchr(p, '@')) {
82
image_name = qemu_rbd_next_tok(p, '@', &p);
83
84
found_str = qemu_rbd_next_tok(p, ':', &p);
85
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
86
image_name = qemu_rbd_next_tok(p, ':', &p);
87
}
88
/* Check for namespace in the image_name */
89
- if (strchr(image_name, '/')) {
90
+ if (qemu_rbd_strchr(image_name, '/')) {
91
found_str = qemu_rbd_next_tok(image_name, '/', &image_name);
92
qemu_rbd_unescape(found_str);
93
qdict_put_str(options, "namespace", found_str);
94
diff --git a/tests/qemu-iotests/231 b/tests/qemu-iotests/231
95
index XXXXXXX..XXXXXXX 100755
96
--- a/tests/qemu-iotests/231
97
+++ b/tests/qemu-iotests/231
98
@@ -XXX,XX +XXX,XX @@ _filter_conf()
99
$QEMU_IMG info "json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=${BOGUS_CONF}'}" 2>&1 | _filter_conf
100
$QEMU_IMG info "json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'${BOGUS_CONF}'}" 2>&1 | _filter_conf
101
102
+# Regression test: the qemu-img invocation is expected to fail, but it should
103
+# not seg fault the parser.
104
+$QEMU_IMG create "rbd:rbd/aa\/bb:conf=${BOGUS_CONF}" 1M 2>&1 | _filter_conf
105
+
106
# success, all done
107
echo "*** done"
108
rm -f $seq.full
109
diff --git a/tests/qemu-iotests/231.out b/tests/qemu-iotests/231.out
110
index XXXXXXX..XXXXXXX 100644
111
--- a/tests/qemu-iotests/231.out
112
+++ b/tests/qemu-iotests/231.out
113
@@ -XXX,XX +XXX,XX @@ unable to get monitor info from DNS SRV with service name: ceph-mon
114
qemu-img: Could not open 'json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=BOGUS_CONF'}': error connecting: No such file or directory
115
unable to get monitor info from DNS SRV with service name: ceph-mon
116
qemu-img: Could not open 'json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'BOGUS_CONF'}': error connecting: No such file or directory
117
+Formatting 'rbd:rbd/aa\/bb:conf=BOGUS_CONF', fmt=raw size=1048576
118
+unable to get monitor info from DNS SRV with service name: ceph-mon
119
+qemu-img: rbd:rbd/aa\/bb:conf=BOGUS_CONF: error connecting: No such file or directory
120
*** done
121
--
122
2.31.1
123
124
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Introduce a new API for thread-local blk_io_plug() that does not
2
2
traverse the block graph. The goal is to make blk_io_plug() multi-queue
3
bdrv_write_threshold_exceeded() is unused.
3
friendly.
4
4
5
bdrv_write_threshold_is_set() is used only to double check the value of
5
Instead of having block drivers track whether or not we're in a plugged
6
bs->write_threshold_offset in tests. No real sense in it (both tests do
6
section, provide an API that allows them to defer a function call until
7
check real value with help of bdrv_write_threshold_get())
7
we're unplugged: blk_io_plug_call(fn, opaque). If blk_io_plug_call() is
8
8
called multiple times with the same fn/opaque pair, then fn() is only
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
called once at the end of the function - resulting in batching.
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
11
Message-Id: <20210506090621.11848-5-vsementsov@virtuozzo.com>
11
This patch introduces the API and changes blk_io_plug()/blk_io_unplug().
12
blk_io_plug()/blk_io_unplug() no longer require a BlockBackend argument
13
because the plug state is now thread-local.
14
15
Later patches convert block drivers to blk_io_plug_call() and then we
16
can finally remove .bdrv_co_io_plug() once all block drivers have been
17
converted.
18
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
14
[mreitz: Adjusted commit message as per Eric's suggestion]
22
Acked-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
Message-id: 20230530180959.1108766-2-stefanha@redhat.com
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
25
---
17
include/block/write-threshold.h | 24 ------------------------
26
MAINTAINERS | 1 +
18
block/write-threshold.c | 19 -------------------
27
include/sysemu/block-backend-io.h | 13 +--
19
tests/unit/test-write-threshold.c | 4 ----
28
block/block-backend.c | 22 -----
20
3 files changed, 47 deletions(-)
29
block/plug.c | 159 ++++++++++++++++++++++++++++++
21
30
hw/block/dataplane/xen-block.c | 8 +-
22
diff --git a/include/block/write-threshold.h b/include/block/write-threshold.h
31
hw/block/virtio-blk.c | 4 +-
23
index XXXXXXX..XXXXXXX 100644
32
hw/scsi/virtio-scsi.c | 6 +-
24
--- a/include/block/write-threshold.h
33
block/meson.build | 1 +
25
+++ b/include/block/write-threshold.h
34
8 files changed, 173 insertions(+), 41 deletions(-)
26
@@ -XXX,XX +XXX,XX @@ void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes);
35
create mode 100644 block/plug.c
27
*/
36
28
uint64_t bdrv_write_threshold_get(const BlockDriverState *bs);
37
diff --git a/MAINTAINERS b/MAINTAINERS
38
index XXXXXXX..XXXXXXX 100644
39
--- a/MAINTAINERS
40
+++ b/MAINTAINERS
41
@@ -XXX,XX +XXX,XX @@ F: util/aio-*.c
42
F: util/aio-*.h
43
F: util/fdmon-*.c
44
F: block/io.c
45
+F: block/plug.c
46
F: migration/block*
47
F: include/block/aio.h
48
F: include/block/aio-wait.h
49
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/include/sysemu/block-backend-io.h
52
+++ b/include/sysemu/block-backend-io.h
53
@@ -XXX,XX +XXX,XX @@ void blk_iostatus_set_err(BlockBackend *blk, int error);
54
int blk_get_max_iov(BlockBackend *blk);
55
int blk_get_max_hw_iov(BlockBackend *blk);
29
56
30
-/*
57
-/*
31
- * bdrv_write_threshold_is_set
58
- * blk_io_plug/unplug are thread-local operations. This means that multiple
32
- *
59
- * IOThreads can simultaneously call plug/unplug, but the caller must ensure
33
- * Tell if a write threshold is set for a given BDS.
60
- * that each unplug() is called in the same IOThread of the matching plug().
34
- */
61
- */
35
-bool bdrv_write_threshold_is_set(const BlockDriverState *bs);
62
-void coroutine_fn blk_co_io_plug(BlockBackend *blk);
36
-
63
-void co_wrapper blk_io_plug(BlockBackend *blk);
37
-/*
64
-
38
- * bdrv_write_threshold_exceeded
65
-void coroutine_fn blk_co_io_unplug(BlockBackend *blk);
39
- *
66
-void co_wrapper blk_io_unplug(BlockBackend *blk);
40
- * Return the extent of a write request that exceeded the threshold,
67
+void blk_io_plug(void);
41
- * or zero if the request is below the threshold.
68
+void blk_io_unplug(void);
42
- * Return zero also if the threshold was not set.
69
+void blk_io_plug_call(void (*fn)(void *), void *opaque);
43
- *
70
44
- * NOTE: here we assume the following holds for each request this code
71
AioContext *blk_get_aio_context(BlockBackend *blk);
45
- * deals with:
72
BlockAcctStats *blk_get_stats(BlockBackend *blk);
46
- *
73
diff --git a/block/block-backend.c b/block/block-backend.c
47
- * assert((req->offset + req->bytes) <= UINT64_MAX)
74
index XXXXXXX..XXXXXXX 100644
48
- *
75
--- a/block/block-backend.c
49
- * Please not there is *not* an actual C assert().
76
+++ b/block/block-backend.c
50
- */
77
@@ -XXX,XX +XXX,XX @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
51
-uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
78
notifier_list_add(&blk->insert_bs_notifiers, notify);
52
- const BdrvTrackedRequest *req);
53
-
54
/*
55
* bdrv_write_threshold_check_write
56
*
57
diff --git a/block/write-threshold.c b/block/write-threshold.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/write-threshold.c
60
+++ b/block/write-threshold.c
61
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_write_threshold_get(const BlockDriverState *bs)
62
return bs->write_threshold_offset;
63
}
79
}
64
80
65
-bool bdrv_write_threshold_is_set(const BlockDriverState *bs)
81
-void coroutine_fn blk_co_io_plug(BlockBackend *blk)
66
-{
82
-{
67
- return bs->write_threshold_offset > 0;
83
- BlockDriverState *bs = blk_bs(blk);
84
- IO_CODE();
85
- GRAPH_RDLOCK_GUARD();
86
-
87
- if (bs) {
88
- bdrv_co_io_plug(bs);
89
- }
68
-}
90
-}
69
-
91
-
70
-uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
92
-void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
71
- const BdrvTrackedRequest *req)
72
-{
93
-{
73
- if (bdrv_write_threshold_is_set(bs)) {
94
- BlockDriverState *bs = blk_bs(blk);
74
- if (req->offset > bs->write_threshold_offset) {
95
- IO_CODE();
75
- return (req->offset - bs->write_threshold_offset) + req->bytes;
96
- GRAPH_RDLOCK_GUARD();
76
- }
97
-
77
- if ((req->offset + req->bytes) > bs->write_threshold_offset) {
98
- if (bs) {
78
- return (req->offset + req->bytes) - bs->write_threshold_offset;
99
- bdrv_co_io_unplug(bs);
79
- }
80
- }
100
- }
81
- return 0;
82
-}
101
-}
83
-
102
-
84
void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes)
103
BlockAcctStats *blk_get_stats(BlockBackend *blk)
85
{
104
{
86
bs->write_threshold_offset = threshold_bytes;
105
IO_CODE();
87
diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c
106
diff --git a/block/plug.c b/block/plug.c
88
index XXXXXXX..XXXXXXX 100644
107
new file mode 100644
89
--- a/tests/unit/test-write-threshold.c
108
index XXXXXXX..XXXXXXX
90
+++ b/tests/unit/test-write-threshold.c
109
--- /dev/null
91
@@ -XXX,XX +XXX,XX @@ static void test_threshold_not_set_on_init(void)
110
+++ b/block/plug.c
92
BlockDriverState bs;
111
@@ -XXX,XX +XXX,XX @@
93
memset(&bs, 0, sizeof(bs));
112
+/* SPDX-License-Identifier: GPL-2.0-or-later */
94
113
+/*
95
- g_assert(!bdrv_write_threshold_is_set(&bs));
114
+ * Block I/O plugging
96
-
115
+ *
97
res = bdrv_write_threshold_get(&bs);
116
+ * Copyright Red Hat.
98
g_assert_cmpint(res, ==, 0);
117
+ *
118
+ * This API defers a function call within a blk_io_plug()/blk_io_unplug()
119
+ * section, allowing multiple calls to batch up. This is a performance
120
+ * optimization that is used in the block layer to submit several I/O requests
121
+ * at once instead of individually:
122
+ *
123
+ * blk_io_plug(); <-- start of plugged region
124
+ * ...
125
+ * blk_io_plug_call(my_func, my_obj); <-- deferred my_func(my_obj) call
126
+ * blk_io_plug_call(my_func, my_obj); <-- another
127
+ * blk_io_plug_call(my_func, my_obj); <-- another
128
+ * ...
129
+ * blk_io_unplug(); <-- end of plugged region, my_func(my_obj) is called once
130
+ *
131
+ * This code is actually generic and not tied to the block layer. If another
132
+ * subsystem needs this functionality, it could be renamed.
133
+ */
134
+
135
+#include "qemu/osdep.h"
136
+#include "qemu/coroutine-tls.h"
137
+#include "qemu/notify.h"
138
+#include "qemu/thread.h"
139
+#include "sysemu/block-backend.h"
140
+
141
+/* A function call that has been deferred until unplug() */
142
+typedef struct {
143
+ void (*fn)(void *);
144
+ void *opaque;
145
+} UnplugFn;
146
+
147
+/* Per-thread state */
148
+typedef struct {
149
+ unsigned count; /* how many times has plug() been called? */
150
+ GArray *unplug_fns; /* functions to call at unplug time */
151
+} Plug;
152
+
153
+/* Use get_ptr_plug() to fetch this thread-local value */
154
+QEMU_DEFINE_STATIC_CO_TLS(Plug, plug);
155
+
156
+/* Called at thread cleanup time */
157
+static void blk_io_plug_atexit(Notifier *n, void *value)
158
+{
159
+ Plug *plug = get_ptr_plug();
160
+ g_array_free(plug->unplug_fns, TRUE);
161
+}
162
+
163
+/* This won't involve coroutines, so use __thread */
164
+static __thread Notifier blk_io_plug_atexit_notifier;
165
+
166
+/**
167
+ * blk_io_plug_call:
168
+ * @fn: a function pointer to be invoked
169
+ * @opaque: a user-defined argument to @fn()
170
+ *
171
+ * Call @fn(@opaque) immediately if not within a blk_io_plug()/blk_io_unplug()
172
+ * section.
173
+ *
174
+ * Otherwise defer the call until the end of the outermost
175
+ * blk_io_plug()/blk_io_unplug() section in this thread. If the same
176
+ * @fn/@opaque pair has already been deferred, it will only be called once upon
177
+ * blk_io_unplug() so that accumulated calls are batched into a single call.
178
+ *
179
+ * The caller must ensure that @opaque is not freed before @fn() is invoked.
180
+ */
181
+void blk_io_plug_call(void (*fn)(void *), void *opaque)
182
+{
183
+ Plug *plug = get_ptr_plug();
184
+
185
+ /* Call immediately if we're not plugged */
186
+ if (plug->count == 0) {
187
+ fn(opaque);
188
+ return;
189
+ }
190
+
191
+ GArray *array = plug->unplug_fns;
192
+ if (!array) {
193
+ array = g_array_new(FALSE, FALSE, sizeof(UnplugFn));
194
+ plug->unplug_fns = array;
195
+ blk_io_plug_atexit_notifier.notify = blk_io_plug_atexit;
196
+ qemu_thread_atexit_add(&blk_io_plug_atexit_notifier);
197
+ }
198
+
199
+ UnplugFn *fns = (UnplugFn *)array->data;
200
+ UnplugFn new_fn = {
201
+ .fn = fn,
202
+ .opaque = opaque,
203
+ };
204
+
205
+ /*
206
+ * There won't be many, so do a linear search. If this becomes a bottleneck
207
+ * then a binary search (glib 2.62+) or different data structure could be
208
+ * used.
209
+ */
210
+ for (guint i = 0; i < array->len; i++) {
211
+ if (memcmp(&fns[i], &new_fn, sizeof(new_fn)) == 0) {
212
+ return; /* already exists */
213
+ }
214
+ }
215
+
216
+ g_array_append_val(array, new_fn);
217
+}
218
+
219
+/**
220
+ * blk_io_plug: Defer blk_io_plug_call() functions until blk_io_unplug()
221
+ *
222
+ * blk_io_plug/unplug are thread-local operations. This means that multiple
223
+ * threads can simultaneously call plug/unplug, but the caller must ensure that
224
+ * each unplug() is called in the same thread of the matching plug().
225
+ *
226
+ * Nesting is supported. blk_io_plug_call() functions are only called at the
227
+ * outermost blk_io_unplug().
228
+ */
229
+void blk_io_plug(void)
230
+{
231
+ Plug *plug = get_ptr_plug();
232
+
233
+ assert(plug->count < UINT32_MAX);
234
+
235
+ plug->count++;
236
+}
237
+
238
+/**
239
+ * blk_io_unplug: Run any pending blk_io_plug_call() functions
240
+ *
241
+ * There must have been a matching blk_io_plug() call in the same thread prior
242
+ * to this blk_io_unplug() call.
243
+ */
244
+void blk_io_unplug(void)
245
+{
246
+ Plug *plug = get_ptr_plug();
247
+
248
+ assert(plug->count > 0);
249
+
250
+ if (--plug->count > 0) {
251
+ return;
252
+ }
253
+
254
+ GArray *array = plug->unplug_fns;
255
+ if (!array) {
256
+ return;
257
+ }
258
+
259
+ UnplugFn *fns = (UnplugFn *)array->data;
260
+
261
+ for (guint i = 0; i < array->len; i++) {
262
+ fns[i].fn(fns[i].opaque);
263
+ }
264
+
265
+ /*
266
+ * This resets the array without freeing memory so that appending is cheap
267
+ * in the future.
268
+ */
269
+ g_array_set_size(array, 0);
270
+}
271
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
272
index XXXXXXX..XXXXXXX 100644
273
--- a/hw/block/dataplane/xen-block.c
274
+++ b/hw/block/dataplane/xen-block.c
275
@@ -XXX,XX +XXX,XX @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
276
* is below us.
277
*/
278
if (inflight_atstart > IO_PLUG_THRESHOLD) {
279
- blk_io_plug(dataplane->blk);
280
+ blk_io_plug();
281
}
282
while (rc != rp) {
283
/* pull request from ring */
284
@@ -XXX,XX +XXX,XX @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
285
286
if (inflight_atstart > IO_PLUG_THRESHOLD &&
287
batched >= inflight_atstart) {
288
- blk_io_unplug(dataplane->blk);
289
+ blk_io_unplug();
290
}
291
xen_block_do_aio(request);
292
if (inflight_atstart > IO_PLUG_THRESHOLD) {
293
if (batched >= inflight_atstart) {
294
- blk_io_plug(dataplane->blk);
295
+ blk_io_plug();
296
batched = 0;
297
} else {
298
batched++;
299
@@ -XXX,XX +XXX,XX @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
300
}
301
}
302
if (inflight_atstart > IO_PLUG_THRESHOLD) {
303
- blk_io_unplug(dataplane->blk);
304
+ blk_io_unplug();
305
}
306
307
return done_something;
308
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/hw/block/virtio-blk.c
311
+++ b/hw/block/virtio-blk.c
312
@@ -XXX,XX +XXX,XX @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
313
bool suppress_notifications = virtio_queue_get_notification(vq);
314
315
aio_context_acquire(blk_get_aio_context(s->blk));
316
- blk_io_plug(s->blk);
317
+ blk_io_plug();
318
319
do {
320
if (suppress_notifications) {
321
@@ -XXX,XX +XXX,XX @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
322
virtio_blk_submit_multireq(s, &mrb);
323
}
324
325
- blk_io_unplug(s->blk);
326
+ blk_io_unplug();
327
aio_context_release(blk_get_aio_context(s->blk));
99
}
328
}
100
@@ -XXX,XX +XXX,XX @@ static void test_threshold_set_get(void)
329
101
330
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
102
bdrv_write_threshold_set(&bs, threshold);
331
index XXXXXXX..XXXXXXX 100644
103
332
--- a/hw/scsi/virtio-scsi.c
104
- g_assert(bdrv_write_threshold_is_set(&bs));
333
+++ b/hw/scsi/virtio-scsi.c
105
-
334
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
106
res = bdrv_write_threshold_get(&bs);
335
return -ENOBUFS;
107
g_assert_cmpint(res, ==, threshold);
336
}
337
scsi_req_ref(req->sreq);
338
- blk_io_plug(d->conf.blk);
339
+ blk_io_plug();
340
object_unref(OBJECT(d));
341
return 0;
108
}
342
}
343
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
344
if (scsi_req_enqueue(sreq)) {
345
scsi_req_continue(sreq);
346
}
347
- blk_io_unplug(sreq->dev->conf.blk);
348
+ blk_io_unplug();
349
scsi_req_unref(sreq);
350
}
351
352
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
353
while (!QTAILQ_EMPTY(&reqs)) {
354
req = QTAILQ_FIRST(&reqs);
355
QTAILQ_REMOVE(&reqs, req, next);
356
- blk_io_unplug(req->sreq->dev->conf.blk);
357
+ blk_io_unplug();
358
scsi_req_unref(req->sreq);
359
virtqueue_detach_element(req->vq, &req->elem, 0);
360
virtio_scsi_free_req(req);
361
diff --git a/block/meson.build b/block/meson.build
362
index XXXXXXX..XXXXXXX 100644
363
--- a/block/meson.build
364
+++ b/block/meson.build
365
@@ -XXX,XX +XXX,XX @@ block_ss.add(files(
366
'mirror.c',
367
'nbd.c',
368
'null.c',
369
+ 'plug.c',
370
'qapi.c',
371
'qcow2-bitmap.c',
372
'qcow2-cache.c',
109
--
373
--
110
2.31.1
374
2.40.1
111
112
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Stop using the .bdrv_co_io_plug() API because it is not multi-queue
2
block layer friendly. Use the new blk_io_plug_call() API to batch I/O
3
submission instead.
2
4
3
Testing set/get of one 64bit variable doesn't seem necessary. We have a
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
lot of such variables. Also remaining tests do test set/get anyway.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
8
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20230530180959.1108766-3-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
block/nvme.c | 44 ++++++++++++--------------------------------
13
block/trace-events | 1 -
14
2 files changed, 12 insertions(+), 33 deletions(-)
5
15
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
diff --git a/block/nvme.c b/block/nvme.c
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210506090621.11848-7-vsementsov@virtuozzo.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/unit/test-write-threshold.c | 43 -------------------------------
13
1 file changed, 43 deletions(-)
14
15
diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/unit/test-write-threshold.c
18
--- a/block/nvme.c
18
+++ b/tests/unit/test-write-threshold.c
19
+++ b/block/nvme.c
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
20
#include "block/write-threshold.h"
21
#include "qemu/vfio-helpers.h"
21
22
#include "block/block-io.h"
22
23
#include "block/block_int.h"
23
-static void test_threshold_not_set_on_init(void)
24
+#include "sysemu/block-backend.h"
25
#include "sysemu/replay.h"
26
#include "trace.h"
27
28
@@ -XXX,XX +XXX,XX @@ struct BDRVNVMeState {
29
int blkshift;
30
31
uint64_t max_transfer;
32
- bool plugged;
33
34
bool supports_write_zeroes;
35
bool supports_discard;
36
@@ -XXX,XX +XXX,XX @@ static void nvme_kick(NVMeQueuePair *q)
37
{
38
BDRVNVMeState *s = q->s;
39
40
- if (s->plugged || !q->need_kick) {
41
+ if (!q->need_kick) {
42
return;
43
}
44
trace_nvme_kick(s, q->index);
45
@@ -XXX,XX +XXX,XX @@ static bool nvme_process_completion(NVMeQueuePair *q)
46
NvmeCqe *c;
47
48
trace_nvme_process_completion(s, q->index, q->inflight);
49
- if (s->plugged) {
50
- trace_nvme_process_completion_queue_plugged(s, q->index);
51
- return false;
52
- }
53
54
/*
55
* Support re-entrancy when a request cb() function invokes aio_poll().
56
@@ -XXX,XX +XXX,XX @@ static void nvme_trace_command(const NvmeCmd *cmd)
57
}
58
}
59
60
+static void nvme_unplug_fn(void *opaque)
61
+{
62
+ NVMeQueuePair *q = opaque;
63
+
64
+ QEMU_LOCK_GUARD(&q->lock);
65
+ nvme_kick(q);
66
+ nvme_process_completion(q);
67
+}
68
+
69
static void nvme_submit_command(NVMeQueuePair *q, NVMeRequest *req,
70
NvmeCmd *cmd, BlockCompletionFunc cb,
71
void *opaque)
72
@@ -XXX,XX +XXX,XX @@ static void nvme_submit_command(NVMeQueuePair *q, NVMeRequest *req,
73
q->sq.tail * NVME_SQ_ENTRY_BYTES, cmd, sizeof(*cmd));
74
q->sq.tail = (q->sq.tail + 1) % NVME_QUEUE_SIZE;
75
q->need_kick++;
76
- nvme_kick(q);
77
- nvme_process_completion(q);
78
+ blk_io_plug_call(nvme_unplug_fn, q);
79
qemu_mutex_unlock(&q->lock);
80
}
81
82
@@ -XXX,XX +XXX,XX @@ static void nvme_attach_aio_context(BlockDriverState *bs,
83
}
84
}
85
86
-static void coroutine_fn nvme_co_io_plug(BlockDriverState *bs)
24
-{
87
-{
25
- uint64_t res;
88
- BDRVNVMeState *s = bs->opaque;
26
- BlockDriverState bs;
89
- assert(!s->plugged);
27
- memset(&bs, 0, sizeof(bs));
90
- s->plugged = true;
28
-
29
- res = bdrv_write_threshold_get(&bs);
30
- g_assert_cmpint(res, ==, 0);
31
-}
91
-}
32
-
92
-
33
-static void test_threshold_set_get(void)
93
-static void coroutine_fn nvme_co_io_unplug(BlockDriverState *bs)
34
-{
94
-{
35
- uint64_t threshold = 4 * 1024 * 1024;
95
- BDRVNVMeState *s = bs->opaque;
36
- uint64_t res;
96
- assert(s->plugged);
37
- BlockDriverState bs;
97
- s->plugged = false;
38
- memset(&bs, 0, sizeof(bs));
98
- for (unsigned i = INDEX_IO(0); i < s->queue_count; i++) {
39
-
99
- NVMeQueuePair *q = s->queues[i];
40
- bdrv_write_threshold_set(&bs, threshold);
100
- qemu_mutex_lock(&q->lock);
41
-
101
- nvme_kick(q);
42
- res = bdrv_write_threshold_get(&bs);
102
- nvme_process_completion(q);
43
- g_assert_cmpint(res, ==, threshold);
103
- qemu_mutex_unlock(&q->lock);
104
- }
44
-}
105
-}
45
-
106
-
46
-static void test_threshold_multi_set_get(void)
107
static bool nvme_register_buf(BlockDriverState *bs, void *host, size_t size,
47
-{
108
Error **errp)
48
- uint64_t threshold1 = 4 * 1024 * 1024;
109
{
49
- uint64_t threshold2 = 15 * 1024 * 1024;
110
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
50
- uint64_t res;
111
.bdrv_detach_aio_context = nvme_detach_aio_context,
51
- BlockDriverState bs;
112
.bdrv_attach_aio_context = nvme_attach_aio_context,
52
- memset(&bs, 0, sizeof(bs));
113
114
- .bdrv_co_io_plug = nvme_co_io_plug,
115
- .bdrv_co_io_unplug = nvme_co_io_unplug,
53
-
116
-
54
- bdrv_write_threshold_set(&bs, threshold1);
117
.bdrv_register_buf = nvme_register_buf,
55
- bdrv_write_threshold_set(&bs, threshold2);
118
.bdrv_unregister_buf = nvme_unregister_buf,
56
- res = bdrv_write_threshold_get(&bs);
119
};
57
- g_assert_cmpint(res, ==, threshold2);
120
diff --git a/block/trace-events b/block/trace-events
58
-}
121
index XXXXXXX..XXXXXXX 100644
59
-
122
--- a/block/trace-events
60
static void test_threshold_not_trigger(void)
123
+++ b/block/trace-events
61
{
124
@@ -XXX,XX +XXX,XX @@ nvme_kick(void *s, unsigned q_index) "s %p q #%u"
62
uint64_t threshold = 4 * 1024 * 1024;
125
nvme_dma_flush_queue_wait(void *s) "s %p"
63
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
126
nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x"
64
{
127
nvme_process_completion(void *s, unsigned q_index, int inflight) "s %p q #%u inflight %d"
65
size_t i;
128
-nvme_process_completion_queue_plugged(void *s, unsigned q_index) "s %p q #%u"
66
TestStruct tests[] = {
129
nvme_complete_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
67
- { "/write-threshold/not-set-on-init",
130
nvme_submit_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
68
- test_threshold_not_set_on_init },
131
nvme_submit_command_raw(int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7) "%02x %02x %02x %02x %02x %02x %02x %02x"
69
- { "/write-threshold/set-get",
70
- test_threshold_set_get },
71
- { "/write-threshold/multi-set-get",
72
- test_threshold_multi_set_get },
73
{ "/write-threshold/not-trigger",
74
test_threshold_not_trigger },
75
{ "/write-threshold/trigger",
76
--
132
--
77
2.31.1
133
2.40.1
78
79
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Stop using the .bdrv_co_io_plug() API because it is not multi-queue
2
block layer friendly. Use the new blk_io_plug_call() API to batch I/O
3
submission instead.
2
4
3
If mirror is READY than cancel operation is not discarding the whole
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
result of the operation, but instead it's a documented way get a
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
point-in-time snapshot of source disk.
7
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
8
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20230530180959.1108766-4-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
block/blkio.c | 43 ++++++++++++++++++++++++-------------------
13
1 file changed, 24 insertions(+), 19 deletions(-)
6
14
7
So, we should not cancel any requests if mirror is READ and
15
diff --git a/block/blkio.c b/block/blkio.c
8
force=false. Let's fix that case.
9
10
Note, that bug that we have before this commit is not critical, as the
11
only .bdrv_cancel_in_flight implementation is nbd_cancel_in_flight()
12
and it cancels only requests waiting for reconnection, so it should be
13
rare case.
14
15
Fixes: 521ff8b779b11c394dbdc43f02e158dd99df308a
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <20210421075858.40197-1-vsementsov@virtuozzo.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
include/block/block_int.h | 2 +-
21
include/qemu/job.h | 2 +-
22
block/backup.c | 2 +-
23
block/mirror.c | 6 ++++--
24
job.c | 2 +-
25
tests/qemu-iotests/264 | 2 +-
26
6 files changed, 9 insertions(+), 7 deletions(-)
27
28
diff --git a/include/block/block_int.h b/include/block/block_int.h
29
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block_int.h
17
--- a/block/blkio.c
31
+++ b/include/block/block_int.h
18
+++ b/block/blkio.c
32
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
19
@@ -XXX,XX +XXX,XX @@
33
* of in-flight requests, so don't waste the time if possible.
20
#include "qemu/error-report.h"
34
*
21
#include "qapi/qmp/qdict.h"
35
* One example usage is to avoid waiting for an nbd target node reconnect
22
#include "qemu/module.h"
36
- * timeout during job-cancel.
23
+#include "sysemu/block-backend.h"
37
+ * timeout during job-cancel with force=true.
24
#include "exec/memory.h" /* for ram_block_discard_disable() */
38
*/
25
39
void (*bdrv_cancel_in_flight)(BlockDriverState *bs);
26
#include "block/block-io.h"
40
27
@@ -XXX,XX +XXX,XX @@ static void blkio_detach_aio_context(BlockDriverState *bs)
41
diff --git a/include/qemu/job.h b/include/qemu/job.h
28
NULL, NULL, NULL);
42
index XXXXXXX..XXXXXXX 100644
29
}
43
--- a/include/qemu/job.h
30
44
+++ b/include/qemu/job.h
31
-/* Call with s->blkio_lock held to submit I/O after enqueuing a new request */
45
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
32
-static void blkio_submit_io(BlockDriverState *bs)
46
/**
33
+/*
47
* If the callback is not NULL, it will be invoked in job_cancel_async
34
+ * Called by blk_io_unplug() or immediately if not plugged. Called without
48
*/
35
+ * blkio_lock.
49
- void (*cancel)(Job *job);
36
+ */
50
+ void (*cancel)(Job *job, bool force);
37
+static void blkio_unplug_fn(void *opaque)
51
38
{
52
39
- if (qatomic_read(&bs->io_plugged) == 0) {
53
/** Called when the job is freed */
40
- BDRVBlkioState *s = bs->opaque;
54
diff --git a/block/backup.c b/block/backup.c
41
+ BDRVBlkioState *s = opaque;
55
index XXXXXXX..XXXXXXX 100644
42
56
--- a/block/backup.c
43
+ WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
57
+++ b/block/backup.c
44
blkioq_do_io(s->blkioq, NULL, 0, 0, NULL);
58
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
59
}
45
}
60
}
46
}
61
47
62
-static void backup_cancel(Job *job)
48
+/*
63
+static void backup_cancel(Job *job, bool force)
49
+ * Schedule I/O submission after enqueuing a new request. Called without
50
+ * blkio_lock.
51
+ */
52
+static void blkio_submit_io(BlockDriverState *bs)
53
+{
54
+ BDRVBlkioState *s = bs->opaque;
55
+
56
+ blk_io_plug_call(blkio_unplug_fn, s);
57
+}
58
+
59
static int coroutine_fn
60
blkio_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
64
{
61
{
65
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
62
@@ -XXX,XX +XXX,XX @@ blkio_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
66
63
67
diff --git a/block/mirror.c b/block/mirror.c
64
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
68
index XXXXXXX..XXXXXXX 100644
65
blkioq_discard(s->blkioq, offset, bytes, &cod, 0);
69
--- a/block/mirror.c
66
- blkio_submit_io(bs);
70
+++ b/block/mirror.c
67
}
71
@@ -XXX,XX +XXX,XX @@ static bool mirror_drained_poll(BlockJob *job)
68
72
return !!s->in_flight;
69
+ blkio_submit_io(bs);
70
qemu_coroutine_yield();
71
return cod.ret;
73
}
72
}
74
73
@@ -XXX,XX +XXX,XX @@ blkio_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
75
-static void mirror_cancel(Job *job)
74
76
+static void mirror_cancel(Job *job, bool force)
75
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
77
{
76
blkioq_readv(s->blkioq, offset, iov, iovcnt, &cod, 0);
78
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
77
- blkio_submit_io(bs);
79
BlockDriverState *target = blk_bs(s->target);
78
}
80
79
81
- bdrv_cancel_in_flight(target);
80
+ blkio_submit_io(bs);
82
+ if (force || !job_is_ready(job)) {
81
qemu_coroutine_yield();
83
+ bdrv_cancel_in_flight(target);
82
84
+ }
83
if (use_bounce_buffer) {
84
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_co_pwritev(BlockDriverState *bs, int64_t offset,
85
86
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
87
blkioq_writev(s->blkioq, offset, iov, iovcnt, &cod, blkio_flags);
88
- blkio_submit_io(bs);
89
}
90
91
+ blkio_submit_io(bs);
92
qemu_coroutine_yield();
93
94
if (use_bounce_buffer) {
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_co_flush(BlockDriverState *bs)
96
97
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
98
blkioq_flush(s->blkioq, &cod, 0);
99
- blkio_submit_io(bs);
100
}
101
102
+ blkio_submit_io(bs);
103
qemu_coroutine_yield();
104
return cod.ret;
85
}
105
}
86
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_co_pwrite_zeroes(BlockDriverState *bs,
87
static const BlockJobDriver mirror_job_driver = {
107
88
diff --git a/job.c b/job.c
108
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
89
index XXXXXXX..XXXXXXX 100644
109
blkioq_write_zeroes(s->blkioq, offset, bytes, &cod, blkio_flags);
90
--- a/job.c
110
- blkio_submit_io(bs);
91
+++ b/job.c
92
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single(Job *job)
93
static void job_cancel_async(Job *job, bool force)
94
{
95
if (job->driver->cancel) {
96
- job->driver->cancel(job);
97
+ job->driver->cancel(job, force);
98
}
111
}
99
if (job->user_paused) {
112
100
/* Do not call job_enter here, the caller will handle it. */
113
+ blkio_submit_io(bs);
101
diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264
114
qemu_coroutine_yield();
102
index XXXXXXX..XXXXXXX 100755
115
return cod.ret;
103
--- a/tests/qemu-iotests/264
116
}
104
+++ b/tests/qemu-iotests/264
117
105
@@ -XXX,XX +XXX,XX @@ class TestNbdReconnect(iotests.QMPTestCase):
118
-static void coroutine_fn blkio_co_io_unplug(BlockDriverState *bs)
106
self.assert_qmp(result, 'return', {})
119
-{
107
120
- BDRVBlkioState *s = bs->opaque;
108
def cancel_job(self):
121
-
109
- result = self.vm.qmp('block-job-cancel', device='drive0')
122
- WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
110
+ result = self.vm.qmp('block-job-cancel', device='drive0', force=True)
123
- blkio_submit_io(bs);
111
self.assert_qmp(result, 'return', {})
124
- }
112
125
-}
113
start_t = time.time()
126
-
127
typedef enum {
128
BMRR_OK,
129
BMRR_SKIP,
130
@@ -XXX,XX +XXX,XX @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
131
.bdrv_co_pwritev = blkio_co_pwritev, \
132
.bdrv_co_flush_to_disk = blkio_co_flush, \
133
.bdrv_co_pwrite_zeroes = blkio_co_pwrite_zeroes, \
134
- .bdrv_co_io_unplug = blkio_co_io_unplug, \
135
.bdrv_refresh_limits = blkio_refresh_limits, \
136
.bdrv_register_buf = blkio_register_buf, \
137
.bdrv_unregister_buf = blkio_unregister_buf, \
114
--
138
--
115
2.31.1
139
2.40.1
116
117
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Stop using the .bdrv_co_io_plug() API because it is not multi-queue
2
block layer friendly. Use the new blk_io_plug_call() API to batch I/O
3
submission instead.
2
4
3
We don't need this extra logic: it doesn't make code simpler.
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
8
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20230530180959.1108766-5-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
include/block/raw-aio.h | 7 -------
13
block/file-posix.c | 10 ----------
14
block/io_uring.c | 44 ++++++++++++++++-------------------------
15
block/trace-events | 5 ++---
16
4 files changed, 19 insertions(+), 47 deletions(-)
4
17
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210506090621.11848-8-vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/unit/test-write-threshold.c | 20 +++-----------------
12
1 file changed, 3 insertions(+), 17 deletions(-)
13
14
diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/unit/test-write-threshold.c
20
--- a/include/block/raw-aio.h
17
+++ b/tests/unit/test-write-threshold.c
21
+++ b/include/block/raw-aio.h
18
@@ -XXX,XX +XXX,XX @@ static void test_threshold_trigger(void)
22
@@ -XXX,XX +XXX,XX @@ int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
19
g_assert_cmpuint(bdrv_write_threshold_get(&bs), ==, 0);
23
QEMUIOVector *qiov, int type);
24
void luring_detach_aio_context(LuringState *s, AioContext *old_context);
25
void luring_attach_aio_context(LuringState *s, AioContext *new_context);
26
-
27
-/*
28
- * luring_io_plug/unplug work in the thread's current AioContext, therefore the
29
- * caller must ensure that they are paired in the same IOThread.
30
- */
31
-void luring_io_plug(void);
32
-void luring_io_unplug(void);
33
#endif
34
35
#ifdef _WIN32
36
diff --git a/block/file-posix.c b/block/file-posix.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/file-posix.c
39
+++ b/block/file-posix.c
40
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
41
laio_io_plug();
42
}
43
#endif
44
-#ifdef CONFIG_LINUX_IO_URING
45
- if (s->use_linux_io_uring) {
46
- luring_io_plug();
47
- }
48
-#endif
20
}
49
}
21
50
22
-typedef struct TestStruct {
51
static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
23
- const char *name;
52
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
24
- void (*func)(void);
53
laio_io_unplug(s->aio_max_batch);
25
-} TestStruct;
54
}
55
#endif
56
-#ifdef CONFIG_LINUX_IO_URING
57
- if (s->use_linux_io_uring) {
58
- luring_io_unplug();
59
- }
60
-#endif
61
}
62
63
static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
64
diff --git a/block/io_uring.c b/block/io_uring.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block/io_uring.c
67
+++ b/block/io_uring.c
68
@@ -XXX,XX +XXX,XX @@
69
#include "block/raw-aio.h"
70
#include "qemu/coroutine.h"
71
#include "qapi/error.h"
72
+#include "sysemu/block-backend.h"
73
#include "trace.h"
74
75
/* Only used for assertions. */
76
@@ -XXX,XX +XXX,XX @@ typedef struct LuringAIOCB {
77
} LuringAIOCB;
78
79
typedef struct LuringQueue {
80
- int plugged;
81
unsigned int in_queue;
82
unsigned int in_flight;
83
bool blocked;
84
@@ -XXX,XX +XXX,XX @@ static void luring_process_completions_and_submit(LuringState *s)
85
{
86
luring_process_completions(s);
87
88
- if (!s->io_q.plugged && s->io_q.in_queue > 0) {
89
+ if (s->io_q.in_queue > 0) {
90
ioq_submit(s);
91
}
92
}
93
@@ -XXX,XX +XXX,XX @@ static void qemu_luring_poll_ready(void *opaque)
94
static void ioq_init(LuringQueue *io_q)
95
{
96
QSIMPLEQ_INIT(&io_q->submit_queue);
97
- io_q->plugged = 0;
98
io_q->in_queue = 0;
99
io_q->in_flight = 0;
100
io_q->blocked = false;
101
}
102
103
-void luring_io_plug(void)
104
+static void luring_unplug_fn(void *opaque)
105
{
106
- AioContext *ctx = qemu_get_current_aio_context();
107
- LuringState *s = aio_get_linux_io_uring(ctx);
108
- trace_luring_io_plug(s);
109
- s->io_q.plugged++;
110
-}
26
-
111
-
27
112
-void luring_io_unplug(void)
28
int main(int argc, char **argv)
113
-{
29
{
114
- AioContext *ctx = qemu_get_current_aio_context();
30
- size_t i;
115
- LuringState *s = aio_get_linux_io_uring(ctx);
31
- TestStruct tests[] = {
116
- assert(s->io_q.plugged);
32
- { "/write-threshold/not-trigger",
117
- trace_luring_io_unplug(s, s->io_q.blocked, s->io_q.plugged,
33
- test_threshold_not_trigger },
118
- s->io_q.in_queue, s->io_q.in_flight);
34
- { "/write-threshold/trigger",
119
- if (--s->io_q.plugged == 0 &&
35
- test_threshold_trigger },
120
- !s->io_q.blocked && s->io_q.in_queue > 0) {
36
- { NULL, NULL }
121
+ LuringState *s = opaque;
37
- };
122
+ trace_luring_unplug_fn(s, s->io_q.blocked, s->io_q.in_queue,
38
-
123
+ s->io_q.in_flight);
39
g_test_init(&argc, &argv, NULL);
124
+ if (!s->io_q.blocked && s->io_q.in_queue > 0) {
40
- for (i = 0; tests[i].name != NULL; i++) {
125
ioq_submit(s);
41
- g_test_add_func(tests[i].name, tests[i].func);
126
}
42
- }
127
}
43
+ g_test_add_func("/write-threshold/not-trigger", test_threshold_not_trigger);
128
@@ -XXX,XX +XXX,XX @@ static int luring_do_submit(int fd, LuringAIOCB *luringcb, LuringState *s,
44
+ g_test_add_func("/write-threshold/trigger", test_threshold_trigger);
129
130
QSIMPLEQ_INSERT_TAIL(&s->io_q.submit_queue, luringcb, next);
131
s->io_q.in_queue++;
132
- trace_luring_do_submit(s, s->io_q.blocked, s->io_q.plugged,
133
- s->io_q.in_queue, s->io_q.in_flight);
134
- if (!s->io_q.blocked &&
135
- (!s->io_q.plugged ||
136
- s->io_q.in_flight + s->io_q.in_queue >= MAX_ENTRIES)) {
137
- ret = ioq_submit(s);
138
- trace_luring_do_submit_done(s, ret);
139
- return ret;
140
+ trace_luring_do_submit(s, s->io_q.blocked, s->io_q.in_queue,
141
+ s->io_q.in_flight);
142
+ if (!s->io_q.blocked) {
143
+ if (s->io_q.in_flight + s->io_q.in_queue >= MAX_ENTRIES) {
144
+ ret = ioq_submit(s);
145
+ trace_luring_do_submit_done(s, ret);
146
+ return ret;
147
+ }
45
+
148
+
46
return g_test_run();
149
+ blk_io_plug_call(luring_unplug_fn, s);
150
}
151
return 0;
47
}
152
}
153
diff --git a/block/trace-events b/block/trace-events
154
index XXXXXXX..XXXXXXX 100644
155
--- a/block/trace-events
156
+++ b/block/trace-events
157
@@ -XXX,XX +XXX,XX @@ file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "
158
# io_uring.c
159
luring_init_state(void *s, size_t size) "s %p size %zu"
160
luring_cleanup_state(void *s) "%p freed"
161
-luring_io_plug(void *s) "LuringState %p plug"
162
-luring_io_unplug(void *s, int blocked, int plugged, int queued, int inflight) "LuringState %p blocked %d plugged %d queued %d inflight %d"
163
-luring_do_submit(void *s, int blocked, int plugged, int queued, int inflight) "LuringState %p blocked %d plugged %d queued %d inflight %d"
164
+luring_unplug_fn(void *s, int blocked, int queued, int inflight) "LuringState %p blocked %d queued %d inflight %d"
165
+luring_do_submit(void *s, int blocked, int queued, int inflight) "LuringState %p blocked %d queued %d inflight %d"
166
luring_do_submit_done(void *s, int ret) "LuringState %p submitted to kernel %d"
167
luring_co_submit(void *bs, void *s, void *luringcb, int fd, uint64_t offset, size_t nbytes, int type) "bs %p s %p luringcb %p fd %d offset %" PRId64 " nbytes %zd type %d"
168
luring_process_completion(void *s, void *aiocb, int ret) "LuringState %p luringcb %p ret %d"
48
--
169
--
49
2.31.1
170
2.40.1
50
51
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Stop using the .bdrv_co_io_plug() API because it is not multi-queue
2
2
block layer friendly. Use the new blk_io_plug_call() API to batch I/O
3
"qemu/typedefs.h" is enough for include/block/write-threshold.h header
3
submission instead.
4
with forward declaration of BlockDriverState. Also drop extra includes
4
5
from block/write-threshold.c and tests/unit/test-write-threshold.c
5
Note that a dev_max_batch check is dropped in laio_io_unplug() because
6
6
the semantics of unplug_fn() are different from .bdrv_co_unplug():
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
1. unplug_fn() is only called when the last blk_io_unplug() call occurs,
8
Message-Id: <20210506090621.11848-9-vsementsov@virtuozzo.com>
8
not every time blk_io_unplug() is called.
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
2. unplug_fn() is per-thread, not per-BlockDriverState, so there is no
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
way to get per-BlockDriverState fields like dev_max_batch.
11
12
Therefore this condition cannot be moved to laio_unplug_fn(). It is not
13
obvious that this condition affects performance in practice, so I am
14
removing it instead of trying to come up with a more complex mechanism
15
to preserve the condition.
16
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Acked-by: Kevin Wolf <kwolf@redhat.com>
20
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
21
Message-id: 20230530180959.1108766-6-stefanha@redhat.com
22
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
23
---
12
include/block/write-threshold.h | 2 +-
24
include/block/raw-aio.h | 7 -------
13
block/write-threshold.c | 2 --
25
block/file-posix.c | 28 ----------------------------
14
tests/unit/test-write-threshold.c | 1 -
26
block/linux-aio.c | 41 +++++++++++------------------------------
15
3 files changed, 1 insertion(+), 4 deletions(-)
27
3 files changed, 11 insertions(+), 65 deletions(-)
16
28
17
diff --git a/include/block/write-threshold.h b/include/block/write-threshold.h
29
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
18
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/write-threshold.h
31
--- a/include/block/raw-aio.h
20
+++ b/include/block/write-threshold.h
32
+++ b/include/block/raw-aio.h
33
@@ -XXX,XX +XXX,XX @@ int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
34
35
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
36
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
37
-
38
-/*
39
- * laio_io_plug/unplug work in the thread's current AioContext, therefore the
40
- * caller must ensure that they are paired in the same IOThread.
41
- */
42
-void laio_io_plug(void);
43
-void laio_io_unplug(uint64_t dev_max_batch);
44
#endif
45
/* io_uring.c - Linux io_uring implementation */
46
#ifdef CONFIG_LINUX_IO_URING
47
diff --git a/block/file-posix.c b/block/file-posix.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/file-posix.c
50
+++ b/block/file-posix.c
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
52
return raw_co_prw(bs, offset, bytes, qiov, QEMU_AIO_WRITE);
53
}
54
55
-static void coroutine_fn raw_co_io_plug(BlockDriverState *bs)
56
-{
57
- BDRVRawState __attribute__((unused)) *s = bs->opaque;
58
-#ifdef CONFIG_LINUX_AIO
59
- if (s->use_linux_aio) {
60
- laio_io_plug();
61
- }
62
-#endif
63
-}
64
-
65
-static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
66
-{
67
- BDRVRawState __attribute__((unused)) *s = bs->opaque;
68
-#ifdef CONFIG_LINUX_AIO
69
- if (s->use_linux_aio) {
70
- laio_io_unplug(s->aio_max_batch);
71
- }
72
-#endif
73
-}
74
-
75
static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
76
{
77
BDRVRawState *s = bs->opaque;
78
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
79
.bdrv_co_copy_range_from = raw_co_copy_range_from,
80
.bdrv_co_copy_range_to = raw_co_copy_range_to,
81
.bdrv_refresh_limits = raw_refresh_limits,
82
- .bdrv_co_io_plug = raw_co_io_plug,
83
- .bdrv_co_io_unplug = raw_co_io_unplug,
84
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
85
86
.bdrv_co_truncate = raw_co_truncate,
87
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
88
.bdrv_co_copy_range_from = raw_co_copy_range_from,
89
.bdrv_co_copy_range_to = raw_co_copy_range_to,
90
.bdrv_refresh_limits = raw_refresh_limits,
91
- .bdrv_co_io_plug = raw_co_io_plug,
92
- .bdrv_co_io_unplug = raw_co_io_unplug,
93
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
94
95
.bdrv_co_truncate = raw_co_truncate,
96
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
97
.bdrv_co_pwritev = raw_co_pwritev,
98
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
99
.bdrv_refresh_limits = cdrom_refresh_limits,
100
- .bdrv_co_io_plug = raw_co_io_plug,
101
- .bdrv_co_io_unplug = raw_co_io_unplug,
102
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
103
104
.bdrv_co_truncate = raw_co_truncate,
105
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
106
.bdrv_co_pwritev = raw_co_pwritev,
107
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
108
.bdrv_refresh_limits = cdrom_refresh_limits,
109
- .bdrv_co_io_plug = raw_co_io_plug,
110
- .bdrv_co_io_unplug = raw_co_io_unplug,
111
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
112
113
.bdrv_co_truncate = raw_co_truncate,
114
diff --git a/block/linux-aio.c b/block/linux-aio.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/block/linux-aio.c
117
+++ b/block/linux-aio.c
21
@@ -XXX,XX +XXX,XX @@
118
@@ -XXX,XX +XXX,XX @@
22
#ifndef BLOCK_WRITE_THRESHOLD_H
119
#include "qemu/event_notifier.h"
23
#define BLOCK_WRITE_THRESHOLD_H
120
#include "qemu/coroutine.h"
24
25
-#include "block/block_int.h"
26
+#include "qemu/typedefs.h"
27
28
/*
29
* bdrv_write_threshold_set:
30
diff --git a/block/write-threshold.c b/block/write-threshold.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/write-threshold.c
33
+++ b/block/write-threshold.c
34
@@ -XXX,XX +XXX,XX @@
35
36
#include "qemu/osdep.h"
37
#include "block/block_int.h"
38
-#include "qemu/coroutine.h"
39
#include "block/write-threshold.h"
40
-#include "qemu/notify.h"
41
#include "qapi/error.h"
121
#include "qapi/error.h"
42
#include "qapi/qapi-commands-block-core.h"
122
+#include "sysemu/block-backend.h"
43
#include "qapi/qapi-events-block-core.h"
123
44
diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c
124
/* Only used for assertions. */
45
index XXXXXXX..XXXXXXX 100644
125
#include "qemu/coroutine_int.h"
46
--- a/tests/unit/test-write-threshold.c
126
@@ -XXX,XX +XXX,XX @@ struct qemu_laiocb {
47
+++ b/tests/unit/test-write-threshold.c
127
};
48
@@ -XXX,XX +XXX,XX @@
128
49
*/
129
typedef struct {
50
130
- int plugged;
51
#include "qemu/osdep.h"
131
unsigned int in_queue;
52
-#include "qapi/error.h"
132
unsigned int in_flight;
53
#include "block/block_int.h"
133
bool blocked;
54
#include "block/write-threshold.h"
134
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completions_and_submit(LinuxAioState *s)
55
135
{
136
qemu_laio_process_completions(s);
137
138
- if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
139
+ if (!QSIMPLEQ_EMPTY(&s->io_q.pending)) {
140
ioq_submit(s);
141
}
142
}
143
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_poll_ready(EventNotifier *opaque)
144
static void ioq_init(LaioQueue *io_q)
145
{
146
QSIMPLEQ_INIT(&io_q->pending);
147
- io_q->plugged = 0;
148
io_q->in_queue = 0;
149
io_q->in_flight = 0;
150
io_q->blocked = false;
151
@@ -XXX,XX +XXX,XX @@ static uint64_t laio_max_batch(LinuxAioState *s, uint64_t dev_max_batch)
152
return max_batch;
153
}
154
155
-void laio_io_plug(void)
156
+static void laio_unplug_fn(void *opaque)
157
{
158
- AioContext *ctx = qemu_get_current_aio_context();
159
- LinuxAioState *s = aio_get_linux_aio(ctx);
160
+ LinuxAioState *s = opaque;
161
162
- s->io_q.plugged++;
163
-}
164
-
165
-void laio_io_unplug(uint64_t dev_max_batch)
166
-{
167
- AioContext *ctx = qemu_get_current_aio_context();
168
- LinuxAioState *s = aio_get_linux_aio(ctx);
169
-
170
- assert(s->io_q.plugged);
171
- s->io_q.plugged--;
172
-
173
- /*
174
- * Why max batch checking is performed here:
175
- * Another BDS may have queued requests with a higher dev_max_batch and
176
- * therefore in_queue could now exceed our dev_max_batch. Re-check the max
177
- * batch so we can honor our device's dev_max_batch.
178
- */
179
- if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) ||
180
- (!s->io_q.plugged &&
181
- !s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending))) {
182
+ if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
183
ioq_submit(s);
184
}
185
}
186
@@ -XXX,XX +XXX,XX @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
187
188
QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next);
189
s->io_q.in_queue++;
190
- if (!s->io_q.blocked &&
191
- (!s->io_q.plugged ||
192
- s->io_q.in_queue >= laio_max_batch(s, dev_max_batch))) {
193
- ioq_submit(s);
194
+ if (!s->io_q.blocked) {
195
+ if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch)) {
196
+ ioq_submit(s);
197
+ } else {
198
+ blk_io_plug_call(laio_unplug_fn, s);
199
+ }
200
}
201
202
return 0;
56
--
203
--
57
2.31.1
204
2.40.1
58
59
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
No block driver implements .bdrv_co_io_plug() anymore. Get rid of the
2
function pointers.
2
3
3
write-notifiers are used only for write-threshold. New code for such
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
purpose should create filters.
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
7
Acked-by: Kevin Wolf <kwolf@redhat.com>
8
Message-id: 20230530180959.1108766-7-stefanha@redhat.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
include/block/block-io.h | 3 ---
12
include/block/block_int-common.h | 11 ----------
13
block/io.c | 37 --------------------------------
14
3 files changed, 51 deletions(-)
5
15
6
Let's better special-case write-threshold and drop write notifiers at
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
7
all. (Actually, write-threshold is special-cased anyway, as the only
8
user of write-notifiers)
9
10
So, create a new direct interface for bdrv_co_write_req_prepare() and
11
drop all write-notifier related logic from write-threshold.c.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20210506090621.11848-2-vsementsov@virtuozzo.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
[mreitz: Adjusted comment as per Eric's suggestion]
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
21
include/block/block_int.h | 1 -
22
include/block/write-threshold.h | 9 +++++
23
block/io.c | 5 ++-
24
block/write-threshold.c | 70 +++++++--------------------------
25
4 files changed, 27 insertions(+), 58 deletions(-)
26
27
diff --git a/include/block/block_int.h b/include/block/block_int.h
28
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block_int.h
18
--- a/include/block/block-io.h
30
+++ b/include/block/block_int.h
19
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx);
21
22
AioContext *child_of_bds_get_parent_aio_context(BdrvChild *c);
23
24
-void coroutine_fn GRAPH_RDLOCK bdrv_co_io_plug(BlockDriverState *bs);
25
-void coroutine_fn GRAPH_RDLOCK bdrv_co_io_unplug(BlockDriverState *bs);
26
-
27
bool coroutine_fn GRAPH_RDLOCK
28
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
29
uint32_t granularity, Error **errp);
30
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block_int-common.h
33
+++ b/include/block/block_int-common.h
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
35
void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_debug_event)(
36
BlockDriverState *bs, BlkdebugEvent event);
37
38
- /* io queue for linux-aio */
39
- void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs);
40
- void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_unplug)(
41
- BlockDriverState *bs);
42
-
43
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
44
45
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_can_store_new_dirty_bitmap)(
31
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
32
47
unsigned int in_flight;
33
/* threshold limit for writes, in bytes. "High water mark". */
48
unsigned int serialising_in_flight;
34
uint64_t write_threshold_offset;
49
35
- NotifierWithReturn write_threshold_notifier;
50
- /*
36
51
- * counter for nested bdrv_io_plug.
37
/* Writing to the list requires the BQL _and_ the dirty_bitmap_mutex.
52
- * Accessed with atomic ops.
38
* Reading from the list can be done with either the BQL or the
53
- */
39
diff --git a/include/block/write-threshold.h b/include/block/write-threshold.h
54
- unsigned io_plugged;
40
index XXXXXXX..XXXXXXX 100644
55
-
41
--- a/include/block/write-threshold.h
56
/* do we need to tell the quest if we have a volatile write cache? */
42
+++ b/include/block/write-threshold.h
57
int enable_write_cache;
43
@@ -XXX,XX +XXX,XX @@ bool bdrv_write_threshold_is_set(const BlockDriverState *bs);
58
44
uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
45
const BdrvTrackedRequest *req);
46
47
+/*
48
+ * bdrv_write_threshold_check_write
49
+ *
50
+ * Check whether the specified request exceeds the write threshold.
51
+ * If so, send a corresponding event and disable write threshold checking.
52
+ */
53
+void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset,
54
+ int64_t bytes);
55
+
56
#endif
57
diff --git a/block/io.c b/block/io.c
59
diff --git a/block/io.c b/block/io.c
58
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
59
--- a/block/io.c
61
--- a/block/io.c
60
+++ b/block/io.c
62
+++ b/block/io.c
61
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
62
#include "block/blockjob_int.h"
64
return mem;
63
#include "block/block_int.h"
64
#include "block/coroutines.h"
65
+#include "block/write-threshold.h"
66
#include "qemu/cutils.h"
67
#include "qapi/error.h"
68
#include "qemu/error-report.h"
69
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
70
} else {
71
assert(child->perm & BLK_PERM_WRITE);
72
}
73
- return notifier_with_return_list_notify(&bs->before_write_notifiers,
74
- req);
75
+ bdrv_write_threshold_check_write(bs, offset, bytes);
76
+ return 0;
77
case BDRV_TRACKED_TRUNCATE:
78
assert(child->perm & BLK_PERM_RESIZE);
79
return 0;
80
diff --git a/block/write-threshold.c b/block/write-threshold.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/write-threshold.c
83
+++ b/block/write-threshold.c
84
@@ -XXX,XX +XXX,XX @@ bool bdrv_write_threshold_is_set(const BlockDriverState *bs)
85
return bs->write_threshold_offset > 0;
86
}
65
}
87
66
88
-static void write_threshold_disable(BlockDriverState *bs)
67
-void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
89
-{
68
-{
90
- if (bdrv_write_threshold_is_set(bs)) {
69
- BdrvChild *child;
91
- notifier_with_return_remove(&bs->write_threshold_notifier);
70
- IO_CODE();
92
- bs->write_threshold_offset = 0;
71
- assert_bdrv_graph_readable();
72
-
73
- QLIST_FOREACH(child, &bs->children, next) {
74
- bdrv_co_io_plug(child->bs);
75
- }
76
-
77
- if (qatomic_fetch_inc(&bs->io_plugged) == 0) {
78
- BlockDriver *drv = bs->drv;
79
- if (drv && drv->bdrv_co_io_plug) {
80
- drv->bdrv_co_io_plug(bs);
81
- }
93
- }
82
- }
94
-}
83
-}
95
-
84
-
96
uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
85
-void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
97
const BdrvTrackedRequest *req)
98
{
99
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs,
100
return 0;
101
}
102
103
-static int coroutine_fn before_write_notify(NotifierWithReturn *notifier,
104
- void *opaque)
105
-{
86
-{
106
- BdrvTrackedRequest *req = opaque;
87
- BdrvChild *child;
107
- BlockDriverState *bs = req->bs;
88
- IO_CODE();
108
- uint64_t amount = 0;
89
- assert_bdrv_graph_readable();
109
-
90
-
110
- amount = bdrv_write_threshold_exceeded(bs, req);
91
- assert(bs->io_plugged);
111
- if (amount > 0) {
92
- if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
112
- qapi_event_send_block_write_threshold(
93
- BlockDriver *drv = bs->drv;
113
- bs->node_name,
94
- if (drv && drv->bdrv_co_io_unplug) {
114
- amount,
95
- drv->bdrv_co_io_unplug(bs);
115
- bs->write_threshold_offset);
96
- }
116
-
117
- /* autodisable to avoid flooding the monitor */
118
- write_threshold_disable(bs);
119
- }
97
- }
120
-
98
-
121
- return 0; /* should always let other notifiers run */
99
- QLIST_FOREACH(child, &bs->children, next) {
100
- bdrv_co_io_unplug(child->bs);
101
- }
122
-}
102
-}
123
-
103
-
124
-static void write_threshold_register_notifier(BlockDriverState *bs)
104
/* Helper that undoes bdrv_register_buf() when it fails partway through */
125
-{
105
static void GRAPH_RDLOCK
126
- bs->write_threshold_notifier.notify = before_write_notify;
106
bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size,
127
- bdrv_add_before_write_notifier(bs, &bs->write_threshold_notifier);
128
-}
129
-
130
-static void write_threshold_update(BlockDriverState *bs,
131
- int64_t threshold_bytes)
132
-{
133
- bs->write_threshold_offset = threshold_bytes;
134
-}
135
-
136
void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes)
137
{
138
- if (bdrv_write_threshold_is_set(bs)) {
139
- if (threshold_bytes > 0) {
140
- write_threshold_update(bs, threshold_bytes);
141
- } else {
142
- write_threshold_disable(bs);
143
- }
144
- } else {
145
- if (threshold_bytes > 0) {
146
- /* avoid multiple registration */
147
- write_threshold_register_notifier(bs);
148
- write_threshold_update(bs, threshold_bytes);
149
- }
150
- /* discard bogus disable request */
151
- }
152
+ bs->write_threshold_offset = threshold_bytes;
153
}
154
155
void qmp_block_set_write_threshold(const char *node_name,
156
@@ -XXX,XX +XXX,XX @@ void qmp_block_set_write_threshold(const char *node_name,
157
158
aio_context_release(aio_context);
159
}
160
+
161
+void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset,
162
+ int64_t bytes)
163
+{
164
+ int64_t end = offset + bytes;
165
+ uint64_t wtr = bs->write_threshold_offset;
166
+
167
+ if (wtr > 0 && end > wtr) {
168
+ qapi_event_send_block_write_threshold(bs->node_name, end - wtr, wtr);
169
+
170
+ /* autodisable to avoid flooding the monitor */
171
+ bdrv_write_threshold_set(bs, 0);
172
+ }
173
+}
174
--
107
--
175
2.31.1
108
2.40.1
176
177
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
Max reported the following bug:
3
Some virtio-blk drivers (e.g. virtio-blk-vhost-vdpa) supports the fd
4
passing. Let's expose this to the user, so the management layer
5
can pass the file descriptor of an already opened path.
4
6
5
$ ./qemu-img create -f raw src.img 1G
7
If the libblkio virtio-blk driver supports fd passing, let's always
6
$ ./qemu-img create -f raw dst.img 1G
8
use qemu_open() to open the `path`, so we can handle fd passing
9
from the management layer through the "/dev/fdset/N" special path.
7
10
8
$ (echo '
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
{"execute":"qmp_capabilities"}
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
10
{"execute":"blockdev-mirror",
13
Message-id: 20230530071941.8954-2-sgarzare@redhat.com
11
"arguments":{"job-id":"mirror",
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
"device":"source",
15
---
13
"target":"target",
16
block/blkio.c | 53 ++++++++++++++++++++++++++++++++++++++++++---------
14
"sync":"full",
17
1 file changed, 44 insertions(+), 9 deletions(-)
15
"filter-node-name":"mirror-top"}}
16
'; sleep 3; echo '
17
{"execute":"human-monitor-command",
18
"arguments":{"command-line":
19
"qemu-io mirror-top \"write 0 1G\""}}') \
20
| x86_64-softmmu/qemu-system-x86_64 \
21
-qmp stdio \
22
-blockdev file,node-name=source,filename=src.img \
23
-blockdev file,node-name=target,filename=dst.img \
24
-object iothread,id=iothr0 \
25
-device virtio-blk,drive=source,iothread=iothr0
26
18
27
crashes:
19
diff --git a/block/blkio.c b/block/blkio.c
28
29
0 raise () at /usr/lib/libc.so.6
30
1 abort () at /usr/lib/libc.so.6
31
2 error_exit
32
(err=<optimized out>,
33
msg=msg@entry=0x55fbb1634790 <__func__.27> "qemu_mutex_unlock_impl")
34
at ../util/qemu-thread-posix.c:37
35
3 qemu_mutex_unlock_impl
36
(mutex=mutex@entry=0x55fbb25ab6e0,
37
file=file@entry=0x55fbb1636957 "../util/async.c",
38
line=line@entry=650)
39
at ../util/qemu-thread-posix.c:109
40
4 aio_context_release (ctx=ctx@entry=0x55fbb25ab680) at ../util/async.c:650
41
5 bdrv_do_drained_begin
42
(bs=bs@entry=0x55fbb3a87000, recursive=recursive@entry=false,
43
parent=parent@entry=0x0,
44
ignore_bds_parents=ignore_bds_parents@entry=false,
45
poll=poll@entry=true) at ../block/io.c:441
46
6 bdrv_do_drained_begin
47
(poll=true, ignore_bds_parents=false, parent=0x0, recursive=false,
48
bs=0x55fbb3a87000) at ../block/io.c:448
49
7 blk_drain (blk=0x55fbb26c5a00) at ../block/block-backend.c:1718
50
8 blk_unref (blk=0x55fbb26c5a00) at ../block/block-backend.c:498
51
9 blk_unref (blk=0x55fbb26c5a00) at ../block/block-backend.c:491
52
10 hmp_qemu_io (mon=0x7fffaf3fc7d0, qdict=<optimized out>)
53
at ../block/monitor/block-hmp-cmds.c:628
54
55
man pthread_mutex_unlock
56
...
57
EPERM The mutex type is PTHREAD_MUTEX_ERRORCHECK or
58
PTHREAD_MUTEX_RECURSIVE, or the mutex is a robust mutex, and the
59
current thread does not own the mutex.
60
61
So, thread doesn't own the mutex. And we have iothread here.
62
63
Next, note that AIO_WAIT_WHILE() documents that ctx must be acquired
64
exactly once by caller. But where is it acquired in the call stack?
65
Seems nowhere.
66
67
qemuio_command do acquire aio context.. But we need context acquired
68
around blk_unref() as well and actually around blk_insert_bs() too.
69
70
Let's refactor qemuio_command so that it doesn't acquire aio context
71
but callers do that instead. This way we can cleanly acquire aio
72
context in hmp_qemu_io() around all three calls.
73
74
Reported-by: Max Reitz <mreitz@redhat.com>
75
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
76
Message-Id: <20210423134233.51495-1-vsementsov@virtuozzo.com>
77
[mreitz: Fixed comment]
78
Signed-off-by: Max Reitz <mreitz@redhat.com>
79
---
80
block/monitor/block-hmp-cmds.c | 31 +++++++++++++++++++++----------
81
qemu-io-cmds.c | 8 ++++----
82
qemu-io.c | 17 +++++++++++++++--
83
3 files changed, 40 insertions(+), 16 deletions(-)
84
85
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
86
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
87
--- a/block/monitor/block-hmp-cmds.c
21
--- a/block/blkio.c
88
+++ b/block/monitor/block-hmp-cmds.c
22
+++ b/block/blkio.c
89
@@ -XXX,XX +XXX,XX @@ void hmp_eject(Monitor *mon, const QDict *qdict)
23
@@ -XXX,XX +XXX,XX @@ static int blkio_virtio_blk_common_open(BlockDriverState *bs,
90
91
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
92
{
24
{
93
- BlockBackend *blk;
25
const char *path = qdict_get_try_str(options, "path");
94
+ BlockBackend *blk = NULL;
26
BDRVBlkioState *s = bs->opaque;
95
+ BlockDriverState *bs = NULL;
27
- int ret;
96
BlockBackend *local_blk = NULL;
28
+ bool fd_supported = false;
97
+ AioContext *ctx = NULL;
29
+ int fd, ret;
98
bool qdev = qdict_get_try_bool(qdict, "qdev", false);
30
99
const char *device = qdict_get_str(qdict, "device");
31
if (!path) {
100
const char *command = qdict_get_str(qdict, "command");
32
error_setg(errp, "missing 'path' option");
101
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
33
return -EINVAL;
102
} else {
103
blk = blk_by_name(device);
104
if (!blk) {
105
- BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
106
- if (bs) {
107
- blk = local_blk = blk_new(bdrv_get_aio_context(bs),
108
- 0, BLK_PERM_ALL);
109
- ret = blk_insert_bs(blk, bs, &err);
110
- if (ret < 0) {
111
- goto fail;
112
- }
113
- } else {
114
+ bs = bdrv_lookup_bs(NULL, device, &err);
115
+ if (!bs) {
116
goto fail;
117
}
118
}
119
}
34
}
120
35
121
+ ctx = blk ? blk_get_aio_context(blk) : bdrv_get_aio_context(bs);
36
- ret = blkio_set_str(s->blkio, "path", path);
122
+ aio_context_acquire(ctx);
37
- qdict_del(options, "path");
38
- if (ret < 0) {
39
- error_setg_errno(errp, -ret, "failed to set path: %s",
40
- blkio_get_error_msg());
41
- return ret;
42
- }
43
-
44
if (!(flags & BDRV_O_NOCACHE)) {
45
error_setg(errp, "cache.direct=off is not supported");
46
return -EINVAL;
47
}
123
+
48
+
124
+ if (bs) {
49
+ if (blkio_get_int(s->blkio, "fd", &fd) == 0) {
125
+ blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL);
50
+ fd_supported = true;
126
+ ret = blk_insert_bs(blk, bs, &err);
51
+ }
52
+
53
+ /*
54
+ * If the libblkio driver supports fd passing, let's always use qemu_open()
55
+ * to open the `path`, so we can handle fd passing from the management
56
+ * layer through the "/dev/fdset/N" special path.
57
+ */
58
+ if (fd_supported) {
59
+ int open_flags;
60
+
61
+ if (flags & BDRV_O_RDWR) {
62
+ open_flags = O_RDWR;
63
+ } else {
64
+ open_flags = O_RDONLY;
65
+ }
66
+
67
+ fd = qemu_open(path, open_flags, errp);
68
+ if (fd < 0) {
69
+ return -EINVAL;
70
+ }
71
+
72
+ ret = blkio_set_int(s->blkio, "fd", fd);
127
+ if (ret < 0) {
73
+ if (ret < 0) {
128
+ goto fail;
74
+ error_setg_errno(errp, -ret, "failed to set fd: %s",
75
+ blkio_get_error_msg());
76
+ qemu_close(fd);
77
+ return ret;
78
+ }
79
+ } else {
80
+ ret = blkio_set_str(s->blkio, "path", path);
81
+ if (ret < 0) {
82
+ error_setg_errno(errp, -ret, "failed to set path: %s",
83
+ blkio_get_error_msg());
84
+ return ret;
129
+ }
85
+ }
130
+ }
86
+ }
131
+
87
+
132
/*
88
+ qdict_del(options, "path");
133
* Notably absent: Proper permission management. This is sad, but it seems
134
* almost impossible to achieve without changing the semantics and thereby
135
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
136
137
fail:
138
blk_unref(local_blk);
139
+
89
+
140
+ if (ctx) {
90
return 0;
141
+ aio_context_release(ctx);
142
+ }
143
+
144
hmp_handle_error(mon, err);
145
}
91
}
146
92
147
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/qemu-io-cmds.c
150
+++ b/qemu-io-cmds.c
151
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t help_cmd = {
152
.oneline = "help for one or all commands",
153
};
154
155
+/*
156
+ * Called with aio context of blk acquired. Or with qemu_get_aio_context()
157
+ * context acquired if blk is NULL.
158
+ */
159
int qemuio_command(BlockBackend *blk, const char *cmd)
160
{
161
- AioContext *ctx;
162
char *input;
163
const cmdinfo_t *ct;
164
char **v;
165
@@ -XXX,XX +XXX,XX @@ int qemuio_command(BlockBackend *blk, const char *cmd)
166
if (c) {
167
ct = find_command(v[0]);
168
if (ct) {
169
- ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
170
- aio_context_acquire(ctx);
171
ret = command(blk, ct, c, v);
172
- aio_context_release(ctx);
173
} else {
174
fprintf(stderr, "command \"%s\" not found\n", v[0]);
175
ret = -EINVAL;
176
diff --git a/qemu-io.c b/qemu-io.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/qemu-io.c
179
+++ b/qemu-io.c
180
@@ -XXX,XX +XXX,XX @@ static void prep_fetchline(void *opaque)
181
*fetchable= 1;
182
}
183
184
+static int do_qemuio_command(const char *cmd)
185
+{
186
+ int ret;
187
+ AioContext *ctx =
188
+ qemuio_blk ? blk_get_aio_context(qemuio_blk) : qemu_get_aio_context();
189
+
190
+ aio_context_acquire(ctx);
191
+ ret = qemuio_command(qemuio_blk, cmd);
192
+ aio_context_release(ctx);
193
+
194
+ return ret;
195
+}
196
+
197
static int command_loop(void)
198
{
199
int i, fetchable = 0, prompted = 0;
200
@@ -XXX,XX +XXX,XX @@ static int command_loop(void)
201
char *input;
202
203
for (i = 0; !quit_qemu_io && i < ncmdline; i++) {
204
- ret = qemuio_command(qemuio_blk, cmdline[i]);
205
+ ret = do_qemuio_command(cmdline[i]);
206
if (ret < 0) {
207
last_error = ret;
208
}
209
@@ -XXX,XX +XXX,XX @@ static int command_loop(void)
210
if (input == NULL) {
211
break;
212
}
213
- ret = qemuio_command(qemuio_blk, input);
214
+ ret = do_qemuio_command(input);
215
g_free(input);
216
217
if (ret < 0) {
218
--
93
--
219
2.31.1
94
2.40.1
220
221
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
Instead of buffering the test output into a StringIO, patch it on
4
the fly by wrapping sys.stdout's write method. This can be
5
done unconditionally, even if using -d, which makes execute_unittest
6
a bit simpler.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Tested-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20210323181928.311862-2-pbonzini@redhat.com>
12
Message-Id: <20210503110110.476887-2-pbonzini@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/240.out | 8 ++--
16
tests/qemu-iotests/245.out | 8 ++--
17
tests/qemu-iotests/295.out | 6 +--
18
tests/qemu-iotests/296.out | 8 ++--
19
tests/qemu-iotests/iotests.py | 70 ++++++++++++++++++++---------------
20
5 files changed, 56 insertions(+), 44 deletions(-)
21
22
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
23
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qemu-iotests/240.out
25
+++ b/tests/qemu-iotests/240.out
26
@@ -XXX,XX +XXX,XX @@
27
{"return": {}}
28
{"execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
29
{"return": {}}
30
-==Attach two SCSI disks using the same block device and the same iothread==
31
+.==Attach two SCSI disks using the same block device and the same iothread==
32
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}}
33
{"return": {}}
34
{"execute": "object-add", "arguments": {"id": "iothread0", "qom-type": "iothread"}}
35
@@ -XXX,XX +XXX,XX @@
36
{"return": {}}
37
{"execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
38
{"return": {}}
39
-==Attach two SCSI disks using the same block device but different iothreads==
40
+.==Attach two SCSI disks using the same block device but different iothreads==
41
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}}
42
{"return": {}}
43
{"execute": "object-add", "arguments": {"id": "iothread0", "qom-type": "iothread"}}
44
@@ -XXX,XX +XXX,XX @@
45
{"return": {}}
46
{"execute": "blockdev-del", "arguments": {"node-name": "hd0"}}
47
{"return": {}}
48
-==Attach a SCSI disks using the same block device as a NBD server==
49
+.==Attach a SCSI disks using the same block device as a NBD server==
50
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}}
51
{"return": {}}
52
{"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-nbd.sock"}, "type": "unix"}}}
53
@@ -XXX,XX +XXX,XX @@
54
{"return": {}}
55
{"execute": "device_add", "arguments": {"drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd0"}}
56
{"return": {}}
57
-....
58
+.
59
----------------------------------------------------------------------
60
Ran 4 tests
61
62
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/245.out
65
+++ b/tests/qemu-iotests/245.out
66
@@ -XXX,XX +XXX,XX @@
67
-{"execute": "job-finalize", "arguments": {"id": "commit0"}}
68
+..{"execute": "job-finalize", "arguments": {"id": "commit0"}}
69
{"return": {}}
70
{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
71
{"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
72
-{"execute": "job-finalize", "arguments": {"id": "stream0"}}
73
+...{"execute": "job-finalize", "arguments": {"id": "stream0"}}
74
{"return": {}}
75
{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
76
{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
77
-{"execute": "job-finalize", "arguments": {"id": "stream0"}}
78
+.{"execute": "job-finalize", "arguments": {"id": "stream0"}}
79
{"return": {}}
80
{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
81
{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
82
-.....................
83
+...............
84
----------------------------------------------------------------------
85
Ran 21 tests
86
87
diff --git a/tests/qemu-iotests/295.out b/tests/qemu-iotests/295.out
88
index XXXXXXX..XXXXXXX 100644
89
--- a/tests/qemu-iotests/295.out
90
+++ b/tests/qemu-iotests/295.out
91
@@ -XXX,XX +XXX,XX @@
92
{"return": {}}
93
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
94
{"return": {}}
95
-{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
96
+.{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
97
{"return": {}}
98
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
99
{"return": {}}
100
@@ -XXX,XX +XXX,XX @@ Job failed: Invalid password, cannot unlock any keyslot
101
{"return": {}}
102
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
103
{"return": {}}
104
-{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
105
+.{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
106
{"return": {}}
107
{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}}
108
{"return": {}}
109
@@ -XXX,XX +XXX,XX @@ Job failed: All the active keyslots match the (old) password that was given and
110
{"return": {}}
111
{"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}}
112
{"return": {}}
113
-...
114
+.
115
----------------------------------------------------------------------
116
Ran 3 tests
117
118
diff --git a/tests/qemu-iotests/296.out b/tests/qemu-iotests/296.out
119
index XXXXXXX..XXXXXXX 100644
120
--- a/tests/qemu-iotests/296.out
121
+++ b/tests/qemu-iotests/296.out
122
@@ -XXX,XX +XXX,XX @@ Job failed: Failed to get shared "consistent read" lock
123
qemu-img: Failed to get shared "consistent read" lock
124
Is another process using the image [TEST_DIR/test.img]?
125
126
-Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
127
+.Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
128
129
Job failed: Block node is read-only
130
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
131
@@ -XXX,XX +XXX,XX @@ Job failed: Failed to get shared "consistent read" lock
132
{"return": {}}
133
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
134
{"return": {}}
135
-Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
136
+.Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
137
138
{"return": {}}
139
{"error": {"class": "GenericError", "desc": "Failed to get \"write\" lock"}}
140
-Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
141
+.Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10
142
143
{"return": {}}
144
{"return": {}}
145
-....
146
+.
147
----------------------------------------------------------------------
148
Ran 4 tests
149
150
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
151
index XXXXXXX..XXXXXXX 100644
152
--- a/tests/qemu-iotests/iotests.py
153
+++ b/tests/qemu-iotests/iotests.py
154
@@ -XXX,XX +XXX,XX @@
155
import bz2
156
from collections import OrderedDict
157
import faulthandler
158
-import io
159
import json
160
import logging
161
import os
162
@@ -XXX,XX +XXX,XX @@
163
import sys
164
import time
165
from typing import (Any, Callable, Dict, Iterable,
166
- List, Optional, Sequence, Tuple, TypeVar)
167
+ List, Optional, Sequence, TextIO, Tuple, Type, TypeVar)
168
import unittest
169
170
from contextlib import contextmanager
171
@@ -XXX,XX +XXX,XX @@ def func_wrapper(*args, **kwargs):
172
return func(*args, **kwargs)
173
return func_wrapper
174
175
+# We need to filter out the time taken from the output so that
176
+# qemu-iotest can reliably diff the results against master output,
177
+# and hide skipped tests from the reference output.
178
+
179
+class ReproducibleTestResult(unittest.TextTestResult):
180
+ def addSkip(self, test, reason):
181
+ # Same as TextTestResult, but print dot instead of "s"
182
+ unittest.TestResult.addSkip(self, test, reason)
183
+ if self.showAll:
184
+ self.stream.writeln("skipped {0!r}".format(reason))
185
+ elif self.dots:
186
+ self.stream.write(".")
187
+ self.stream.flush()
188
+
189
+class ReproducibleStreamWrapper:
190
+ def __init__(self, stream: TextIO):
191
+ self.stream = stream
192
+
193
+ def __getattr__(self, attr):
194
+ if attr in ('stream', '__getstate__'):
195
+ raise AttributeError(attr)
196
+ return getattr(self.stream, attr)
197
+
198
+ def write(self, arg=None):
199
+ arg = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', arg)
200
+ arg = re.sub(r' \(skipped=\d+\)', r'', arg)
201
+ self.stream.write(arg)
202
+
203
+class ReproducibleTestRunner(unittest.TextTestRunner):
204
+ def __init__(self, stream: Optional[TextIO] = None,
205
+ resultclass: Type[unittest.TestResult] = ReproducibleTestResult,
206
+ **kwargs: Any) -> None:
207
+ rstream = ReproducibleStreamWrapper(stream or sys.stdout)
208
+ super().__init__(stream=rstream, # type: ignore
209
+ descriptions=True,
210
+ resultclass=resultclass,
211
+ **kwargs)
212
+
213
def execute_unittest(debug=False):
214
"""Executes unittests within the calling module."""
215
216
verbosity = 2 if debug else 1
217
-
218
- if debug:
219
- output = sys.stdout
220
- else:
221
- # We need to filter out the time taken from the output so that
222
- # qemu-iotest can reliably diff the results against master output.
223
- output = io.StringIO()
224
-
225
- runner = unittest.TextTestRunner(stream=output, descriptions=True,
226
- verbosity=verbosity)
227
- try:
228
- # unittest.main() will use sys.exit(); so expect a SystemExit
229
- # exception
230
- unittest.main(testRunner=runner)
231
- finally:
232
- # We need to filter out the time taken from the output so that
233
- # qemu-iotest can reliably diff the results against master output.
234
- if not debug:
235
- out = output.getvalue()
236
- out = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', out)
237
-
238
- # Hide skipped tests from the reference output
239
- out = re.sub(r'OK \(skipped=\d+\)', 'OK', out)
240
- out_first_line, out_rest = out.split('\n', 1)
241
- out = out_first_line.replace('s', '.') + '\n' + out_rest
242
-
243
- sys.stderr.write(out)
244
+ runner = ReproducibleTestRunner(verbosity=verbosity)
245
+ unittest.main(testRunner=runner)
246
247
def execute_setup_common(supported_fmts: Sequence[str] = (),
248
supported_platforms: Sequence[str] = (),
249
--
250
2.31.1
251
252
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
Python test scripts that use unittest consist of multiple tests.
4
unittest.main allows selecting which tests to run, but currently this
5
is not possible because the iotests wrapper ignores sys.argv.
6
7
unittest.main command line options also allow the user to pick the
8
desired options for verbosity, failfast mode, etc. While "-d" is
9
currently translated to "-v", it also enables extra debug output,
10
and other options are not available at all.
11
12
These command line options only work if the unittest.main testRunner
13
argument is a type, rather than a TestRunner instance. Therefore, pass
14
the class name and "verbosity" argument to unittest.main, and adjust for
15
the different default warnings between TextTestRunner and unittest.main.
16
17
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
18
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Tested-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
20
Message-Id: <20210323181928.311862-3-pbonzini@redhat.com>
21
Message-Id: <20210503110110.476887-3-pbonzini@redhat.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
tests/qemu-iotests/iotests.py | 14 +++++++++-----
25
1 file changed, 9 insertions(+), 5 deletions(-)
26
27
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/iotests.py
30
+++ b/tests/qemu-iotests/iotests.py
31
@@ -XXX,XX +XXX,XX @@ def __init__(self, stream: Optional[TextIO] = None,
32
resultclass=resultclass,
33
**kwargs)
34
35
-def execute_unittest(debug=False):
36
+def execute_unittest(argv: List[str], debug: bool = False) -> None:
37
"""Executes unittests within the calling module."""
38
39
- verbosity = 2 if debug else 1
40
- runner = ReproducibleTestRunner(verbosity=verbosity)
41
- unittest.main(testRunner=runner)
42
+ # Some tests have warnings, especially ResourceWarnings for unclosed
43
+ # files and sockets. Ignore them for now to ensure reproducibility of
44
+ # the test output.
45
+ unittest.main(argv=argv,
46
+ testRunner=ReproducibleTestRunner,
47
+ verbosity=2 if debug else 1,
48
+ warnings=None if sys.warnoptions else 'ignore')
49
50
def execute_setup_common(supported_fmts: Sequence[str] = (),
51
supported_platforms: Sequence[str] = (),
52
@@ -XXX,XX +XXX,XX @@ def execute_test(*args, test_function=None, **kwargs):
53
54
debug = execute_setup_common(*args, **kwargs)
55
if not test_function:
56
- execute_unittest(debug)
57
+ execute_unittest(sys.argv, debug)
58
else:
59
test_function()
60
61
--
62
2.31.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
In the next patch, "check" will learn how to execute a test script without
4
going through TestRunner. To enable this, keep only the text output
5
and subprocess handling in the TestRunner; move into TestEnv the logic
6
to prepare for running a subprocess.
7
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Tested-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20210323181928.311862-4-pbonzini@redhat.com>
12
Message-Id: <20210503110110.476887-4-pbonzini@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/testenv.py | 17 ++++++++++++++++-
16
tests/qemu-iotests/testrunner.py | 14 +-------------
17
2 files changed, 17 insertions(+), 14 deletions(-)
18
19
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/testenv.py
22
+++ b/tests/qemu-iotests/testenv.py
23
@@ -XXX,XX +XXX,XX @@
24
import random
25
import subprocess
26
import glob
27
-from typing import Dict, Any, Optional, ContextManager
28
+from typing import List, Dict, Any, Optional, ContextManager
29
30
31
def isxfile(path: str) -> bool:
32
@@ -XXX,XX +XXX,XX @@ class TestEnv(ContextManager['TestEnv']):
33
'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
34
'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_']
35
36
+ def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
37
+ if self.debug:
38
+ args.append('-d')
39
+
40
+ with open(args[0], encoding="utf-8") as f:
41
+ try:
42
+ if f.readline().rstrip() == '#!/usr/bin/env python3':
43
+ args.insert(0, self.python)
44
+ except UnicodeDecodeError: # binary test? for future.
45
+ pass
46
+
47
+ os_env = os.environ.copy()
48
+ os_env.update(self.get_env())
49
+ return os_env
50
+
51
def get_env(self) -> Dict[str, str]:
52
env = {}
53
for v in self.env_variables:
54
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
55
index XXXXXXX..XXXXXXX 100644
56
--- a/tests/qemu-iotests/testrunner.py
57
+++ b/tests/qemu-iotests/testrunner.py
58
@@ -XXX,XX +XXX,XX @@ class TestRunner(ContextManager['TestRunner']):
59
def __init__(self, env: TestEnv, makecheck: bool = False,
60
color: str = 'auto') -> None:
61
self.env = env
62
- self.test_run_env = self.env.get_env()
63
self.makecheck = makecheck
64
self.last_elapsed = LastElapsedTime('.last-elapsed-cache', env)
65
66
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
67
silent_unlink(p)
68
69
args = [str(f_test.resolve())]
70
- if self.env.debug:
71
- args.append('-d')
72
-
73
- with f_test.open(encoding="utf-8") as f:
74
- try:
75
- if f.readline().rstrip() == '#!/usr/bin/env python3':
76
- args.insert(0, self.env.python)
77
- except UnicodeDecodeError: # binary test? for future.
78
- pass
79
-
80
- env = os.environ.copy()
81
- env.update(self.test_run_env)
82
+ env = self.env.prepare_subprocess(args)
83
84
t0 = time.time()
85
with f_bad.open('w', encoding="utf-8") as f:
86
--
87
2.31.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
Right now there is no easy way for "check" to print a reproducer command.
4
Because such a reproducer command line would be huge, we can instead teach
5
check to start a command of our choice. This can be for example a Python
6
unit test with arguments to only run a specific subtest.
7
8
Move the trailing empty line to print_env(), since it always looks better
9
and one caller was not adding it.
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Tested-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Message-Id: <20210323181928.311862-5-pbonzini@redhat.com>
15
Message-Id: <20210503110110.476887-5-pbonzini@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
tests/qemu-iotests/check | 19 ++++++++++++++++++-
19
tests/qemu-iotests/testenv.py | 3 ++-
20
tests/qemu-iotests/testrunner.py | 1 -
21
3 files changed, 20 insertions(+), 3 deletions(-)
22
23
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
24
index XXXXXXX..XXXXXXX 100755
25
--- a/tests/qemu-iotests/check
26
+++ b/tests/qemu-iotests/check
27
@@ -XXX,XX +XXX,XX @@
28
import os
29
import sys
30
import argparse
31
+import shutil
32
+from pathlib import Path
33
+
34
from findtests import TestFinder
35
from testenv import TestEnv
36
from testrunner import TestRunner
37
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
38
'rerun failed ./check command, starting from the '
39
'middle of the process.')
40
g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*',
41
- help='tests to run')
42
+ help='tests to run, or "--" followed by a command')
43
44
return p
45
46
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
47
imgopts=args.imgopts, misalign=args.misalign,
48
debug=args.debug, valgrind=args.valgrind)
49
50
+ if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
51
+ if not args.tests:
52
+ sys.exit("missing command after '--'")
53
+ cmd = args.tests
54
+ env.print_env()
55
+ exec_pathstr = shutil.which(cmd[0])
56
+ if exec_pathstr is None:
57
+ sys.exit('command not found: ' + cmd[0])
58
+ exec_path = Path(exec_pathstr).resolve()
59
+ cmd[0] = str(exec_path)
60
+ full_env = env.prepare_subprocess(cmd)
61
+ os.chdir(exec_path.parent)
62
+ os.execve(cmd[0], cmd, full_env)
63
+
64
testfinder = TestFinder(test_dir=env.source_iotests)
65
66
groups = args.groups.split(',') if args.groups else None
67
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
68
index XXXXXXX..XXXXXXX 100644
69
--- a/tests/qemu-iotests/testenv.py
70
+++ b/tests/qemu-iotests/testenv.py
71
@@ -XXX,XX +XXX,XX @@ def print_env(self) -> None:
72
PLATFORM -- {platform}
73
TEST_DIR -- {TEST_DIR}
74
SOCK_DIR -- {SOCK_DIR}
75
-SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}"""
76
+SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
77
+"""
78
79
args = collections.defaultdict(str, self.get_env())
80
81
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
82
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/qemu-iotests/testrunner.py
84
+++ b/tests/qemu-iotests/testrunner.py
85
@@ -XXX,XX +XXX,XX @@ def run_tests(self, tests: List[str]) -> bool:
86
87
if not self.makecheck:
88
self.env.print_env()
89
- print()
90
91
test_field_width = max(len(os.path.basename(t)) for t in tests) + 2
92
93
--
94
2.31.1
95
96
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
Due to a typo, in this case the SOCK_DIR was not being created.
4
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Tested-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Message-Id: <20210323181928.311862-6-pbonzini@redhat.com>
9
Message-Id: <20210503110110.476887-6-pbonzini@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/testenv.py | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/testenv.py
18
+++ b/tests/qemu-iotests/testenv.py
19
@@ -XXX,XX +XXX,XX @@ def init_directories(self) -> None:
20
try:
21
self.sock_dir = os.environ['SOCK_DIR']
22
self.tmp_sock_dir = False
23
- Path(self.test_dir).mkdir(parents=True, exist_ok=True)
24
+ Path(self.sock_dir).mkdir(parents=True, exist_ok=True)
25
except KeyError:
26
self.sock_dir = tempfile.mkdtemp()
27
self.tmp_sock_dir = True
28
--
29
2.31.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Connor Kuehl <ckuehl@redhat.com>
2
1
3
The contents of this patch were initially developed and posted by Han
4
Han[1], however, it appears the original patch was not applied. Since
5
then, the relevant documentation has been moved and adapted to a new
6
format.
7
8
I've taken most of the original wording and tweaked it according to
9
some of the feedback from the original patch submission. I've also
10
adapted it to restructured text, which is the format the documentation
11
currently uses.
12
13
[1] https://lists.nongnu.org/archive/html/qemu-block/2019-10/msg01253.html
14
15
Fixes: https://bugzilla.redhat.com/1763105
16
Signed-off-by: Han Han <hhan@redhat.com>
17
Suggested-by: Max Reitz <mreitz@redhat.com>
18
[ Max: provided description of data_file_raw behavior ]
19
Signed-off-by: Connor Kuehl <ckuehl@redhat.com>
20
Message-Id: <20210505195512.391128-1-ckuehl@redhat.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
23
docs/tools/qemu-img.rst | 31 +++++++++++++++++++++++++++++++
24
1 file changed, 31 insertions(+)
25
26
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
27
index XXXXXXX..XXXXXXX 100644
28
--- a/docs/tools/qemu-img.rst
29
+++ b/docs/tools/qemu-img.rst
30
@@ -XXX,XX +XXX,XX @@ Supported image file formats:
31
issue ``lsattr filename`` to check if the NOCOW flag is set or not
32
(Capital 'C' is NOCOW flag).
33
34
+ ``data_file``
35
+ Filename where all guest data will be stored. If this option is used,
36
+ the qcow2 file will only contain the image's metadata.
37
+
38
+ Note: Data loss will occur if the given filename already exists when
39
+ using this option with ``qemu-img create`` since ``qemu-img`` will create
40
+ the data file anew, overwriting the file's original contents. To simply
41
+ update the reference to point to the given pre-existing file, use
42
+ ``qemu-img amend``.
43
+
44
+ ``data_file_raw``
45
+ If this option is set to ``on``, QEMU will always keep the external data
46
+ file consistent as a standalone read-only raw image.
47
+
48
+ It does this by forwarding all write accesses to the qcow2 file through to
49
+ the raw data file, including their offsets. Therefore, data that is visible
50
+ on the qcow2 node (i.e., to the guest) at some offset is visible at the same
51
+ offset in the raw data file. This results in a read-only raw image. Writes
52
+ that bypass the qcow2 metadata may corrupt the qcow2 metadata because the
53
+ out-of-band writes may result in the metadata falling out of sync with the
54
+ raw image.
55
+
56
+ If this option is ``off``, QEMU will use the data file to store data in an
57
+ arbitrary manner. The file’s content will not make sense without the
58
+ accompanying qcow2 metadata. Where data is written will have no relation to
59
+ its offset as seen by the guest, and some writes (specifically zero writes)
60
+ may not be forwarded to the data file at all, but will only be handled by
61
+ modifying qcow2 metadata.
62
+
63
+ This option can only be enabled if ``data_file`` is set.
64
+
65
``Other``
66
67
QEMU also supports various other image file formats for
68
--
69
2.31.1
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Now, after huge update of block graph permission update algorithm, we
4
don't need this workaround with active state of the filter. Drop it and
5
use new smart bdrv_drop_filter() function.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210506194143.394141-1-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/copy-on-read.c | 33 +--------------------------------
12
1 file changed, 1 insertion(+), 32 deletions(-)
13
14
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/copy-on-read.c
17
+++ b/block/copy-on-read.c
18
@@ -XXX,XX +XXX,XX @@
19
20
21
typedef struct BDRVStateCOR {
22
- bool active;
23
BlockDriverState *bottom_bs;
24
bool chain_frozen;
25
} BDRVStateCOR;
26
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
27
*/
28
bdrv_ref(bottom_bs);
29
}
30
- state->active = true;
31
state->bottom_bs = bottom_bs;
32
33
/*
34
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
35
uint64_t perm, uint64_t shared,
36
uint64_t *nperm, uint64_t *nshared)
37
{
38
- BDRVStateCOR *s = bs->opaque;
39
-
40
- if (!s->active) {
41
- /*
42
- * While the filter is being removed
43
- */
44
- *nperm = 0;
45
- *nshared = BLK_PERM_ALL;
46
- return;
47
- }
48
-
49
*nperm = perm & PERM_PASSTHROUGH;
50
*nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
51
52
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
53
54
void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
55
{
56
- BdrvChild *child;
57
- BlockDriverState *bs;
58
BDRVStateCOR *s = cor_filter_bs->opaque;
59
60
- child = bdrv_filter_child(cor_filter_bs);
61
- if (!child) {
62
- return;
63
- }
64
- bs = child->bs;
65
-
66
- /* Retain the BDS until we complete the graph change. */
67
- bdrv_ref(bs);
68
- /* Hold a guest back from writing while permissions are being reset. */
69
- bdrv_drained_begin(bs);
70
- /* Drop permissions before the graph change. */
71
- s->active = false;
72
/* unfreeze, as otherwise bdrv_replace_node() will fail */
73
if (s->chain_frozen) {
74
s->chain_frozen = false;
75
bdrv_unfreeze_backing_chain(cor_filter_bs, s->bottom_bs);
76
}
77
- bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort);
78
- bdrv_replace_node(cor_filter_bs, bs, &error_abort);
79
-
80
- bdrv_drained_end(bs);
81
- bdrv_unref(bs);
82
+ bdrv_drop_filter(cor_filter_bs, &error_abort);
83
bdrv_unref(cor_filter_bs);
84
}
85
86
--
87
2.31.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
pylint 2.8 introduces consider-using-with error, suggesting
4
to use the 'with' block statement when possible.
5
6
Modify all subprocess.Popen call to use the 'with' statement,
7
except the one in __init__ of QemuIoInteractive class, since
8
it is assigned to a class field and used in other methods.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20210510190449.65948-1-eesposit@redhat.com>
12
[mreitz: Disable bad-option-value warning in the iotests' pylintrc, so
13
that disabling consider-using-with in QemuIoInteractive will
14
not produce a warning in pre-2.8 pylint versions]
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/iotests.py | 65 ++++++++++++++++----------------
18
tests/qemu-iotests/pylintrc | 3 ++
19
tests/qemu-iotests/testrunner.py | 22 +++++------
20
3 files changed, 47 insertions(+), 43 deletions(-)
21
22
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
23
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qemu-iotests/iotests.py
25
+++ b/tests/qemu-iotests/iotests.py
26
@@ -XXX,XX +XXX,XX @@ def qemu_tool_pipe_and_status(tool: str, args: Sequence[str],
27
Run a tool and return both its output and its exit code
28
"""
29
stderr = subprocess.STDOUT if connect_stderr else None
30
- subp = subprocess.Popen(args,
31
- stdout=subprocess.PIPE,
32
- stderr=stderr,
33
- universal_newlines=True)
34
- output = subp.communicate()[0]
35
- if subp.returncode < 0:
36
- cmd = ' '.join(args)
37
- sys.stderr.write(f'{tool} received signal {-subp.returncode}: {cmd}\n')
38
- return (output, subp.returncode)
39
+ with subprocess.Popen(args, stdout=subprocess.PIPE,
40
+ stderr=stderr, universal_newlines=True) as subp:
41
+ output = subp.communicate()[0]
42
+ if subp.returncode < 0:
43
+ cmd = ' '.join(args)
44
+ sys.stderr.write(f'{tool} received signal \
45
+ {-subp.returncode}: {cmd}\n')
46
+ return (output, subp.returncode)
47
48
def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]:
49
"""
50
@@ -XXX,XX +XXX,XX @@ def qemu_io_silent_check(*args):
51
class QemuIoInteractive:
52
def __init__(self, *args):
53
self.args = qemu_io_args_no_fmt + list(args)
54
+ # We need to keep the Popen objext around, and not
55
+ # close it immediately. Therefore, disable the pylint check:
56
+ # pylint: disable=consider-using-with
57
self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE,
58
stdout=subprocess.PIPE,
59
stderr=subprocess.STDOUT,
60
@@ -XXX,XX +XXX,XX @@ def qemu_nbd_popen(*args):
61
cmd.extend(args)
62
63
log('Start NBD server')
64
- p = subprocess.Popen(cmd)
65
- try:
66
- while not os.path.exists(pid_file):
67
- if p.poll() is not None:
68
- raise RuntimeError(
69
- "qemu-nbd terminated with exit code {}: {}"
70
- .format(p.returncode, ' '.join(cmd)))
71
-
72
- time.sleep(0.01)
73
- yield
74
- finally:
75
- if os.path.exists(pid_file):
76
- os.remove(pid_file)
77
- log('Kill NBD server')
78
- p.kill()
79
- p.wait()
80
+ with subprocess.Popen(cmd) as p:
81
+ try:
82
+ while not os.path.exists(pid_file):
83
+ if p.poll() is not None:
84
+ raise RuntimeError(
85
+ "qemu-nbd terminated with exit code {}: {}"
86
+ .format(p.returncode, ' '.join(cmd)))
87
+
88
+ time.sleep(0.01)
89
+ yield
90
+ finally:
91
+ if os.path.exists(pid_file):
92
+ os.remove(pid_file)
93
+ log('Kill NBD server')
94
+ p.kill()
95
+ p.wait()
96
97
def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
98
'''Return True if two image files are identical'''
99
@@ -XXX,XX +XXX,XX @@ def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
100
101
def create_image(name, size):
102
'''Create a fully-allocated raw image with sector markers'''
103
- file = open(name, 'wb')
104
- i = 0
105
- while i < size:
106
- sector = struct.pack('>l504xl', i // 512, i // 512)
107
- file.write(sector)
108
- i = i + 512
109
- file.close()
110
+ with open(name, 'wb') as file:
111
+ i = 0
112
+ while i < size:
113
+ sector = struct.pack('>l504xl', i // 512, i // 512)
114
+ file.write(sector)
115
+ i = i + 512
116
117
def image_size(img):
118
'''Return image's virtual size'''
119
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
120
index XXXXXXX..XXXXXXX 100644
121
--- a/tests/qemu-iotests/pylintrc
122
+++ b/tests/qemu-iotests/pylintrc
123
@@ -XXX,XX +XXX,XX @@ disable=invalid-name,
124
too-many-public-methods,
125
# pylint warns about Optional[] etc. as unsubscriptable in 3.9
126
unsubscriptable-object,
127
+ # Sometimes we need to disable a newly introduced pylint warning.
128
+ # Doing so should not produce a warning in older versions of pylint.
129
+ bad-option-value,
130
# These are temporary, and should be removed:
131
missing-docstring,
132
too-many-return-statements,
133
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
134
index XXXXXXX..XXXXXXX 100644
135
--- a/tests/qemu-iotests/testrunner.py
136
+++ b/tests/qemu-iotests/testrunner.py
137
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
138
139
t0 = time.time()
140
with f_bad.open('w', encoding="utf-8") as f:
141
- proc = subprocess.Popen(args, cwd=str(f_test.parent), env=env,
142
- stdout=f, stderr=subprocess.STDOUT)
143
- try:
144
- proc.wait()
145
- except KeyboardInterrupt:
146
- proc.terminate()
147
- proc.wait()
148
- return TestResult(status='not run',
149
- description='Interrupted by user',
150
- interrupted=True)
151
- ret = proc.returncode
152
+ with subprocess.Popen(args, cwd=str(f_test.parent), env=env,
153
+ stdout=f, stderr=subprocess.STDOUT) as proc:
154
+ try:
155
+ proc.wait()
156
+ except KeyboardInterrupt:
157
+ proc.terminate()
158
+ proc.wait()
159
+ return TestResult(status='not run',
160
+ description='Interrupted by user',
161
+ interrupted=True)
162
+ ret = proc.returncode
163
164
elapsed = round(time.time() - t0, 1)
165
166
--
167
2.31.1
168
169
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
They are unused now.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210506090621.11848-3-vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
include/block/block_int.h | 12 ------------
12
block.c | 1 -
13
block/io.c | 6 ------
14
3 files changed, 19 deletions(-)
15
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block_int.h
19
+++ b/include/block/block_int.h
20
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
21
*/
22
int64_t total_sectors;
23
24
- /* Callback before write request is processed */
25
- NotifierWithReturnList before_write_notifiers;
26
-
27
/* threshold limit for writes, in bytes. "High water mark". */
28
uint64_t write_threshold_offset;
29
30
@@ -XXX,XX +XXX,XX @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
31
bool bdrv_backing_overridden(BlockDriverState *bs);
32
33
34
-/**
35
- * bdrv_add_before_write_notifier:
36
- *
37
- * Register a callback that is invoked before write requests are processed but
38
- * after any throttling or waiting for overlapping requests.
39
- */
40
-void bdrv_add_before_write_notifier(BlockDriverState *bs,
41
- NotifierWithReturn *notifier);
42
-
43
/**
44
* bdrv_add_aio_context_notifier:
45
*
46
diff --git a/block.c b/block.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block.c
49
+++ b/block.c
50
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_new(void)
51
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
52
QLIST_INIT(&bs->op_blockers[i]);
53
}
54
- notifier_with_return_list_init(&bs->before_write_notifiers);
55
qemu_co_mutex_init(&bs->reqs_lock);
56
qemu_mutex_init(&bs->dirty_bitmap_mutex);
57
bs->refcnt = 1;
58
diff --git a/block/io.c b/block/io.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/block/io.c
61
+++ b/block/io.c
62
@@ -XXX,XX +XXX,XX @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
63
return true;
64
}
65
66
-void bdrv_add_before_write_notifier(BlockDriverState *bs,
67
- NotifierWithReturn *notifier)
68
-{
69
- notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
70
-}
71
-
72
void bdrv_io_plug(BlockDriverState *bs)
73
{
74
BdrvChild *child;
75
--
76
2.31.1
77
78
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
These tests use bdrv_write_threshold_exceeded() API, which is used only
3
The virtio-blk-vhost-vdpa driver in libblkio 1.3.0 supports the fd
4
for test (since pre-previous commit). Better is testing real API, which
4
passing through the new 'fd' property.
5
is used in block.c as well.
6
5
7
So, let's call bdrv_write_threshold_check_write(), and check is
6
Since now we are using qemu_open() on '@path' if the virtio-blk driver
8
bs->write_threshold_offset cleared or not (it's cleared iff threshold
7
supports the fd passing, let's announce it.
9
triggered).
8
In this way, the management layer can pass the file descriptor of an
9
already opened vhost-vdpa character device. This is useful especially
10
when the device can only be accessed with certain privileges.
10
11
11
Also we get rid of BdrvTrackedRequest use here. Note, that paranoiac
12
Add the '@fdset' feature only when the virtio-blk-vhost-vdpa driver
12
bdrv_check_request() calls were added in 8b1170012b1 to protect
13
in libblkio supports it.
13
BdrvTrackedRequest. Drop them now.
14
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Suggested-by: Markus Armbruster <armbru@redhat.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <20210506090621.11848-4-vsementsov@virtuozzo.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
18
Message-id: 20230530071941.8954-3-sgarzare@redhat.com
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
---
20
---
21
tests/unit/test-write-threshold.c | 22 ++++------------------
21
qapi/block-core.json | 6 ++++++
22
1 file changed, 4 insertions(+), 18 deletions(-)
22
meson.build | 4 ++++
23
2 files changed, 10 insertions(+)
23
24
24
diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c
25
diff --git a/qapi/block-core.json b/qapi/block-core.json
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/unit/test-write-threshold.c
27
--- a/qapi/block-core.json
27
+++ b/tests/unit/test-write-threshold.c
28
+++ b/qapi/block-core.json
28
@@ -XXX,XX +XXX,XX @@ static void test_threshold_multi_set_get(void)
29
@@ -XXX,XX +XXX,XX @@
29
30
#
30
static void test_threshold_not_trigger(void)
31
# @path: path to the vhost-vdpa character device.
31
{
32
#
32
- uint64_t amount = 0;
33
+# Features:
33
uint64_t threshold = 4 * 1024 * 1024;
34
+# @fdset: Member @path supports the special "/dev/fdset/N" path
34
BlockDriverState bs;
35
+# (since 8.1)
35
- BdrvTrackedRequest req;
36
+#
36
37
# Since: 7.2
37
memset(&bs, 0, sizeof(bs));
38
##
38
- memset(&req, 0, sizeof(req));
39
{ 'struct': 'BlockdevOptionsVirtioBlkVhostVdpa',
39
- req.offset = 1024;
40
'data': { 'path': 'str' },
40
- req.bytes = 1024;
41
+ 'features': [ { 'name' :'fdset',
41
-
42
+ 'if': 'CONFIG_BLKIO_VHOST_VDPA_FD' } ],
42
- bdrv_check_request(req.offset, req.bytes, &error_abort);
43
'if': 'CONFIG_BLKIO' }
43
44
44
bdrv_write_threshold_set(&bs, threshold);
45
##
45
- amount = bdrv_write_threshold_exceeded(&bs, &req);
46
diff --git a/meson.build b/meson.build
46
- g_assert_cmpuint(amount, ==, 0);
47
index XXXXXXX..XXXXXXX 100644
47
+ bdrv_write_threshold_check_write(&bs, 1024, 1024);
48
--- a/meson.build
48
+ g_assert_cmpuint(bdrv_write_threshold_get(&bs), ==, threshold);
49
+++ b/meson.build
49
}
50
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_LZO', lzo.found())
50
51
config_host_data.set('CONFIG_MPATH', mpathpersist.found())
51
52
config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
52
static void test_threshold_trigger(void)
53
config_host_data.set('CONFIG_BLKIO', blkio.found())
53
{
54
+if blkio.found()
54
- uint64_t amount = 0;
55
+ config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
55
uint64_t threshold = 4 * 1024 * 1024;
56
+ blkio.version().version_compare('>=1.3.0'))
56
BlockDriverState bs;
57
+endif
57
- BdrvTrackedRequest req;
58
config_host_data.set('CONFIG_CURL', curl.found())
58
59
config_host_data.set('CONFIG_CURSES', curses.found())
59
memset(&bs, 0, sizeof(bs));
60
config_host_data.set('CONFIG_GBM', gbm.found())
60
- memset(&req, 0, sizeof(req));
61
- req.offset = (4 * 1024 * 1024) - 1024;
62
- req.bytes = 2 * 1024;
63
-
64
- bdrv_check_request(req.offset, req.bytes, &error_abort);
65
66
bdrv_write_threshold_set(&bs, threshold);
67
- amount = bdrv_write_threshold_exceeded(&bs, &req);
68
- g_assert_cmpuint(amount, >=, 1024);
69
+ bdrv_write_threshold_check_write(&bs, threshold - 1024, 2 * 1024);
70
+ g_assert_cmpuint(bdrv_write_threshold_get(&bs), ==, 0);
71
}
72
73
typedef struct TestStruct {
74
--
61
--
75
2.31.1
62
2.40.1
76
77
diff view generated by jsdifflib