cryptospore / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
ff9ada
From b56684f6c1bef4fb5bf87ac5a1106d3830c05ad0 Mon Sep 17 00:00:00 2001
ff9ada
From: Hanna Reitz <hreitz@redhat.com>
ff9ada
Date: Fri, 4 Feb 2022 12:10:10 +0100
ff9ada
Subject: [PATCH 4/6] iotests/281: Test lingering timers
ff9ada
ff9ada
RH-Author: Hanna Reitz <hreitz@redhat.com>
ff9ada
RH-MergeRequest: 117: block/nbd: Handle AioContext changes
ff9ada
RH-Commit: [4/6] aaad466941637a34224dc037bbea37d128b5676b
ff9ada
RH-Bugzilla: 2035185
ff9ada
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
ff9ada
RH-Acked-by: Eric Blake <eblake@redhat.com>
ff9ada
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ff9ada
ff9ada
Prior to "block/nbd: Delete reconnect delay timer when done" and
ff9ada
"block/nbd: Delete open timer when done", both of those timers would
ff9ada
remain scheduled even after successfully (re-)connecting to the server,
ff9ada
and they would not even be deleted when the BDS is deleted.
ff9ada
ff9ada
This test constructs exactly this situation:
ff9ada
(1) Configure an @open-timeout, so the open timer is armed, and
ff9ada
(2) Configure a @reconnect-delay and trigger a reconnect situation
ff9ada
    (which succeeds immediately), so the reconnect delay timer is armed.
ff9ada
Then we immediately delete the BDS, and sleep for longer than the
ff9ada
@open-timeout and @reconnect-delay.  Prior to said patches, this caused
ff9ada
one (or both) of the timer CBs to access already-freed data.
ff9ada
ff9ada
Accessing freed data may or may not crash, so this test can produce
ff9ada
false successes, but I do not know how to show the problem in a better
ff9ada
or more reliable way.  If you run this test on "block/nbd: Assert there
ff9ada
are no timers when closed" and without the fix patches mentioned above,
ff9ada
you should reliably see an assertion failure.
ff9ada
(But all other tests that use the reconnect delay timer (264 and 277)
ff9ada
will fail in that configuration, too; as will nbd-reconnect-on-open,
ff9ada
which uses the open timer.)
ff9ada
ff9ada
Remove this test from the quick group because of the two second sleep
ff9ada
this patch introduces.
ff9ada
ff9ada
(I decided to put this test case into 281, because the main bug this
ff9ada
series addresses is in the interaction of the NBD block driver and I/O
ff9ada
threads, which is precisely the scope of 281.  The test case for that
ff9ada
other bug will also be put into the test class added here.
ff9ada
ff9ada
Also, excuse the test class's name, I couldn't come up with anything
ff9ada
better.  The "yield" part will make sense two patches from now.)
ff9ada
ff9ada
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
ff9ada
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
ff9ada
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
ff9ada
(cherry picked from commit eaf1e85d4ddefdbd197f393fa9c5acc7ba8133b0)
ff9ada
ff9ada
Conflict:
ff9ada
- @open-timeout was introduced after the 6.2 release, and has not been
ff9ada
  backported.  Consequently, there is no open_timer, and we can (and
ff9ada
  must) drop the respective parts of the test here.
ff9ada
ff9ada
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
ff9ada
---
ff9ada
 tests/qemu-iotests/281     | 73 ++++++++++++++++++++++++++++++++++++--
ff9ada
 tests/qemu-iotests/281.out |  4 +--
ff9ada
 2 files changed, 73 insertions(+), 4 deletions(-)
ff9ada
ff9ada
diff --git a/tests/qemu-iotests/281 b/tests/qemu-iotests/281
ff9ada
index 956698083f..13c588be75 100755
ff9ada
--- a/tests/qemu-iotests/281
ff9ada
+++ b/tests/qemu-iotests/281
ff9ada
@@ -1,5 +1,5 @@
ff9ada
 #!/usr/bin/env python3
ff9ada
-# group: rw quick
ff9ada
+# group: rw
ff9ada
 #
ff9ada
 # Test cases for blockdev + IOThread interactions
ff9ada
 #
ff9ada
@@ -20,8 +20,9 @@
ff9ada
 #
ff9ada
 
ff9ada
 import os
ff9ada
+import time
ff9ada
 import iotests
ff9ada
-from iotests import qemu_img
ff9ada
+from iotests import qemu_img, QemuStorageDaemon
ff9ada
 
ff9ada
 image_len = 64 * 1024 * 1024
ff9ada
 
