1
The following changes since commit c6a5fc2ac76c5ab709896ee1b0edd33685a67ed1:
1
The following changes since commit 30aa19446d82358a30eac3b556b4d6641e00b7c1:
2
2
3
decodetree: Add --output-null for meson testing (2023-05-31 19:56:42 -0700)
3
Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20200812' into staging (2020-08-24 16:39:53 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-08-26
8
8
9
for you to fetch changes up to 98b126f5e3228a346c774e569e26689943b401dd:
9
for you to fetch changes up to a5d3cfa2dc775e5d99f013703b8508f1d989d588:
10
10
11
qapi: add '@fdset' feature for BlockdevOptionsVirtioBlkVhostVdpa (2023-06-01 11:08:21 -0400)
11
iotests: Add tests for qcow2 images with extended L2 entries (2020-08-26 08:49:51 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Pull request
14
Block patches:
15
15
- qcow2 subclusters (extended L2 entries)
16
- Stefano Garzarella's blkio block driver 'fd' parameter
17
- My thread-local blk_io_plug() series
18
16
19
----------------------------------------------------------------
17
----------------------------------------------------------------
18
v2:
19
- Fixed the shebang line in iotest 271
20
20
21
Stefan Hajnoczi (6):
21
----------------------------------------------------------------
22
block: add blk_io_plug_call() API
22
Alberto Garcia (34):
23
block/nvme: convert to blk_io_plug_call() API
23
qcow2: Make Qcow2AioTask store the full host offset
24
block/blkio: convert to blk_io_plug_call() API
24
qcow2: Convert qcow2_get_cluster_offset() into qcow2_get_host_offset()
25
block/io_uring: convert to blk_io_plug_call() API
25
qcow2: Add calculate_l2_meta()
26
block/linux-aio: convert to blk_io_plug_call() API
26
qcow2: Split cluster_needs_cow() out of count_cow_clusters()
27
block: remove bdrv_co_io_plug() API
27
qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in handle_copied()
28
qcow2: Add get_l2_entry() and set_l2_entry()
29
qcow2: Document the Extended L2 Entries feature
30
qcow2: Add dummy has_subclusters() function
31
qcow2: Add subcluster-related fields to BDRVQcow2State
32
qcow2: Add offset_to_sc_index()
33
qcow2: Add offset_into_subcluster() and size_to_subclusters()
34
qcow2: Add l2_entry_size()
35
qcow2: Update get/set_l2_entry() and add get/set_l2_bitmap()
36
qcow2: Add QCow2SubclusterType and qcow2_get_subcluster_type()
37
qcow2: Add qcow2_get_subcluster_range_type()
38
qcow2: Add qcow2_cluster_is_allocated()
39
qcow2: Add cluster type parameter to qcow2_get_host_offset()
40
qcow2: Replace QCOW2_CLUSTER_* with QCOW2_SUBCLUSTER_*
41
qcow2: Handle QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC
42
qcow2: Add subcluster support to calculate_l2_meta()
43
qcow2: Add subcluster support to qcow2_get_host_offset()
44
qcow2: Add subcluster support to zero_in_l2_slice()
45
qcow2: Add subcluster support to discard_in_l2_slice()
46
qcow2: Add subcluster support to check_refcounts_l2()
47
qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()
48
qcow2: Clear the L2 bitmap when allocating a compressed cluster
49
qcow2: Add subcluster support to handle_alloc_space()
50
qcow2: Add subcluster support to qcow2_co_pwrite_zeroes()
51
qcow2: Add subcluster support to qcow2_measure()
52
qcow2: Add prealloc field to QCowL2Meta
53
qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit
54
qcow2: Allow preallocation and backing files if extended_l2 is set
55
qcow2: Assert that expand_zero_clusters_in_l1() does not support
56
subclusters
57
iotests: Add tests for qcow2 images with extended L2 entries
28
58
29
Stefano Garzarella (2):
59
docs/interop/qcow2.txt | 68 ++-
30
block/blkio: use qemu_open() to support fd passing for virtio-blk
60
docs/qcow2-cache.txt | 19 +-
31
qapi: add '@fdset' feature for BlockdevOptionsVirtioBlkVhostVdpa
61
qapi/block-core.json | 7 +
32
62
block/qcow2.h | 211 ++++++-
33
MAINTAINERS | 1 +
63
include/block/block_int.h | 1 +
34
qapi/block-core.json | 6 ++
64
block/qcow2-cluster.c | 906 +++++++++++++++++++++----------
35
meson.build | 4 +
65
block/qcow2-refcount.c | 47 +-
36
include/block/block-io.h | 3 -
66
block/qcow2.c | 302 +++++++----
37
include/block/block_int-common.h | 11 ---
67
block/trace-events | 2 +-
38
include/block/raw-aio.h | 14 ---
68
tests/qemu-iotests/031.out | 8 +-
39
include/sysemu/block-backend-io.h | 13 +--
69
tests/qemu-iotests/036.out | 4 +-
40
block/blkio.c | 96 ++++++++++++------
70
tests/qemu-iotests/049.out | 102 ++--
41
block/block-backend.c | 22 -----
71
tests/qemu-iotests/060.out | 3 +-
42
block/file-posix.c | 38 -------
72
tests/qemu-iotests/061 | 6 +
43
block/io.c | 37 -------
73
tests/qemu-iotests/061.out | 25 +-
44
block/io_uring.c | 44 ++++-----
74
tests/qemu-iotests/065 | 12 +-
45
block/linux-aio.c | 41 +++-----
75
tests/qemu-iotests/082.out | 39 +-
46
block/nvme.c | 44 +++------
76
tests/qemu-iotests/085.out | 38 +-
47
block/plug.c | 159 ++++++++++++++++++++++++++++++
77
tests/qemu-iotests/144.out | 4 +-
48
hw/block/dataplane/xen-block.c | 8 +-
78
tests/qemu-iotests/182.out | 2 +-
49
hw/block/virtio-blk.c | 4 +-
79
tests/qemu-iotests/185.out | 8 +-
50
hw/scsi/virtio-scsi.c | 6 +-
80
tests/qemu-iotests/198 | 2 +
51
block/meson.build | 1 +
81
tests/qemu-iotests/206.out | 6 +-
52
block/trace-events | 6 +-
82
tests/qemu-iotests/242.out | 5 +
53
20 files changed, 293 insertions(+), 265 deletions(-)
83
tests/qemu-iotests/255.out | 8 +-
54
create mode 100644 block/plug.c
84
tests/qemu-iotests/271 | 901 ++++++++++++++++++++++++++++++
85
tests/qemu-iotests/271.out | 726 +++++++++++++++++++++++++
86
tests/qemu-iotests/274.out | 49 +-
87
tests/qemu-iotests/280.out | 2 +-
88
tests/qemu-iotests/291.out | 2 +
89
tests/qemu-iotests/302.out | 1 +
90
tests/qemu-iotests/303.out | 4 +-
91
tests/qemu-iotests/common.filter | 1 +
92
tests/qemu-iotests/group | 1 +
93
34 files changed, 2952 insertions(+), 570 deletions(-)
94
create mode 100755 tests/qemu-iotests/271
95
create mode 100644 tests/qemu-iotests/271.out
55
96
56
--
97
--
57
2.40.1
98
2.26.2
99
100
diff view generated by jsdifflib
Deleted patch
1
Introduce a new API for thread-local blk_io_plug() that does not
2
traverse the block graph. The goal is to make blk_io_plug() multi-queue
3
friendly.
4
1
5
Instead of having block drivers track whether or not we're in a plugged
6
section, provide an API that allows them to defer a function call until
7
we're unplugged: blk_io_plug_call(fn, opaque). If blk_io_plug_call() is
8
called multiple times with the same fn/opaque pair, then fn() is only
9
called once at the end of the function - resulting in batching.
10
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>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
22
Acked-by: Kevin Wolf <kwolf@redhat.com>
23
Message-id: 20230530180959.1108766-2-stefanha@redhat.com
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
---
26
MAINTAINERS | 1 +
27
include/sysemu/block-backend-io.h | 13 +--
28
block/block-backend.c | 22 -----
29
block/plug.c | 159 ++++++++++++++++++++++++++++++
30
hw/block/dataplane/xen-block.c | 8 +-
31
hw/block/virtio-blk.c | 4 +-
32
hw/scsi/virtio-scsi.c | 6 +-
33
block/meson.build | 1 +
34
8 files changed, 173 insertions(+), 41 deletions(-)
35
create mode 100644 block/plug.c
36
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);
56
57
-/*
58
- * blk_io_plug/unplug are thread-local operations. This means that multiple
59
- * IOThreads can simultaneously call plug/unplug, but the caller must ensure
60
- * that each unplug() is called in the same IOThread of the matching plug().
61
- */
62
-void coroutine_fn blk_co_io_plug(BlockBackend *blk);
63
-void co_wrapper blk_io_plug(BlockBackend *blk);
64
-
65
-void coroutine_fn blk_co_io_unplug(BlockBackend *blk);
66
-void co_wrapper blk_io_unplug(BlockBackend *blk);
67
+void blk_io_plug(void);
68
+void blk_io_unplug(void);
69
+void blk_io_plug_call(void (*fn)(void *), void *opaque);
70
71
AioContext *blk_get_aio_context(BlockBackend *blk);
72
BlockAcctStats *blk_get_stats(BlockBackend *blk);
73
diff --git a/block/block-backend.c b/block/block-backend.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/block-backend.c
76
+++ b/block/block-backend.c
77
@@ -XXX,XX +XXX,XX @@ void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
78
notifier_list_add(&blk->insert_bs_notifiers, notify);
79
}
80
81
-void coroutine_fn blk_co_io_plug(BlockBackend *blk)
82
-{
83
- BlockDriverState *bs = blk_bs(blk);
84
- IO_CODE();
85
- GRAPH_RDLOCK_GUARD();
86
-
87
- if (bs) {
88
- bdrv_co_io_plug(bs);
89
- }
90
-}
91
-
92
-void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
93
-{
94
- BlockDriverState *bs = blk_bs(blk);
95
- IO_CODE();
96
- GRAPH_RDLOCK_GUARD();
97
-
98
- if (bs) {
99
- bdrv_co_io_unplug(bs);
100
- }
101
-}
102
-
103
BlockAcctStats *blk_get_stats(BlockBackend *blk)
104
{
105
IO_CODE();
106
diff --git a/block/plug.c b/block/plug.c
107
new file mode 100644
108
index XXXXXXX..XXXXXXX
109
--- /dev/null
110
+++ b/block/plug.c
111
@@ -XXX,XX +XXX,XX @@
112
+/* SPDX-License-Identifier: GPL-2.0-or-later */
113
+/*
114
+ * Block I/O plugging
115
+ *
116
+ * Copyright Red Hat.
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));
328
}
329
330
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
331
index XXXXXXX..XXXXXXX 100644
332
--- a/hw/scsi/virtio-scsi.c
333
+++ b/hw/scsi/virtio-scsi.c
334
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
335
return -ENOBUFS;
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;
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',
373
--
374
2.40.1
diff view generated by jsdifflib
Deleted patch
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.
4
1
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-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(-)
15
16
diff --git a/block/nvme.c b/block/nvme.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nvme.c
19
+++ b/block/nvme.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "qemu/vfio-helpers.h"
22
#include "block/block-io.h"
23
#include "block/block_int.h"
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)
87
-{
88
- BDRVNVMeState *s = bs->opaque;
89
- assert(!s->plugged);
90
- s->plugged = true;
91
-}
92
-
93
-static void coroutine_fn nvme_co_io_unplug(BlockDriverState *bs)
94
-{
95
- BDRVNVMeState *s = bs->opaque;
96
- assert(s->plugged);
97
- s->plugged = false;
98
- for (unsigned i = INDEX_IO(0); i < s->queue_count; i++) {
99
- NVMeQueuePair *q = s->queues[i];
100
- qemu_mutex_lock(&q->lock);
101
- nvme_kick(q);
102
- nvme_process_completion(q);
103
- qemu_mutex_unlock(&q->lock);
104
- }
105
-}
106
-
107
static bool nvme_register_buf(BlockDriverState *bs, void *host, size_t size,
108
Error **errp)
109
{
110
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
111
.bdrv_detach_aio_context = nvme_detach_aio_context,
112
.bdrv_attach_aio_context = nvme_attach_aio_context,
113
114
- .bdrv_co_io_plug = nvme_co_io_plug,
115
- .bdrv_co_io_unplug = nvme_co_io_unplug,
116
-
117
.bdrv_register_buf = nvme_register_buf,
118
.bdrv_unregister_buf = nvme_unregister_buf,
119
};
120
diff --git a/block/trace-events b/block/trace-events
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/trace-events
123
+++ b/block/trace-events
124
@@ -XXX,XX +XXX,XX @@ nvme_kick(void *s, unsigned q_index) "s %p q #%u"
125
nvme_dma_flush_queue_wait(void *s) "s %p"
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"
127
nvme_process_completion(void *s, unsigned q_index, int inflight) "s %p q #%u inflight %d"
128
-nvme_process_completion_queue_plugged(void *s, unsigned q_index) "s %p q #%u"
129
nvme_complete_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
130
nvme_submit_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
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"
132
--
133
2.40.1
diff view generated by jsdifflib
Deleted patch
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.
4
1
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-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(-)
14
15
diff --git a/block/blkio.c b/block/blkio.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/blkio.c
18
+++ b/block/blkio.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "qemu/error-report.h"
21
#include "qapi/qmp/qdict.h"
22
#include "qemu/module.h"
23
+#include "sysemu/block-backend.h"
24
#include "exec/memory.h" /* for ram_block_discard_disable() */
25
26
#include "block/block-io.h"
27
@@ -XXX,XX +XXX,XX @@ static void blkio_detach_aio_context(BlockDriverState *bs)
28
NULL, NULL, NULL);
29
}
30
31
-/* Call with s->blkio_lock held to submit I/O after enqueuing a new request */
32
-static void blkio_submit_io(BlockDriverState *bs)
33
+/*
34
+ * Called by blk_io_unplug() or immediately if not plugged. Called without
35
+ * blkio_lock.
36
+ */
37
+static void blkio_unplug_fn(void *opaque)
38
{
39
- if (qatomic_read(&bs->io_plugged) == 0) {
40
- BDRVBlkioState *s = bs->opaque;
41
+ BDRVBlkioState *s = opaque;
42
43
+ WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
44
blkioq_do_io(s->blkioq, NULL, 0, 0, NULL);
45
}
46
}
47
48
+/*
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)
61
{
62
@@ -XXX,XX +XXX,XX @@ blkio_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
63
64
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
65
blkioq_discard(s->blkioq, offset, bytes, &cod, 0);
66
- blkio_submit_io(bs);
67
}
68
69
+ blkio_submit_io(bs);
70
qemu_coroutine_yield();
71
return cod.ret;
72
}
73
@@ -XXX,XX +XXX,XX @@ blkio_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
74
75
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
76
blkioq_readv(s->blkioq, offset, iov, iovcnt, &cod, 0);
77
- blkio_submit_io(bs);
78
}
79
80
+ blkio_submit_io(bs);
81
qemu_coroutine_yield();
82
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;
105
}
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkio_co_pwrite_zeroes(BlockDriverState *bs,
107
108
WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
109
blkioq_write_zeroes(s->blkioq, offset, bytes, &cod, blkio_flags);
110
- blkio_submit_io(bs);
111
}
112
113
+ blkio_submit_io(bs);
114
qemu_coroutine_yield();
115
return cod.ret;
116
}
117
118
-static void coroutine_fn blkio_co_io_unplug(BlockDriverState *bs)
119
-{
120
- BDRVBlkioState *s = bs->opaque;
121
-
122
- WITH_QEMU_LOCK_GUARD(&s->blkio_lock) {
123
- blkio_submit_io(bs);
124
- }
125
-}
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, \
138
--
139
2.40.1
diff view generated by jsdifflib
Deleted patch
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.
4
1
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(-)
17
18
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/raw-aio.h
21
+++ b/include/block/raw-aio.h
22
@@ -XXX,XX +XXX,XX @@ int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
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
49
}
50
51
static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
52
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_io_unplug(BlockDriverState *bs)
53
laio_io_unplug(s->aio_max_batch);
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
-}
111
-
112
-void luring_io_unplug(void)
113
-{
114
- AioContext *ctx = qemu_get_current_aio_context();
115
- LuringState *s = aio_get_linux_io_uring(ctx);
116
- assert(s->io_q.plugged);
117
- trace_luring_io_unplug(s, s->io_q.blocked, s->io_q.plugged,
118
- s->io_q.in_queue, s->io_q.in_flight);
119
- if (--s->io_q.plugged == 0 &&
120
- !s->io_q.blocked && s->io_q.in_queue > 0) {
121
+ LuringState *s = opaque;
122
+ trace_luring_unplug_fn(s, s->io_q.blocked, s->io_q.in_queue,
123
+ s->io_q.in_flight);
124
+ if (!s->io_q.blocked && s->io_q.in_queue > 0) {
125
ioq_submit(s);
126
}
127
}
128
@@ -XXX,XX +XXX,XX @@ static int luring_do_submit(int fd, LuringAIOCB *luringcb, LuringState *s,
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
+ }
148
+
149
+ blk_io_plug_call(luring_unplug_fn, s);
150
}
151
return 0;
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"
169
--
170
2.40.1
diff view generated by jsdifflib
Deleted patch
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.
4
1
5
Note that a dev_max_batch check is dropped in laio_io_unplug() because
6
the semantics of unplug_fn() are different from .bdrv_co_unplug():
7
1. unplug_fn() is only called when the last blk_io_unplug() call occurs,
8
not every time blk_io_unplug() is called.
9
2. unplug_fn() is per-thread, not per-BlockDriverState, so there is no
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>
23
---
24
include/block/raw-aio.h | 7 -------
25
block/file-posix.c | 28 ----------------------------
26
block/linux-aio.c | 41 +++++++++++------------------------------
27
3 files changed, 11 insertions(+), 65 deletions(-)
28
29
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/block/raw-aio.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
118
@@ -XXX,XX +XXX,XX @@
119
#include "qemu/event_notifier.h"
120
#include "qemu/coroutine.h"
121
#include "qapi/error.h"
122
+#include "sysemu/block-backend.h"
123
124
/* Only used for assertions. */
125
#include "qemu/coroutine_int.h"
126
@@ -XXX,XX +XXX,XX @@ struct qemu_laiocb {
127
};
128
129
typedef struct {
130
- int plugged;
131
unsigned int in_queue;
132
unsigned int in_flight;
133
bool blocked;
134
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completions_and_submit(LinuxAioState *s)
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;
203
--
204
2.40.1
diff view generated by jsdifflib
Deleted patch
1
No block driver implements .bdrv_co_io_plug() anymore. Get rid of the
2
function pointers.
3
1
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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(-)
15
16
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-io.h
19
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ void 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)(
46
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
47
unsigned int in_flight;
48
unsigned int serialising_in_flight;
49
50
- /*
51
- * counter for nested bdrv_io_plug.
52
- * Accessed with atomic ops.
53
- */
54
- unsigned io_plugged;
55
-
56
/* do we need to tell the quest if we have a volatile write cache? */
57
int enable_write_cache;
58
59
diff --git a/block/io.c b/block/io.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/block/io.c
62
+++ b/block/io.c
63
@@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
64
return mem;
65
}
66
67
-void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
68
-{
69
- BdrvChild *child;
70
- IO_CODE();
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
- }
82
- }
83
-}
84
-
85
-void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
86
-{
87
- BdrvChild *child;
88
- IO_CODE();
89
- assert_bdrv_graph_readable();
90
-
91
- assert(bs->io_plugged);
92
- if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
93
- BlockDriver *drv = bs->drv;
94
- if (drv && drv->bdrv_co_io_unplug) {
95
- drv->bdrv_co_io_unplug(bs);
96
- }
97
- }
98
-
99
- QLIST_FOREACH(child, &bs->children, next) {
100
- bdrv_co_io_unplug(child->bs);
101
- }
102
-}
103
-
104
/* Helper that undoes bdrv_register_buf() when it fails partway through */
105
static void GRAPH_RDLOCK
106
bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size,
107
--
108
2.40.1
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
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.
6
7
If the libblkio virtio-blk driver supports fd passing, let's always
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.
10
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
13
Message-id: 20230530071941.8954-2-sgarzare@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
16
block/blkio.c | 53 ++++++++++++++++++++++++++++++++++++++++++---------
17
1 file changed, 44 insertions(+), 9 deletions(-)
18
19
diff --git a/block/blkio.c b/block/blkio.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/blkio.c
22
+++ b/block/blkio.c
23
@@ -XXX,XX +XXX,XX @@ static int blkio_virtio_blk_common_open(BlockDriverState *bs,
24
{
25
const char *path = qdict_get_try_str(options, "path");
26
BDRVBlkioState *s = bs->opaque;
27
- int ret;
28
+ bool fd_supported = false;
29
+ int fd, ret;
30
31
if (!path) {
32
error_setg(errp, "missing 'path' option");
33
return -EINVAL;
34
}
35
36
- ret = blkio_set_str(s->blkio, "path", path);
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
}
48
+
49
+ if (blkio_get_int(s->blkio, "fd", &fd) == 0) {
50
+ fd_supported = true;
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);
73
+ if (ret < 0) {
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;
85
+ }
86
+ }
87
+
88
+ qdict_del(options, "path");
89
+
90
return 0;
91
}
92
93
--
94
2.40.1
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
The virtio-blk-vhost-vdpa driver in libblkio 1.3.0 supports the fd
4
passing through the new 'fd' property.
5
6
Since now we are using qemu_open() on '@path' if the virtio-blk driver
7
supports the fd passing, let's announce it.
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.
11
12
Add the '@fdset' feature only when the virtio-blk-vhost-vdpa driver
13
in libblkio supports it.
14
15
Suggested-by: Markus Armbruster <armbru@redhat.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@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
---
21
qapi/block-core.json | 6 ++++++
22
meson.build | 4 ++++
23
2 files changed, 10 insertions(+)
24
25
diff --git a/qapi/block-core.json b/qapi/block-core.json
26
index XXXXXXX..XXXXXXX 100644
27
--- a/qapi/block-core.json
28
+++ b/qapi/block-core.json
29
@@ -XXX,XX +XXX,XX @@
30
#
31
# @path: path to the vhost-vdpa character device.
32
#
33
+# Features:
34
+# @fdset: Member @path supports the special "/dev/fdset/N" path
35
+# (since 8.1)
36
+#
37
# Since: 7.2
38
##
39
{ 'struct': 'BlockdevOptionsVirtioBlkVhostVdpa',
40
'data': { 'path': 'str' },
41
+ 'features': [ { 'name' :'fdset',
42
+ 'if': 'CONFIG_BLKIO_VHOST_VDPA_FD' } ],
43
'if': 'CONFIG_BLKIO' }
44
45
##
46
diff --git a/meson.build b/meson.build
47
index XXXXXXX..XXXXXXX 100644
48
--- a/meson.build
49
+++ b/meson.build
50
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_LZO', lzo.found())
51
config_host_data.set('CONFIG_MPATH', mpathpersist.found())
52
config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api)
53
config_host_data.set('CONFIG_BLKIO', blkio.found())
54
+if blkio.found()
55
+ config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
56
+ blkio.version().version_compare('>=1.3.0'))
57
+endif
58
config_host_data.set('CONFIG_CURL', curl.found())
59
config_host_data.set('CONFIG_CURSES', curses.found())
60
config_host_data.set('CONFIG_GBM', gbm.found())
61
--
62
2.40.1
diff view generated by jsdifflib