:p
atchew
Login
The following changes since commit 47c1cc30e440860aa695358f7c2dd0b9d7b53d16: Update version for v3.1.0-rc2 release (2018-11-20 18:10:26 +0000) are available in the Git repository at: git://repo.or.cz/qemu/kevin.git tags/for-upstream for you to fetch changes up to 924956b1efc50af7cc334b7a14f56aa213ca27ef: iotests: Enhance 223 to cover multiple bitmap granularities (2018-11-22 16:43:52 +0100) ---------------------------------------------------------------- Block layer patches: - block: Fix update of BDRV_O_AUTO_RDONLY in update_flags_from_options() - qemu-img: Fix memory leak and typo in error message - nvme: Fixes for lockups and crashes - scsi-disk: Fix crash if underlying host file or disk returns error - Several qemu-iotests fixes and improvements ---------------------------------------------------------------- Alberto Garcia (1): block: Fix update of BDRV_O_AUTO_RDONLY in update_flags_from_options() Daniel P. Berrangé (1): iotests: fix nbd test 233 to work correctly with raw images Eric Blake (2): iotests: Skip 233 if certtool not installed iotests: Enhance 223 to cover multiple bitmap granularities Igor Druzhinin (1): nvme: call blk_drain in NVMe reset code to avoid lockups Kevin Wolf (3): iotests: Replace time.clock() with Timeout iotests: Replace assertEquals() with assertEqual() Revert "nvme: fix oob access issue(CVE-2018-16847)" Logan Gunthorpe (1): nvme: fix bug with PCI IRQ pins on teardown Max Reitz (2): qemu-img: Fix typo qemu-img: Fix leak Paolo Bonzini (1): nvme: fix out-of-bounds access to the CMB Richard W.M. Jones (1): scsi-disk: Fix crash if underlying host file or disk returns error block.c | 4 +-- hw/block/nvme.c | 12 +++----- hw/scsi/scsi-disk.c | 2 +- qemu-img.c | 3 +- tests/nvme-test.c | 68 ++++++++++++++++++++++++++++++++++++------- tests/Makefile.include | 2 +- tests/qemu-iotests/041 | 6 ++-- tests/qemu-iotests/118 | 20 +++++-------- tests/qemu-iotests/223 | 43 ++++++++++++++++++++++----- tests/qemu-iotests/223.out | 32 +++++++++++++++----- tests/qemu-iotests/233 | 9 ++++-- tests/qemu-iotests/common.tls | 3 ++ tests/qemu-iotests/iotests.py | 2 +- 13 files changed, 148 insertions(+), 58 deletions(-)
time.clock() is deprecated since Python 3.3. Current Python versions warn that the function will be removed in Python 3.8, and those warnings make the test case 118 fail. Replace it with the Timeout mechanism that is compatible with both Python 2 and 3, and makes the code even a little nicer. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> --- tests/qemu-iotests/118 | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118 index XXXXXXX..XXXXXXX 100755 --- a/tests/qemu-iotests/118 +++ b/tests/qemu-iotests/118 @@ -XXX,XX +XXX,XX @@ class ChangeBaseClass(iotests.QMPTestCase): if not self.has_real_tray: return - timeout = time.clock() + 3 - while not self.has_opened and time.clock() < timeout: - self.process_events() - if not self.has_opened: - self.fail('Timeout while waiting for the tray to open') + with iotests.Timeout(3, 'Timeout while waiting for the tray to open'): + while not self.has_opened: + self.process_events() def wait_for_close(self): if not self.has_real_tray: return - timeout = time.clock() + 3 - while not self.has_closed and time.clock() < timeout: - self.process_events() - if not self.has_opened: - self.fail('Timeout while waiting for the tray to close') + with iotests.Timeout(3, 'Timeout while waiting for the tray to close'): + while not self.has_closed: + self.process_events() class GeneralChangeTestsBaseClass(ChangeBaseClass): -- 2.19.1
TestCase.assertEquals() is deprecated since Python 2.7. Recent Python versions print a warning when the function is called, which makes test cases fail. Replace it with the preferred spelling assertEqual(). Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> --- tests/qemu-iotests/041 | 6 +++--- tests/qemu-iotests/118 | 4 ++-- tests/qemu-iotests/iotests.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index XXXXXXX..XXXXXXX 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -XXX,XX +XXX,XX @@ new_state = "1" self.assert_qmp(event, 'data/id', 'drive0') event = self.vm.get_qmp_event(wait=True) - self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') + self.assertEqual(event['event'], 'BLOCK_JOB_ERROR') self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/operation', 'read') result = self.vm.qmp('query-block-jobs') @@ -XXX,XX +XXX,XX @@ new_state = "1" self.assert_qmp(event, 'data/id', 'drive0') event = self.vm.get_qmp_event(wait=True) - self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') + self.assertEqual(event['event'], 'BLOCK_JOB_ERROR') self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/operation', 'read') result = self.vm.qmp('query-block-jobs') @@ -XXX,XX +XXX,XX @@ new_state = "1" self.assert_qmp(result, 'return', {}) event = self.vm.event_wait(name='BLOCK_JOB_ERROR') - self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') + self.assertEqual(event['event'], 'BLOCK_JOB_ERROR') self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/operation', 'write') result = self.vm.qmp('query-block-jobs') diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118 index XXXXXXX..XXXXXXX 100755 --- a/tests/qemu-iotests/118 +++ b/tests/qemu-iotests/118 @@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass): result = self.vm.qmp('blockdev-close-tray', id=self.device_name) # Should be a no-op self.assert_qmp(result, 'return', {}) - self.assertEquals(self.vm.get_qmp_events(wait=False), []) + self.assertEqual(self.vm.get_qmp_events(wait=False), []) def test_remove_on_closed(self): if not self.has_real_tray: @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): read_only_mode='retain') self.assert_qmp(result, 'error/class', 'GenericError') - self.assertEquals(self.vm.get_qmp_events(wait=False), []) + self.assertEqual(self.vm.get_qmp_events(wait=False), []) result = self.vm.qmp('query-block') self.assert_qmp(result, 'return[0]/inserted/ro', False) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index XXXXXXX..XXXXXXX 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase): def wait_ready_and_cancel(self, drive='drive0'): self.wait_ready(drive=drive) event = self.cancel_and_wait(drive=drive) - self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED') + self.assertEqual(event['event'], 'BLOCK_JOB_COMPLETED') self.assert_qmp(event, 'data/type', 'mirror') self.assert_qmp(event, 'data/offset', event['data']['len']) -- 2.19.1
From: Eric Blake <eblake@redhat.com> The use of TLS while building qemu is optional. While the 'certtool' binary should be available on every platform that supports building against TLS, that does not imply that the developer has installed it. Make the test gracefully skip in that case. Reported-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- tests/qemu-iotests/common.tls | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/qemu-iotests/common.tls b/tests/qemu-iotests/common.tls index XXXXXXX..XXXXXXX 100644 --- a/tests/qemu-iotests/common.tls +++ b/tests/qemu-iotests/common.tls @@ -XXX,XX +XXX,XX @@ tls_x509_cleanup() tls_x509_init() { + (certtool --help) >/dev/null 2>&1 || \ + _notrun "certtool utility not found, skipping test" + mkdir -p "${tls_dir}" # use a fixed key so we don't waste system entropy on -- 2.19.1
From: Max Reitz <mreitz@redhat.com> Fixes: d402b6a21a825a5c07aac9251990860723d49f5d Reported-by: Kevin Wolf <kwolf@redhat.com> Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- qemu-img.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-img.c b/qemu-img.c index XXXXXXX..XXXXXXX 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt) return 1; } if (!proto_drv->create_opts) { - error_report("Protocal driver '%s' does not support image creation", + error_report("Protocol driver '%s' does not support image creation", proto_drv->format_name); return 1; } -- 2.19.1
From: Max Reitz <mreitz@redhat.com> create_opts was leaked here. This is not too bad since the process is about to exit anyway, but relying on that does not make the code nicer to read. Fixes: d402b6a21a825a5c07aac9251990860723d49f5d Reported-by: Kevin Wolf <kwolf@redhat.com> Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- qemu-img.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu-img.c b/qemu-img.c index XXXXXXX..XXXXXXX 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt) if (!proto_drv->create_opts) { error_report("Protocol driver '%s' does not support image creation", proto_drv->format_name); + qemu_opts_free(create_opts); return 1; } create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); -- 2.19.1
From: "Richard W.M. Jones" <rjones@redhat.com> Commit 40dce4ee6 "scsi-disk: fix rerror/werror=ignore" introduced a bug which causes qemu to crash with the assertion error below if the host file or disk returns an error: qemu-system-x86_64: hw/scsi/scsi-bus.c:1374: scsi_req_complete: Assertion `req->status == -1' failed. Kevin Wolf suggested this fix: < kwolf> Hm, should the final return false; in that patch actually be a return true? < kwolf> Because I think he didn't intend to change anything except BLOCK_ERROR_ACTION_IGNORE Buglink: https://bugs.launchpad.net/qemu/+bug/1804323 Fixes: 40dce4ee61c68395f6d463fae792f61b7c003bce Signed-off-by: Richard W.M. Jones <rjones@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- hw/scsi/scsi-disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index XXXXXXX..XXXXXXX 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -XXX,XX +XXX,XX @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) if (action == BLOCK_ERROR_ACTION_STOP) { scsi_req_retry(&r->req); } - return false; + return true; } static void scsi_write_complete_noio(SCSIDiskReq *r, int ret) -- 2.19.1
From: Alberto Garcia <berto@igalia.com> Commit e35bdc123a4ace9f4d3fcca added the auto-read-only option and the code to update its corresponding flag in update_flags_from_options(), but forgot to clear the flag if auto-read-only is false. Signed-off-by: Alberto Garcia <berto@igalia.com> Reported-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- block.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/block.c b/block.c index XXXXXXX..XXXXXXX 100644 --- a/block.c +++ b/block.c @@ -XXX,XX +XXX,XX @@ static int bdrv_open_flags(BlockDriverState *bs, int flags) static void update_flags_from_options(int *flags, QemuOpts *opts) { - *flags &= ~BDRV_O_CACHE_MASK; + *flags &= ~(BDRV_O_CACHE_MASK | BDRV_O_RDWR | BDRV_O_AUTO_RDONLY); assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH)); if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) { @@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts) *flags |= BDRV_O_NOCACHE; } - *flags &= ~BDRV_O_RDWR; - assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY)); if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) { *flags |= BDRV_O_RDWR; -- 2.19.1
From: Daniel P. Berrangé <berrange@redhat.com> The first qemu-io command must honour the $IMGFMT that is set rather than hardcoding qcow2. The qemu-nbd commands should also set $IMGFMT to avoid the insecure format probe warning. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- tests/qemu-iotests/233 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/233 b/tests/qemu-iotests/233 index XXXXXXX..XXXXXXX 100755 --- a/tests/qemu-iotests/233 +++ b/tests/qemu-iotests/233 @@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'w -P 0x11 1m 1m' "$TEST_IMG" | _filter_qemu_io echo echo "== check TLS client to plain server fails ==" -nbd_server_start_tcp_socket "$TEST_IMG" +nbd_server_start_tcp_socket -f $IMGFMT "$TEST_IMG" $QEMU_IMG info --image-opts \ --object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \ @@ -XXX,XX +XXX,XX @@ nbd_server_stop echo echo "== check plain client to TLS server fails ==" -nbd_server_start_tcp_socket --object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes --tls-creds tls0 "$TEST_IMG" +nbd_server_start_tcp_socket \ + --object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes \ + --tls-creds tls0 \ + -f $IMGFMT "$TEST_IMG" $QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g" @@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'r -P 0x11 1m 1m' -c 'w -P 0x22 1m 1m' --image-opts \ driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \ 2>&1 | _filter_qemu_io -$QEMU_IO -f qcow2 -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io # success, all done echo "*** done" -- 2.19.1
From: Igor Druzhinin <igor.druzhinin@citrix.com> When blk_flush called in NVMe reset path S/C queues are already freed which means that re-entering AIO handling loop having some IO requests unfinished will lockup or crash as their SG structures being potentially reused. Call blk_drain before freeing the queues to avoid this nasty scenario. Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- hw/block/nvme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index XXXXXXX..XXXXXXX 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -XXX,XX +XXX,XX @@ static void nvme_clear_ctrl(NvmeCtrl *n) { int i; + blk_drain(n->conf.blk); + for (i = 0; i < n->num_queues; i++) { if (n->sq[i] != NULL) { nvme_free_sq(n->sq[i], n); -- 2.19.1
From: Paolo Bonzini <pbonzini@redhat.com> Because the CMB BAR has a min_access_size of 2, if you read the last byte it will try to memcpy *2* bytes from n->cmbuf, causing an off-by-one error. This is CVE-2018-16847. Another way to fix this might be to register the CMB as a RAM memory region, which would also be more efficient. However, that might be a change for big-endian machines; I didn't think this through and I don't know how real hardware works. Add a basic testcase for the CMB in case somebody does this change later on. Cc: Keith Busch <keith.busch@intel.com> Cc: qemu-block@nongnu.org Reported-by: Li Qiang <liq3ea@gmail.com> Reviewed-by: Li Qiang <liq3ea@gmail.com> Tested-by: Li Qiang <liq3ea@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- hw/block/nvme.c | 2 +- tests/nvme-test.c | 68 +++++++++++++++++++++++++++++++++++------- tests/Makefile.include | 2 +- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index XXXXXXX..XXXXXXX 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvme_cmb_ops = { .write = nvme_cmb_write, .endianness = DEVICE_LITTLE_ENDIAN, .impl = { - .min_access_size = 2, + .min_access_size = 1, .max_access_size = 8, }, }; diff --git a/tests/nvme-test.c b/tests/nvme-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/nvme-test.c +++ b/tests/nvme-test.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "libqtest.h" +#include "libqos/libqos-pc.h" + +static QOSState *qnvme_start(const char *extra_opts) +{ + QOSState *qs; + const char *arch = qtest_get_arch(); + const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw " + "-device nvme,addr=0x4.0,serial=foo,drive=drv0 %s"; + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qs = qtest_pc_boot(cmd, extra_opts ? : ""); + global_qtest = qs->qts; + return qs; + } + + g_printerr("nvme tests are only available on x86\n"); + exit(EXIT_FAILURE); +} + +static void qnvme_stop(QOSState *qs) +{ + qtest_shutdown(qs); +} -/* Tests only initialization so far. TODO: Replace with functional tests */ static void nop(void) { + QOSState *qs; + + qs = qnvme_start(NULL); + qnvme_stop(qs); } -int main(int argc, char **argv) +static void nvmetest_cmb_test(void) { - int ret; + const int cmb_bar_size = 2 * MiB; + QOSState *qs; + QPCIDevice *pdev; + QPCIBar bar; - g_test_init(&argc, &argv, NULL); - qtest_add_func("/nvme/nop", nop); + qs = qnvme_start("-global nvme.cmb_size_mb=2"); + pdev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0)); + g_assert(pdev != NULL); + + qpci_device_enable(pdev); + bar = qpci_iomap(pdev, 2, NULL); + + qpci_io_writel(pdev, bar, 0, 0xccbbaa99); + g_assert_cmpint(qpci_io_readb(pdev, bar, 0), ==, 0x99); + g_assert_cmpint(qpci_io_readw(pdev, bar, 0), ==, 0xaa99); + + /* Test partially out-of-bounds accesses. */ + qpci_io_writel(pdev, bar, cmb_bar_size - 1, 0x44332211); + g_assert_cmpint(qpci_io_readb(pdev, bar, cmb_bar_size - 1), ==, 0x11); + g_assert_cmpint(qpci_io_readw(pdev, bar, cmb_bar_size - 1), !=, 0x2211); + g_assert_cmpint(qpci_io_readl(pdev, bar, cmb_bar_size - 1), !=, 0x44332211); + g_free(pdev); - qtest_start("-drive id=drv0,if=none,file=null-co://,format=raw " - "-device nvme,drive=drv0,serial=foo"); - ret = g_test_run(); + qnvme_stop(qs); +} - qtest_end(); +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + qtest_add_func("/nvme/nop", nop); + qtest_add_func("/nvme/cmb_test", nvmetest_cmb_test); - return ret; + return g_test_run(); } diff --git a/tests/Makefile.include b/tests/Makefile.include index XXXXXXX..XXXXXXX 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -XXX,XX +XXX,XX @@ tests/test-hmp$(EXESUF): tests/test-hmp.o tests/machine-none-test$(EXESUF): tests/machine-none-test.o tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y) tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y) -tests/nvme-test$(EXESUF): tests/nvme-test.o +tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y) tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o tests/ac97-test$(EXESUF): tests/ac97-test.o -- 2.19.1
This reverts commit 5e3c0220d7e4f0361c4d36c697a8842f2b583402. We have a better fix commited for this now. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- hw/block/nvme.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index XXXXXXX..XXXXXXX 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -XXX,XX +XXX,XX @@ static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { NvmeCtrl *n = (NvmeCtrl *)opaque; - - if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) { - return; - } memcpy(&n->cmbuf[addr], &data, size); } @@ -XXX,XX +XXX,XX @@ static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size) uint64_t val; NvmeCtrl *n = (NvmeCtrl *)opaque; - if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) { - return 0; - } memcpy(&val, &n->cmbuf[addr], size); return val; } -- 2.19.1
From: Logan Gunthorpe <logang@deltatee.com> When the submission and completion queues are being torn down the IRQ will be asserted for the completion queue when the submsission queue is deleted. Then when the completion queue is deleted it stays asserted. Thus, on systems that do not use MSI, no further interrupts can be triggered on the host. Linux sees this as a long delay when unbinding the nvme device. Eventually the interrupt timeout occurs and it continues. To fix this we ensure we deassert the IRQ for a CQ when it is deleted. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- hw/block/nvme.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index XXXXXXX..XXXXXXX 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -XXX,XX +XXX,XX @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd) trace_nvme_err_invalid_del_cq_notempty(qid); return NVME_INVALID_QUEUE_DEL; } + nvme_irq_deassert(n, cq); trace_nvme_del_cq(qid); nvme_free_cq(cq, n); return NVME_SUCCESS; -- 2.19.1
From: Eric Blake <eblake@redhat.com> Testing granularity at the same size as the cluster isn't quite as fun as what happens when it is larger or smaller. This enhancement also shows that qemu's nbd server can serve the same disk over multiple exports simultaneously. Signed-off-by: Eric Blake <eblake@redhat.com> Tested-by: John Snow <jsnow@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- tests/qemu-iotests/223 | 43 +++++++++++++++++++++++++++++++------- tests/qemu-iotests/223.out | 32 +++++++++++++++++++++------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223 index XXXXXXX..XXXXXXX 100755 --- a/tests/qemu-iotests/223 +++ b/tests/qemu-iotests/223 @@ -XXX,XX +XXX,XX @@ run_qemu() } echo -echo "=== Create partially sparse image, then add dirty bitmap ===" +echo "=== Create partially sparse image, then add dirty bitmaps ===" echo -_make_test_img 4M +# Two bitmaps, to contrast granularity issues +_make_test_img -o cluster_size=4k 4M $QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io run_qemu <<EOF { "execute": "qmp_capabilities" } @@ -XXX,XX +XXX,XX @@ run_qemu <<EOF "arguments": { "node": "n", "name": "b", - "persistent": true + "persistent": true, + "granularity": 65536 + } +} +{ "execute": "block-dirty-bitmap-add", + "arguments": { + "node": "n", + "name": "b2", + "persistent": true, + "granularity": 512 } } { "execute": "quit" } @@ -XXX,XX +XXX,XX @@ echo echo "=== Write part of the file under active bitmap ===" echo -$QEMU_IO -c 'w -P 0x22 2M 2M' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'w -P 0x22 512 512' -c 'w -P 0x33 2M 2M' "$TEST_IMG" \ + | _filter_qemu_io echo -echo "=== End dirty bitmap, and start serving image over NBD ===" +echo "=== End dirty bitmaps, and start serving image over NBD ===" echo _launch_qemu 2> >(_filter_nbd) @@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"blockdev-add", "file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable", "arguments":{"node":"n", "name":"b"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable", + "arguments":{"node":"n", "name":"b2"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return" @@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", "arguments":{"device":"n"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", "arguments":{"name":"n", "bitmap":"b"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", + "arguments":{"device":"n", "name":"n2"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", + "arguments":{"name":"n2", "bitmap":"b2"}}' "return" echo -echo "=== Contrast normal status with dirty-bitmap status ===" +echo "=== Contrast normal status to large granularity dirty-bitmap ===" echo QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT IMG="driver=nbd,export=n,server.type=unix,server.path=$TEST_DIR/nbd" -$QEMU_IO -r -c 'r -P 0 0 1m' -c 'r -P 0x11 1m 1m' \ - -c 'r -P 0x22 2m 2m' --image-opts "$IMG" | _filter_qemu_io +$QEMU_IO -r -c 'r -P 0x22 512 512' -c 'r -P 0 512k 512k' -c 'r -P 0x11 1m 1m' \ + -c 'r -P 0x33 2m 2m' --image-opts "$IMG" | _filter_qemu_io $QEMU_IMG map --output=json --image-opts \ "$IMG" | _filter_qemu_img_map $QEMU_IMG map --output=json --image-opts \ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b" | _filter_qemu_img_map +echo +echo "=== Contrast to small granularity dirty-bitmap ===" +echo + +IMG="driver=nbd,export=n2,server.type=unix,server.path=$TEST_DIR/nbd" +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map + echo echo "=== End NBD server ===" echo _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove", "arguments":{"name":"n"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove", + "arguments":{"name":"n2"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return" diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index XXXXXXX..XXXXXXX 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -XXX,XX +XXX,XX @@ QA output created by 223 -=== Create partially sparse image, then add dirty bitmap === +=== Create partially sparse image, then add dirty bitmaps === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 wrote 2097152/2097152 bytes at offset 1048576 @@ -XXX,XX +XXX,XX @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} +{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} === Write part of the file under active bitmap === +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 2097152/2097152 bytes at offset 2097152 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -=== End dirty bitmap, and start serving image over NBD === +=== End dirty bitmaps, and start serving image over NBD === {"return": {}} {"return": {}} @@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 2097152 {"return": {}} {"return": {}} {"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} -=== Contrast normal status with dirty-bitmap status === +=== Contrast normal status to large granularity dirty-bitmap === -read 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 524288/524288 bytes at offset 524288 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 1048576/1048576 bytes at offset 1048576 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 2097152/2097152 bytes at offset 2097152 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false}, +[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true}, +{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false}, { "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": true}] -[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true}, +[{ "start": 0, "length": 65536, "depth": 0, "zero": false, "data": false}, +{ "start": 65536, "length": 2031616, "depth": 0, "zero": false, "data": true}, +{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}] + +=== Contrast to small granularity dirty-bitmap === + +[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true}, +{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false}, +{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true}, { "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}] === End NBD server === @@ -XXX,XX +XXX,XX @@ read 2097152/2097152 bytes at offset 2097152 {"return": {}} {"return": {}} {"return": {}} +{"return": {}} *** done -- 2.19.1
The following changes since commit 13356edb87506c148b163b8c7eb0695647d00c2a: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-01-24 09:45:33 +0000) are available in the Git repository at: https://repo.or.cz/qemu/kevin.git tags/for-upstream for you to fetch changes up to d570177b50c389f379f93183155a27d44856ab46: qemu-img: Change info key names for protocol nodes (2023-02-01 16:52:33 +0100) v4: - Fixed the 'qemu-img-close-errors' test case to run only on Linux and only with the file protocol, use qemu-io instead of truncate v3: - Make the compiler happier on BSD and CentOS Stream 8 v2: - Rebased to resolve merge conflicts in coroutine.h ---------------------------------------------------------------- Block layer patches - qemu-img info: Show protocol-level information - Move more functions to coroutines - Make coroutine annotations ready for static analysis - qemu-img: Fix exit code for errors closing the image - qcow2 bitmaps: Fix theoretical corruption in error path - pflash: Only load non-zero parts of backend image to save memory - Code cleanup and test case improvements ---------------------------------------------------------------- Alberto Faria (2): coroutine: annotate coroutine_fn for libclang block: Add no_coroutine_fn and coroutine_mixed_fn marker Emanuele Giuseppe Esposito (14): block-coroutine-wrapper: support void functions block: Convert bdrv_io_plug() to co_wrapper block: Convert bdrv_io_unplug() to co_wrapper block: Convert bdrv_is_inserted() to co_wrapper block: Rename refresh_total_sectors to bdrv_refresh_total_sectors block: Convert bdrv_refresh_total_sectors() to co_wrapper_mixed block-backend: use bdrv_getlength instead of blk_getlength block: use bdrv_co_refresh_total_sectors when possible block: Convert bdrv_get_allocated_file_size() to co_wrapper block: Convert bdrv_get_info() to co_wrapper_mixed block: Convert bdrv_eject() to co_wrapper block: Convert bdrv_lock_medium() to co_wrapper block: Convert bdrv_debug_event() to co_wrapper_mixed block: Rename bdrv_load/save_vmstate() to bdrv_co_load/save_vmstate() Hanna Reitz (12): block: Improve empty format-specific info dump block/file: Add file-specific image info block/vmdk: Change extent info type block: Split BlockNodeInfo off of ImageInfo qemu-img: Use BlockNodeInfo block/qapi: Let bdrv_query_image_info() recurse block/qapi: Introduce BlockGraphInfo block/qapi: Add indentation to bdrv_node_info_dump() iotests: Filter child node information iotests/106, 214, 308: Read only one size line qemu-img: Let info print block graph qemu-img: Change info key names for protocol nodes Kevin Wolf (4): qcow2: Fix theoretical corruption in store_bitmap() error path qemu-img commit: Report errors while closing the image qemu-img bitmap: Report errors while closing the image qemu-iotests: Test qemu-img bitmap/commit exit code on error Paolo Bonzini (2): qemu-io: do not reinvent the blk_pwrite_zeroes wheel block: remove bdrv_coroutine_enter Philippe Mathieu-Daudé (1): block/nbd: Add missing <qemu/bswap.h> include Thomas Huth (2): tests/qemu-iotests/312: Mark "quorum" as required driver tests/qemu-iotests/262: Check for availability of "blkverify" first Xiang Zheng (1): pflash: Only read non-zero parts of backend image qapi/block-core.json | 123 +++++++- include/block/block-common.h | 11 +- include/block/block-io.h | 41 ++- include/block/block_int-common.h | 26 +- include/block/block_int-io.h | 5 +- include/block/nbd.h | 1 + include/block/qapi.h | 14 +- include/qemu/osdep.h | 44 +++ include/sysemu/block-backend-io.h | 31 +- block.c | 88 +++--- block/blkdebug.c | 11 +- block/blkio.c | 15 +- block/blklogwrites.c | 6 +- block/blkreplay.c | 6 +- block/blkverify.c | 6 +- block/block-backend.c | 38 +-- block/commit.c | 4 +- block/copy-on-read.c | 18 +- block/crypto.c | 14 +- block/curl.c | 10 +- block/file-posix.c | 137 +++++---- block/file-win32.c | 18 +- block/filter-compress.c | 20 +- block/gluster.c | 23 +- block/io.c | 76 ++--- block/iscsi.c | 17 +- block/mirror.c | 6 +- block/monitor/block-hmp-cmds.c | 2 +- block/nbd.c | 8 +- block/nfs.c | 4 +- block/null.c | 13 +- block/nvme.c | 14 +- block/preallocate.c | 16 +- block/qapi.c | 317 ++++++++++++++++----- block/qcow.c | 5 +- block/qcow2-bitmap.c | 5 +- block/qcow2-refcount.c | 2 +- block/qcow2.c | 17 +- block/qed.c | 11 +- block/quorum.c | 8 +- block/raw-format.c | 25 +- block/rbd.c | 9 +- block/replication.c | 6 +- block/ssh.c | 4 +- block/throttle.c | 6 +- block/vdi.c | 7 +- block/vhdx.c | 5 +- block/vmdk.c | 22 +- block/vpc.c | 5 +- blockdev.c | 8 +- hw/block/block.c | 36 ++- hw/scsi/scsi-disk.c | 5 + qemu-img.c | 100 +++++-- qemu-io-cmds.c | 62 +--- tests/unit/test-block-iothread.c | 3 + scripts/block-coroutine-wrapper.py | 20 +- tests/qemu-iotests/iotests.py | 18 +- block/meson.build | 1 + tests/qemu-iotests/065 | 2 +- tests/qemu-iotests/106 | 4 +- tests/qemu-iotests/214 | 6 +- tests/qemu-iotests/262 | 3 +- tests/qemu-iotests/302.out | 5 + tests/qemu-iotests/308 | 4 +- tests/qemu-iotests/312 | 1 + tests/qemu-iotests/common.filter | 22 +- tests/qemu-iotests/common.rc | 22 +- tests/qemu-iotests/tests/qemu-img-close-errors | 96 +++++++ tests/qemu-iotests/tests/qemu-img-close-errors.out | 23 ++ 69 files changed, 1209 insertions(+), 552 deletions(-) create mode 100755 tests/qemu-iotests/tests/qemu-img-close-errors create mode 100644 tests/qemu-iotests/tests/qemu-img-close-errors.out