ff9ada
@@ -243,6 +244,74 @@ class TestBlockdevBackupAbort(iotests.QMPTestCase):
ff9ada
         # Hangs on failure, we expect this error.
ff9ada
         self.assert_qmp(result, 'error/class', 'GenericError')
ff9ada
 
ff9ada
+# Test for RHBZ#2033626
ff9ada
+class TestYieldingAndTimers(iotests.QMPTestCase):
ff9ada
+    sock = os.path.join(iotests.sock_dir, 'nbd.sock')
ff9ada
+    qsd = None
ff9ada
+
ff9ada
+    def setUp(self):
ff9ada
+        self.create_nbd_export()
ff9ada
+
ff9ada
+        # Simple VM with an NBD block device connected to the NBD export
ff9ada
+        # provided by the QSD
ff9ada
+        self.vm = iotests.VM()
ff9ada
+        self.vm.add_blockdev('nbd,node-name=nbd,server.type=unix,' +
ff9ada
+                             f'server.path={self.sock},export=exp,' +
ff9ada
+                             'reconnect-delay=1')
ff9ada
+
ff9ada
+        self.vm.launch()
ff9ada
+
ff9ada
+    def tearDown(self):
ff9ada
+        self.stop_nbd_export()
ff9ada
+        self.vm.shutdown()
ff9ada
+
ff9ada
+    def test_timers_with_blockdev_del(self):
ff9ada
+        # Stop and restart the NBD server, and do some I/O on the client to
ff9ada
+        # trigger a reconnect and start the reconnect delay timer
ff9ada
+        self.stop_nbd_export()
ff9ada
+        self.create_nbd_export()
ff9ada
+
ff9ada
+        result = self.vm.qmp('human-monitor-command',
ff9ada
+                             command_line='qemu-io nbd "write 0 512"')
ff9ada
+        self.assert_qmp(result, 'return', '')
ff9ada
+
ff9ada
+        # Reconnect is done, so the reconnect delay timer should be gone.
ff9ada
+        # (But there used to be a bug where it remained active, for which this
ff9ada
+        # is a regression test.)
ff9ada
+
ff9ada
+        # Delete the BDS to see whether the timer is gone.  If it is not,
ff9ada
+        # it will remain active, fire later, and then access freed data.
ff9ada
+        # (Or, with "block/nbd: Assert there are no timers when closed"
ff9ada
+        # applied, the assertion added in that patch will fail.)
ff9ada
+        result = self.vm.qmp('blockdev-del', node_name='nbd')
ff9ada
+        self.assert_qmp(result, 'return', {})
ff9ada
+
ff9ada
+        # Give the timer some time to fire (it has a timeout of 1 s).
ff9ada
+        # (Sleeping in an iotest may ring some alarm bells, but note that if
ff9ada
+        # the timing is off here, the test will just always pass.  If we kill
ff9ada
+        # the VM too early, then we just kill the timer before it can fire,
ff9ada
+        # thus not see the error, and so the test will pass.)
ff9ada
+        time.sleep(2)
ff9ada
+
ff9ada
+    def create_nbd_export(self):
ff9ada
+        assert self.qsd is None
ff9ada
+
ff9ada
+        # Simple NBD export of a null-co BDS
ff9ada
+        self.qsd = QemuStorageDaemon(
ff9ada
+            '--blockdev',
ff9ada
+            'null-co,node-name=null,read-zeroes=true',
ff9ada
+
ff9ada
+            '--nbd-server',
ff9ada
+            f'addr.type=unix,addr.path={self.sock}',
ff9ada
+
ff9ada
+            '--export',
ff9ada
+            'nbd,id=exp,node-name=null,name=exp,writable=true'
ff9ada
+        )
ff9ada
+
ff9ada
+    def stop_nbd_export(self):
ff9ada
+        self.qsd.stop()
ff9ada
+        self.qsd = None
ff9ada
+
ff9ada
 if __name__ == '__main__':
ff9ada
     iotests.main(supported_fmts=['qcow2'],
ff9ada
                  supported_protocols=['file'])
ff9ada
diff --git a/tests/qemu-iotests/281.out b/tests/qemu-iotests/281.out
ff9ada
index 89968f35d7..914e3737bd 100644
ff9ada
--- a/tests/qemu-iotests/281.out
ff9ada
+++ b/tests/qemu-iotests/281.out
ff9ada
@@ -1,5 +1,5 @@
ff9ada
-....
ff9ada
+.....
ff9ada
 ----------------------------------------------------------------------
ff9ada
-Ran 4 tests
ff9ada
+Ran 5 tests
ff9ada
 
ff9ada
 OK
ff9ada
-- 
ff9ada
2.27.0
ff9ada