Skip to content

Commit

Permalink
iotests: Test commit with iothreads and ongoing I/O
Browse files Browse the repository at this point in the history
This tests exercises graph locking, draining, and graph modifications
with AioContext switches a lot. Amongst others, it serves as a
regression test for bdrv_graph_wrlock() deadlocking because it is called
with a locked AioContext and for AioContext handling in the NBD server.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230517152834.277483-4-kwolf@redhat.com>
Tested-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
kevmw committed May 19, 2023
1 parent 7c1f51b commit 95fdd8d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
4 changes: 4 additions & 0 deletions tests/qemu-iotests/iotests.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,10 @@ def qmp(self, cmd: str, args: Optional[Dict[str, object]] = None) \
assert self._qmp is not None
return self._qmp.cmd(cmd, args)

def get_qmp(self) -> QEMUMonitorProtocol:
assert self._qmp is not None
return self._qmp

def stop(self, kill_signal=15):
self._p.send_signal(kill_signal)
self._p.wait()
Expand Down
56 changes: 52 additions & 4 deletions tests/qemu-iotests/tests/graph-changes-while-io
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@
import os
from threading import Thread
import iotests
from iotests import imgfmt, qemu_img, qemu_img_create, QMPTestCase, \
QemuStorageDaemon
from iotests import imgfmt, qemu_img, qemu_img_create, qemu_io, \
QMPTestCase, QemuStorageDaemon


top = os.path.join(iotests.test_dir, 'top.img')
nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')


def do_qemu_img_bench() -> None:
def do_qemu_img_bench(count: int = 2000000) -> None:
"""
Do some I/O requests on `nbd_sock`.
"""
qemu_img('bench', '-f', 'raw', '-c', '2000000',
qemu_img('bench', '-f', 'raw', '-c', str(count),
f'nbd+unix:///node0?socket={nbd_sock}')


Expand Down Expand Up @@ -84,6 +84,54 @@ class TestGraphChangesWhileIO(QMPTestCase):

bench_thr.join()

def test_commit_while_io(self) -> None:
# Run qemu-img bench in the background
bench_thr = Thread(target=do_qemu_img_bench, args=(200000, ))
bench_thr.start()

qemu_io('-c', 'write 0 64k', top)
qemu_io('-c', 'write 128k 64k', top)

result = self.qsd.qmp('blockdev-add', {
'driver': imgfmt,
'node-name': 'overlay',
'backing': None,
'file': {
'driver': 'file',
'filename': top
}
})
self.assert_qmp(result, 'return', {})

result = self.qsd.qmp('blockdev-snapshot', {
'node': 'node0',
'overlay': 'overlay',
})
self.assert_qmp(result, 'return', {})

# While qemu-img bench is running, repeatedly commit overlay to node0
while bench_thr.is_alive():
result = self.qsd.qmp('block-commit', {
'job-id': 'job0',
'device': 'overlay',
})
self.assert_qmp(result, 'return', {})

result = self.qsd.qmp('block-job-cancel', {
'device': 'job0',
})
self.assert_qmp(result, 'return', {})

cancelled = False
while not cancelled:
for event in self.qsd.get_qmp().get_events(wait=10.0):
if event['event'] != 'JOB_STATUS_CHANGE':
continue
if event['data']['status'] == 'null':
cancelled = True

bench_thr.join()

if __name__ == '__main__':
# Format must support raw backing files
iotests.main(supported_fmts=['qcow', 'qcow2', 'qed'],
Expand Down
4 changes: 2 additions & 2 deletions tests/qemu-iotests/tests/graph-changes-while-io.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.
..
----------------------------------------------------------------------
Ran 1 tests
Ran 2 tests

OK

0 comments on commit 95fdd8d

Please sign in to comment.