iotests/308: Add multi-threading sanity test
Run qemu-img bench on a simple multi-threaded FUSE export to test that it works. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Hanna Czenczek <hreitz@redhat.com> Message-ID: <20260309150856.26800-26-hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Hanna Czenczek committed
Mar 9, 2026 at 16:08 UTC
2224bff1ba90f3061a3f240be9994d755ba2770e
2 files changed
+107
tests/qemu-iotests/308
+51
@@ -441,6 +441,57 @@ $QEMU_IO -c 'read -P 0 0 64M' "$TEST_IMG" | _filter_qemu_io
441
442
_cleanup_test_img
443
444
+echo
445
+echo '=== Multi-threading ==='
446
+
447
+# Just set up a null block device, export it (with multi-threading), and run
448
+# qemu-img bench on it (to get parallel requests)
449
+
450
+_launch_qemu
451
+_send_qemu_cmd $QEMU_HANDLE \
452
+ "{'execute': 'qmp_capabilities'}" \
453
+ 'return'
454
+
455
+_send_qemu_cmd $QEMU_HANDLE \
456
+ "{'execute': 'blockdev-add',
457
+ 'arguments': {
458
+ 'driver': 'null-co',
459
+ 'node-name': 'null'
460
+ } }" \
461
+ 'return'
462
+
463
+for id in iothread{0,1,2,3}; do
464
+ _send_qemu_cmd $QEMU_HANDLE \
465
+ "{'execute': 'object-add',
466
+ 'arguments': {
467
+ 'qom-type': 'iothread',
468
+ 'id': '$id'
469
+ } }" \
470
+ 'return'
471
+done
472
+
473
+echo
474
+
475
+iothreads="['iothread0', 'iothread1', 'iothread2', 'iothread3']"
476
+fuse_export_add \
477
+ 'export' \
478
+ "'mountpoint': '$EXT_MP', 'iothread': $iothreads" \
479
+ 'return' \
480
+ 'null'
481
+
482
+echo
483
+$QEMU_IMG bench -f raw "$EXT_MP" |
484
+ sed -e 's/[0-9.]\+ seconds/X.XXX seconds/'
485
+echo
486
+
487
+fuse_export_del 'export'
488
+
489
+_send_qemu_cmd $QEMU_HANDLE \
490
+ "{'execute': 'quit'}" \
491
+ 'return'
492
+
493
+wait=yes _cleanup_qemu
494
+
495
# success, all done
496
echo "*** done"
497
rm -f $seq.full
tests/qemu-iotests/308.out
+56
@@ -217,4 +217,60 @@ read 67108864/67108864 bytes at offset 0
217
{"return": {}}
218
read 67108864/67108864 bytes at offset 0
219
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
220
+
221
+=== Multi-threading ===
222
+{'execute': 'qmp_capabilities'}
223
+{"return": {}}
224
+{'execute': 'blockdev-add',
225
+ 'arguments': {
226
+ 'driver': 'null-co',
227
+ 'node-name': 'null'
228
+ } }
229
+{"return": {}}
230
+{'execute': 'object-add',
231
+ 'arguments': {
232
+ 'qom-type': 'iothread',
233
+ 'id': 'iothread0'
234
+ } }
235
+{"return": {}}
236
+{'execute': 'object-add',
237
+ 'arguments': {
238
+ 'qom-type': 'iothread',
239
+ 'id': 'iothread1'
240
+ } }
241
+{"return": {}}
242
+{'execute': 'object-add',
243
+ 'arguments': {
244
+ 'qom-type': 'iothread',
245
+ 'id': 'iothread2'
246
+ } }
247
+{"return": {}}
248
+{'execute': 'object-add',
249
+ 'arguments': {
250
+ 'qom-type': 'iothread',
251
+ 'id': 'iothread3'
252
+ } }
253
+{"return": {}}
254
+
255
+{'execute': 'block-export-add',
256
+ 'arguments': {
257
+ 'type': 'fuse',
258
+ 'id': 'export',
259
+ 'node-name': 'null',
260
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'iothread': ['iothread0', 'iothread1', 'iothread2', 'iothread3']
261
+ } }
262
+{"return": {}}
263
+
264
+Sending 75000 read requests, 4096 bytes each, 64 in parallel (starting at offset 0, step size 4096)
265
+Run completed in X.XXX seconds.
266
+
267
+{'execute': 'block-export-del',
268
+ 'arguments': {
269
+ 'id': 'export'
270
+ } }
271
+{"return": {}}
272
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}}
273
+{'execute': 'quit'}
274
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
275
+{"return": {}}
276
*** done