From 2382db1479af0ec735e42a0d4f31c88b95a4fd43 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 08 2014 08:11:48 +0000 Subject: import qemu-kvm-1.5.3-60.el7_0.7 --- diff --git a/SOURCES/kvm-block-make-top-argument-to-block-commit-optional.patch b/SOURCES/kvm-block-make-top-argument-to-block-commit-optional.patch new file mode 100644 index 0000000..36f7b1d --- /dev/null +++ b/SOURCES/kvm-block-make-top-argument-to-block-commit-optional.patch @@ -0,0 +1,201 @@ +From 915f7feb718ab551f6a0c0e05939e369c3aab759 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:12 +0200 +Subject: [PATCH 5/7] block: make 'top' argument to block-commit optional + +Message-id: <1408552814-23031-6-git-send-email-eblake@redhat.com> +Patchwork-id: 60647 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 5/7] block: make 'top' argument to block-commit optional +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Jeff Cody + +Now that active layer block-commit is supported, the 'top' argument +no longer needs to be mandatory. + +Change it to optional, with the default being the active layer in the +device chain. + +[kwolf: Rebased and resolved conflict in tests/qemu-iotests/040] + +Reviewed-by: Eric Blake +Reviewed-by: Benoit Canet +Signed-off-by: Jeff Cody +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 7676e2c597000eff3a7233b40cca768b358f9bc9) + +Conflicts: + qapi/block-core.json - downstream in qapi-schema.json still + tests/qemu-iotests/040 - context due to no common event handling + +Signed-off-by: Eric Blake +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 16 ++++++++++++++-- + qapi-schema.json | 7 ++++--- + qmp-commands.hx | 5 +++-- + tests/qemu-iotests/040 | 28 ++++++++++++++++++---------- + 4 files changed, 39 insertions(+), 17 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index e51203c..a94c9d3 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1463,7 +1463,8 @@ void qmp_block_stream(const char *device, bool has_base, + } + + void qmp_block_commit(const char *device, +- bool has_base, const char *base, const char *top, ++ bool has_base, const char *base, ++ bool has_top, const char *top, + bool has_speed, int64_t speed, + Error **errp) + { +@@ -1478,6 +1479,11 @@ void qmp_block_commit(const char *device, + /* drain all i/o before commits */ + bdrv_drain_all(); + ++ /* Important Note: ++ * libvirt relies on the DeviceNotFound error class in order to probe for ++ * live commit feature versions; for this to work, we must make sure to ++ * perform the device lookup before any generic errors that may occur in a ++ * scenario in which all optional arguments are omitted. */ + bs = bdrv_find(device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); +@@ -1487,7 +1493,7 @@ void qmp_block_commit(const char *device, + /* default top_bs is the active layer */ + top_bs = bs; + +- if (top) { ++ if (has_top && top) { + if (strcmp(bs->filename, top) != 0) { + top_bs = bdrv_find_backing_image(bs, top); + } +@@ -1509,6 +1515,12 @@ void qmp_block_commit(const char *device, + return; + } + ++ /* Do not allow attempts to commit an image into itself */ ++ if (top_bs == base_bs) { ++ error_setg(errp, "cannot commit an image into itself"); ++ return; ++ } ++ + if (top_bs == bs) { + commit_active_start(bs, base_bs, speed, on_error, block_job_cb, + bs, &local_err); +diff --git a/qapi-schema.json b/qapi-schema.json +index aaa86f5..3768872 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -1838,8 +1838,9 @@ + # @base: #optional The file name of the backing image to write data into. + # If not specified, this is the deepest backing image + # +-# @top: The file name of the backing image within the image chain, +-# which contains the topmost data to be committed down. ++# @top: #optional The file name of the backing image within the image chain, ++# which contains the topmost data to be committed down. If ++# not specified, this is the active layer. + # + # If top == base, that is an error. + # If top == active, the job will not be completed by itself, +@@ -1867,7 +1868,7 @@ + # + ## + { 'command': 'block-commit', +- 'data': { 'device': 'str', '*base': 'str', 'top': 'str', ++ 'data': { 'device': 'str', '*base': 'str', '*top': 'str', + '*speed': 'int' } } + + ## +diff --git a/qmp-commands.hx b/qmp-commands.hx +index 1d4be84..b6b6246 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -1005,7 +1005,7 @@ EQMP + + { + .name = "block-commit", +- .args_type = "device:B,base:s?,top:s,speed:o?", ++ .args_type = "device:B,base:s?,top:s?,speed:o?", + .mhandler.cmd_new = qmp_marshal_input_block_commit, + }, + +@@ -1023,7 +1023,8 @@ Arguments: + If not specified, this is the deepest backing image + (json-string, optional) + - "top": The file name of the backing image within the image chain, +- which contains the topmost data to be committed down. ++ which contains the topmost data to be committed down. If ++ not specified, this is the active layer. (json-string, optional) + + If top == base, that is an error. + If top == active, the job will not be completed by itself, +diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 +index cf80e0c..c5ab930 100755 +--- a/tests/qemu-iotests/040 ++++ b/tests/qemu-iotests/040 +@@ -63,11 +63,7 @@ class ImageCommitTestCase(iotests.QMPTestCase): + i = i + 512 + file.close() + +- def run_commit_test(self, top, base, need_ready=False): +- self.assert_no_active_commit() +- result = self.vm.qmp('block-commit', device='drive0', top=top, base=base) +- self.assert_qmp(result, 'return', {}) +- ++ def wait_for_complete(self, need_ready=False): + completed = False + ready = False + while not completed: +@@ -90,6 +86,18 @@ class ImageCommitTestCase(iotests.QMPTestCase): + self.assert_no_active_commit() + self.vm.shutdown() + ++ def run_commit_test(self, top, base, need_ready=False): ++ self.assert_no_active_commit() ++ result = self.vm.qmp('block-commit', device='drive0', top=top, base=base) ++ self.assert_qmp(result, 'return', {}) ++ self.wait_for_complete(need_ready) ++ ++ def run_default_commit_test(self): ++ self.assert_no_active_commit() ++ result = self.vm.qmp('block-commit', device='drive0') ++ self.assert_qmp(result, 'return', {}) ++ self.wait_for_complete() ++ + class TestSingleDrive(ImageCommitTestCase): + image_len = 1 * 1024 * 1024 + test_len = 1 * 1024 * 256 +@@ -141,17 +149,17 @@ class TestSingleDrive(ImageCommitTestCase): + self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + ++ def test_top_is_default_active(self): ++ self.run_default_commit_test() ++ self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) ++ self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) ++ + def test_top_and_base_reversed(self): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img) + self.assert_qmp(result, 'error/class', 'GenericError') + self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img) + +- def test_top_omitted(self): +- self.assert_no_active_commit() +- result = self.vm.qmp('block-commit', device='drive0') +- self.assert_qmp(result, 'error/class', 'GenericError') +- self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing") + + class TestRelativePaths(ImageCommitTestCase): + image_len = 1 * 1024 * 1024 +-- +1.7.1 + diff --git a/SOURCES/kvm-blockjob-Add-block_job_yield.patch b/SOURCES/kvm-blockjob-Add-block_job_yield.patch new file mode 100644 index 0000000..92b267b --- /dev/null +++ b/SOURCES/kvm-blockjob-Add-block_job_yield.patch @@ -0,0 +1,77 @@ +From c1c69c1b13d64f7d892c8b661714fe388b1a6047 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:09 +0200 +Subject: [PATCH 2/7] blockjob: Add block_job_yield() + +Message-id: <1408552814-23031-3-git-send-email-eblake@redhat.com> +Patchwork-id: 60644 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 2/7] blockjob: Add block_job_yield() +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +This will unset busy flag and put coroutine to sleep, can be used to +wait for QMP complete/cancel. + +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit dc71ce45ded4e872e25c2de32d5e7a71842b0985) +Signed-off-by: Eric Blake + +Signed-off-by: Miroslav Rezanina +--- + blockjob.c | 14 ++++++++++++++ + include/block/blockjob.h | 8 ++++++++ + 2 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/blockjob.c b/blockjob.c +index a4430a0..1117ee7 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -206,6 +206,20 @@ void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) + job->busy = true; + } + ++void block_job_yield(BlockJob *job) ++{ ++ assert(job->busy); ++ ++ /* Check cancellation *before* setting busy = false, too! */ ++ if (block_job_is_cancelled(job)) { ++ return; ++ } ++ ++ job->busy = false; ++ qemu_coroutine_yield(); ++ job->busy = true; ++} ++ + BlockJobInfo *block_job_query(BlockJob *job) + { + BlockJobInfo *info = g_new0(BlockJobInfo, 1); +diff --git a/include/block/blockjob.h b/include/block/blockjob.h +index 5a7d859..11f7c7e 100644 +--- a/include/block/blockjob.h ++++ b/include/block/blockjob.h +@@ -144,6 +144,14 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, + void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); + + /** ++ * block_job_yield: ++ * @job: The job that calls the function. ++ * ++ * Yield the block job coroutine. ++ */ ++void block_job_yield(BlockJob *job); ++ ++/** + * block_job_completed: + * @job: The job being completed. + * @ret: The status code. +-- +1.7.1 + diff --git a/SOURCES/kvm-memory-Don-t-call-memory_region_update_coalesced_ran.patch b/SOURCES/kvm-memory-Don-t-call-memory_region_update_coalesced_ran.patch new file mode 100644 index 0000000..3c0f1e7 --- /dev/null +++ b/SOURCES/kvm-memory-Don-t-call-memory_region_update_coalesced_ran.patch @@ -0,0 +1,63 @@ +From 6e840c55cf077c166740a837edd92b8346be2cb9 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Fri, 8 Aug 2014 03:23:27 +0200 +Subject: [PATCH 10/10] memory: Don't call memory_region_update_coalesced_range if nothing changed + +Message-id: <1407468207-28928-1-git-send-email-famz@redhat.com> +Patchwork-id: 60486 +O-Subject: [RHEL-7.0.z qemu-kvm PATCH] memory: Don't call memory_region_update_coalesced_range if nothing changed +Bugzilla: 1124660 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Amos Kong + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1124660 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=7805797 + +With huge number of PCI devices in the system (for example, 200 +virtio-blk-pci), this unconditional call can slow down emulation of +irrelevant PCI operations drastically, such as a BAR update on a device +that has no coalescing region. So avoid it. + +Signed-off-by: Fam Zheng +Signed-off-by: Paolo Bonzini +(cherry picked from commit ab5b3db5d711b290d63e954dc64647dd51cef962) +Signed-off-by: Fam Zheng +--- + memory.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + memory.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/memory.c b/memory.c +index edaf6fd..a71d096 100644 +--- a/memory.c ++++ b/memory.c +@@ -1210,6 +1210,7 @@ void memory_region_add_coalescing(MemoryRegion *mr, + void memory_region_clear_coalescing(MemoryRegion *mr) + { + CoalescedMemoryRange *cmr; ++ bool updated = false; + + qemu_flush_coalesced_mmio_buffer(); + mr->flush_coalesced_mmio = false; +@@ -1218,8 +1219,12 @@ void memory_region_clear_coalescing(MemoryRegion *mr) + cmr = QTAILQ_FIRST(&mr->coalesced); + QTAILQ_REMOVE(&mr->coalesced, cmr, link); + g_free(cmr); ++ updated = true; ++ } ++ ++ if (updated) { ++ memory_region_update_coalesced_range(mr); + } +- memory_region_update_coalesced_range(mr); + } + + void memory_region_set_flush_coalesced(MemoryRegion *mr) +-- +1.7.1 + diff --git a/SOURCES/kvm-mirror-Fix-qiov-size-for-short-requests.patch b/SOURCES/kvm-mirror-Fix-qiov-size-for-short-requests.patch new file mode 100644 index 0000000..4ae2a35 --- /dev/null +++ b/SOURCES/kvm-mirror-Fix-qiov-size-for-short-requests.patch @@ -0,0 +1,93 @@ +From cb60b78e889e738f88e4c056d7312290869e4f1d Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:14 +0200 +Subject: [PATCH 7/7] mirror: Fix qiov size for short requests + +Message-id: <1408552814-23031-8-git-send-email-eblake@redhat.com> +Patchwork-id: 60650 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 7/7] mirror: Fix qiov size for short requests +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +When mirroring an image of a size that is not a multiple of the +mirror job granularity, the last request would have the right nb_sectors +argument, but a qiov that is rounded up to the next multiple of the +granularity. Don't do this. + +This fixes a segfault that is caused by raw-posix being confused by this +and allocating a buffer with request length, but operating on it with +qiov length. + +[s/Driver/Drive/ in qemu-iotests 041 as suggested by Eric +--Stefan] + +Reported-by: Eric Blake +Signed-off-by: Kevin Wolf +Tested-by: Eric Blake +Reviewed-by: Eric Blake +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 5a0f6fd5c84573387056e0464a7fc0c6fb70b2dc) + +Conflicts: + tests/qemu-iotests/041.out - context with fewer tests run downstream + +Signed-off-by: Eric Blake +Signed-off-by: Miroslav Rezanina +--- + block/mirror.c | 4 +++- + tests/qemu-iotests/041 | 5 +++++ + tests/qemu-iotests/041.out | 4 ++-- + 3 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index cdc0268..b7cf4ab 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -243,9 +243,11 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s) + next_sector = sector_num; + while (nb_chunks-- > 0) { + MirrorBuffer *buf = QSIMPLEQ_FIRST(&s->buf_free); ++ size_t remaining = (nb_sectors * BDRV_SECTOR_SIZE) - op->qiov.size; ++ + QSIMPLEQ_REMOVE_HEAD(&s->buf_free, next); + s->buf_free_count--; +- qemu_iovec_add(&op->qiov, buf, s->granularity); ++ qemu_iovec_add(&op->qiov, buf, MIN(s->granularity, remaining)); + + /* Advance the HBitmapIter in parallel, so that we do not examine + * the same sector twice. +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index 912e499..b654081 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -270,6 +270,11 @@ class TestSingleDriveZeroLength(TestSingleDrive): + test_small_buffer2 = None + test_large_cluster = None + ++class TestSingleDriveUnalignedLength(TestSingleDrive): ++ image_len = 1025 * 1024 ++ test_small_buffer2 = None ++ test_large_cluster = None ++ + class TestMirrorNoBacking(ImageMirroringTestCase): + image_len = 2 * 1024 * 1024 # MB + +diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out +index cfa5c0d..802ffaa 100644 +--- a/tests/qemu-iotests/041.out ++++ b/tests/qemu-iotests/041.out +@@ -1,5 +1,5 @@ +-................................... ++........................................... + ---------------------------------------------------------------------- +-Ran 35 tests ++Ran 43 tests + + OK +-- +1.7.1 + diff --git a/SOURCES/kvm-mirror-Fix-resource-leak-when-bdrv_getlength-fails.patch b/SOURCES/kvm-mirror-Fix-resource-leak-when-bdrv_getlength-fails.patch new file mode 100644 index 0000000..ff3922b --- /dev/null +++ b/SOURCES/kvm-mirror-Fix-resource-leak-when-bdrv_getlength-fails.patch @@ -0,0 +1,46 @@ +From 64f938d5b7ae0c2b1029b9816f45c8e5c0e0f560 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:08 +0200 +Subject: [PATCH 1/7] mirror: Fix resource leak when bdrv_getlength fails + +Message-id: <1408552814-23031-2-git-send-email-eblake@redhat.com> +Patchwork-id: 60646 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 1/7] mirror: Fix resource leak when bdrv_getlength fails +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +The direct return will skip releasing of all the resouces at +immediate_exit, don't miss that. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 373df5b135b4a54e0abb394e9e703fef3ded093c) +Signed-off-by: Eric Blake + +Signed-off-by: Miroslav Rezanina +--- + block/mirror.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index 47e14cd..9b3e229 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -307,8 +307,8 @@ static void coroutine_fn mirror_run(void *opaque) + + s->common.len = bdrv_getlength(bs); + if (s->common.len <= 0) { +- block_job_completed(&s->common, s->common.len); +- return; ++ ret = s->common.len; ++ goto immediate_exit; + } + + length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity; +-- +1.7.1 + diff --git a/SOURCES/kvm-mirror-Go-through-ready-complete-process-for-0-len-i.patch b/SOURCES/kvm-mirror-Go-through-ready-complete-process-for-0-len-i.patch new file mode 100644 index 0000000..1156d36 --- /dev/null +++ b/SOURCES/kvm-mirror-Go-through-ready-complete-process-for-0-len-i.patch @@ -0,0 +1,69 @@ +From a437bfcdaad8e387709506ccaa992895f76afa8e Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:10 +0200 +Subject: [PATCH 3/7] mirror: Go through ready -> complete process for 0 len image + +Message-id: <1408552814-23031-4-git-send-email-eblake@redhat.com> +Patchwork-id: 60645 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 3/7] mirror: Go through ready -> complete process for 0 len image +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +When mirroring or active committing a zero length image, BLOCK_JOB_READY +is not reported now, instead the job completes because we short circuit +the mirror job loop. + +This is inconsistent with non-zero length images, and only confuses +management software. + +Let's do the same thing when seeing a 0-length image: report ready +immediately; wait for block-job-cancel or block-job-complete; clear the +cancel flag as existing non-zero image synced case (cancelled after +ready); then jump to the exit. + +Reported-by: Eric Blake +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 9e48b025400b2d284e17860862b0a4aa02c6032d) + +Conflicts: + block/mirror.c - no backport of qapi events + +Signed-off-by: Eric Blake +Signed-off-by: Miroslav Rezanina +--- + block/mirror.c | 11 ++++++++++- + 1 files changed, 10 insertions(+), 1 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index 9b3e229..cdc0268 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -306,9 +306,18 @@ static void coroutine_fn mirror_run(void *opaque) + } + + s->common.len = bdrv_getlength(bs); +- if (s->common.len <= 0) { ++ if (s->common.len < 0) { + ret = s->common.len; + goto immediate_exit; ++ } else if (s->common.len == 0) { ++ /* Report BLOCK_JOB_READY and wait for complete. */ ++ block_job_ready(&s->common); ++ s->synced = true; ++ while (!block_job_is_cancelled(&s->common) && !s->should_complete) { ++ block_job_yield(&s->common); ++ } ++ s->common.cancelled = false; ++ goto immediate_exit; + } + + length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity; +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Test-0-length-image-for-mirror.patch b/SOURCES/kvm-qemu-iotests-Test-0-length-image-for-mirror.patch new file mode 100644 index 0000000..7a77c05 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Test-0-length-image-for-mirror.patch @@ -0,0 +1,93 @@ +From 8042a9daf7913e39b7ee4f6417f1d934e5dabbff Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:13 +0200 +Subject: [PATCH 6/7] qemu-iotests: Test 0-length image for mirror + +Message-id: <1408552814-23031-7-git-send-email-eblake@redhat.com> +Patchwork-id: 60648 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 6/7] qemu-iotests: Test 0-length image for mirror +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +All behavior and invariant should hold for images with 0 length, so +add a class to repeat all the tests in TestSingleDrive. + +Hide two unapplicable test methods that would fail with 0 image length +because it's also used as cluster size. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 3b9f27d2b34cb8c5cc6cec993712c7e1943e9de9) + +Conflicts: + tests/qemu-iotests/041 - context due to no common event handling + +Signed-off-by: Eric Blake +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/041 | 11 ++++++++--- + tests/qemu-iotests/041.out | 4 ++-- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 +index bcfb759..912e499 100755 +--- a/tests/qemu-iotests/041 ++++ b/tests/qemu-iotests/041 +@@ -123,7 +123,7 @@ class TestSingleDrive(ImageMirroringTestCase): + image_len = 1 * 1024 * 1024 # MB + + def setUp(self): +- self.create_image(backing_img, TestSingleDrive.image_len) ++ self.create_image(backing_img, self.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) + self.vm = iotests.VM().add_drive(test_img) + self.vm.launch() +@@ -222,7 +222,7 @@ class TestSingleDrive(ImageMirroringTestCase): + self.assert_no_active_block_jobs() + + qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,size=%d' +- % (TestSingleDrive.image_len, TestSingleDrive.image_len), target_img) ++ % (self.image_len, self.image_len), target_img) + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + buf_size=65536, mode='existing', target=target_img) + self.assert_qmp(result, 'return', {}) +@@ -238,7 +238,7 @@ class TestSingleDrive(ImageMirroringTestCase): + self.assert_no_active_block_jobs() + + qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s' +- % (TestSingleDrive.image_len, backing_img), target_img) ++ % (self.image_len, backing_img), target_img) + result = self.vm.qmp('drive-mirror', device='drive0', sync='full', + mode='existing', target=target_img) + self.assert_qmp(result, 'return', {}) +@@ -265,6 +265,11 @@ class TestSingleDrive(ImageMirroringTestCase): + target=target_img) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + ++class TestSingleDriveZeroLength(TestSingleDrive): ++ image_len = 0 ++ test_small_buffer2 = None ++ test_large_cluster = None ++ + class TestMirrorNoBacking(ImageMirroringTestCase): + image_len = 2 * 1024 * 1024 # MB + +diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out +index 6d9bee1..cfa5c0d 100644 +--- a/tests/qemu-iotests/041.out ++++ b/tests/qemu-iotests/041.out +@@ -1,5 +1,5 @@ +-........................... ++................................... + ---------------------------------------------------------------------- +-Ran 27 tests ++Ran 35 tests + + OK +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Test-BLOCK_JOB_READY-event-for-0Kb-imag.patch b/SOURCES/kvm-qemu-iotests-Test-BLOCK_JOB_READY-event-for-0Kb-imag.patch new file mode 100644 index 0000000..ff61734 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Test-BLOCK_JOB_READY-event-for-0Kb-imag.patch @@ -0,0 +1,107 @@ +From 2b17bf64d8b033b7a85b67597282d1751d027d7a Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 20 Aug 2014 16:40:11 +0200 +Subject: [PATCH 4/7] qemu-iotests: Test BLOCK_JOB_READY event for 0Kb image active commit + +Message-id: <1408552814-23031-5-git-send-email-eblake@redhat.com> +Patchwork-id: 60649 +O-Subject: [qemu-kvm-rhev 7.0.z PATCH 4/7] qemu-iotests: Test BLOCK_JOB_READY event for 0Kb image active commit +Bugzilla: 1132806 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +There should be a BLOCK_JOB_READY event with active commit, regardless +of image length. Let's test the 0 length image case, and make sure it +goes through the ready->complete process. + +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 8b9a30ca5bc10545637429486836f3c206c39fab) + +Conflicts: + tests/qemu-iotests/040 - context, due to no common event infrastructure + +Signed-off-by: Eric Blake +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/040 | 12 +++++++++--- + tests/qemu-iotests/040.out | 4 ++-- + 2 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 +index f210fb7..cf80e0c 100755 +--- a/tests/qemu-iotests/040 ++++ b/tests/qemu-iotests/040 +@@ -63,12 +63,13 @@ class ImageCommitTestCase(iotests.QMPTestCase): + i = i + 512 + file.close() + +- def run_commit_test(self, top, base): ++ def run_commit_test(self, top, base, need_ready=False): + self.assert_no_active_commit() + result = self.vm.qmp('block-commit', device='drive0', top=top, base=base) + self.assert_qmp(result, 'return', {}) + + completed = False ++ ready = False + while not completed: + for event in self.vm.get_qmp_events(wait=True): + if event['event'] == 'BLOCK_JOB_COMPLETED': +@@ -76,8 +77,11 @@ class ImageCommitTestCase(iotests.QMPTestCase): + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/offset', self.image_len) + self.assert_qmp(event, 'data/len', self.image_len) ++ if need_ready: ++ self.assertTrue(ready, "Expecting BLOCK_JOB_COMPLETED event") + completed = True + elif event['event'] == 'BLOCK_JOB_READY': ++ ready = True + self.assert_qmp(event, 'data/type', 'commit') + self.assert_qmp(event, 'data/device', 'drive0') + self.assert_qmp(event, 'data/len', self.image_len) +@@ -91,7 +95,7 @@ class TestSingleDrive(ImageCommitTestCase): + test_len = 1 * 1024 * 256 + + def setUp(self): +- self.create_image(backing_img, TestSingleDrive.image_len) ++ self.create_image(backing_img, self.image_len) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) + qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) + qemu_io('-c', 'write -P 0xab 0 524288', backing_img) +@@ -133,7 +137,7 @@ class TestSingleDrive(ImageCommitTestCase): + self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found') + + def test_top_is_active(self): +- self.run_commit_test(test_img, backing_img) ++ self.run_commit_test(test_img, backing_img, need_ready=True) + self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + +@@ -265,6 +269,8 @@ class TestSetSpeed(ImageCommitTestCase): + + self.cancel_and_wait() + ++class TestActiveZeroLengthImage(TestSingleDrive): ++ image_len = 0 + + if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2', 'qed']) +diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out +index b6f2576..42314e9 100644 +--- a/tests/qemu-iotests/040.out ++++ b/tests/qemu-iotests/040.out +@@ -1,5 +1,5 @@ +-................ ++........................ + ---------------------------------------------------------------------- +-Ran 16 tests ++Ran 24 tests + + OK +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-Don-t-cache-MSIMessage.patch b/SOURCES/kvm-vfio-Don-t-cache-MSIMessage.patch new file mode 100644 index 0000000..9e69317 --- /dev/null +++ b/SOURCES/kvm-vfio-Don-t-cache-MSIMessage.patch @@ -0,0 +1,80 @@ +From f0550083eabcc0fff10cd8a55ed534f8563ce022 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:03:20 +0200 +Subject: [PATCH 07/10] vfio: Don't cache MSIMessage + +Message-id: <20140807210320.11689.35203.stgit@gimli.home> +Patchwork-id: 60483 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 6/6] vfio: Don't cache MSIMessage +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +Upstream: 9b3af4c0e40f14b5173ad6e2d9fcc376207ec1dd + +Commit 40509f7f added a test to avoid updating KVM MSI routes when the +MSIMessage is unchanged and f4d45d47 switched to relying on this +rather than doing our own comparison. Our cached msg is effectively +unused now. Remove it. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 8 ++------ + 1 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 688e2ef..abaa4c1 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -131,7 +131,6 @@ typedef struct VFIOMSIVector { + EventNotifier interrupt; + EventNotifier kvm_interrupt; + struct VFIODevice *vdev; /* back pointer to device */ +- MSIMessage msg; /* cache the MSI message so we know when it changes */ + int virq; + bool use; + } VFIOMSIVector; +@@ -725,7 +724,6 @@ static void vfio_add_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage *msg, + return; + } + +- vector->msg = *msg; + vector->virq = virq; + } + +@@ -741,7 +739,6 @@ static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector) + static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg) + { + kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg); +- vector->msg = msg; + } + + static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, +@@ -920,6 +917,7 @@ retry: + + for (i = 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector = &vdev->msi_vectors[i]; ++ MSIMessage msg = msi_get_message(&vdev->pdev, i); + + vector->vdev = vdev; + vector->virq = -1; +@@ -932,13 +930,11 @@ retry: + qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), + vfio_msi_interrupt, NULL, vector); + +- vector->msg = msi_get_message(&vdev->pdev, i); +- + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vfio_add_kvm_msi_virq(vector, &vector->msg, false); ++ vfio_add_kvm_msi_virq(vector, &msg, false); + } + + /* Set interrupt type prior to possible interrupts */ +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-Fix-MSI-X-vector-expansion.patch b/SOURCES/kvm-vfio-Fix-MSI-X-vector-expansion.patch new file mode 100644 index 0000000..a4a54d4 --- /dev/null +++ b/SOURCES/kvm-vfio-Fix-MSI-X-vector-expansion.patch @@ -0,0 +1,95 @@ +From bdd720aafc6099e126b682f70e4163e1b2097594 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:03:14 +0200 +Subject: [PATCH 06/10] vfio: Fix MSI-X vector expansion + +Message-id: <20140807210314.11689.89693.stgit@gimli.home> +Patchwork-id: 60482 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 5/6] vfio: Fix MSI-X vector expansion +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +Upstream: c048be5cc92ae201c339d46984476c4629275ed6 + +When new MSI-X vectors are enabled we need to disable MSI-X and +re-enable it with the correct number of vectors. That means we need +to reprogram the eventfd triggers for each vector. Prior to f4d45d47 +vector->use tracked whether a vector was masked or unmasked and we +could always pick the KVM path when available for unmasked vectors. +Now vfio doesn't track mask state itself and vector->use and virq +remains configured even for masked vectors. Therefore we need to ask +the MSI-X code whether a vector is masked in order to select the +correct signaling path. As noted in the comment, MSI relies on +hardware to handle masking. + +Signed-off-by: Alex Williamson +Cc: qemu-stable@nongnu.org # QEMU 2.1 +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 38 +++++++++++++++++++++++++++++--------- + 1 files changed, 29 insertions(+), 9 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index bd37924..688e2ef 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -119,11 +119,20 @@ typedef struct VFIOINTx { + } VFIOINTx; + + typedef struct VFIOMSIVector { +- EventNotifier interrupt; /* eventfd triggered on interrupt */ +- EventNotifier kvm_interrupt; /* eventfd triggered for KVM irqfd bypass */ ++ /* ++ * Two interrupt paths are configured per vector. The first, is only used ++ * for interrupts injected via QEMU. This is typically the non-accel path, ++ * but may also be used when we want QEMU to handle masking and pending ++ * bits. The KVM path bypasses QEMU and is therefore higher performance, ++ * but requires masking at the device. virq is used to track the MSI route ++ * through KVM, thus kvm_interrupt is only available when virq is set to a ++ * valid (>= 0) value. ++ */ ++ EventNotifier interrupt; ++ EventNotifier kvm_interrupt; + struct VFIODevice *vdev; /* back pointer to device */ + MSIMessage msg; /* cache the MSI message so we know when it changes */ +- int virq; /* KVM irqchip route for QEMU bypass */ ++ int virq; + bool use; + } VFIOMSIVector; + +@@ -662,13 +671,24 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix) + fds = (int32_t *)&irq_set->data; + + for (i = 0; i < vdev->nr_vectors; i++) { +- if (!vdev->msi_vectors[i].use) { +- fds[i] = -1; +- } else if (vdev->msi_vectors[i].virq >= 0) { +- fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt); +- } else { +- fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); ++ int fd = -1; ++ ++ /* ++ * MSI vs MSI-X - The guest has direct access to MSI mask and pending ++ * bits, therefore we always use the KVM signaling path when setup. ++ * MSI-X mask and pending bits are emulated, so we want to use the ++ * KVM signaling path only when configured and unmasked. ++ */ ++ if (vdev->msi_vectors[i].use) { ++ if (vdev->msi_vectors[i].virq < 0 || ++ (msix && msix_is_masked(&vdev->pdev, i))) { ++ fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); ++ } else { ++ fd = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt); ++ } + } ++ ++ fds[i] = fd; + } + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-correct-debug-macro-typo.patch b/SOURCES/kvm-vfio-correct-debug-macro-typo.patch new file mode 100644 index 0000000..d91ba42 --- /dev/null +++ b/SOURCES/kvm-vfio-correct-debug-macro-typo.patch @@ -0,0 +1,43 @@ +From 18f67233db4f428332e100ccb194090675db0cdb Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:02:57 +0200 +Subject: [PATCH 03/10] vfio: correct debug macro typo + +Message-id: <20140807210257.11689.30368.stgit@gimli.home> +Patchwork-id: 60479 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 2/6] vfio: correct debug macro typo +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +From: Bandan Das + +Upstream: 8b6d14087d487203f4d1a67aeaddc3be6c73f49f + +Change to DEBUG_VFIO in vfio_msi_interrupt() for debug +messages to get printed + +Signed-off-by: Bandan Das +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index b5387ca..7f6ebf9 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -619,7 +619,7 @@ static void vfio_msi_interrupt(void *opaque) + return; + } + +-#ifdef VFIO_DEBUG ++#ifdef DEBUG_VFIO + MSIMessage msg; + + if (vdev->interrupt == VFIO_INT_MSIX) { +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Add-debug-config-options-to-disable-MSI-X-K.patch b/SOURCES/kvm-vfio-pci-Add-debug-config-options-to-disable-MSI-X-K.patch new file mode 100644 index 0000000..a2f925e --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Add-debug-config-options-to-disable-MSI-X-K.patch @@ -0,0 +1,82 @@ +From 8b417dd4a269341d4167ac7df64285869d37af58 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:02:51 +0200 +Subject: [PATCH 02/10] vfio-pci: Add debug config options to disable MSI/X KVM support + +Message-id: <20140807210251.11689.35960.stgit@gimli.home> +Patchwork-id: 60478 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 1/6] vfio-pci: Add debug config options to disable MSI/X KVM support +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +It's sometimes useful to be able to verify interrupts are passing +through correctly. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 24 ++++++++++++++++++++---- + 1 files changed, 20 insertions(+), 4 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index b04170e..b5387ca 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -52,6 +52,8 @@ + /* Extra debugging, trap acceleration paths for more logging */ + #define VFIO_ALLOW_MMAP 1 + #define VFIO_ALLOW_KVM_INTX 1 ++#define VFIO_ALLOW_KVM_MSI 1 ++#define VFIO_ALLOW_KVM_MSIX 1 + + struct VFIODevice; + +@@ -617,9 +619,21 @@ static void vfio_msi_interrupt(void *opaque) + return; + } + +- DPRINTF("%s(%04x:%02x:%02x.%x) vector %d\n", __func__, ++#ifdef VFIO_DEBUG ++ MSIMessage msg; ++ ++ if (vdev->interrupt == VFIO_INT_MSIX) { ++ msg = msi_get_message(&vdev->pdev, nr); ++ } else if (vdev->interrupt == VFIO_INT_MSI) { ++ msg = msix_get_message(&vdev->pdev, nr); ++ } else { ++ abort(); ++ } ++ ++ DPRINTF("%s(%04x:%02x:%02x.%x) vector %d 0x%"PRIx64"/0x%x\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, +- vdev->host.function, nr); ++ vdev->host.function, nr, msg.address, msg.data); ++#endif + + if (vdev->interrupt == VFIO_INT_MSIX) { + msix_notify(&vdev->pdev, nr); +@@ -687,7 +701,8 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1; ++ vector->virq = msg && VFIO_ALLOW_KVM_MSIX ? ++ kvm_irqchip_add_msi_route(kvm_state, *msg) : -1; + if (vector->virq < 0 || + kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq) < 0) { +@@ -854,7 +869,8 @@ retry: + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vector->virq = kvm_irqchip_add_msi_route(kvm_state, vector->msg); ++ vector->virq = VFIO_ALLOW_KVM_MSI ? ++ kvm_irqchip_add_msi_route(kvm_state, vector->msg) : -1; + if (vector->virq < 0 || + kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq) < 0) { +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Fix-MSI-X-debug-code.patch b/SOURCES/kvm-vfio-pci-Fix-MSI-X-debug-code.patch new file mode 100644 index 0000000..f480bf0 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Fix-MSI-X-debug-code.patch @@ -0,0 +1,42 @@ +From 1311f877741665964f5c6a56854a033ad704ef46 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:03:03 +0200 +Subject: [PATCH 04/10] vfio-pci: Fix MSI/X debug code + +Message-id: <20140807210302.11689.73901.stgit@gimli.home> +Patchwork-id: 60480 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 3/6] vfio-pci: Fix MSI/X debug code +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +Upstream: 9035f8c09bebb63c0cc6014acf5c7066ef778aff + +Use the correct MSI message function for debug info. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 7f6ebf9..5f0460a 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -623,9 +623,9 @@ static void vfio_msi_interrupt(void *opaque) + MSIMessage msg; + + if (vdev->interrupt == VFIO_INT_MSIX) { +- msg = msi_get_message(&vdev->pdev, nr); +- } else if (vdev->interrupt == VFIO_INT_MSI) { + msg = msix_get_message(&vdev->pdev, nr); ++ } else if (vdev->interrupt == VFIO_INT_MSI) { ++ msg = msi_get_message(&vdev->pdev, nr); + } else { + abort(); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Fix-MSI-X-masking-performance.patch b/SOURCES/kvm-vfio-pci-Fix-MSI-X-masking-performance.patch new file mode 100644 index 0000000..9731731 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Fix-MSI-X-masking-performance.patch @@ -0,0 +1,411 @@ +From a48a4761390e9aa917ebef7628dfc72f905910ee Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 7 Aug 2014 21:03:08 +0200 +Subject: [PATCH 05/10] vfio-pci: Fix MSI-X masking performance + +Message-id: <20140807210308.11689.93757.stgit@gimli.home> +Patchwork-id: 60481 +O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 4/6] vfio-pci: Fix MSI-X masking performance +Bugzilla: 1110693 1110695 +RH-Acked-by: Bandan Das +RH-Acked-by: Amos Kong +RH-Acked-by: Laszlo Ersek + +Upstream: f4d45d47826377722700894dbf7f47444527a9d2 + +There are still old guests out there that over-exercise MSI-X masking. +The current code completely sets-up and tears-down an MSI-X vector on +the "use" and "release" callbacks. While this is functional, it can +slow an old guest to a crawl. We can easily skip the KVM parts of +this so that we keep the MSI route and irqfd setup. We do however +need to switch VFIO to trigger a different eventfd while masked. +Actually, we have the option of continuing to use -1 to disable the +trigger, but by using another EventNotifier we can allow the MSI-X +core to emulate pending bits and re-fire the vector once unmasked. +MSI code gets updated as well to use the same setup and teardown +structures and functions. + +Prior to this change, an igbvf assigned to a RHEL5 guest gets about +20Mbps and 50 transactions/s with netperf (remote or VF->PF). With +this change, we get line rate and 3k transactions/s remote or 2Gbps +and 6k+ transactions/s to the PF. No significant change is expected +for newer guests with more well behaved MSI-X support. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 233 +++++++++++++++++++++++++++++++------------------------ + 1 files changed, 131 insertions(+), 102 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 5f0460a..bd37924 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -120,6 +120,7 @@ typedef struct VFIOINTx { + + typedef struct VFIOMSIVector { + EventNotifier interrupt; /* eventfd triggered on interrupt */ ++ EventNotifier kvm_interrupt; /* eventfd triggered for KVM irqfd bypass */ + struct VFIODevice *vdev; /* back pointer to device */ + MSIMessage msg; /* cache the MSI message so we know when it changes */ + int virq; /* KVM irqchip route for QEMU bypass */ +@@ -663,10 +664,11 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix) + for (i = 0; i < vdev->nr_vectors; i++) { + if (!vdev->msi_vectors[i].use) { + fds[i] = -1; +- continue; ++ } else if (vdev->msi_vectors[i].virq >= 0) { ++ fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt); ++ } else { ++ fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); + } +- +- fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); + } + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); +@@ -676,6 +678,52 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix) + return ret; + } + ++static void vfio_add_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage *msg, ++ bool msix) ++{ ++ int virq; ++ ++ if ((msix && !VFIO_ALLOW_KVM_MSIX) || ++ (!msix && !VFIO_ALLOW_KVM_MSI) || !msg) { ++ return; ++ } ++ ++ if (event_notifier_init(&vector->kvm_interrupt, 0)) { ++ return; ++ } ++ ++ virq = kvm_irqchip_add_msi_route(kvm_state, *msg); ++ if (virq < 0) { ++ event_notifier_cleanup(&vector->kvm_interrupt); ++ return; ++ } ++ ++ if (kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->kvm_interrupt, ++ virq) < 0) { ++ kvm_irqchip_release_virq(kvm_state, virq); ++ event_notifier_cleanup(&vector->kvm_interrupt); ++ return; ++ } ++ ++ vector->msg = *msg; ++ vector->virq = virq; ++} ++ ++static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector) ++{ ++ kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->kvm_interrupt, ++ vector->virq); ++ kvm_irqchip_release_virq(kvm_state, vector->virq); ++ vector->virq = -1; ++ event_notifier_cleanup(&vector->kvm_interrupt); ++} ++ ++static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg) ++{ ++ kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg); ++ vector->msg = msg; ++} ++ + static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, + MSIMessage *msg, IOHandler *handler) + { +@@ -688,30 +736,32 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, + vdev->host.function, nr); + + vector = &vdev->msi_vectors[nr]; +- vector->vdev = vdev; +- vector->use = true; +- +- msix_vector_use(pdev, nr); + +- if (event_notifier_init(&vector->interrupt, 0)) { +- error_report("vfio: Error: event_notifier_init failed"); ++ if (!vector->use) { ++ vector->vdev = vdev; ++ vector->virq = -1; ++ if (event_notifier_init(&vector->interrupt, 0)) { ++ error_report("vfio: Error: event_notifier_init failed"); ++ } ++ vector->use = true; ++ msix_vector_use(pdev, nr); + } + ++ qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), ++ handler, NULL, vector); ++ + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vector->virq = msg && VFIO_ALLOW_KVM_MSIX ? +- kvm_irqchip_add_msi_route(kvm_state, *msg) : -1; +- if (vector->virq < 0 || +- kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, +- vector->virq) < 0) { +- if (vector->virq >= 0) { +- kvm_irqchip_release_virq(kvm_state, vector->virq); +- vector->virq = -1; ++ if (vector->virq >= 0) { ++ if (!msg) { ++ vfio_remove_kvm_msi_virq(vector); ++ } else { ++ vfio_update_kvm_msi_virq(vector, *msg); + } +- qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), +- handler, NULL, vector); ++ } else { ++ vfio_add_kvm_msi_virq(vector, msg, true); + } + + /* +@@ -742,7 +792,11 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + +- *pfd = event_notifier_get_fd(&vector->interrupt); ++ if (vector->virq >= 0) { ++ *pfd = event_notifier_get_fd(&vector->kvm_interrupt); ++ } else { ++ *pfd = event_notifier_get_fd(&vector->interrupt); ++ } + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + g_free(irq_set); +@@ -764,50 +818,41 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) + { + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOMSIVector *vector = &vdev->msi_vectors[nr]; +- int argsz; +- struct vfio_irq_set *irq_set; +- int32_t *pfd; + + DPRINTF("%s(%04x:%02x:%02x.%x) vector %d released\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, nr); + + /* +- * XXX What's the right thing to do here? This turns off the interrupt +- * completely, but do we really just want to switch the interrupt to +- * bouncing through userspace and let msix.c drop it? Not sure. ++ * There are still old guests that mask and unmask vectors on every ++ * interrupt. If we're using QEMU bypass with a KVM irqfd, leave all of ++ * the KVM setup in place, simply switch VFIO to use the non-bypass ++ * eventfd. We'll then fire the interrupt through QEMU and the MSI-X ++ * core will mask the interrupt and set pending bits, allowing it to ++ * be re-asserted on unmask. Nothing to do if already using QEMU mode. + */ +- msix_vector_unuse(pdev, nr); +- +- argsz = sizeof(*irq_set) + sizeof(*pfd); ++ if (vector->virq >= 0) { ++ int argsz; ++ struct vfio_irq_set *irq_set; ++ int32_t *pfd; + +- irq_set = g_malloc0(argsz); +- irq_set->argsz = argsz; +- irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | +- VFIO_IRQ_SET_ACTION_TRIGGER; +- irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; +- irq_set->start = nr; +- irq_set->count = 1; +- pfd = (int32_t *)&irq_set->data; ++ argsz = sizeof(*irq_set) + sizeof(*pfd); + +- *pfd = -1; ++ irq_set = g_malloc0(argsz); ++ irq_set->argsz = argsz; ++ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | ++ VFIO_IRQ_SET_ACTION_TRIGGER; ++ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; ++ irq_set->start = nr; ++ irq_set->count = 1; ++ pfd = (int32_t *)&irq_set->data; + +- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); ++ *pfd = event_notifier_get_fd(&vector->interrupt); + +- g_free(irq_set); ++ ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + +- if (vector->virq < 0) { +- qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), +- NULL, NULL, NULL); +- } else { +- kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->interrupt, +- vector->virq); +- kvm_irqchip_release_virq(kvm_state, vector->virq); +- vector->virq = -1; ++ g_free(irq_set); + } +- +- event_notifier_cleanup(&vector->interrupt); +- vector->use = false; + } + + static void vfio_enable_msix(VFIODevice *vdev) +@@ -857,28 +902,28 @@ retry: + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + + vector->vdev = vdev; ++ vector->virq = -1; + vector->use = true; + + if (event_notifier_init(&vector->interrupt, 0)) { + error_report("vfio: Error: event_notifier_init failed"); + } + ++ qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), ++ vfio_msi_interrupt, NULL, vector); ++ + vector->msg = msi_get_message(&vdev->pdev, i); + + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vector->virq = VFIO_ALLOW_KVM_MSI ? +- kvm_irqchip_add_msi_route(kvm_state, vector->msg) : -1; +- if (vector->virq < 0 || +- kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, +- vector->virq) < 0) { +- qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), +- vfio_msi_interrupt, NULL, vector); +- } ++ vfio_add_kvm_msi_virq(vector, &vector->msg, false); + } + ++ /* Set interrupt type prior to possible interrupts */ ++ vdev->interrupt = VFIO_INT_MSI; ++ + ret = vfio_enable_vectors(vdev, false); + if (ret) { + if (ret < 0) { +@@ -891,14 +936,10 @@ retry: + for (i = 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + if (vector->virq >= 0) { +- kvm_irqchip_remove_irqfd_notifier(kvm_state, &vector->interrupt, +- vector->virq); +- kvm_irqchip_release_virq(kvm_state, vector->virq); +- vector->virq = -1; +- } else { +- qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), +- NULL, NULL, NULL); ++ vfio_remove_kvm_msi_virq(vector); + } ++ qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), ++ NULL, NULL, NULL); + event_notifier_cleanup(&vector->interrupt); + } + +@@ -910,11 +951,17 @@ retry: + } + vdev->nr_vectors = 0; + ++ /* ++ * Failing to setup MSI doesn't really fall within any specification. ++ * Let's try leaving interrupts disabled and hope the guest figures ++ * out to fall back to INTx for this device. ++ */ ++ error_report("vfio: Error: Failed to enable MSI"); ++ vdev->interrupt = VFIO_INT_NONE; ++ + return; + } + +- vdev->interrupt = VFIO_INT_MSI; +- + DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__, + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function, vdev->nr_vectors); +@@ -922,6 +969,20 @@ retry: + + static void vfio_disable_msi_common(VFIODevice *vdev) + { ++ int i; ++ ++ for (i = 0; i < vdev->nr_vectors; i++) { ++ VFIOMSIVector *vector = &vdev->msi_vectors[i]; ++ if (vdev->msi_vectors[i].use) { ++ if (vector->virq >= 0) { ++ vfio_remove_kvm_msi_virq(vector); ++ } ++ qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), ++ NULL, NULL, NULL); ++ event_notifier_cleanup(&vector->interrupt); ++ } ++ } ++ + g_free(vdev->msi_vectors); + vdev->msi_vectors = NULL; + vdev->nr_vectors = 0; +@@ -943,6 +1004,7 @@ static void vfio_disable_msix(VFIODevice *vdev) + for (i = 0; i < vdev->nr_vectors; i++) { + if (vdev->msi_vectors[i].use) { + vfio_msix_vector_release(&vdev->pdev, i); ++ msix_vector_unuse(&vdev->pdev, i); + } + } + +@@ -958,30 +1020,7 @@ static void vfio_disable_msix(VFIODevice *vdev) + + static void vfio_disable_msi(VFIODevice *vdev) + { +- int i; +- + vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX); +- +- for (i = 0; i < vdev->nr_vectors; i++) { +- VFIOMSIVector *vector = &vdev->msi_vectors[i]; +- +- if (!vector->use) { +- continue; +- } +- +- if (vector->virq >= 0) { +- kvm_irqchip_remove_irqfd_notifier(kvm_state, +- &vector->interrupt, vector->virq); +- kvm_irqchip_release_virq(kvm_state, vector->virq); +- vector->virq = -1; +- } else { +- qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), +- NULL, NULL, NULL); +- } +- +- event_notifier_cleanup(&vector->interrupt); +- } +- + vfio_disable_msi_common(vdev); + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, +@@ -1001,17 +1040,7 @@ static void vfio_update_msi(VFIODevice *vdev) + } + + msg = msi_get_message(&vdev->pdev, i); +- +- if (msg.address != vector->msg.address || +- msg.data != vector->msg.data) { +- +- DPRINTF("%s(%04x:%02x:%02x.%x) MSI vector %d changed\n", +- __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, i); +- +- kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg); +- vector->msg = msg; +- } ++ vfio_update_kvm_msi_virq(vector, msg); + } + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-virtio-net-Do-not-filter-VLANs-without-F_CTRL_VLAN.patch b/SOURCES/kvm-virtio-net-Do-not-filter-VLANs-without-F_CTRL_VLAN.patch new file mode 100644 index 0000000..0739415 --- /dev/null +++ b/SOURCES/kvm-virtio-net-Do-not-filter-VLANs-without-F_CTRL_VLAN.patch @@ -0,0 +1,51 @@ +From 75ccf361064e8eb2fc7f5e7606cbd0760c9baf7e Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Mon, 4 Aug 2014 04:12:07 +0200 +Subject: [PATCH 08/10] virtio-net: Do not filter VLANs without F_CTRL_VLAN + +Message-id: <1407125528-27862-2-git-send-email-akong@redhat.com> +Patchwork-id: 60415 +O-Subject: [RHEL-7.1/7.0.z qemu-kvm PATCH 1/2] virtio-net: Do not filter VLANs without F_CTRL_VLAN +Bugzilla: 1130149 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Xiao Wang +RH-Acked-by: Vlad Yasevich + +From: Stefan Fritsch + +If VIRTIO_NET_F_CTRL_VLAN is not negotiated, do not filter out all +VLAN-tagged packets but send them to the guest. + +This fixes VLANs with OpenBSD guests (and probably NetBSD, too, because +the OpenBSD driver started as a port from NetBSD). + +Signed-off-by: Stefan Fritsch +Signed-off-by: Amos Kong +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 0b1eaa8803e680de9a05727355dfe3d306b81e17) +Signed-off-by: Miroslav Rezanina +--- + hw/net/virtio-net.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index f72be9f..8e58139 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -490,6 +490,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) + } + vhost_net_ack_features(tap_get_vhost_net(nc->peer), features); + } ++ ++ if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) { ++ memset(n->vlans, 0, MAX_VLAN >> 3); ++ } else { ++ memset(n->vlans, 0xff, MAX_VLAN >> 3); ++ } + } + + static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, +-- +1.7.1 + diff --git a/SOURCES/kvm-virtio-net-add-vlan-receive-state-to-RxFilterInfo.patch b/SOURCES/kvm-virtio-net-add-vlan-receive-state-to-RxFilterInfo.patch new file mode 100644 index 0000000..e8a07a0 --- /dev/null +++ b/SOURCES/kvm-virtio-net-add-vlan-receive-state-to-RxFilterInfo.patch @@ -0,0 +1,148 @@ +From 2bfc8b6bf5e03e3b8c0c7dc1743f719cc4273784 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Mon, 4 Aug 2014 04:12:08 +0200 +Subject: [PATCH 09/10] virtio-net: add vlan receive state to RxFilterInfo + +Message-id: <1407125528-27862-3-git-send-email-akong@redhat.com> +Patchwork-id: 60416 +O-Subject: [RHEL-7.1/7.0.z qemu-kvm PATCH 2/2] virtio-net: add vlan receive state to RxFilterInfo +Bugzilla: 1130149 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Xiao Wang +RH-Acked-by: Vlad Yasevich + +Stefan Fritsch just fixed a virtio-net driver bug [1], virtio-net won't +filter out VLAN-tagged packets if VIRTIO_NET_F_CTRL_VLAN isn't negotiated. + +This patch added a new field to @RxFilterInfo to indicate vlan receive +state ('normal', 'none', 'all'). If VIRTIO_NET_F_CTRL_VLAN isn't +negotiated, vlan receive state will be 'all', then all VLAN-tagged packets +will be received by guest. + +This patch also fixed a boundary issue in visiting vlan table. + +[1] http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg02604.html + +Signed-off-by: Amos Kong +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Eric Blake +(backport from commit f7bc8ef8091229a4bec0e2a40af90abb8dcb3834) +Signed-off-by: Miroslav Rezanina +--- + hw/net/virtio-net.c | 42 +++++++++++++++++++++++++++++------------- + qapi-schema.json | 3 +++ + qmp-commands.hx | 2 ++ + 3 files changed, 34 insertions(+), 13 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 8e58139..4a50869 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -222,13 +222,33 @@ static char *mac_strdup_printf(const uint8_t *mac) + mac[1], mac[2], mac[3], mac[4], mac[5]); + } + ++static intList *get_vlan_table(VirtIONet *n) ++{ ++ intList *list, *entry; ++ int i, j; ++ ++ list = NULL; ++ for (i = 0; i < MAX_VLAN >> 5; i++) { ++ for (j = 0; n->vlans[i] && j <= 0x1f; j++) { ++ if (n->vlans[i] & (1U << j)) { ++ entry = g_malloc0(sizeof(*entry)); ++ entry->value = (i << 5) + j; ++ entry->next = list; ++ list = entry; ++ } ++ } ++ } ++ ++ return list; ++} ++ + static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) + { + VirtIONet *n = qemu_get_nic_opaque(nc); ++ VirtIODevice *vdev = VIRTIO_DEVICE(n); + RxFilterInfo *info; + strList *str_list, *entry; +- intList *int_list, *int_entry; +- int i, j; ++ int i; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(nc->name); +@@ -273,19 +293,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) + str_list = entry; + } + info->multicast_table = str_list; ++ info->vlan_table = get_vlan_table(n); + +- int_list = NULL; +- for (i = 0; i < MAX_VLAN >> 5; i++) { +- for (j = 0; n->vlans[i] && j < 0x1f; j++) { +- if (n->vlans[i] & (1U << j)) { +- int_entry = g_malloc0(sizeof(*int_entry)); +- int_entry->value = (i << 5) + j; +- int_entry->next = int_list; +- int_list = int_entry; +- } +- } ++ if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) { ++ info->vlan = RX_STATE_ALL; ++ } else if (!info->vlan_table) { ++ info->vlan = RX_STATE_NONE; ++ } else { ++ info->vlan = RX_STATE_NORMAL; + } +- info->vlan_table = int_list; + + /* enable event notification after query */ + nc->rxfilter_notify_enabled = 1; +diff --git a/qapi-schema.json b/qapi-schema.json +index 017b3b7..aaa86f5 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -4044,6 +4044,8 @@ + # + # @unicast: unicast receive state + # ++# @vlan: vlan receive state (Since 2.0) ++# + # @broadcast-allowed: whether to receive broadcast + # + # @multicast-overflow: multicast table is overflowed or not +@@ -4067,6 +4069,7 @@ + 'promiscuous': 'bool', + 'multicast': 'RxState', + 'unicast': 'RxState', ++ 'vlan': 'RxState', + 'broadcast-allowed': 'bool', + 'multicast-overflow': 'bool', + 'unicast-overflow': 'bool', +diff --git a/qmp-commands.hx b/qmp-commands.hx +index 08a01ee..1d4be84 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -3230,6 +3230,7 @@ Each array entry contains the following: + - "promiscuous": promiscuous mode is enabled (json-bool) + - "multicast": multicast receive state (one of 'normal', 'none', 'all') + - "unicast": unicast receive state (one of 'normal', 'none', 'all') ++- "vlan": vlan receive state (one of 'normal', 'none', 'all') (Since 2.0) + - "broadcast-allowed": allow to receive broadcast (json-bool) + - "multicast-overflow": multicast table is overflowed (json-bool) + - "unicast-overflow": unicast table is overflowed (json-bool) +@@ -3247,6 +3248,7 @@ Example: + "name": "vnet0", + "main-mac": "52:54:00:12:34:56", + "unicast": "normal", ++ "vlan": "normal", + "vlan-table": [ + 4, + 0 +-- +1.7.1 + diff --git a/SOURCES/kvm-vmstate-reduce-code-duplication.patch b/SOURCES/kvm-vmstate-reduce-code-duplication.patch new file mode 100644 index 0000000..e41edad --- /dev/null +++ b/SOURCES/kvm-vmstate-reduce-code-duplication.patch @@ -0,0 +1,158 @@ +From 8f92bf7e5891ec22b84b7969f24e6918ee5a9e38 Mon Sep 17 00:00:00 2001 +From: Michael S. Tsirkin +Date: Wed, 14 May 2014 08:24:25 +0200 +Subject: [PATCH 01/10] vmstate: reduce code duplication + +Message-id: <1400055633-6261-1-git-send-email-mst@redhat.com> +Patchwork-id: 58848 +O-Subject: [PATCH qemu-kvm RHEL7.0.z 1/5] vmstate: reduce code duplication +Bugzilla: 1095706 +RH-Acked-by: Juan Quintela +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Dr. David Alan Gilbert (git) + +move size offset and number of elements math out +to functions, to reduce code duplication. + +Signed-off-by: Michael S. Tsirkin +Cc: "Dr. David Alan Gilbert" +Signed-off-by: Juan Quintela +(cherry picked from commit 35fc1f71899fd42323bd8f33da18f0211e0d2727) +--- + savevm.c | 100 +++++++++++++++++++++++++++++++++------------------------------ + 1 file changed, 52 insertions(+), 48 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + savevm.c | 100 ++++++++++++++++++++++++++++++++----------------------------- + 1 files changed, 52 insertions(+), 48 deletions(-) + +diff --git a/savevm.c b/savevm.c +index 5d1b563..94512dd 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -1675,6 +1675,50 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, + static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque); + ++static int vmstate_n_elems(void *opaque, VMStateField *field) ++{ ++ int n_elems = 1; ++ ++ if (field->flags & VMS_ARRAY) { ++ n_elems = field->num; ++ } else if (field->flags & VMS_VARRAY_INT32) { ++ n_elems = *(int32_t *)(opaque+field->num_offset); ++ } else if (field->flags & VMS_VARRAY_UINT32) { ++ n_elems = *(uint32_t *)(opaque+field->num_offset); ++ } else if (field->flags & VMS_VARRAY_UINT16) { ++ n_elems = *(uint16_t *)(opaque+field->num_offset); ++ } else if (field->flags & VMS_VARRAY_UINT8) { ++ n_elems = *(uint8_t *)(opaque+field->num_offset); ++ } ++ ++ return n_elems; ++} ++ ++static int vmstate_size(void *opaque, VMStateField *field) ++{ ++ int size = field->size; ++ ++ if (field->flags & VMS_VBUFFER) { ++ size = *(int32_t *)(opaque+field->size_offset); ++ if (field->flags & VMS_MULTIPLY) { ++ size *= field->size; ++ } ++ } ++ ++ return size; ++} ++ ++static void *vmstate_base_addr(void *opaque, VMStateField *field) ++{ ++ void *base_addr = opaque + field->offset; ++ ++ if (field->flags & VMS_POINTER) { ++ base_addr = *(void **)base_addr + field->start; ++ } ++ ++ return base_addr; ++} ++ + int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque, int version_id) + { +@@ -1700,30 +1744,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, + field->field_exists(opaque, version_id)) || + (!field->field_exists && + field->version_id <= version_id)) { +- void *base_addr = opaque + field->offset; +- int i, n_elems = 1; +- int size = field->size; +- +- if (field->flags & VMS_VBUFFER) { +- size = *(int32_t *)(opaque+field->size_offset); +- if (field->flags & VMS_MULTIPLY) { +- size *= field->size; +- } +- } +- if (field->flags & VMS_ARRAY) { +- n_elems = field->num; +- } else if (field->flags & VMS_VARRAY_INT32) { +- n_elems = *(int32_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT32) { +- n_elems = *(uint32_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT16) { +- n_elems = *(uint16_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT8) { +- n_elems = *(uint8_t *)(opaque+field->num_offset); +- } +- if (field->flags & VMS_POINTER) { +- base_addr = *(void **)base_addr + field->start; +- } ++ void *base_addr = vmstate_base_addr(opaque, field); ++ int i, n_elems = vmstate_n_elems(opaque, field); ++ int size = vmstate_size(opaque, field); ++ + for (i = 0; i < n_elems; i++) { + void *addr = base_addr + size * i; + +@@ -1768,30 +1792,10 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, + while(field->name) { + if (!field->field_exists || + field->field_exists(opaque, vmsd->version_id)) { +- void *base_addr = opaque + field->offset; +- int i, n_elems = 1; +- int size = field->size; +- +- if (field->flags & VMS_VBUFFER) { +- size = *(int32_t *)(opaque+field->size_offset); +- if (field->flags & VMS_MULTIPLY) { +- size *= field->size; +- } +- } +- if (field->flags & VMS_ARRAY) { +- n_elems = field->num; +- } else if (field->flags & VMS_VARRAY_INT32) { +- n_elems = *(int32_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT32) { +- n_elems = *(uint32_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT16) { +- n_elems = *(uint16_t *)(opaque+field->num_offset); +- } else if (field->flags & VMS_VARRAY_UINT8) { +- n_elems = *(uint8_t *)(opaque+field->num_offset); +- } +- if (field->flags & VMS_POINTER) { +- base_addr = *(void **)base_addr + field->start; +- } ++ void *base_addr = vmstate_base_addr(opaque, field); ++ int i, n_elems = vmstate_n_elems(opaque, field); ++ int size = vmstate_size(opaque, field); ++ + for (i = 0; i < n_elems; i++) { + void *addr = base_addr + size * i; + +-- +1.7.1 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 6dd3fe0..9ee96c1 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -73,7 +73,7 @@ Obsoletes: %1 < %{obsoletes_version} \ Summary: QEMU is a FAST! processor emulator Name: %{pkgname}%{?pkgsuffix} Version: 1.5.3 -Release: 60%{?dist}.5 +Release: 60%{?dist}.7 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 10 License: GPLv2+ and LGPLv2+ and BSD @@ -2294,6 +2294,46 @@ Patch1122: kvm-zero-initialize-KVM_SET_GSI_ROUTING-input.patch Patch1123: kvm-skip-system-call-when-msi-route-is-unchanged.patch # For bz#1095782 - CVE-2014-0182 qemu-kvm: qemu: virtio: out-of-bounds buffer write on state load with invalid config_len [rhel-7.0.z] Patch1124: kvm-Allow-mismatched-virtio-config-len.patch +# For bz#1095706 - CVE-2013-4527 qemu-kvm: qemu: hpet: buffer overrun on invalid state load [rhel-7.0.z] +Patch1125: kvm-vmstate-reduce-code-duplication.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1126: kvm-vfio-pci-Add-debug-config-options-to-disable-MSI-X-K.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1127: kvm-vfio-correct-debug-macro-typo.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1128: kvm-vfio-pci-Fix-MSI-X-debug-code.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1129: kvm-vfio-pci-Fix-MSI-X-masking-performance.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1130: kvm-vfio-Fix-MSI-X-vector-expansion.patch +# For bz#1110693 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +# For bz#1110695 - 2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput +Patch1131: kvm-vfio-Don-t-cache-MSIMessage.patch +# For bz#1130149 - rx filter incorrect when guest disables VLAN filtering +Patch1132: kvm-virtio-net-Do-not-filter-VLANs-without-F_CTRL_VLAN.patch +# For bz#1130149 - rx filter incorrect when guest disables VLAN filtering +Patch1133: kvm-virtio-net-add-vlan-receive-state-to-RxFilterInfo.patch +# For bz#1124660 - [FJ7.0 Bug] RHEL7.0 guest attaching 150 or more virtio-blk disks fails to start up +Patch1134: kvm-memory-Don-t-call-memory_region_update_coalesced_ran.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1135: kvm-mirror-Fix-resource-leak-when-bdrv_getlength-fails.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1136: kvm-blockjob-Add-block_job_yield.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1137: kvm-mirror-Go-through-ready-complete-process-for-0-len-i.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1138: kvm-qemu-iotests-Test-BLOCK_JOB_READY-event-for-0Kb-imag.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1139: kvm-block-make-top-argument-to-block-commit-optional.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1140: kvm-qemu-iotests-Test-0-length-image-for-mirror.patch +# For bz#1132806 - advertise active commit to libvirt +Patch1141: kvm-mirror-Fix-qiov-size-for-short-requests.patch BuildRequires: zlib-devel @@ -3620,6 +3660,23 @@ cp %{SOURCE18} pc-bios # keep "make check" happy %patch1122 -p1 %patch1123 -p1 %patch1124 -p1 +%patch1125 -p1 +%patch1126 -p1 +%patch1127 -p1 +%patch1128 -p1 +%patch1129 -p1 +%patch1130 -p1 +%patch1131 -p1 +%patch1132 -p1 +%patch1133 -p1 +%patch1134 -p1 +%patch1135 -p1 +%patch1136 -p1 +%patch1137 -p1 +%patch1138 -p1 +%patch1139 -p1 +%patch1140 -p1 +%patch1141 -p1 %build buildarch="%{kvm_target}-softmmu" @@ -4036,6 +4093,37 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_libdir}/pkgconfig/libcacard.pc %changelog +* Tue Aug 26 2014 Miroslav Rezanina - 1.5.3-60.el7_0.7 +- kvm-mirror-Fix-resource-leak-when-bdrv_getlength-fails.patch [bz#1132806] +- kvm-blockjob-Add-block_job_yield.patch [bz#1132806] +- kvm-mirror-Go-through-ready-complete-process-for-0-len-i.patch [bz#1132806] +- kvm-qemu-iotests-Test-BLOCK_JOB_READY-event-for-0Kb-imag.patch [bz#1132806] +- kvm-block-make-top-argument-to-block-commit-optional.patch [bz#1132806] +- kvm-qemu-iotests-Test-0-length-image-for-mirror.patch [bz#1132806] +- kvm-mirror-Fix-qiov-size-for-short-requests.patch [bz#1132806] +- Resolves: bz#1132806 + (advertise active commit to libvirt) + +* Fri Aug 15 2014 Miroslav Rezanina - 1.5.3-60.el7_0.6 +- kvm-vmstate-reduce-code-duplication.patch [bz#1095706] +- kvm-vfio-pci-Add-debug-config-options-to-disable-MSI-X-K.patch [bz#1110693 bz#1110695] +- kvm-vfio-correct-debug-macro-typo.patch [bz#1110693 bz#1110695] +- kvm-vfio-pci-Fix-MSI-X-debug-code.patch [bz#1110693 bz#1110695] +- kvm-vfio-pci-Fix-MSI-X-masking-performance.patch [bz#1110693 bz#1110695] +- kvm-vfio-Fix-MSI-X-vector-expansion.patch [bz#1110693 bz#1110695] +- kvm-vfio-Don-t-cache-MSIMessage.patch [bz#1110693 bz#1110695] +- kvm-virtio-net-Do-not-filter-VLANs-without-F_CTRL_VLAN.patch [bz#1130149] +- kvm-virtio-net-add-vlan-receive-state-to-RxFilterInfo.patch [bz#1130149] +- kvm-memory-Don-t-call-memory_region_update_coalesced_ran.patch [bz#1124660] +- Resolves: bz#1110693 + (2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput) +- Resolves: bz#1110695 + (2x RHEL 5.10 VM running on RHEL 7 KVM have low TCP_STREAM throughput) +- Resolves: bz#1124660 + ([FJ7.0 Bug] RHEL7.0 guest attaching 150 or more virtio-blk disks fails to start up) +- Resolves: bz#1130149 + (rx filter incorrect when guest disables VLAN filtering) + * Wed Jul 02 2014 Miroslav Rezanina - 1.5.3-60.el7_0.5 - kvm-Allow-mismatched-virtio-config-len.patch [bz#1095782] - Resolves: bz#1095782