* [PATCH v2 1/3] iotests: run the test pool with the 'fork' start method
2026-07-15 10:34 [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
@ 2026-07-15 10:34 ` Denis V. Lunev
2026-07-22 8:45 ` Daniel P. Berrangé
2026-07-15 10:34 ` [PATCH v2 2/3] iotests: skip FUSE tests when FUSE is not usable Denis V. Lunev
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-07-15 10:34 UTC (permalink / raw)
To: qemu-block, qemu-devel; +Cc: den, Kevin Wolf, Hanna Reitz
run_tests_pool() shares the runner via the class attribute
TestRunner.shared_self, relying on worker processes to inherit it.
That only works with the 'fork' start method. Python 3.14 switched
the Linux default to 'forkserver', so workers see shared_self as
None and parallel runs abort with:
assert runner is not None
AssertionError
Only reproduces with Python 3.14+ and 'check -jN' (N > 1); meson
runs one test per process and never calls run_tests_pool(), so CI
is unaffected.
Request get_context('fork') explicitly; it is available on all
supported Python versions and a no-op before 3.14.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Hanna Reitz <hreitz@redhat.com>
---
tests/qemu-iotests/testrunner.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
index dbe2dddc32..cc36867719 100644
--- a/tests/qemu-iotests/testrunner.py
+++ b/tests/qemu-iotests/testrunner.py
@@ -26,7 +26,7 @@
import json
import shutil
import sys
-from multiprocessing import Pool
+from multiprocessing import get_context
from typing import List, Optional, Any, Sequence, Dict
from testenv import TestEnv
@@ -125,7 +125,7 @@ def run_tests_pool(self, tests: List[str],
assert TestRunner.shared_self is None
TestRunner.shared_self = self
- with Pool(jobs) as p:
+ with get_context('fork').Pool(jobs) as p:
results = p.starmap(self.proc_run_test,
zip(tests, [test_field_width] * len(tests)))
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/3] iotests: run the test pool with the 'fork' start method
2026-07-15 10:34 ` [PATCH v2 1/3] iotests: run the test pool with the 'fork' start method Denis V. Lunev
@ 2026-07-22 8:45 ` Daniel P. Berrangé
0 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2026-07-22 8:45 UTC (permalink / raw)
To: Denis V. Lunev; +Cc: qemu-block, qemu-devel, Kevin Wolf, Hanna Reitz
On Wed, Jul 15, 2026 at 12:34:49PM +0200, Denis V. Lunev wrote:
> run_tests_pool() shares the runner via the class attribute
> TestRunner.shared_self, relying on worker processes to inherit it.
> That only works with the 'fork' start method. Python 3.14 switched
> the Linux default to 'forkserver', so workers see shared_self as
> None and parallel runs abort with:
>
> assert runner is not None
> AssertionError
>
> Only reproduces with Python 3.14+ and 'check -jN' (N > 1); meson
> runs one test per process and never calls run_tests_pool(), so CI
> is unaffected.
>
> Request get_context('fork') explicitly; it is available on all
> supported Python versions and a no-op before 3.14.
>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Kevin Wolf <kwolf@redhat.com>
> CC: Hanna Reitz <hreitz@redhat.com>
> ---
> tests/qemu-iotests/testrunner.py | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/3] iotests: skip FUSE tests when FUSE is not usable
2026-07-15 10:34 [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
2026-07-15 10:34 ` [PATCH v2 1/3] iotests: run the test pool with the 'fork' start method Denis V. Lunev
@ 2026-07-15 10:34 ` Denis V. Lunev
2026-07-22 8:46 ` Daniel P. Berrangé
2026-07-15 10:34 ` [PATCH v2 3/3] iotests/migrate-bitmaps-postcopy-test: replace the timing assertion with a content check Denis V. Lunev
2026-07-22 8:39 ` [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-07-15 10:34 UTC (permalink / raw)
To: qemu-block, qemu-devel; +Cc: den, Kevin Wolf, Hanna Reitz
file-io-error, fuse-allow-other and fuse-mmap-shared skip only when
FUSE is not compiled in. When FUSE is built in but unusable at run
time (no /dev/fuse access, fusermount lacking permissions), the
export fails to mount with "Failed to mount FUSE session to export"
and the tests report a spurious failure instead of skipping, like
NBD tests already do for missing NBD support.
Add _notrun_on_fuse_error() to common.rc and use it in the shell
tests. fuse-mmap-shared is Python, so it gets an equivalent inline
check.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Hanna Reitz <hreitz@redhat.com>
---
tests/qemu-iotests/common.rc | 14 ++++++++++++++
tests/qemu-iotests/tests/file-io-error | 4 +---
tests/qemu-iotests/tests/fuse-allow-other | 2 ++
tests/qemu-iotests/tests/fuse-mmap-shared | 9 ++++++---
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 298bc483e0..bcb1ec50a9 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -981,6 +981,20 @@ _require_drivers()
done
}
+# Skip if FUSE is unusable: not compiled in, or the export failed to
+# mount. $1 is the failing 'block-export-add' reply.
+_notrun_on_fuse_error()
+{
+ case "$1" in
+ *"Parameter 'type' does not accept value 'fuse'"*)
+ _notrun "No FUSE support"
+ ;;
+ *"Failed to mount FUSE session"*)
+ _notrun "FUSE not usable in this environment"
+ ;;
+ esac
+}
+
# Check that we have a file system that allows huge (but very sparse) files
#
_require_large_file()
diff --git a/tests/qemu-iotests/tests/file-io-error b/tests/qemu-iotests/tests/file-io-error
index fb8db73b31..0d970c102f 100755
--- a/tests/qemu-iotests/tests/file-io-error
+++ b/tests/qemu-iotests/tests/file-io-error
@@ -89,9 +89,7 @@ output=$(_send_qemu_cmd $QEMU_HANDLE \
'return' \
| grep -v 'option allow_other only allowed if')
-if echo "$output" | grep -q "Parameter 'type' does not accept value 'fuse'"; then
- _notrun 'No FUSE support'
-fi
+_notrun_on_fuse_error "$output"
echo "$output"
echo
diff --git a/tests/qemu-iotests/tests/fuse-allow-other b/tests/qemu-iotests/tests/fuse-allow-other
index eaa39f8f23..50a36601d7 100755
--- a/tests/qemu-iotests/tests/fuse-allow-other
+++ b/tests/qemu-iotests/tests/fuse-allow-other
@@ -77,6 +77,8 @@ fuse_export_add()
_notrun "allow_other not supported"
fi
+ _notrun_on_fuse_error "$output"
+
echo "$output"
}
diff --git a/tests/qemu-iotests/tests/fuse-mmap-shared b/tests/qemu-iotests/tests/fuse-mmap-shared
index 52941a3bb6..b190105894 100755
--- a/tests/qemu-iotests/tests/fuse-mmap-shared
+++ b/tests/qemu-iotests/tests/fuse-mmap-shared
@@ -28,9 +28,12 @@ def test_fuse_support(mount_point):
})
test_qsd.stop()
if 'error' in res:
- assert (res['error']['desc'] ==
- "Parameter 'type' does not accept value 'fuse'")
- iotests.notrun('No FUSE support')
+ desc = res['error']['desc']
+ if desc == "Parameter 'type' does not accept value 'fuse'":
+ iotests.notrun('No FUSE support')
+ if 'Failed to mount FUSE session' in desc:
+ iotests.notrun('FUSE not usable in this environment')
+ assert False, desc
# Shared mmap when using direct IO is only supported for Linux kernels >= 6.6
# with commit e78662e818f94 ("fuse: add a new fuse init flag to relax
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 2/3] iotests: skip FUSE tests when FUSE is not usable
2026-07-15 10:34 ` [PATCH v2 2/3] iotests: skip FUSE tests when FUSE is not usable Denis V. Lunev
@ 2026-07-22 8:46 ` Daniel P. Berrangé
0 siblings, 0 replies; 8+ messages in thread
From: Daniel P. Berrangé @ 2026-07-22 8:46 UTC (permalink / raw)
To: Denis V. Lunev; +Cc: qemu-block, qemu-devel, Kevin Wolf, Hanna Reitz
On Wed, Jul 15, 2026 at 12:34:50PM +0200, Denis V. Lunev wrote:
> file-io-error, fuse-allow-other and fuse-mmap-shared skip only when
> FUSE is not compiled in. When FUSE is built in but unusable at run
> time (no /dev/fuse access, fusermount lacking permissions), the
> export fails to mount with "Failed to mount FUSE session to export"
> and the tests report a spurious failure instead of skipping, like
> NBD tests already do for missing NBD support.
>
> Add _notrun_on_fuse_error() to common.rc and use it in the shell
> tests. fuse-mmap-shared is Python, so it gets an equivalent inline
> check.
>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Kevin Wolf <kwolf@redhat.com>
> CC: Hanna Reitz <hreitz@redhat.com>
> ---
> tests/qemu-iotests/common.rc | 14 ++++++++++++++
> tests/qemu-iotests/tests/file-io-error | 4 +---
> tests/qemu-iotests/tests/fuse-allow-other | 2 ++
> tests/qemu-iotests/tests/fuse-mmap-shared | 9 ++++++---
> 4 files changed, 23 insertions(+), 6 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 3/3] iotests/migrate-bitmaps-postcopy-test: replace the timing assertion with a content check
2026-07-15 10:34 [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
2026-07-15 10:34 ` [PATCH v2 1/3] iotests: run the test pool with the 'fork' start method Denis V. Lunev
2026-07-15 10:34 ` [PATCH v2 2/3] iotests: skip FUSE tests when FUSE is not usable Denis V. Lunev
@ 2026-07-15 10:34 ` Denis V. Lunev
2026-07-15 10:55 ` Vladimir Sementsov-Ogievskiy
2026-07-22 8:39 ` [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-07-15 10:34 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: den, Kevin Wolf, Hanna Reitz, Vladimir Sementsov-Ogievskiy
`downtime * 10 < postcopy_time` was an unnormalized wall-clock
heuristic (commit e80a4150a5) that fails on fast hosts, where the
bitmap payload now transfers in under a second.
Check the actual invariant instead: right after RESUME, bitmap0's
content hash on the destination must not yet match the fully
migrated value. Throttle max-bandwidth first, since all-zero chunks
skip the payload write and would otherwise let a fast host finish
the transfer before the check runs.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Hanna Reitz <hreitz@redhat.com>
CC: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
.../tests/migrate-bitmaps-postcopy-test | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test
index c519e6db8c..33ff2b861f 100755
--- a/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test
+++ b/tests/qemu-iotests/tests/migrate-bitmaps-postcopy-test
@@ -160,12 +160,26 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
self.vm_b.cmd('migrate-set-capabilities', capabilities=caps)
+ # Throttle so the chunks covering our discards (the only ones
+ # not skipped by the all-zero fast path) can't outrun the check
+ # below.
+ self.vm_a.cmd('migrate-set-parameters', max_bandwidth=16536)
+
self.vm_a.cmd('migrate', uri='exec:cat>' + fifo)
self.vm_a.cmd('migrate-start-postcopy')
event_resume = self.vm_b.event_wait('RESUME')
self.vm_b_events.append(event_resume)
+
+ # bitmap0 can't already have its final content: that requires
+ # the bit data to have actually arrived.
+ result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
+ node='drive0', name='bitmap0')
+ assert result['return']['sha256'] != all_discards_sha256
+
+ self.vm_a.cmd('migrate-set-parameters', max_bandwidth=0)
+
return (event_resume, discards1_sha256, all_discards_sha256)
def test_postcopy_success(self):
@@ -186,7 +200,6 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
downtime = event_dist(event_stop, event_resume)
postcopy_time = event_dist(event_resume, event_complete)
- assert downtime * 10 < postcopy_time
if debug:
print('downtime:', downtime)
print('postcopy_time:', postcopy_time)
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 3/3] iotests/migrate-bitmaps-postcopy-test: replace the timing assertion with a content check
2026-07-15 10:34 ` [PATCH v2 3/3] iotests/migrate-bitmaps-postcopy-test: replace the timing assertion with a content check Denis V. Lunev
@ 2026-07-15 10:55 ` Vladimir Sementsov-Ogievskiy
0 siblings, 0 replies; 8+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2026-07-15 10:55 UTC (permalink / raw)
To: Denis V. Lunev, qemu-block, qemu-devel; +Cc: Kevin Wolf, Hanna Reitz
On 15.07.26 13:34, Denis V. Lunev wrote:
> `downtime * 10 < postcopy_time` was an unnormalized wall-clock
> heuristic (commit e80a4150a5) that fails on fast hosts, where the
> bitmap payload now transfers in under a second.
>
> Check the actual invariant instead: right after RESUME, bitmap0's
> content hash on the destination must not yet match the fully
> migrated value. Throttle max-bandwidth first, since all-zero chunks
> skip the payload write and would otherwise let a fast host finish
> the transfer before the check runs.
>
> Signed-off-by: Denis V. Lunev<den@openvz.org>
> CC: Kevin Wolf<kwolf@redhat.com>
> CC: Hanna Reitz<hreitz@redhat.com>
> CC: Vladimir Sementsov-Ogievskiy<vsementsov@yandex-team.ru>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/3] iotests: fix three spurious local failures
2026-07-15 10:34 [PATCH v2 0/3] iotests: fix three spurious local failures Denis V. Lunev
` (2 preceding siblings ...)
2026-07-15 10:34 ` [PATCH v2 3/3] iotests/migrate-bitmaps-postcopy-test: replace the timing assertion with a content check Denis V. Lunev
@ 2026-07-22 8:39 ` Denis V. Lunev
3 siblings, 0 replies; 8+ messages in thread
From: Denis V. Lunev @ 2026-07-22 8:39 UTC (permalink / raw)
To: Denis V. Lunev, qemu-block, qemu-devel
Cc: Kevin Wolf, Hanna Reitz, Vladimir Sementsov-Ogievskiy
On 7/15/26 12:34, Denis V. Lunev wrote:
> This email originated from an IP that might not be authorized by the domain it was sent from.
> Do not click links or open attachments unless it is an email you expected to receive.
> Three independent fixes found while chasing a clean './check -qcow2'
> run on a Python 3.14 host. Unrelated to each other, sent as one
> series since they came out of the same session.
>
> v2:
> - patch 1: drop the now-unused 'Pool' import (Kevin)
> - patch 2: rename _notrun_on_no_fuse to _notrun_on_fuse_error (Kevin)
> - patch 3: replace the dropped assertion with a check that bitmap0's
> content on the destination has not reached its final value right
> after RESUME, throttling migration bandwidth
>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Kevin Wolf <kwolf@redhat.com>
> CC: Hanna Reitz <hreitz@redhat.com>
> CC: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
>
> Denis V. Lunev (3):
> iotests: run the test pool with the 'fork' start method
> iotests: skip FUSE tests when FUSE is not usable
> iotests/migrate-bitmaps-postcopy-test: replace the timing assertion
> with a content check
>
> tests/qemu-iotests/common.rc | 14 ++++++++++++++
> tests/qemu-iotests/testrunner.py | 4 ++--
> tests/qemu-iotests/tests/file-io-error | 4 +---
> tests/qemu-iotests/tests/fuse-allow-other | 2 ++
> tests/qemu-iotests/tests/fuse-mmap-shared | 9 ++++++---
> .../tests/migrate-bitmaps-postcopy-test | 15 ++++++++++++++-
> 6 files changed, 39 insertions(+), 9 deletions(-)
>
ping
^ permalink raw reply [flat|nested] 8+ messages in thread